agent: netlink: Only add an ipv6 address if ipv6 is enabled

When running Kata Containers on CSPs, the CSPs may enforce their
clusters to be IPv4-only.

Checking the OCI spec passed down to container, on a GKE cluster, we can
see:
```
    "sysctl": {
      ...
      "net.ipv6.conf.all.disable_ipv6": "1",
      "net.ipv6.conf.default.disable_ipv6": "1",
      ...
    },
```

Even with ipv6 being explicitly disabled (behind our back ;-)), we've
noticed that IPv6 addresses would be received, but then as IPv6 was
disabled we'd break on CreatePodSandbox with the following error:
```
Warning  FailedCreatePodSandBox  4s    kubelet            Failed to
create pod sandbox: rpc error: code = Unknown desc = failed to create
containerd task: failed to create shim task: "update interface: Failed
to add address fe80::c44c:1cff:fe84:f6b7: NetlinkError(ErrorMessage {
code: Some(-13), header: [64, 0, 0, 0, 20, 0, 5, 5, 19, 0, 0, 0, 0, 0,
0, 0, 10, 64, 0, 0, 2, 0, 0, 0, 20, 0, 1, 0, 254, 128, 0, 0, 0, 0, 0, 0,
196, 76, 28, 255, 254, 132, 246, 183, 20, 0, 2, 0, 254, 128, 0, 0, 0, 0,
0, 0, 196, 76, 28, 255, 254, 132, 246, 183] })\n\nStack backtrace:\n
0: <unknown>\n   1: <unknown>\n   2: <unknown>\n   3: <unknown>\n   4:
<unknown>\n   5: <unknown>\n   6: <unknown>\n   7: <unknown>\n   8:
<unknown>\n   9: <unknown>\n  10: <unknown>": unknown
```

A huge shoutout to Fupan Li for helping with the debug on this one!

Fixes: #11200

Signed-off-by: Fabiano Fidêncio <fidencio@northflank.com>
This commit is contained in:
Fabiano Fidêncio 2025-05-01 11:52:01 +02:00
parent 7e404dd13f
commit 4ce00ea434

View File

@ -20,6 +20,7 @@ use protocols::types::{ARPNeighbor, IPAddress, IPFamily, Interface, Route};
use rtnetlink::{new_connection, IpVersion};
use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::fs;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::ops::Deref;
use std::str::{self, FromStr};
@ -113,12 +114,30 @@ impl Handle {
self.enable_link(link.index(), false).await?;
}
// Get whether the network stack has ipv6 enabled or disabled.
let supports_ipv6_all = fs::read_to_string("/proc/sys/net/ipv6/conf/all/disable_ipv6")
.map(|s| s.trim() == "0")
.unwrap_or(false);
let supports_ipv6_default =
fs::read_to_string("/proc/sys/net/ipv6/conf/default/disable_ipv6")
.map(|s| s.trim() == "0")
.unwrap_or(false);
let supports_ipv6 = supports_ipv6_default || supports_ipv6_all;
// Add new ip addresses from request
for ip_address in &iface.IPAddresses {
let ip = IpAddr::from_str(ip_address.address())?;
let mask = ip_address.mask().parse::<u8>()?;
self.add_addresses(link.index(), std::iter::once(IpNetwork::new(ip, mask)?))
let net = IpNetwork::new(ip, mask)?;
if !net.is_ipv4() && !supports_ipv6 {
// If we're dealing with an ipv6 address, but the stack does not
// support ipv6, skip adding it otherwise it will lead to an
// error at the "CreatePodSandbox" time.
continue;
}
self.add_addresses(link.index(), std::iter::once(net))
.await?;
}