Merge pull request #8585 from Luap99/rootless-net-alias

Add support for rootless network-aliases and static ip/mac
This commit is contained in:
OpenShift Merge Robot
2021-01-28 04:58:28 -05:00
committed by GitHub
13 changed files with 60 additions and 35 deletions

View File

@ -2,7 +2,7 @@ ARG GOLANG_VERSION=1.15
ARG ALPINE_VERSION=3.12 ARG ALPINE_VERSION=3.12
ARG CNI_VERSION=v0.8.0 ARG CNI_VERSION=v0.8.0
ARG CNI_PLUGINS_VERSION=v0.8.7 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 FROM golang:${GOLANG_VERSION}-alpine${ALPINE_VERSION} AS golang-base
RUN apk add --no-cache git RUN apk add --no-cache git
@ -33,4 +33,4 @@ COPY rootless-cni-infra /usr/local/bin
ENV CNI_PATH=/opt/cni/bin ENV CNI_PATH=/opt/cni/bin
CMD ["sleep", "infinity"] CMD ["sleep", "infinity"]
ENV ROOTLESS_CNI_INFRA_VERSION=3 ENV ROOTLESS_CNI_INFRA_VERSION=5

View File

@ -21,16 +21,19 @@ wait_unshare_net() {
done 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() { cmd_entrypoint_alloc() {
if [ "$#" -ne 3 ]; then if [ "$#" -ne 6 ]; then
echo >&2 "Usage: $ARG0 alloc CONTAINER_ID NETWORK_NAME POD_NAME" echo >&2 "Usage: $ARG0 alloc CONTAINER_ID NETWORK_NAME POD_NAME IP MAC CAP_ARGS"
exit 1 exit 1
fi fi
ID="$1" ID="$1"
NET="$2" NET="$2"
K8S_POD_NAME="$3" K8S_POD_NAME="$3"
IP="$4"
MAC="$5"
CAP_ARGS="$6"
dir="${BASE}/${ID}" dir="${BASE}/${ID}"
mkdir -p "${dir}/attached" "${dir}/attached-args" mkdir -p "${dir}/attached" "${dir}/attached-args"
@ -46,9 +49,18 @@ cmd_entrypoint_alloc() {
nsenter -t "${pid}" -n ip link set lo up nsenter -t "${pid}" -n ip link set lo up
fi fi
CNI_ARGS="IgnoreUnknown=1;K8S_POD_NAME=${K8S_POD_NAME}" 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) nwcount=$(find "${dir}/attached" -type f | wc -l)
CNI_IFNAME="eth${nwcount}" 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}" cnitool add "${NET}" "/proc/${pid}/ns/net" >"${dir}/attached/${NET}"
echo "${CNI_ARGS}" >"${dir}/attached-args/${NET}" echo "${CNI_ARGS}" >"${dir}/attached-args/${NET}"

View File

@ -25,7 +25,7 @@ import (
// Built from ../contrib/rootless-cni-infra. // Built from ../contrib/rootless-cni-infra.
var rootlessCNIInfraImage = map[string]string{ 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 ( const (
@ -58,9 +58,33 @@ func AllocRootlessCNI(ctx context.Context, c *Container) (ns.NetNS, []*cnitypes.
return nil, nil, err return nil, nil, err
} }
k8sPodName := getCNIPodName(c) // passed to CNI as K8S_POD_NAME 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)) cniResults := make([]*cnitypes.Result, len(networks))
for i, nw := range 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 { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -137,11 +161,11 @@ func getCNIPodName(c *Container) string {
return c.Name() return c.Name()
} }
func rootlessCNIInfraCallAlloc(infra *Container, id, nw, k8sPodName string) (*cnitypes.Result, error) { func rootlessCNIInfraCallAlloc(infra *Container, id, nw, k8sPodName, ip, mac, capArgs string) (*cnitypes.Result, error) {
logrus.Debugf("rootless CNI: alloc %q, %q, %q", id, nw, k8sPodName) logrus.Debugf("rootless CNI: alloc %q, %q, %q, %q, %q, %q", id, nw, k8sPodName, ip, mac, capArgs)
var err error var err error
_, err = rootlessCNIInfraExec(infra, "alloc", id, nw, k8sPodName) _, err = rootlessCNIInfraExec(infra, "alloc", id, nw, k8sPodName, ip, mac, capArgs)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -30,7 +30,7 @@ func exclusiveOptions(opt1, opt2 string) error {
// input for creating a container. // input for creating a container.
func (s *SpecGenerator) Validate() error { func (s *SpecGenerator) Validate() error {
if rootless.IsRootless() { if rootless.IsRootless() && len(s.CNINetworks) == 0 {
if s.StaticIP != nil || s.StaticIPv6 != nil { if s.StaticIP != nil || s.StaticIPv6 != nil {
return ErrNoStaticIPRootless return ErrNoStaticIPRootless
} }

View File

@ -20,7 +20,7 @@ func exclusivePodOptions(opt1, opt2 string) error {
// Validate verifies the input is valid // Validate verifies the input is valid
func (p *PodSpecGenerator) Validate() error { func (p *PodSpecGenerator) Validate() error {
if rootless.IsRootless() { if rootless.IsRootless() && len(p.CNINetworks) == 0 {
if p.StaticIP != nil { if p.StaticIP != nil {
return ErrNoStaticIPRootless return ErrNoStaticIPRootless
} }

View File

@ -49,7 +49,7 @@ var _ = Describe("Podman create with --ip flag", func() {
}) })
It("Podman create --ip with non-allocatable IP", 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 := podmanTest.Podman([]string{"create", "--name", "test", "--ip", "203.0.113.124", ALPINE, "ls"})
result.WaitWithDefaultTimeout() result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0)) Expect(result.ExitCode()).To(Equal(0))
@ -63,7 +63,7 @@ var _ = Describe("Podman create with --ip flag", func() {
ip := GetRandomIPAddress() ip := GetRandomIPAddress()
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", ip, ALPINE, "ip", "addr"}) result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", ip, ALPINE, "ip", "addr"})
result.WaitWithDefaultTimeout() result.WaitWithDefaultTimeout()
// Rootless static ip assignment should error // Rootless static ip assignment without network should error
if rootless.IsRootless() { if rootless.IsRootless() {
Expect(result.ExitCode()).To(Equal(125)) Expect(result.ExitCode()).To(Equal(125))
} else { } else {
@ -81,7 +81,7 @@ var _ = Describe("Podman create with --ip flag", func() {
}) })
It("Podman create two containers with the same IP", 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() ip := GetRandomIPAddress()
result := podmanTest.Podman([]string{"create", "--name", "test1", "--ip", ip, ALPINE, "sleep", "999"}) result := podmanTest.Podman([]string{"create", "--name", "test1", "--ip", ip, ALPINE, "sleep", "999"})
result.WaitWithDefaultTimeout() result.WaitWithDefaultTimeout()

View File

@ -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 := podmanTest.Podman([]string{"run", "--network", net, "--mac-address", "92:d0:c6:00:29:34", ALPINE, "ip", "addr"})
result.WaitWithDefaultTimeout() result.WaitWithDefaultTimeout()
if rootless.IsRootless() { Expect(result.ExitCode()).To(Equal(0))
Expect(result.ExitCode()).To(Equal(125)) Expect(result.OutputToString()).To(ContainSubstring("92:d0:c6:00:29:34"))
} else {
Expect(result.ExitCode()).To(Equal(0))
Expect(result.OutputToString()).To(ContainSubstring("92:d0:c6:00:29:34"))
}
}) })
}) })

View File

@ -553,7 +553,7 @@ var _ = Describe("Podman create", func() {
}) })
It("create container in pod with IP should fail", 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" name := "createwithstaticip"
pod := podmanTest.RunTopContainerInPod("", "new:"+name) pod := podmanTest.RunTopContainerInPod("", "new:"+name)
pod.WaitWithDefaultTimeout() pod.WaitWithDefaultTimeout()
@ -565,7 +565,7 @@ var _ = Describe("Podman create", func() {
}) })
It("create container in pod with mac should fail", 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" name := "createwithstaticmac"
pod := podmanTest.RunTopContainerInPod("", "new:"+name) pod := podmanTest.RunTopContainerInPod("", "new:"+name)
pod.WaitWithDefaultTimeout() pod.WaitWithDefaultTimeout()

View File

@ -408,7 +408,6 @@ var _ = Describe("Podman network", func() {
Expect(lines[1]).To(Equal(netName2)) Expect(lines[1]).To(Equal(netName2))
}) })
It("podman network with multiple aliases", func() { It("podman network with multiple aliases", func() {
Skip("Until DNSName is updated on our CI images")
var worked bool var worked bool
netName := "aliasTest" + stringid.GenerateNonCryptoID() netName := "aliasTest" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", netName}) session := podmanTest.Podman([]string{"network", "create", netName})

View File

@ -233,7 +233,7 @@ var _ = Describe("Podman pod create", func() {
ip := GetRandomIPAddress() ip := GetRandomIPAddress()
podCreate := podmanTest.Podman([]string{"pod", "create", "--ip", ip, "--name", name}) podCreate := podmanTest.Podman([]string{"pod", "create", "--ip", ip, "--name", name})
podCreate.WaitWithDefaultTimeout() podCreate.WaitWithDefaultTimeout()
// Rootless should error // Rootless should error without network
if rootless.IsRootless() { if rootless.IsRootless() {
Expect(podCreate.ExitCode()).To(Equal(125)) Expect(podCreate.ExitCode()).To(Equal(125))
} else { } else {
@ -246,7 +246,7 @@ var _ = Describe("Podman pod create", func() {
}) })
It("podman container in pod with IP address shares IP address", 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" podName := "test"
ctrName := "testCtr" ctrName := "testCtr"
ip := GetRandomIPAddress() ip := GetRandomIPAddress()

View File

@ -101,7 +101,7 @@ var _ = Describe("Podman pod inspect", func() {
}) })
It("podman pod inspect outputs show correct MAC", 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" podName := "testPod"
macAddr := "42:43:44:00:00:01" macAddr := "42:43:44:00:00:01"
create := podmanTest.Podman([]string{"pod", "create", "--name", podName, "--mac-address", macAddr}) create := podmanTest.Podman([]string{"pod", "create", "--name", podName, "--mac-address", macAddr})

View File

@ -621,7 +621,6 @@ var _ = Describe("Podman run networking", func() {
}) })
It("podman run in custom CNI network with --static-ip", func() { It("podman run in custom CNI network with --static-ip", func() {
SkipIfRootless("Rootless mode does not support --ip")
netName := stringid.GenerateNonCryptoID() netName := stringid.GenerateNonCryptoID()
ipAddr := "10.25.30.128" ipAddr := "10.25.30.128"
create := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.30.0/24", netName}) create := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.30.0/24", netName})
@ -633,10 +632,6 @@ var _ = Describe("Podman run networking", func() {
run.WaitWithDefaultTimeout() run.WaitWithDefaultTimeout()
Expect(run.ExitCode()).To(BeZero()) Expect(run.ExitCode()).To(BeZero())
Expect(run.OutputToString()).To(ContainSubstring(ipAddr)) 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() { It("podman rootless fails custom CNI network with --uidmap", func() {
@ -658,7 +653,6 @@ var _ = Describe("Podman run networking", func() {
}) })
It("podman run with new:pod and static-ip", func() { It("podman run with new:pod and static-ip", func() {
SkipIfRootless("Rootless does not support --ip")
netName := stringid.GenerateNonCryptoID() netName := stringid.GenerateNonCryptoID()
ipAddr := "10.25.40.128" ipAddr := "10.25.40.128"
podname := "testpod" podname := "testpod"

View File

@ -19,7 +19,7 @@ var _ = Describe("Podman run with --ip flag", func() {
) )
BeforeEach(func() { BeforeEach(func() {
SkipIfRootless("rootless does not support --ip") SkipIfRootless("rootless does not support --ip without network")
tempdir, err = CreateTempDirInTempDir() tempdir, err = CreateTempDirInTempDir()
if err != nil { if err != nil {
os.Exit(1) os.Exit(1)