从 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

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

Last updated