除了第二节讨论的开发者自己赋予 entrypoint 进程管理多进程的能力,这里我更推荐借助 Kubernetes 来做这件事情。我想现在应该也没有人对容器进行人工管理了,大部分人应该都转向了容器编排和调度工具 Kubernetes 阵营了(对于那些还在使用 Swarm 的一小波人,我劝你们早日弃暗投明 :))。
Kubernetes 中可以将多个容器编排到一个 Pod 里面,共享同一个 Linux NameSpace。这项技术的本质是使用 Kubernetes 提供一个 pause 镜像,展开来说就是先用 pause 镜像实例化出 NameSpace,然后其他容器加入这个 NameSpace 从而实现 NameSpace 共享。突然意识到这块需要有容器和 NameSpace 的技术背景,限于篇幅,希望你可以自行搜索这种技术背景。或者我下一篇文章讨论一下容器技术的本质。
言归正传,我们来介绍一下 pause。pause 是 Kubernetes 在 1.16 版本引入的技术,要使用 pause,我们只需要在 Pod 创建的 yaml 中指定 shareProcessNamespace 参数为 true,如下:
- apiVersion: v1
- kind: Pod
- metadata:
- name: nginx
- spec:
- shareProcessNamespace: true
- containers:
- - name: nginx
- image: nginx
- - name: shell
- image: busybox
- securityContext:
- capabilities:
- add:
- - SYS_PTRACE
- stdin: true
- tty: true
创建 Pod:
- kubectl apply -fshare-process-namespace.yaml
attach 到 Pod 中,ps 查看进程列表:
- / # ps ax
- PID USER TIME COMMAND
- 1 root 0:00 /pause
- 8 root 0:00 nginx: master process nginx -g daemon off;
- 14 101 0:00 nginx: worker process
- 15 root 0:00 sh
- 21 root 0:00 ps ax
我们可以看到 Pod 中的 1 号进程变成了 /pause,其他容器的 entrypoint 进程都变成了 1 号进程的子进程。这个时候开始逐渐逼近事情的本质了:/pause 进程是如何处理将孤儿进程的父进程置为 1 号进程进而避免僵尸进程的呢?我们看一下源码,git repo: pause.c:
- #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 %sn", 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 processn");
-
- 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 terminatedn");
- return 42;
- }
(编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|