借助 Pause 容器调试 Pod
在 K8S 中,Pod 是最核心、最基础的资源对象,也是 Kubernetes 中调度最小单元。在介绍 Pause 容器之前需要先说明下 Pod 与容器的关系来理解为什么需要 Pause 容器来帮助调试
1. Pod 与 容器的关系
Pod 是一个抽象的逻辑概念,它是一组(一个或者多个)容器的集合,这些容器之间共享同一份存储、网络等资源。
使用 kubectl get pods -o wide
可以查看 pod 的列表,其中 READY 列代表该 Pod 总共有 1 个容器,并且该容器已经成功启动,可以对外提供服务了
[root@master-1 ~]# kubectl get pods -n ncss-v3 -o wide | grep operation
operation-cf45b5777-vq8x4 1/1 Running 760 91d 10.244.0.169 master-1 <none> <none>
此时使用 docker ps
查看指定 Pod 的容器,可以grep
出两个容器
[root@master-1 ~]# docker ps -a | grep operation-cf45b5777-vq8x4
# 业务容器
2591c532008a 8ebd9efd951d "/bin/sh -c 'cp -f /…" 30 hours ago Up 30 hours k8s_operation_operation-cf45b5777-vq8x4_ncss-v3_57501f2c-60f3-4acf-95b0-19c9ee1ec293_760
# pause 容器
2dce6e228773 registry.nscloud:5000/google_containers/pause:3.1 "/pause" 12 days ago Up 12 days k8s_POD_operation-cf45b5777-vq8x4_ncss-v3_57501f2c-60f3-4acf-95b0-19c9ee1ec293_10
这个 pause
容器,是一个很特殊的容器,它又叫 infra 容器,是每个 Pod 都会自动创建的容器,它不属于用户自定义的容器。
那么这个 pause 容器有什么用呢?
2. Pause 容器
pause 容器镜像
使用 docker insepct [CONTAAINER_ID]
查看一下 pause 容器的详情信息,可以发现 pause 容器使用的镜像为
registry.nscloud:5000/google_containers/pause:3.1
在 Kubelet 进程的参数中,也有 --pod-infra-container-image
,同样也指定的是pause
镜像
[root@master-1 ~]# ps aux | grep kubelet
root 14471 14.1 0.2 4674828 125708 ? Ssl Oct11 2578:19 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --cgroup-driver=systemd --network-plugin=cni --pod-infra-container-image=registry.nscloud:5000/google_containers/pause:3.1 ...
该镜像非常小,由于它总是处于 Pause (暂时)状态,所以取名叫 pause,可以找一个pause
容器的进程进行查看
[root@master-1 ~]# cat /proc/23199/status | head -n 10
Name: pause
State: S (sleeping)
Tgid: 23199
Ngid: 0
Pid: 23199
PPid: 22612
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 64
pause 容器作用
上面我们说,一个 Pod 是由一组容器组成的,这些容器之间共享存储和网络资源,那么网络资源是如何共享的呢?
假设现在有一个 Pod,它包含两个容器(A 和 B),K8S 是通过让他们加入(join)另一个第三方容器的 network namespace
实现的共享,而这个第三方容器就是 pause
容器。
这么做的目的,其实很简单,想象一下,如果没有这样的第三方容器,会发生怎样的结果?
没有 pause 容器,那么 A 和 B 要共享网络,要不就是 A 加入 B 的 network namespace,或者就是 B 加入 A 的 network namespace, 而无论是谁加入谁,只要 network 的 owner 退出了,该 Pod 里的所有其他容器网络都会立马异常,这显然是不合理的。
反过来,由于 pause 里只有是挂起一个容器,里面没有任何复杂的逻辑,只要不主动杀掉 Pod,pause 都会一直存活,这样一来就能保证在 Pod 运行期间同一 Pod 里的容器网络的稳定。
我们在同一 Pod 里所有容器里看到的网络视图,都是完全一样的,包括网络设备、IP 地址、Mac 地址等等,因为他们其实全是同一份,而这一份都来自于 Pod 第一次创建的这个 Infra container。
由于所有的应用容器都要依赖于 pause 容器,因此在 Pod 启动时,它总是创建的第一个容器,可以说 Pod 的生命周期就是 pause 容器的生命周期。
3. 结论验证
针对docker ps
查询的两个容器,可以分别使用nsenter
命令查询该容器所在的网络命空间内的地址信息
pause容器
[root@master-1 ~]# docker inspect 2dce6e228773 | grep \"Pid\"
"Pid": 23199,
[root@master-1 ~]#
[root@master-1 ~]#
[root@master-1 ~]# nsenter -t 23199 -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
3: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
link/ether e2:3c:a6:05:0e:84 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.244.0.169/24 scope global eth0
valid_lft forever preferred_lft forever
业务容器
[root@master-1 ~]# docker inspect 2591c532008a | grep \"Pid\"
"Pid": 15696,
[root@master-1 ~]#
[root@master-1 ~]#
[root@master-1 ~]# nsenter -t 15696 -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
3: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
link/ether e2:3c:a6:05:0e:84 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.244.0.169/24 scope global eth0
valid_lft forever preferred_lft forever
从图中可以看出Pod
内的业务容器和pause
容器通过ip a
命令返回的结果完全一致,由此可以推断出二者处在同一个网络命名空间内
4. pause 容器调试
假如当容器网络出现故障时,了解到pause
容器后就可以下两个方面进行分析。
一、在容器编排系统中,如 Kubernetes,pause
容器与业务容器共享网络命名空间。通过检查pause
容器的网络配置,如 IP 地址分配、网络接口状态以及路由信息等,可以了解整个 Pod 的网络基础情况。当业务容器出现无法访问外部网络或容器之间无法通信等问题时,检查pause
容器的网络能够快速确定是否是网络命名空间层面出现问题,比如网络插件故障或者网络策略配置错误。
二、由于pause
容器和业务容器共享网络,可以在pause
容器所在的节点上,利用抓包工具(如tcpdump
)在pause
容器的网络命名空间中进行网络流量监测。命令可参考
nsenter - t <pause_container_pid> - n tcpdump - i eth0
这种监测方式能够观察整个 Pod 内进出的网络流量,对于排查网络通信故障或者分析网络性能问题十分关键。例如,当发现某个业务容器发送的请求没有得到响应时,可以在pause
容器的网络命名空间中抓包,查看请求是否真正发出、是否有响应返回以及响应的具体内容等。