需求描述
在特定的业务场景下,某些pod需要添加指定类型的网卡,以满足业务需求. 如下图所示:
pod内运行的服务是gobgpd, 监听179端口,且需要与物理环境的路由器建立bgp链接,于是有以下要求:
- 由于服务本身监听端口,为了兼容两个pod调度在同一node上的情况,不能使用hostnetwork(否则会出现端口冲突), 需要使用容器网络;
- 由于需要与物理环境的路由器建立bgp链接, 需要一个能与外部物理网络联通的网卡, 且IP需要固定,以便路由器上的配置能固定不变;
方案设计
方案逻辑图如上所示, 利用multus cni为pod添加一个macvlan类型的网卡,并桥接至node的br0, 并将IP分配范围的起始值都设定为指定IP(示例为172.31.59.2):
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: rs0-gobgpd-nic
spec:
config: '{
"cniVersion": "0.3.0",
"type": "macvlan",
"master": "br0",
"mode": "bridge",
"ipam": {
"type": "host-local",
"subnet": "172.31.59.0/24",
"rangeStart": "172.31.59.2",
"rangeEnd": "172.31.59.2",
"routes": [
{ "dst": "0.0.0.0/0" }
],
"gateway": "172.31.59.254"
}
}'
并在pod/deployment/statefulset的annotation中添加相应的配置即可:
apiVersion: apps/v1
kind: Deployment
metadata:
name: rs0
spec:
...
...
template:
...
...
annotations:
k8s.v1.cni.cncf.io/networks: '[
{ "name" : "rs0-gobgpd-nic", # 配置名要添加的网卡
"interface" : "if-user" } # pod内部显示的该网卡名称
]'
...
...
故障描述
正常情况下, kubectl apply 创建网卡和pod后,pod便能够正常启动,生产实践中,可能由于业务更新或维护操作不当,出现如下问题:
- 使用kubectl get pod 发现 pod 始终处于containerCreating的状态;
- 使用kubectl describe pod发现Events中有如下报错:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- ... Warning FailedCreatePodSandBox 95s kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "0666940b1c8abe008700ccc51def41f5cff84859a0c4347617437577b57316ae" network for pod "rs0-785874578b-8frsw": networkPlugin cni failed to set up pod "rs0-785874578b-8frsw" network: [rs0-785874578b-8frsw:rs0-gobgpd-nic]: error adding container to network "rs0-gobgpd-nic": failed to allocate for range 0: no IP addresses available in range set: 172.31.59.2-172.31.59.2 ...
根据报错的提示,是指定的IP不可用,此时尝试更换一个指定的IP(如172.31.59.3)则可以正常创建。但是上文已经说明,IP只能固定不变,否则就会额外涉及到交换机上的配置变更,在生产环境这是不可接受的。于是需要查清故障原因。
-
根据 kubectl get pod -o wide 或 kubectl describe pod 的结果,登录到pod的node上进行调查,进入node的/var/lib/cni/networks/ 目录下,进入其中以网卡配置命名(rs0-gobgpd-nic)的目录中, 发现其中有一个以该IP命名的文件。
root@node3:/var/lib/cni/networks/rs0-gobgpd-nic# ll total 16 drwxr-xr-x 2 root root 4096 Mar 29 16:51 ./ drwxr-xr-x 4 root root 4096 Mar 24 10:25 ../ -rw-r--r-- 1 root root 73 Mar 29 16:51 172.31.59.2 -rw-r--r-- 1 root root 11 Mar 29 16:51 last_reserved_ip.0 -rwxr-x--- 1 root root 0 Mar 24 10:25 lock*
正常情况下,网卡是在pod的启动过程中加入到pod中的,因此,在pod未启动时, 网卡不应已分配IP, 此目录下的这个文件的存在表示该网卡已被分配该IP, 这是不符合预期的。
解决方法
删除上述目录下的以IP命名的文件, 此时无需额外的操作,直接再查看pod状态,会发现pod已正常启动,用kubectl describe pod 查看event也可以看到相关的信息:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
...
Normal AddedInterface 8s multus Add if-user [172.31.59.2/24] from mjqkubea/rs0-gobgpd-nic