nerdctl icon indicating copy to clipboard operation
nerdctl copied to clipboard

Supports multiple IP address assignment for `nerdctl run` and `nerdctl compose up`

Open kbrierly opened this issue 1 year ago • 7 comments

Per (https://github.com/containerd/nerdctl/issues/3556#issuecomment-2466527814) I am opening an issue on what seems to be CNI concurrency issue.

I am having CNI issues when using multiple networks. One is macvlan network and the other is a bridge network. I've also attempted dual macvlan with similar results. What happens looks like an ordering issue. Sometimes the bridge interface would try and come up as a macvlan for example or as below shows the macvlan tries to come up as a bridge . I made a basic test compose file with hello-world and it happens there are well. Nothing is currently assigned the ip. I've tried other unused ip's as well.

I found this when trying to use 2.0.0-rc3 and I retried when 2.0.0 was released and the problem persists. The same compose file works without issue in docker compose.

This is the result from a "nerdctl compose up". The home.local is macvlan, proxy.home.local is a bridge. Single network services start with no issues.

# nerdctl compose up  
INFO[0000] Ensuring image hello-world                   
INFO[0000] Creating container test                      
FATA[0003] failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running hook #0: error running hook: exit status 1, stdout: , stderr: time="2024-11-09T11:06:52-06:00" level=fatal msg="failed to call cni.Setup: plugin type=\"bridge\" failed (add): failed to allocate all requested IPs: 10.0.0.171": unknown 
FATA[0003] error while creating container test: exit status 1

The hello-world compose file:

services:
  hello:
    image: hello-world
    container_name: test
    hostname: test
    networks:
      home.local:
        ipv4_address: 10.0.0.171
        mac_address: 02:42:0a:00:01:47
      proxy.home.local:
          ipv4_address: 10.100.100.127
     
networks:
    home.local:
        name: home.local
        external: true
    proxy.home.local:
        name: proxy.home.local
        external: true

Network creation commands and cni versions:

# nerdctl network create -d macvlan --subnet=10.0.0.0/24 --gateway=10.0.0.1 -o parent=bond0 -o macvlan_mode=bridge home.local
# nerdctl network create --subnet=10.100.100.0/24 proxy.home.local

# /opt/cni/bin/macvlan -v
CNI macvlan plugin v1.6.0
CNI protocol versions supported: 0.1.0, 0.2.0, 0.3.0, 0.3.1, 0.4.0, 1.0.0, 1.1.0
# /opt/cni/bin/bridge -v
CNI bridge plugin v1.6.0
CNI protocol versions supported: 0.1.0, 0.2.0, 0.3.0, 0.3.1, 0.4.0, 1.0.0, 1.1.0

kbrierly avatar Nov 10 '24 05:11 kbrierly

Bug confirmed, Let us figure it out

Zheaoli avatar Nov 10 '24 16:11 Zheaoli

OK, here's the detail

I'm not sure if this a bug or not. For now, we do not support multiple IP address assignment yet.

https://github.com/containerd/nerdctl/blob/main/pkg/cmd/container/create.go#L634-L662

Your compose file will be converted to the command nerdctl run --pull=never --net=home.local --ip=10.0.0.171 --mac-address=02:42:0a:00:01:47 --net=proxy.home.local --ip=10.100.100.127 --hostname=test --restart=no hello-world

The last IP address will override the first IP address. So the issue comes here.

I'm not sure we should support multiple IP address assignment. WDYT @AkihiroSuda

Zheaoli avatar Nov 26 '24 14:11 Zheaoli

I'm not sure we should support multiple IP address assignment.

It should correspond to whether Docker supports multiple IP address assignment

AkihiroSuda avatar Nov 26 '24 14:11 AkihiroSuda

I'm not sure we should support multiple IP address assignment.

It should correspond to whether Docker supports multiple IP address assignment

Same idea, Let us figure it out

Zheaoli avatar Nov 26 '24 15:11 Zheaoli

I have figured it out.

I have the same issue using the nerdctl that comes with Rancher Desktop on macOS. Switching to Docker fixes it. So, Docker supports multiple IP address assignment.

gflohr avatar Feb 28 '25 07:02 gflohr

Docker does not support passing multiple networks and multiple ips on the run command: the last specified ip will be used for the first specified network (<- the logic in that escapes me, but whatever). I personally think this ^ is just buggy and should support multiple ips.

eg:

docker run -ti --net one --ip "10.42.0.42" --net two --ip "10.42.0.43" debian
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.42.0.43  netmask 255.255.255.0  broadcast 10.42.0.255
        ether d6:a5:f6:5c:73:51  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.43.0.2  netmask 255.255.255.0  broadcast 10.43.0.255
        ether 26:0a:28:de:1b:1c  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

The same is likely true for mac and ipv6 as well. Same for port bindings.

I suspect what docker does with that compose file is create, then connect (for each network), then run.

If I am not mistaken, fixing this in nerdctl requires a good many different things to happen and likely significant effort:

  1. [ ] implement network connect that we apparently do not have
  2. [ ] replace all labels for ip, ipv6, mac, to support slices instead of string (this will likely break backward compatibility if not done very carefully)
  3. [ ] rewrite a good section of ocihook (and maybe netutil)
  4. [ ] possibly rewrite compose logic to leverage connect when presented with multiple networks

I need some of this. Not personally interested in the compose part, but I need multi-ip with multi-networks, so, I am likely to go for 2. and 3, and either 1. or allow multi-ips to be specified on run.

If anyone else is interested in this and wants to chime in, give me a ping so that we either collaborate on this or at least don't duplicate effort.

apostasie avatar May 23 '25 00:05 apostasie

Actually, docker DOES support specifying details for multiple networks on run - just with this syntax:

docker run -itd --network=name=my-net1,ip=192.0.2.42 --network=name=my-net2,ip=192.0.3.42 busybox

apostasie avatar May 24 '25 01:05 apostasie