0%

K8S问题排查-附加网络Pod无法启动

问题背景

使用附加网络的Pod在服务器重启后启动异常,报错信息如下:

1
2
3
4
5
6
Events:
Type Reason Age From Message
Normal Scheduled 53m default-scheduler Successfully assigned xxx/xxx1-64784c458b-q67tx to node001
Warning FailedCreatePodSandBox 53m kubelet, node001 Failed to create pod sandbox: rpc er or: code = Unknown desc = failed to set up sandbox container "xxx" network for pod "xxxl-64784c458b-q67tx": NetworkPlugin cni failed to set up pod "xxx1-64784c458b-q67tx_xxx" network: Multus: Err adding pod to network "net-netl-nodeOOl": Multus: error in invoke Delegate add - "macvlan": failed to create macvlan: device or resource busy
Warning FailedCreatePodSandBox 53m kubelet, node001 Failed to create pod sandbox: rpc er or: code = Unknown desc = failed to set up sandbox container "xxx" network for pod "xxxl-64784c458b-q67tx": NetworkPlugin cni failed to set up pod "xxx1-64784c458b-q67tx_xxx" network: Multus: Err adding pod to network "net-netl-nodeOOl": Multus: error in invoke Delegate add - "macvlan": failed to create macvlan: device or resource busy
...

分析过程

从日志初步看,创建Pod的sandbox异常,具体是Multus无法将Pod添加到net-netl-nodeOOl网络命名空间内,再具体点是Multus无法创建macvlan网络,原因是device or resource busy

最后的这个错误信息还是比较常见的,从字面理解,就是设备或资源忙,常见于共享存储的卸载场景。那这里也应该类似,有什么设备或资源处于被占用状态,所以执行macvlan的创建失败,既然是附加网络的问题,那优先查看了下附加网络相关的CRD资源,没什么异常;

网上根据日志搜索一番,也没有什么比较相关的问题,那就看代码吧,首先找到Multus的源码,根据上述日志找相关处理逻辑,没有找到。再一想,Multus实现macvlan网络使用的是macvlan插件,再下载插件代码,找到了相关处理逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
plugins/main/macvlan/macvlan.go:169
if err := netlink.LinkAdd(mv); err != nil {
return nil, fmt.Errorf("failed to create macvlan: %v", err)
}

// LinkAdd adds a new link device. The type and features of the device
// are taken from the parameters in the link object.
// Equivalent to: `ip link add $link`
func LinkAdd(link Link) error {
return pkgHandle.LinkAdd(link)
}

// LinkAdd adds a new link device. The type and features of the device
// are taken from the parameters in the link object.
// Equivalent to: `ip link add $link`
func (h *Handle) LinkAdd(link Link) error {
return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
}
...

根据上述代码和注释简单的看,是在执行ip link add $link命令时报错,实际验证看看:

1
2
[root@node001 ~] ip link add link bond1 name macvlan1 type macvlan mode bridge
RTNETLINK answers: Device or resource busy

确实如此,在bond1接口上无法配置macvlan,那换一个接口试试:

1
2
3
4
5
6
[root@node001 ~] ip link add link bond0 name macvlan1 type macvlan mode bridge
[root@node001 ~] ip link show
...
110: macvlan1@bond0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether ea:31:c9:7f:d9:a4 brd ff:ff:ff:ff:ff:ff
...

配置成功,说明bond1接口有什么问题,看看这俩接口有没有差异:

1
2
3
4
5
6
7
8
9
10
11
12
[root@node001 ~] ip addr show
...
2: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 0c:da:41:1d:6f:ca brd ff:ff:ff:ff:ff:ff
inet x.x.x.x/16 brd x.x.255.255 scope global bond0
valid_lft forever preferred_lft forever
inet6 fe80::eda:41ff:fe1d:6fca/64 scope link
valid_lft forever preferred_lft forever
...
17: bond1: <BROADCAST,MULTICAST,MASTER,SLAVE,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 0c:da:41:1d:a8:62 brd ff:ff:ff:ff:ff:ff
...

对比两个接口可以发现两个差异点:

  1. bond0配置了IP地址,而bond1没有配置;
  2. bond0是MASTER角色,bond1既是MASTER,又是SLAVE角色;

考虑到bond0接口是用来建集群的,bond1接口是给Multus创建macvlan网络用的,所以第一个差异点属于正常现象。第二个是什么情况呢?一般来说,配置bond的目的是把几个物理接口作为SLAVE角色聚合成bond接口,这样既能增加服务器的可靠性,又增加了可用网络宽带,为用户提供不间断的网络服务。配置后,实际的物理接口应该是SLAVE角色,而聚合后的bond接口应该是MASTER角色,所以正常来说,不会同时出现两个角色才对;

查看两个bond的相关配置,没有发现什么异常,反过来讲,如果配置的有问题,那初次部署就应该报错了,而不是重启节点才发现。所以,问题的关键是重启导致的。也就是说,可能是在重启后的启动脚本里加了什么配置影响的;

搜索相关资料[1],发现在配置过程中可能有这么一个操作:

1
2
4、在/etc/rc.d/rc.local文件中加入如下语句,使系统启动自动运行
ifenslave bond0 eth0 eth1

查看问题环境上怎么配置的:

1
2
3
4
[root@node001 ~] cat /etc/rc.local
...
touch /var/lock/subsys/local
ifenslave bond0 bond1 enp661s0f0 enp661s0f1 ens1f0 ens1f1

发现有类似的配置,但不同的是,问题环境上配置了两个bond,并且配置在了一个命令里。感觉不是太对,个人理解这么配置应该会把bond1也认为是bond0的SLAVE,修改一下试试:

1
2
3
4
5
6
[root@node001 ~] cat /etc/rc.local
...
touch /var/lock/subsys/local
ifenslave bond0 enp661s0f0 enp661s0f1
ifenslave bond1 ens1f0 ens1f1
[root@node001 ~] systemctl restart network

再观察两个bond接口的角色,发现恢复正常,再看看异常Pod,也都起来了。

1
2
[root@node001 ~] kubectl get pod -A |grep -v Running
NAMESPACE NAME READY STATUS RESTARTS AGE

解决方案

rc.local里的两个bond的命令拆开分别配置即可。

参考资料

  1. https://www.cnblogs.com/geaozhang/p/6763876.html