# 从 Pause 容器到 Pod

在 K8s 中，Pod 是最核心、最基础的资源对象，它是 Kubernetes 中调度最小单元

## 1 Pod 与 容器的关系

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

```
$ kubectl get pods -o wide
NAME                                                        READY   STATUS    RESTARTS   AGE     IP              NODE                  NOMINATED NODE   READINESS GATES
xdbmysql57001-1                                             1/1     Running   0          28h     xx.xx.xx.xx     xxxxxxxxx(hostname)   <none>           <none>
```

登陆到该 Pod 年在到 worker 节点上，使用 docker ps 查看容器

```
$ docker ps  | grep xdbmysql57001-1
dfb3074170cb   93c9519dde20                                                                          "sh -c 'umask 0022 &…"   29 hours ago   Up 29 hours                                            k8s_mysql_xdbmysql57001-1_default_df6f8607-d0cf-41c2-bea7-394f188fe7c1_0
a82be1d8d896   k8s.gcr.io/pause:3.6                                                                  "/pause"                 29 hours ago   Up 29 hours                                            k8s_POD_xdbmysql57001-1_default_df6f8607-d0cf-41c2-bea7-394f188fe7c1_0
```

咦？上面不是说该 Pod 只有一个容器吗？怎么这个 grep 出来，却有两个呢？

实际上，这个 pause 容器，是一个很特殊的容器，它又叫 infra 容器，是每个 Pod 都会自动创建的容器，它不属于用户自定义的容器。

## 2 Pause 容器

使用 `docker insepct [CONTAAINER_ID]` 查看一下 pause 容器的详情信息，可以发现 pause 容器使用的镜像为 `k8s.gcr.io/pause:3.6`

```
$ docker images | grep pause
k8s.gcr.io/pause 3.6 6270bb605e12 3 years ago 683kB
```

该镜像非常小，由于它总是处于 Pause （暂时）状态，所以取名叫 pause

想了解该 pause 容器的构成（代码是用 C 语言写的）的可以去官方仓库上一看究竟：[https://github.com/kubernetes/kubernetes/tree/master/build/pause](https://github.com/kubernetes/kubernetes/tree/master/build/pause)

### 2.1 pause 容器作用

上面我们说，一个 Pod 是由一组容器组成的，这些容器之间共享存储和网络资源，那么网络资源是如何共享的呢？

假设现在有一个 Pod，它包含两个容器（A 和 B），K8S 是通过让他们加入（join）另一个第三方容器的 network namespace 实现的共享，而这个第三方容器就是 pause 容器。

在 Pod 启动时，pause 是创建的第一个容器，可以说 Pod 的生命周期就是 pause 容器的生命周期。

## 3 手工模拟 Pod

### 3.1 创建 pause 容器

使用 docker run 加如下参数：

* `--name`：指定 pause 容器的名字，fake\_k8s\_pod\_pause
* `-p 8888:80`：将宿主机的 8888 端口映射到容器的 80 端口

```
$ docker run -d -p 8888:80 \
        --ipc=shareable \
        --name fake_k8s_pod_pause \
        k8s.gcr.io/pause:3.6
```

### 3.2 创建 nginx 容器

创建容器之前先准备一下 nginx.conf 配置文件

```
cat <<EOF >> nginx.conf
error_log stderr;
events { worker_connections  1024; }
http {
    access_log /dev/stdout combined;
    server {
        listen 80 default_server;
        server_name iswbm.com www.iswbm.com;
        location / {
            proxy_pass http://127.0.0.1:2368;
        }
    }
}
EOF
```

然后运行如下命令创建名字 fake\_k8s\_pod\_nginx 的 nginx 容器

```
$ docker run -d --name fake_k8s_pod_nginx \
        -v `pwd`/nginx.conf:/etc/nginx/nginx.conf \
        --net=container:fake_k8s_pod_pause \
        --ipc=container:fake_k8s_pod_pause \
        --pid=container:fake_k8s_pod_pause \
        nginx
```

其中 -v 参数是将宿主机上的 nginx.conf 文件挂载给 nginx 容器

除此之外，还有另外三个核心参数：

* `--net`：指定 nginx 要 join 谁的 network namespace，当然是前面创建的fake\_k8s\_pod\_pause
* `--ipc`：指定 ipc mode， 一样指定前面创建的fake\_k8s\_pod\_pause
* `--pid`：指定 nginx 要 join 谁的 pid namespace，照旧是前面创建的fake\_k8s\_pod\_pause

### 3.3 创建 ghost 容器

有了 nginx 还不够，还需要有人提供网页的数据，这里使用 ghost 这个博客应用，参数和上面差不多，这里不再赘述。

```
sudo docker run -d --name ghost \
        --net=container:fake_k8s_pod_pause \
        --ipc=container:fake_k8s_pod_pause \
        --pid=container:fake_k8s_pod_pause
        ghost
```

到这里，就纯手工模拟出了一个符合 K8S Pod 模型的 “Pod” ，只是它并不由 K8S 进行管理。

这个 “Pod” 由一个 fake\_k8s\_pod\_pause 容器（负责提供可稳定共享的命名空间）和两个共享 fake\_k8s\_pod\_pause 容器命名空间的两个应用容器。

### 3.4 访问 Pod 服务

由于我是在 worker （ip 为 172.20.20.11）节点上创建的 Pod，因此在我的 Mac 电脑上，直接访问 `http://172.20.20.11:8888/` 就可以访问该博客啦

## 4 Pod

如果没有 K8s 的 Pod ，你启动一个 ghost 博客服务，你需要手动创建三个容器，当你想销毁这个服务时，同样需要删除三个容器。

而有了 K8S 的 Pod，这三个容器在逻辑上就是一个整体，创建 Pod 就会自动创建三个容器，删除 Pod 就会删除三个容器，从管理上来讲，方便了不少。

这正是 Pod 存在的一个根本意义所在。

## 传送门

[https://k8s.iswbm.com/c02/p02\_learn-kubernetes-pod-via-pause-container.html#id3](https://k8s.iswbm.com/c02/p02_learn-kubernetes-pod-via-pause-container.html#id3)
