本文将展示如何使用共享卷(Volume)来实现相同Pod中的两个容器间通信。
注意:本文针对K8S的版本号为v1.9,其他版本可能会有少许不同。
0x00 准备工作
需要有一个K8S集群,并且配置好了kubectl
命令行工具来与集群通信。如果未准备好集群,那么你可以使用Minikube创建一个K8S集群,或者你也可以使用下面K8S环境二者之一:
如果需要查看K8S版本信息,可以输入指令kubectl version
。
0x01 创建一个运行两个容器的Pod
在本节中,我们会创建一个运行了两个容器的Pod。这两个容器共享了一个可以用于二者间通信的卷。下面是该Pod的配置文件:
apiVersion: v1
kind: Pod
metadata:
name: two-containers
spec:
restartPolicy: Never
volumes:
- name: shared-data
emptyDir: {}
containers:
- name: nginx-container
image: nginx
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html
- name: debian-container
image: debian
volumeMounts:
- name: shared-data
mountPath: /pod-data
command: ["/bin/sh"]
args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]
在该配置文件中,可以看到该Pod拥有一个名为shared-data
的卷。
在该配置文件中,第一个容器运行了一个nginx服务器,共享卷在该容器中的挂载路径为/usr/share/nginx/html
。第二个容器基于debian镜像,共享卷在该容器中的挂载路径为/pod-data
。此外,第二个人容器运行了以下命令,然后终止。
echo Hello from the debian container > /pod-data/index.html
注意,第二个容器在nginx服务器根目录下创建了index.html
文件。
创建Pod和两个容器:
kubectl create -f https://k8s.io/docs/tasks/access-application-cluster/two-container-pod.yaml
查看关于该Pod和容器的信息:
kubectl get pod two-containers --output=yaml
下面是部分输出结果:
apiVersion: v1
kind: Pod
metadata:
...
name: two-containers
namespace: default
...
spec:
...
containerStatuses:
- containerID: docker://c1d8abd1 ...
image: debian
...
lastState:
terminated:
...
name: debian-container
...
- containerID: docker://96c1ff2c5bb ...
image: nginx
...
name: nginx-container
...
state:
running:
...
可以看到,debian容器已经终止了,而nginx容器则仍在运行。
获取一个nginx容器的shell:
kubectl exec -it two-containers -c nginx-container -- /bin/bash
在该shell中,我们验证了nginx仍在运行:
root@two-containers:/# apt-get update
root@two-containers:/# apt-get install curl procps
root@two-containers:/# ps aux
输出结果类似如下:
USER PID ... STAT START TIME COMMAND
root 1 ... Ss 21:12 0:00 nginx: master process nginx -g daemon off;
前面debian容器在nginx的根目录下创建了index.html
文件,下面指令使用curl
向nginx服务器发送一个GET请求:
root@two-containers:/# curl localhost
输出结果显示,nginx服务器返回了debian容器创建的那个web页面:
Hello from the debian container
0x02 总结
Pod中之所以能够包含多个容器,其主要原因是为了支持辅助主程序的辅助程序。辅助程序的经典例子是数据拉取器、数据推送器和代理。辅助程序与主程序间经常需要通信,通常情况下是通过一个共享文件系统来实现的,正如本文中展示的那样;或者,通过环回网络接口localhost。这种方式的一个例子是Web服务器,以及与之配套的拉取Git仓库更新的辅助程序。
本文中的共享卷提供了一种在Pod生命周期内实现容器间通信的方式。如果该Pod被删除并重建,那么共享卷中的任何数据都将会丢失。