借助 Pause 容器调试 Pod

借助 Pause 容器调试 Pod

在 K8S 中,Pod 是最核心、最基础的资源对象,也是 Kubernetes 中调度最小单元。在介绍 Pause 容器之前需要先说明下 Pod 与容器的关系来理解为什么需要 Pause 容器来帮助调试

1. Pod 与 容器的关系

Pod 是一个抽象的逻辑概念,它是一组(一个或者多个)容器的集合,这些容器之间共享同一份存储、网络等资源。

使用 kubectl get pods -o wide可以查看 pod 的列表,其中 READY 列代表该 Pod 总共有 1 个容器,并且该容器已经成功启动,可以对外提供服务了

shell 复制代码
[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出两个容器

shell 复制代码
[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镜像

shell 复制代码
[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容器的进程进行查看

shell 复制代码
[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容器

shell 复制代码
[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

业务容器

shell 复制代码
[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容器的网络命名空间中抓包,查看请求是否真正发出、是否有响应返回以及响应的具体内容等。

相关推荐
sam-12323 分钟前
k8s上部署redis高可用集群
redis·docker·k8s
运维小文2 天前
K8资源之endpoint资源&EP资源
linux·网络·k8s·运维开发
小安运维日记3 天前
CKA认证 | Day1 k8s核心概念与集群搭建
运维·云原生·容器·kubernetes·云计算·k8s
KubeSphere 云原生3 天前
云原生周刊:Istio 1.24.0 正式发布
云计算·k8s·容器平台·kubesphere
Cat_Xu4 天前
【AliCloud】ack + ack-secret-manager + kms 敏感数据安全存储
阿里云·k8s·terraform
景天科技苑7 天前
【云原生开发】K8S多集群资源管理平台架构设计
云原生·容器·kubernetes·k8s·云原生开发·k8s管理系统
小安运维日记8 天前
Linux云计算 |【第五阶段】CLOUD-DAY8
linux·运维·docker·云计算·k8s·学习方法
少陽君9 天前
k8s Sidecar代理
运维·云原生·容器·kubernetes·k8s
小云小白10 天前
springboot 传统应用程序,适配云原生改造
云原生·系统架构·k8s·springboot