Pause 容器存在的意义

1. 简介

Pause 容器,又叫 Infra 容器,本文将探究该容器的作用与原理。 我们知道在 kubelet 的配置中有这样一个参数:

bash 复制代码
KUBELET_POD_INFRA_CONTAINER=--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest

上面是 openshift 中的配置参数,kubernetes 中默认的配置参数是:

css 复制代码
KUBELET_POD_INFRA_CONTAINER=--pod-infra-container-image=gcr.io/google_containers/pause-amd64:3.0

Pause 容器,是可以自己来定义,官方使用的 gcr.io/google_containers/pause-amd64:3.0 容器的代码见 Github,使用 C 语言编写。

Pause 容器镜像非常小,目前在 700KB 左右,永远处于 Pause(暂停)状态

2. Pause 容器背景

像 Pod 这样一个东西,本身是一个逻辑概念。那在机器上,它究竟是怎么实现的呢?这就是我们要解释的一个问题。

举例来说,我们在操作系统里跑一个程序,这个程序可能是由多个线程共同协作的完成的,实际上是由一组 linux 线程组成的,这些线程共享主进程的资源,相互写作完成主程序的工作。 由以上的类比 pod 就类似进程组,管理多个容器的协调工作

pod 要解决的就是容器之间的超亲密关系,核心就在于如何让一个 Pod 里的多个容器之间最高效的共享某些资源和数据。

因为容器之间原本是被 Linux Namespace 和 cgroups 隔开的,所以现在实际要解决的是怎么去打破这个隔离,然后共享某些资源和某些信息。这就是 Pod 的设计要解决的核心问题所在。

所以说具体的解法分为两个部分:网络和存储。
Pause 容器就是为解决 Pod 中的网络问题而生的。

3. Pause 容器的实现

Pod 里的多个容器怎么去共享网络?下面是个例子: 比如说现在有一个 Pod,其中包含了一个容器 A 和一个容器 B,它们两个就要共享 Network Namespace。在 Kubernetes 里的解法是这样的:它会在每个 Pod 里,额外起一个 Infra container 小容器来共享整个 Pod 的 Network Namespace。

Infra container 是一个非常小的镜像,大概 700KB 左右,是一个 C 语言写的、永远处于 "暂停" 状态的容器。由于有了这样一个 Infra container 之后,其他所有容器都会通过 Join Namespace 的方式加入到 Infra container 的 Network Namespace 中。

所以说一个 Pod 里面的所有容器,它们看到的网络视图是完全一样的。即:它们看到的网络设备、IP 地址、Mac 地址等等,跟网络相关的信息,其实全是一份,这一份都来自于 Pod 第一次创建的这个 Infra container。这就是 Pod 解决网络共享的一个解法。

在 Pod 里面,一定有一个 IP 地址,是这个 Pod 的 Network Namespace 对应的地址,也是这个 Infra container 的 IP 地址。所以大家看到的都是一份,而其他所有网络资源,都是一个 Pod 一份,并且被 Pod 中的所有容器共享。这就是 Pod 的网络实现方式。

由于需要有一个相当于说中间的容器存在,所以整个 Pod 里面,必然是 Infra container 第一个启动。并且整个 Pod 的生命周期是等同于 Infra container 的生命周期的,与容器 A 和 B 是无关的。这也是为什么在 Kubernetes 里面,它是允许去单独更新 Pod 里的某一个镜像的,即:做这个操作,整个 Pod 不会重建,也不会重启,这是非常重要的一个设计。

4. 实践

注意:出现如下报错,是因为 docker 新版本针对 ipc 默认使用 private 级别,不共享,要开启共享,需要增加配置

docker: Error response from daemon: can't join IPC of container 8baa4dfd05a5649eddaedbe83f35d555af063217e65d39d44cc20ff9abe45750: non-shareable IPC (hint: use IpcMode:shareable for the donor container

官方配置文档:Docker run reference

ini 复制代码
--ipc="MODE"  : 设置容器的 IPC 模式

可接受的值包括:

描述
"" 使用 Docker Daemon 的默认值
none 拥有私有的 IPC 命名空间,不挂载 /dev/shm
private 拥有私有的 IPC 命名空间
shareable 拥有私有的 IPC 命名空间, 且可以共享给其他容器
container: <name-or-ID> 加入到其他"shareable"容器的命名空间中
host 使用主机系统的命名空间

如果未指定,则使用 Docker Daemon 的默认值,它可以是"private"或"shareable",具体取决于 daemon 的版本和配置。 IPC (POSIX/SysV IPC) 命名空间提供命名共享内存段、信号量和消息队列的隔离。 共享内存段(shared memory segments )用于以加速进程间通信,性能超过管道或网络。 共享内存常用于科学计算和金融服务行业的数据库和定制高性能应用程序。 如果这些类型的应用程序被分解到多个容器中,可能需要共享容器的 IPC 机制,对主容器使用"shareable"模式,其他容器使用"container:<name-or- ID>"模式。

  1. 首先运行一个 pause 容器,并将本地 8080 端口绑定到容器内的 80 端口
css 复制代码
docker run -d --name pause -p 8080:80 --ipc=shareable googlecontainersmirrors/pause:3.1
  1. 启动一个 nginx 服务,并加入到 pause 的网络命名空间中,nginx 将为 localhost:2368 创建一个代理
ini 复制代码
cat <<EOF >> nginx.conf
error_log stderr;
events { worker_connections  1024; }
http {
    access_log /dev/stdout combined;
    server {
        listen 80 default_server;
        server_name example.com www.example.com;
        location / {
            proxy_pass http://127.0.0.1:2368;
        }
    }
}
EOF

docker run -d --name nginx -v `pwd`/nginx.conf:/etc/nginx/nginx.conf --net=container:pause --ipc=container:pause --pid=container:pause nginx
  1. 然后再为 ghost 创建一个应用容器,这是一款博客软件。
css 复制代码
docker run -d --name ghost --net=container:pause --ipc=container:pause --pid=container:pause ghost

现在访问 http://localhost:8880/ 就可以看到 ghost 博客的界面了。说明这几个模块的网络是共通的。

  1. 启动一个辅助工具,方便查看进程信息
shell 复制代码
docker run -d --name busybox --net=container:pause --ipc=container:pause --pid=container:pause busybox

在进入 busybox 查看进程情况,可以看到在 busybox 容器中也能看到 pause, node, nginx 进程的信息,说明就是共享的 ipc 模块,且 pause 的 pid 为 1,pause 可以作为 init 进程来回收任何僵尸进程。

shell 复制代码
/ # ps aux
PID   USER     TIME  COMMAND
  1 root      0:00 /pause
 37 root      0:00 nginx: master process nginx -g daemon off;
 60 101       0:00 nginx: worker process
 61 1000      0:06 node current/index.js
169 root      0:00 sh
187 root      0:00 /bin/sh
199 root      0:00 ps aux

5. 参考

  1. The Almighty Pause Container - Ian Lewis
  2. Kubernetes 之 Pause 容器 - 陈健的博客 | ChenJian Blog
  3. Docker run reference
  4. Pause 容器 · Kubernetes 中文指南------云原生应用架构实战手册
  5. 第 04 讲.理解 Pod 和容器设计模式_哔哩哔哩_bilibili
相关推荐
赵庆明老师1 分钟前
.net framework 的项目部署到docker
docker·eureka·.net
总有刁民想爱朕ha16 分钟前
银河麒麟v10服务器版Docker部署MySQL 8教程
mysql·docker·容器·银河麒麟v10
卜锦元24 分钟前
docker 部署南大通用 GBase 8sV8.8
运维·数据库·docker·容器·部署·运维开发
Garfield200526 分钟前
查找Docker 容器占用的磁盘空间
docker·容器·键盘
宋冠巡27 分钟前
Docker容器化Node.js应用教程
docker·node.js
CappuccinoRose42 分钟前
Docker配置过程完整梳理
后端·python·docker·容器·环境配置
草明1 小时前
MacOS 在使用 docker: no space left on device: unknown
macos·docker
求梦82016 小时前
Java:Windows家庭中文版的Docker下载安装
java·windows·docker
❀͜͡傀儡师16 小时前
docker一键部署Flatnotes笔记工具
笔记·docker·容器
❀͜͡傀儡师17 小时前
docker一键部署夜莺监控
运维·docker·容器