srl-labs / clabernetes

containerlab, but in kubernetes!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Interface and static route cleanup on transient launch failure

flaminidavid opened this issue · comments

The cleanup issue mentioned in #143 is actually impacting external connectivity. For example, if the launcher fails to bring up the router container because the container image is not (yet) available it will leave static routes and bridges behind. This results in the kernel resolving to the wrong bridge interface to reach the container.

[*]─[REDACTED_HOSTNAME]─[/clabernetes]
└──> ssh REDACTED_HOSTNAME
ssh: connect to host REDACTED_HOSTNAME port 22: No route to host <<< SSH fails with no route message :(

[x]─[REDACTED_HOSTNAME]─[/clabernetes]
└──> clab inspect
INFO[0000] Parsing & checking topology file: topo.clab.yaml 
+---+------------------+--------------+------------------------------------------+------+---------+----------------+----------------------+
| # |       Name       | Container ID |                  Image                   | Kind |  State  |  IPv4 Address  |     IPv6 Address     |
+---+------------------+--------------+------------------------------------------+------+---------+----------------+----------------------+
| 1 | REDACTED_HOSTNAME | d9d8482e94d5 | registry:80/REDACTED_OS-lab/REDACTED_OS-lab:latest | REDACTED_OS | running | 172.20.20.2/24 | 2001:172:20:20::2/64 |
+---+------------------+--------------+------------------------------------------+------+---------+----------------+----------------------+

[*]─[REDACTED_HOSTNAME]─[/clabernetes]
└──> ip route 
default via 169.254.1.1 dev eth0 
169.254.1.1 dev eth0 scope link 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
172.20.20.0/24 dev br-9e0abc3fc5c4 proto kernel scope link src 172.20.20.1 linkdown <<< Static route installed during previous REDACTED_HOSTNAME launch attempt which failed (image not available yet)
172.20.20.0/24 dev br-8e01cb23f4e2 proto kernel scope link src 172.20.20.1 linkdown <<< Static route installed during previous REDACTED_HOSTNAME launch attempt which failed (image not available yet)
172.20.20.0/24 dev br-99c0d2f2be16 proto kernel scope link src 172.20.20.1 linkdown <<< Static route installed during previous REDACTED_HOSTNAME launch attempt which failed (image not available yet)
172.20.20.0/24 dev br-0a9d5d103385 proto kernel scope link src 172.20.20.1 linkdown <<< Static route installed during previous REDACTED_HOSTNAME launch attempt which failed (image not available yet)
172.20.20.0/24 dev br-70f3bba49d02 proto kernel scope link src 172.20.20.1 linkdown <<< Static route installed during previous REDACTED_HOSTNAME launch attempt which failed (image not available yet)
172.20.20.0/24 dev br-ade82612ffc0 proto kernel scope link src 172.20.20.1 <<< Static route installed during last launch attempt, which was successful

[*]─[REDACTED_HOSTNAME]─[/clabernetes]
└──> ip route get 172.20.20.2
172.20.20.2 dev br-9e0abc3fc5c4 src 172.20.20.1 uid 0 <<< Kernel resolves to first interface with link down due to static route
    cache 

[*]─[REDACTED_HOSTNAME]─[/clabernetes]
└──> sysctl -w net.ipv4.conf.br-9e0abc3fc5c4.ignore_routes_with_linkdown=1 <<< Set Kernel to ignore routes with link down on this interface
net.ipv4.conf.br-9e0abc3fc5c4.ignore_routes_with_linkdown = 1

[*]─[REDACTED_HOSTNAME]─[/clabernetes]
└──> ip route get 172.20.20.2
172.20.20.2 dev br-8e01cb23f4e2 src 172.20.20.1 uid 0 <<< Kernel resolves to second interface with link down due to static route
    cache 

[*]─[REDACTED_HOSTNAME]─[/clabernetes]
└──> for down_bridge in $(ip link show type bridge | grep br- | awk -F: '{print $2}'); do sysctl -w net.ipv4.conf.$down_bridge.ignore_routes_with_linkdown=1; done
net.ipv4.conf.br-9e0abc3fc5c4.ignore_routes_with_linkdown = 1 <<< Set Kernel to ignore routes with link down on this interface
net.ipv4.conf.br-8e01cb23f4e2.ignore_routes_with_linkdown = 1 <<< Set Kernel to ignore routes with link down on this interface
net.ipv4.conf.br-99c0d2f2be16.ignore_routes_with_linkdown = 1 <<< Set Kernel to ignore routes with link down on this interface
net.ipv4.conf.br-0a9d5d103385.ignore_routes_with_linkdown = 1 <<< Set Kernel to ignore routes with link down on this interface
net.ipv4.conf.br-70f3bba49d02.ignore_routes_with_linkdown = 1 <<< Set Kernel to ignore routes with link down on this interface
net.ipv4.conf.br-ade82612ffc0.ignore_routes_with_linkdown = 1 <<< Set Kernel to ignore routes with link down on this interface

[*]─[REDACTED_HOSTNAME]─[/clabernetes]
└──> ip route get 172.20.20.2
172.20.20.2 dev br-ade82612ffc0 src 172.20.20.1 uid 0 <<< Kernel resolves to the only interface without link down
    cache 

[x]─[REDACTED_HOSTNAME]─[/clabernetes]
└──> ssh REDACTED_HOSTNAME
Warning: Permanently added 'REDACTED_HOSTNAME' (...) to the list of known hosts.
(admin@REDACTED_HOSTNAME) Password: 
REDACTED_HOSTNAME> <<< SSH succeeds :)

@flaminidavid I wonder, you mentioned that the image is not available for some time, but the output shows the registry is being used, and not a local daemon store.

Don't you have images pushed in your private registry ahead of time before launching the lab?

@carlmontanari I wonder if regardless of the above comment all we need to do is call clab dep -c <topo>, with -c flag doing the clean redeployment that should remove the unused docker bridge

if the launcher fails to bring up the router container because the container image is not (yet) available

then the launcher should be crashing. it seems you are execing onto the launcher to test stuff which is cool, but not how this works "irl". in your case it seems maybe you run stuff manually then re-launching after the image is ready or something (lots of assumptions here obv shout if they are incorrect!). I think that none of this is a problem in the normal flow as the launcher would always crash after any failure then we'd have a fresh container to try again. Guses we can add the -c flag if it matters but I dont think it "should".

Sorry folks, I was out.

Don't you have images pushed in your private registry ahead of time before launching the lab?

I agree, I should. I'm probably abusing the launcher's ability to retry here.
I guess my point is that if something (else) fails during launch the launcher ends up in this dirty state.

it seems maybe you run stuff manually then re-launching after the image is ready or something

No, it's just a workaround for discard_unpacked_layers. Basically I deploy a separate registry (and puller) in the same namespace at the same time I deploy a topology via Clabernetes. I should be able to get rid of all that with the Docker config feature you added in #143. I'm not doing anything to the launcher, it's just retrying until the image is there. I don't know what else could make the launcher fail in a similar way, but if it did it would end up dirty (those static routes and bridges left behind).

the launcher would always crash after any failure then we'd have a fresh container to try again

Looks like the launcher container itself doesn't crash, only the router container inside does. Those static routes and bridges live in the launcher and stick around after the router container failure.

Looks like the launcher container itself doesn't crash, only the router container inside does. Those static routes and bridges live in the launcher and stick around after the router container failure.

can you share logs of that? if clab exits non-zero it should crash, if the container starts then goes away, it should crash. if you were on the pod (like made entry point sleep or something and exec'd on) then it would just exit but not crash since then clabernetes is not the entry point. tl;dr yeah if it doesn't it should so logs should help pin point where, but it really should be crashing properly hah. I hope :D

unsure if it will be the "fix" but am adding the -c in #159 just in case. will prolly cut 0.1.2 today so then maybe can test that and let us know if it sorts it!

Thanks! Upgraded today to 0.1.3, it did not fix it. I'll test passing Docker config in a bit, which should be enough for my use case.

I checked that the launcher is using 0.1.3: Image: ghcr.io/srl-labs/clabernetes/clabernetes-launcher:0.1.3

[/clabernetes]
└──> ip route | grep br
172.20.20.0/24 dev br-34417135bcc2 proto kernel scope link src 172.20.20.1 linkdown 
172.20.20.0/24 dev br-9082e6489457 proto kernel scope link src 172.20.20.1 linkdown 
172.20.20.0/24 dev br-c455be425faa proto kernel scope link src 172.20.20.1 linkdown 
172.20.20.0/24 dev br-4c04d38d7c33 proto kernel scope link src 172.20.20.1 linkdown 
172.20.20.0/24 dev br-6dbd9cfb63a7 proto kernel scope link src 172.20.20.1 linkdown 
172.20.20.0/24 dev br-5bbea88fefad proto kernel scope link src 172.20.20.1 linkdown 
172.20.20.0/24 dev br-2a67784d5de3 proto kernel scope link src 172.20.20.1 linkdown 
172.20.20.0/24 dev br-db61001317a1 proto kernel scope link src 172.20.20.1 

@flaminidavid what does docker network ls say in your case?

[/clabernetes]
└──> docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a7671c32b0fa   bridge    bridge    local
db61001317a1   clab      bridge    local
5225d54edb9d   host      host      local
e8c80bd3b98a   none      null      local

In other news, overriding Docker config via spec.imagePull.dockerConfig worked just fine (and switched back pullThroughOverride from never to auto). This is working with AWS ECR, too.

damn haha ok cool thanks a bunch for updating us all. will prolly futz around with this this weekend. I think I accidentally encountered the same issue (recreating it may be another story!) so can for sure see if we can fix... will keep ya posted!