Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v3.0] Add support for rootless network-aliases and static ip/mac #9141

Merged
merged 2 commits into from
Jan 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions contrib/rootless-cni-infra/Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ARG GOLANG_VERSION=1.15
ARG ALPINE_VERSION=3.12
ARG CNI_VERSION=v0.8.0
ARG CNI_PLUGINS_VERSION=v0.8.7
ARG DNSNAME_VERSION=v1.0.0
ARG DNSNAME_VERSION=v1.1.1

FROM golang:${GOLANG_VERSION}-alpine${ALPINE_VERSION} AS golang-base
RUN apk add --no-cache git
Expand Down Expand Up @@ -33,4 +33,4 @@ COPY rootless-cni-infra /usr/local/bin
ENV CNI_PATH=/opt/cni/bin
CMD ["sleep", "infinity"]

ENV ROOTLESS_CNI_INFRA_VERSION=3
ENV ROOTLESS_CNI_INFRA_VERSION=5
20 changes: 16 additions & 4 deletions contrib/rootless-cni-infra/rootless-cni-infra
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,19 @@ wait_unshare_net() {
done
}

# CLI subcommand: "alloc $CONTAINER_ID $NETWORK_NAME $POD_NAME"
# CLI subcommand: "alloc $CONTAINER_ID $NETWORK_NAME $POD_NAME $IP $MAC $CAP_ARGS"
cmd_entrypoint_alloc() {
if [ "$#" -ne 3 ]; then
echo >&2 "Usage: $ARG0 alloc CONTAINER_ID NETWORK_NAME POD_NAME"
if [ "$#" -ne 6 ]; then
echo >&2 "Usage: $ARG0 alloc CONTAINER_ID NETWORK_NAME POD_NAME IP MAC CAP_ARGS"
exit 1
fi

ID="$1"
NET="$2"
K8S_POD_NAME="$3"
IP="$4"
MAC="$5"
CAP_ARGS="$6"

dir="${BASE}/${ID}"
mkdir -p "${dir}/attached" "${dir}/attached-args"
Expand All @@ -46,9 +49,18 @@ cmd_entrypoint_alloc() {
nsenter -t "${pid}" -n ip link set lo up
fi
CNI_ARGS="IgnoreUnknown=1;K8S_POD_NAME=${K8S_POD_NAME}"
if [ "$IP" ]; then
CNI_ARGS="$CNI_ARGS;IP=${IP}"
fi
if [ "$MAC" ]; then
CNI_ARGS="$CNI_ARGS;MAC=${MAC}"
fi
if [ "$CAP_ARGS" ]; then
CAP_ARGS="$CAP_ARGS"
fi
nwcount=$(find "${dir}/attached" -type f | wc -l)
CNI_IFNAME="eth${nwcount}"
export CNI_ARGS CNI_IFNAME
export CNI_ARGS CNI_IFNAME CAP_ARGS
cnitool add "${NET}" "/proc/${pid}/ns/net" >"${dir}/attached/${NET}"
echo "${CNI_ARGS}" >"${dir}/attached-args/${NET}"

Expand Down
34 changes: 29 additions & 5 deletions libpod/rootless_cni_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (

// Built from ../contrib/rootless-cni-infra.
var rootlessCNIInfraImage = map[string]string{
"amd64": "quay.io/libpod/rootless-cni-infra@sha256:304742d5d221211df4ec672807a5842ff11e3729c50bc424ea0cea858f69d7b7", // 3-amd64
"amd64": "quay.io/libpod/rootless-cni-infra@sha256:adf352454666f7ce9ca3e1098448b5ee18f89c4516471ec99447ec9ece917f36", // 5-amd64
}

const (
Expand Down Expand Up @@ -58,9 +58,33 @@ func AllocRootlessCNI(ctx context.Context, c *Container) (ns.NetNS, []*cnitypes.
return nil, nil, err
}
k8sPodName := getCNIPodName(c) // passed to CNI as K8S_POD_NAME
ip := ""
if c.config.StaticIP != nil {
ip = c.config.StaticIP.String()
}
mac := ""
if c.config.StaticMAC != nil {
mac = c.config.StaticMAC.String()
}
aliases, err := c.runtime.state.GetAllNetworkAliases(c)
if err != nil {
return nil, nil, err
}
capArgs := ""
// add network aliases json encoded as capabilityArgs for cni
if len(aliases) > 0 {
capabilityArgs := make(map[string]interface{})
capabilityArgs["aliases"] = aliases
b, err := json.Marshal(capabilityArgs)
if err != nil {
return nil, nil, err
}
capArgs = string(b)
}

cniResults := make([]*cnitypes.Result, len(networks))
for i, nw := range networks {
cniRes, err := rootlessCNIInfraCallAlloc(infra, c.ID(), nw, k8sPodName)
cniRes, err := rootlessCNIInfraCallAlloc(infra, c.ID(), nw, k8sPodName, ip, mac, capArgs)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -137,11 +161,11 @@ func getCNIPodName(c *Container) string {
return c.Name()
}

func rootlessCNIInfraCallAlloc(infra *Container, id, nw, k8sPodName string) (*cnitypes.Result, error) {
logrus.Debugf("rootless CNI: alloc %q, %q, %q", id, nw, k8sPodName)
func rootlessCNIInfraCallAlloc(infra *Container, id, nw, k8sPodName, ip, mac, capArgs string) (*cnitypes.Result, error) {
logrus.Debugf("rootless CNI: alloc %q, %q, %q, %q, %q, %q", id, nw, k8sPodName, ip, mac, capArgs)
var err error

_, err = rootlessCNIInfraExec(infra, "alloc", id, nw, k8sPodName)
_, err = rootlessCNIInfraExec(infra, "alloc", id, nw, k8sPodName, ip, mac, capArgs)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/specgen/container_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func exclusiveOptions(opt1, opt2 string) error {
// input for creating a container.
func (s *SpecGenerator) Validate() error {

if rootless.IsRootless() {
if rootless.IsRootless() && len(s.CNINetworks) == 0 {
if s.StaticIP != nil || s.StaticIPv6 != nil {
return ErrNoStaticIPRootless
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/specgen/pod_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func exclusivePodOptions(opt1, opt2 string) error {
// Validate verifies the input is valid
func (p *PodSpecGenerator) Validate() error {

if rootless.IsRootless() {
if rootless.IsRootless() && len(p.CNINetworks) == 0 {
if p.StaticIP != nil {
return ErrNoStaticIPRootless
}
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/create_staticip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var _ = Describe("Podman create with --ip flag", func() {
})

It("Podman create --ip with non-allocatable IP", func() {
SkipIfRootless("--ip is not supported in rootless mode")
SkipIfRootless("--ip not supported without network in rootless mode")
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", "203.0.113.124", ALPINE, "ls"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expand All @@ -63,7 +63,7 @@ var _ = Describe("Podman create with --ip flag", func() {
ip := GetRandomIPAddress()
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", ip, ALPINE, "ip", "addr"})
result.WaitWithDefaultTimeout()
// Rootless static ip assignment should error
// Rootless static ip assignment without network should error
if rootless.IsRootless() {
Expect(result.ExitCode()).To(Equal(125))
} else {
Expand All @@ -81,7 +81,7 @@ var _ = Describe("Podman create with --ip flag", func() {
})

It("Podman create two containers with the same IP", func() {
SkipIfRootless("--ip not supported in rootless mode")
SkipIfRootless("--ip not supported without network in rootless mode")
ip := GetRandomIPAddress()
result := podmanTest.Podman([]string{"create", "--name", "test1", "--ip", ip, ALPINE, "sleep", "999"})
result.WaitWithDefaultTimeout()
Expand Down
8 changes: 2 additions & 6 deletions test/e2e/create_staticmac_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,7 @@ var _ = Describe("Podman run with --mac-address flag", func() {

result := podmanTest.Podman([]string{"run", "--network", net, "--mac-address", "92:d0:c6:00:29:34", ALPINE, "ip", "addr"})
result.WaitWithDefaultTimeout()
if rootless.IsRootless() {
Expect(result.ExitCode()).To(Equal(125))
} else {
Expect(result.ExitCode()).To(Equal(0))
Expect(result.OutputToString()).To(ContainSubstring("92:d0:c6:00:29:34"))
}
Expect(result.ExitCode()).To(Equal(0))
Expect(result.OutputToString()).To(ContainSubstring("92:d0:c6:00:29:34"))
})
})
4 changes: 2 additions & 2 deletions test/e2e/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ var _ = Describe("Podman create", func() {
})

It("create container in pod with IP should fail", func() {
SkipIfRootless("Setting IP not supported in rootless mode")
SkipIfRootless("Setting IP not supported in rootless mode without network")
name := "createwithstaticip"
pod := podmanTest.RunTopContainerInPod("", "new:"+name)
pod.WaitWithDefaultTimeout()
Expand All @@ -565,7 +565,7 @@ var _ = Describe("Podman create", func() {
})

It("create container in pod with mac should fail", func() {
SkipIfRootless("Setting MAC Address not supported in rootless mode")
SkipIfRootless("Setting MAC Address not supported in rootless mode without network")
name := "createwithstaticmac"
pod := podmanTest.RunTopContainerInPod("", "new:"+name)
pod.WaitWithDefaultTimeout()
Expand Down
1 change: 0 additions & 1 deletion test/e2e/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,6 @@ var _ = Describe("Podman network", func() {
Expect(lines[1]).To(Equal(netName2))
})
It("podman network with multiple aliases", func() {
Skip("Until DNSName is updated on our CI images")
var worked bool
netName := "aliasTest" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", netName})
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/pod_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ var _ = Describe("Podman pod create", func() {
ip := GetRandomIPAddress()
podCreate := podmanTest.Podman([]string{"pod", "create", "--ip", ip, "--name", name})
podCreate.WaitWithDefaultTimeout()
// Rootless should error
// Rootless should error without network
if rootless.IsRootless() {
Expect(podCreate.ExitCode()).To(Equal(125))
} else {
Expand All @@ -246,7 +246,7 @@ var _ = Describe("Podman pod create", func() {
})

It("podman container in pod with IP address shares IP address", func() {
SkipIfRootless("Rootless does not support --ip")
SkipIfRootless("Rootless does not support --ip without network")
podName := "test"
ctrName := "testCtr"
ip := GetRandomIPAddress()
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/pod_inspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ var _ = Describe("Podman pod inspect", func() {
})

It("podman pod inspect outputs show correct MAC", func() {
SkipIfRootless("--mac-address is not supported in rootless mode")
SkipIfRootless("--mac-address is not supported in rootless mode without network")
podName := "testPod"
macAddr := "42:43:44:00:00:01"
create := podmanTest.Podman([]string{"pod", "create", "--name", podName, "--mac-address", macAddr})
Expand Down
6 changes: 0 additions & 6 deletions test/e2e/run_networking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,6 @@ var _ = Describe("Podman run networking", func() {
})

It("podman run in custom CNI network with --static-ip", func() {
SkipIfRootless("Rootless mode does not support --ip")
netName := stringid.GenerateNonCryptoID()
ipAddr := "10.25.30.128"
create := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.30.0/24", netName})
Expand All @@ -633,10 +632,6 @@ var _ = Describe("Podman run networking", func() {
run.WaitWithDefaultTimeout()
Expect(run.ExitCode()).To(BeZero())
Expect(run.OutputToString()).To(ContainSubstring(ipAddr))

create = podmanTest.Podman([]string{"network", "rm", netName})
create.WaitWithDefaultTimeout()
Expect(create.ExitCode()).To(BeZero())
})

It("podman rootless fails custom CNI network with --uidmap", func() {
Expand All @@ -658,7 +653,6 @@ var _ = Describe("Podman run networking", func() {
})

It("podman run with new:pod and static-ip", func() {
SkipIfRootless("Rootless does not support --ip")
netName := stringid.GenerateNonCryptoID()
ipAddr := "10.25.40.128"
podname := "testpod"
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/run_staticip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var _ = Describe("Podman run with --ip flag", func() {
)

BeforeEach(func() {
SkipIfRootless("rootless does not support --ip")
SkipIfRootless("rootless does not support --ip without network")
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
Expand Down