同 Pod 内的容器使用共享卷通信

本文旨在说明如何让一个 Pod 内的两个容器使用一个卷(Volume)进行通信。 参阅如何让两个进程跨容器通过 共享进程名字空间

准备开始

你必须拥有一个 Kubernetes 的集群,且必须配置 kubectl 命令行工具让其与你的集群通信。 建议运行本教程的集群至少有两个节点,且这两个节点不能作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面的 Kubernetes 练习环境之一:

要获知版本信息,请输入 kubectl version.

创建一个包含两个容器的 Pod

在这个练习中,你会创建一个包含两个容器的 Pod。两个容器共享一个卷用于他们之间的通信。 Pod 的配置文件如下:

  1. pods/two-container-pod.yaml
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: two-containers
  5. spec:
  6. restartPolicy: Never
  7. volumes:
  8. - name: shared-data
  9. emptyDir: {}
  10. containers:
  11. - name: nginx-container
  12. image: nginx
  13. volumeMounts:
  14. - name: shared-data
  15. mountPath: /usr/share/nginx/html
  16. - name: debian-container
  17. image: debian
  18. volumeMounts:
  19. - name: shared-data
  20. mountPath: /pod-data
  21. command: ["/bin/sh"]
  22. args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]

在配置文件中,你可以看到 Pod 有一个共享卷,名为 shared-data

配置文件中的第一个容器运行了一个 nginx 服务器。共享卷的挂载路径是 /usr/share/nginx/html。 第二个容器是基于 debian 镜像的,有一个 /pod-data 的挂载路径。第二个容器运行了下面的命令然后终止。

  1. echo Hello from the debian container > /pod-data/index.html

注意,第二个容器在 nginx 服务器的根目录下写了 index.html 文件。

创建一个包含两个容器的 Pod:

  1. kubectl apply -f https://k8s.io/examples/pods/two-container-pod.yaml

查看 Pod 和容器的信息:

  1. kubectl get pod two-containers --output=yaml

这是输出的一部分:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. ...
  5. name: two-containers
  6. namespace: default
  7. ...
  8. spec:
  9. ...
  10. containerStatuses:
  11. - containerID: docker://c1d8abd1 ...
  12. image: debian
  13. ...
  14. lastState:
  15. terminated:
  16. ...
  17. name: debian-container
  18. ...
  19. - containerID: docker://96c1ff2c5bb ...
  20. image: nginx
  21. ...
  22. name: nginx-container
  23. ...
  24. state:
  25. running:
  26. ...

你可以看到 debian 容器已经被终止了,而 nginx 服务器依然在运行。

进入 nginx 容器的 shell:

  1. kubectl exec -it two-containers -c nginx-container -- /bin/bash

在 shell 中,确认 nginx 还在运行。

  1. root@two-containers:/# apt-get update
  2. root@two-containers:/# apt-get install curl procps
  3. root@two-containers:/# ps aux

输出类似于这样:

  1. USER PID ... STAT START TIME COMMAND
  2. root 1 ... Ss 21:12 0:00 nginx: master process nginx -g daemon off;

回忆一下,debian 容器在 nginx 的根目录下创建了 index.html 文件。 使用 curl 向 nginx 服务器发送一个 GET 请求:

  1. root@two-containers:/# curl localhost

输出表示 nginx 向外提供了 debian 容器所写就的页面:

  1. Hello from the debian container

讨论

Pod 能有多个容器的主要原因是为了支持辅助应用(helper applications),以协助主应用(primary application)。 辅助应用的典型例子是数据抽取,数据推送和代理。辅助应用和主应用经常需要相互通信。 就如这个练习所示,通信通常是通过共享文件系统完成的,或者,也通过回环网络接口 localhost 完成。 举个网络接口的例子,web 服务器带有一个协助程序用于拉取 Git 仓库的更新。

在本练习中的卷为 Pod 生命周期中的容器相互通信提供了一种方法。如果 Pod 被删除或者重建了, 任何共享卷中的数据都会丢失。

接下来