k8s 中 pause 容器的理解
概述
通过容器资源隔离的原理中知道容器之间是通过 NameSpace 和 cgroups 隔离开的,但是 pod 中的网络和存储却是共享的.
kubernetes 为了解决网络共享问题,引入了 pause 容器,又叫Infra容器,在kubelet的配置中有KUBELET_POD_INFRA_CONTAINER参数,它的默认配置是:
KUBELET_POD_INFRA_CONTAINER=--pod-infra-container-image=gcr.io/google_containers/pause-amd64:3.0
而 pause 的代码可见Github
网络共享实现原理
只看linux部分。
非常简单,我直接把它贴出来
#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
static void sigdown(int signo) {
psignal(signo, "Shutting down, got signal");
exit(0);
}
static void sigreap(int signo) {
while (waitpid(-1, NULL, WNOHANG) > 0)
;
}
int main(int argc, char **argv) {
int i;
for (i = 1; i < argc; ++i) {
if (!strcasecmp(argv[i], "-v")) {
printf("pause.c %s\n", VERSION_STRING(VERSION));
return 0;
}
}
if (getpid() != 1)
/* Not an error because pause sees use outside of infra containers. */
fprintf(stderr, "Warning: pause should be the first process\n");
if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
return 1;
if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
return 2;
if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap,
.sa_flags = SA_NOCLDSTOP},
NULL) < 0)
return 3;
for (;;)
pause();
fprintf(stderr, "Error: infinite loop terminated\n");
return 42;
}
按照主流程看:
- -v 输出版本号 (不看)
if(getpid() !=1)
确保自己是 pid为 1 的进程。(warning)- 检查
SIGINT
和SIGTERM
信号,收到此信号关闭应用(ctrl-c之类的) - 检查
SIGCHLD
,当子进程停止(ctrl-z之类的行为)或终结(kill之类的行为)时,调用waitpid
方法收割僵尸进程 - 然后一直暂停(循环调用
pause()
)。
waitpid
函数的作用: 收割僵尸进程。 -1 表示所有子进程,WNOHANG表示没有子进程被退出就立即返回。pause
函数的作用为:使调用进程(线程)进入休眠状态(就是挂起);直到接收到信号且信号函数成功返回 pause函数才会返回。
发现主要有两部分功能:
- 承担PID 1的角色,它将通过调用wait来收割这些僵尸进程(见sigreap)。保证不会有僵尸堆积在Kubernetes pods的PID命名空间中。
- 让 pause 容器一直处于暂停状态 。
有了这个不退出的容器之后, 其它所有的容器就可以利用 Join Namespace
这个特性,加入到 pause container 的 NetWork Namespace 中。
此时,所有容器的网络试图就完全一样了,他们看到的都是 pause container 的网络视图,例如 网络设备、IP 地址、Mac 地址等等。
当然了,这也就要求其它容器必须在 pause 容器之后启动。同时,其它任何容器做重建之类操作,整个pod 也不会重启,因为 pause 容器一直存在。
大佬,学习了
学习了,大佬
我都还没玩过k8s