当前位置: 首页 > news >正文

Kubernetes控制平面组件:Kubelet详解(六):pod sandbox(pause)容器

云原生学习路线导航页(持续更新中)

  • kubernetes学习系列快捷链接
    • Kubernetes架构原则和对象设计(一)
    • Kubernetes架构原则和对象设计(二)
    • Kubernetes架构原则和对象设计(三)
    • Kubernetes控制平面组件:etcd(一)
    • Kubernetes控制平面组件:etcd(二)
    • Kubernetes控制平面组件:API Server详解(一)
    • Kubernetes控制平面组件:API Server详解(二)
    • Kubernetes控制平面组件:调度器Scheduler(一)
    • Kubernetes控制平面组件:调度器Scheduler(二)
    • Kubernetes控制平面组件:Controller Manager 之 内置Controller详解
    • Kubernetes控制平面组件:Controller Manager 之 NamespaceController 全方位讲解
    • Kubernetes控制平面组件:Kubelet详解(一):架构 及 API接口层介绍
    • Kubernetes控制平面组件:Kubelet详解(二):核心功能层
    • Kubernetes控制平面组件:Kubelet详解(三):CRI 容器运行时接口层
    • Kubernetes控制平面组件:Kubelet详解(四):gRPC 与 CRI gRPC实现
    • Kubernetes控制平面组件:Kubelet详解(五):切换docker运行时为containerd
    • Kubernetes控制平面组件:Kubelet 之 Static 静态 Pod

本文是 kubernetes 的控制面组件 kubelet 系列文章第六篇,主要讲解了 pod 的 沙箱sandbox容器,也称为pause容器,介绍了pause容器的核心作用、技术细节、工作原理、常用运维命令等,最后还对pause容器的源码进行了分析

  • 希望大家多多 点赞 关注 评论 收藏,作者会更有动力继续编写技术文章

1.pod 的容器组成:sandbox+业务containers

  • 在kubernetes中,pod容器由 sandbox + 业务containers 组成,除了业务自己的功能容器,每一个pod还包含一个sandbox容器,镜像一般为 pause,所以也称为 pause 容器
  • 在 Kubernetes控制平面组件:Kubelet详解(三):CRI 容器运行时接口层 中我们介绍了crictl的基本使用。使用crictl可以查看pod的sandbox容器
    • crictl ps:查看pod 的业务容器
    • crictl pods:查看pod 的sandbox pause容器
    • 下面例子可以看出,虽然都是nginx-sts-0这一个pod,但是找到两个不同的容器
    # 查看pod的sandbox容器
    [root@VM-226-235-tencentos ~]# crictl pods | grep nginx-sts-0
    da081a3c7ba60       10 hours ago        Ready               nginx-sts-0                                    default             0                   (default)
    # 查看pod的业务容器
    [root@VM-226-235-tencentos ~]# crictl ps | grep nginx-sts-0
    d99ea5d921d87       a830707172e80       10 hours ago        Running             nginx                     0                   da081a3c7ba60       nginx-sts-0
    

2.pod 的 sandbox 容器

2.1.pause 容器的核心作用

  • 在 Kubernetes 中,Pod 的沙箱容器(Sandbox Container),通常被称为 pause 容器,是 Pod 实现多容器共享命名空间的核心组件。它的存在对 Pod 的正常运作至关重要,但往往被开发者忽视。
  • pause 容器是 Kubernetes 为每个 Pod 创建的第一个容器,它的核心作用是为 Pod 提供共享的 Linux 命名空间(如网络、IPC、PID 等),并作为 Pod 生命周期的锚点
功能说明
维持命名空间确保 Pod 内的所有容器共享相同的网络、IPC 等命名空间。
防止 Pod 崩溃若所有应用容器退出,pause 容器仍存活,避免 Pod 被误判为终止。
处理僵尸进程作为 PID 1 进程,负责回收孤儿进程(僵尸进程),避免资源泄漏。
Pod 生命周期管理Kubelet 通过监控 pause 容器的状态来判断 Pod 是否存活。

2.2.pause 容器的技术细节

2.2.1.镜像来源
  • 默认镜像:registry.k8s.io/pause:<version>(例如 registry.k8s.io/pause:3.9
  • 镜像体积极小(约 700KB),仅包含一个极简的静态编译的 pause 进程。
2.2.2.进程行为
  • pause 进程启动后会无限休眠(通过调用 pause() 系统调用),不执行任何业务逻辑。
  • 代码开源地址:https://github.com/kubernetes/kubernetes/tree/master/build/pause
2.2.3.资源占用
  • CPU 和内存消耗极低,通常可忽略不计。
  • 示例 crictl pods 输出:
    [root@VM-226-235-tencentos ~]# crictl pods | grep nginx-sts-0da081a3c7ba60       10 hours ago        Ready               nginx-sts-0                                    default             0                   (default)
    

2.3.pause 容器的工作原理

2.3.1.步骤 1:Pod 创建
  1. Kubelet 收到创建 Pod 的指令。
  2. 先创建 pause 容器,该容器初始化 Pod 的共享命名空间(如网络命名空间)。
  3. 其他应用容器(如 Nginx、Redis)加入 pause 容器的命名空间
2.3.2.步骤 2:命名空间共享
  • 网络命名空间:所有容器共享同一个 IP 和端口空间,因此可以通过 localhost 互相通信。
  • IPC 命名空间:允许容器通过 System V IPC 或 POSIX 消息队列通信。
  • PID 命名空间:容器可以看到彼此的进程(通过 ps -ef)。
2.3.3.步骤 3:Pod 终止
  • 当 Pod 被删除时,Kubelet 先终止 pause 容器,触发共享命名空间的释放。
  • 所有关联的应用容器会被自动终止。

2.4.查看 pause 容器

  • 命令

    # 列出所有 Pod 沙箱容器(包括 pause 容器)
    crictl pods# 查看 pause 容器的详细信息,会包含:pause在主机上的进程号、pause镜像等
    crictl inspectp <pause_container_id>
    
  • 我们知道每一个容器,在主机上都是一个进程,pause容器也不例外。从进程输出看,我的主机上跑了很多个pause进程,每个pod都会有一个

    [root@VM-226-235-tencentos ~]# ps  -ef | grep /pause
    root      4754     1  3 00:13 ?        00:23:43 /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.aliyuncs.com/google_containers/pause:3.1 --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock
    65535     5598  5497  0 00:13 ?        00:00:00 /pause
    65535     5600  5520  0 00:13 ?        00:00:00 /pause
    65535     5614  5546  0 00:13 ?        00:00:00 /pause
    65535     5625  5537  0 00:13 ?        00:00:00 /pause
    65535     7203  7146  0 00:14 ?        00:00:00 /pause
    65535     7220  7182  0 00:14 ?        00:00:00 /pause
    65535     7339  7286  0 00:14 ?        00:00:00 /pause
    65535     7346  7298  0 00:14 ?        00:00:00 /pause
    65535     8796  8723  0 00:14 ?        00:00:00 /pause
    65535     8921  8784  0 00:14 ?        00:00:00 /pause
    65535     9013  8866  0 00:14 ?        00:00:00 /pause
    65535     9028  8945  0 00:14 ?        00:00:00 /pause
    65535     9057  8999  0 00:14 ?        00:00:00 /pause
    65535     9063  8980  0 00:14 ?        00:00:00 /pause
    root      9160  9137  0 00:14 ?        00:00:00 /pause
    65535    14471 14451  0 00:16 ?        00:00:00 /pause
    

2.5.常见问题与解答

2.5.1.能否不用 pause 容器?
  • 不能。Kubernetes 依赖 pause 容器实现命名空间共享和生命周期管理。若直接删除 pause 容器,Pod 内的其他容器将无法正常工作。
2.5.2.为什么 pause 容器一直处于运行状态?
  • 这是设计行为。pause 容器需要持续运行以维持命名空间,直到 Pod 被显式删除。
2.5.3.如何自定义 pause 镜像?
  • 修改 Kubelet 的启动参数:
    --pod-infra-container-image=my-registry/pause:custom
    
    注意:自定义镜像需兼容 Kubernetes 的 CRI 接口。
2.5.4.pause 容器占用资源异常?
  • 正常情况下,pause 容器几乎不消耗资源。若发现异常:
    1. 检查是否被攻击者利用(例如恶意进程注入)。
    2. 使用 crictl inspectp 查看容器状态。
    3. 排查节点上的安全漏洞。

2.6.深入理解:pause 容器与僵尸进程

  • 问题:在 Linux 中,孤儿进程会被 PID 1 进程接管。若 PID 1 进程未正确处理 SIGCHLD 信号,僵尸进程会累积。
  • pause 容器的解决方案
    • pause 进程会主动回收子进程,因此即使应用容器内的进程产生僵尸进程,也会被 pause 容器清理。

3.为什么kubernetes要引入pause容器?

  • 首先,pause容器镜像极小,几乎不占用资源,且处于长期sleep状态,不处理业务,极度稳定,基本不会主动退出
  • 此时就可以把一些 net namespace、pid namespace 等挂载给它,使得pod的网络非常稳定。只要pause容器存活,不论业务容器重启多少次,网络namespace都会存在,即使pod是crash的,也可以ping通,只是业务端口可能断掉了
  • 另外,sandbox容器的启动在所有业务容器之前,可以为业务容器提供一个就绪的网络环境等 容器前置依赖

4.pause 容器源码分析

https://github.com/kubernetes/kubernetes/tree/master/build/pause

  • 我们以linux为例:https://github.com/kubernetes/kubernetes/tree/master/build/pause/linux
    在这里插入图片描述

4.1.pause.c

/*
Copyright 2016 The Kubernetes Authors.Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>#define STRINGIFY(x) #x
#define VERSION_STRING(x) STRINGIFY(x)#ifndef VERSION
#define VERSION HEAD
#endif// 信号处理函数:当收到 SIGINT/SIGTERM 时优雅终止容器
static void sigdown(int signo) {psignal(signo, "Shutting down, got signal");exit(0);
}// 信号处理函数:回收僵尸进程(SIGCHLD 信号触发)
static void sigreap(int signo) {// 循环调用 waitpid 回收所有已终止的子进程while (waitpid(-1, NULL, WNOHANG) > 0);
}int main(int argc, char **argv) {int i;// 处理命令行参数 "-v":打印版本信息for (i = 1; i < argc; ++i) {if (!strcasecmp(argv[i], "-v")) {printf("pause.c %s\n", VERSION_STRING(VERSION));return 0;}}// 警告:如果 pause 不是 PID 1(即不是容器第一个进程)if (getpid() != 1)fprintf(stderr, "Warning: pause should be the first process\n");// 注册信号处理器if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)return 1;  // 处理 Ctrl+C/SIGINTif (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)return 2;  // 处理 Kubernetes 发送的终止信号(如 Pod 删除)if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap,.sa_flags = SA_NOCLDSTOP},NULL) < 0)return 3;  // 处理子进程退出(SA_NOCLDSTOP 表示不处理停止事件)// 主循环:通过 pause() 挂起进程,保持容器运行for (;;)pause();  // pause() 会阻塞直到收到信号// 此处代码理论上不会执行fprintf(stderr, "Error: infinite loop terminated\n");return 42;
}

4.2.orphan.c

/*
Copyright 2016 The Kubernetes Authors.Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*//* 测试工具:生成一个孤儿进程,验证 pause 容器的僵尸进程回收能力 */#include <stdio.h>
#include <unistd.h>int main() {pid_t pid;pid = fork();if (pid == 0) {    // 子进程分支// 等待父进程退出(父进程 PID 变为 1)while (getppid() > 1);printf("Child exiting: pid=%d ppid=%d\n", getpid(), getppid());return 0;} else if (pid > 0) {  // 父进程分支// 父进程立即退出,使子进程成为孤儿进程printf("Parent exiting: pid=%d ppid=%d\n", getpid(), getppid());return 0;}// fork 失败处理perror("Could not create child");return 1;
}

相关文章:

  • Kubernetes控制平面组件:Kubelet详解(五):切换docker运行时为containerd
  • 【提高+/省选−】洛谷P1495 —— 【模板】中国剩余定理(CRT)/ 曹冲养猪
  • 游戏引擎学习第291天:跳跃的怪物与占据的树木
  • Linux搜索
  • 【ubuntu24.04】pycharm 死机结束进程
  • 正则表达式 - 语法
  • Trae IDE和VSCode Trae插件初探
  • 第6章 实战案例:基于 STEVAL-IDB011V1 板级 CI/CD 全流程
  • PyTorch音频处理技术及应用研究:从特征提取到相似度分析
  • 中级统计师-统计学基础知识-第三章 参数估计
  • 【沉浸式求职学习day43】【Java面试题精选3】
  • Linux的进程概念
  • Java面试场景:从音视频到AI应用的技术探讨
  • 多用途商务,电子产品发布,科技架构,智能手表交互等发布PPT模版20套一组分享
  • SQL练习(12/81)
  • 18. 结合Selenium和YAML对页面继承对象PO的改造
  • 【锂电池剩余寿命预测】LSTM长短期记忆神经网络锂电池剩余寿命预测(Pytorch完整源码和数据)
  • 学习日志10 java
  • 【Bluedroid】蓝牙HID DEVICE错误报告处理全流程源码解析
  • 操作系统之EXT文件系统
  • 上海徐汇 “家 + 书屋”,创新服务广大家庭
  • 小米汽车回应部分SU7前保险杠形变
  • 跨越三十年友情,61岁余隆和60岁齐默尔曼在上海再度合作
  • 昆明公布3起经济犯罪案例:一人持有820余万假美元被判刑十年
  • 习近平向多哥新任领导人致贺电
  • 美凯龙:董事兼总经理车建兴被立案调查并留置