D3 kubernetes 之pod中容器之间网络通信和容器之间文件共享
》 pod是一个逻辑概念,不是一个隔离的环境。引入pod目的是满足容器之间密切协作关系所需的环境,尤其是网络通信和文件共享的需求
1、容器之间网络通信
》 假设nginx应用程序启用了 http_stub_status_module 模块,以提供关于nginx运行状态的统计信息。同时,获取这些统计信息的访问路径被设置为 /nginx_status,内容如下
location /nginx_status {
stub_status; # 启用 stub_status 模块
allow 127.0.0.1; # 允许从本地访问
deny all; # 拒绝其他访问
}
》 为了能够定期将 nginx_status 路径提供的统计信息存储到数据库中,开发了一个指标采集程序 来完成这项任务。这两个应用程序之间存在密切协作关系,因此它们被定义在同一个pod中。在这种环境下指标采集程序释放可以访问 http://127.0.0.1/nginx_status ,答案是否定的,因为这两个容器的网络命名空间是隔离的
》 不过,这个在pod中是可以的。这是因为kubernetes将这两个容器共享了网络命名空间,使其在一个网络协议栈中。具体来说,当创建一个pod时,kubernetes首先会创建一个 pause容器,这是一个特殊的容器,在创建后即可进入暂停状态,仅用于创建一个容器环境。接着,我们定义的容器会被创建并加入 pause容器的网络命名空间中。
》 这样,pod中所有的容器都处于同一个网络命名空间中,应用程序就像被部署在同一台主机上,可以通过本地回环地址 127.0.0.1访问彼此。
》 接下来,运行一个pod来验证这个结论。创建一个名为pod-network.yaml的文件,内容如下:
cat pod-network.yaml
apiVersion: v1
# api版本
kind: Pod
# 资源类型
metadata:
labels:
# pod标签
app: pod-network
name: pod-network
# pod名称
namespace: default
# 指定命名空间
spec:
# pod中的容器列表
containers:
# 第一个容器
- image: uhub.service.ucloud.cn/librarys/nginx:1.23
# 镜像地址
name: web
# 容器名称
# 第二个容器
- image: uhub.service.ucloud.cn/librarys/centos:7
# 镜像地址
name: collect
# 容器名称
command: ["/bin/bash", "-c", "while true; do sleep 1;done"]
- 创建pod资源
kubectl apply -f pod-network.yaml
- 查看
kubectl get pods -l app=pod-network
NAME READY STATUS RESTARTS AGE
nginx-pod 2/2 Running 0 7m8s
》 在上述结果中,第二列ready的值为 2/2,其中左侧的2表示目前正在运行的容器数量,右侧的2表示定义的容器数量,当两个数值相等时则表示pod内所有容器均正常运行这是仅显示我们定义的两个容器,而不会显示 pause容器,这是因为它是由kubernetes内部管理的,对用户不可见。不过可以在pod所在节点上看到它
- 查看pod所在节点
kubectl get pods pod-network -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-pod 2/2 Running 0 5m31s 10.244.58.206 k8s-node01 <none> <none>
- 可以看到pod被分配到 k8s-node01节点上,进入该节点并执行docker ps命令查看容器
docker ps|grep pod-network
83b7f295c3b5 uhub.service.ucloud.cn/librarys/centos "/bin/bash -c 'while…" About a minute ago Up About a minute k8s_collect_pod-network_default_d15332d1-765c-4b75-8f71-947ba314bf4a_0
e75b90560574 a7be6198544f "/docker-entrypoint.…" 2 minutes ago Up 2 minutes k8s_web_pod-network_default_d15332d1-765c-4b75-8f71-947ba314bf4a_0
8f3339002bbc registry.aliyuncs.com/google_containers/pause:3.9 "/pause" 2 minutes ago Up 2 minutes k8s_POD_pod-network_default_d15332d1-765c-4b75-8f71-947ba314bf4a_0
》 最后一个则是pause容器,它由registry.aliyuncs.com/google_containers/pause:3.9镜像创建,进入web容器,执行curl命令测试访问,将看到统计信息
宿主上创建 响应的nginx配置文件,内如如下
cat www.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /nginx_status {
stub_status; # 启用 stub_status 模块
allow 127.0.0.1; # 允许从本地访问
deny all; # 拒绝其他访问
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# 拷贝到容器中
kubectl cp www.conf pod-network:/etc/nginx/conf.d/ -c web
# 登录容器
kubectl exec -it pod-network -c web -- bash
rm -f /etc/nginx/conf.d/default.conf
nginx -t
nginx -s reload
curl http://127.0.0.1/nginx_status
Active connections: 1
server accepts handled requests
15 15 15
Reading: 0 Writing: 1 Waiting: 0
- 同样在collect容器中也可以访问
kubectl exec -it pod-network -c collect -- bash
[root@pod-network /]# curl http://127.0.0.1/nginx_status
Active connections: 1
server accepts handled requests
16 16 16
Reading: 0 Writing: 1 Waiting: 0
》 这说明web和collect容器在同一个网络协议中共享 pause容器的网络。如果登录到collect发现是无法执行 nginx -t的命令的,说明只是共享了网络
2、容器之间文件共享
》 假设有一个nginx应用程序和一个用于采集nginx访问日志的日志采集程序。这俩应用程序之间存在 密切协作关系,因此将他们定义在同一个pod中
》 在这种环境下,日志采集程序是否可以读取到nginx的访问日志文件呢?答案肯定是否定的,因为这两个容器的文件系统是隔离的。
》 不过在pod中,我们可以通过配置 volume卷轻松实现数据的共享。具体来说,当创建一个pod时,kubernetes首先在pod所在节点的文件系统上创建一个空目录,然后将该目录挂载到容器日志目录中。
》 通过这种方式,在nginx容器的 /var/log/nginx目录写入文件后,日志采集程序容器的 /var/log/nginx 目录中也可以访问和使用该文件
》 接下来验证上述的结论。
- 创建一个名为pod-volume.yaml的文件,内如如下
cat pod-volume.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
app: pod-volume
name: pod-volume
namespace: default
spec:
containers:
# pod中的容器列表
- image: uhub.service.ucloud.cn/librarys/nginx:1.23
# 第一个容器的镜像地址
name: web
# 第一个容器的名称(应用容器)
volumeMounts:
# 卷挂载
- name: log
# 挂载的卷名称
mountPath: /var/log/nginx
# 将卷挂载到容器的路径中
- image: uhub.service.ucloud.cn/librarys/centos:7
# 第二个容器的镜像地址
name: collect
# 第二个容器的名称(日志采集容器)
command: ["/bin/bash", "-c", "while true; do sleep 1;done"]
volumeMounts:
# 卷挂载
- name: log
# 挂载的卷名称
mountPath: /var/log/nginx
# 将卷挂载到容器的路径中
volumes:
# 定义卷
- name: log
#卷名称
emptyDir: {}
# 卷类型
- 创建pod资源
kubectl apply -f pod-volume.yaml
# 查看pod资源
kubectl get pods -l app=pod-volume
NAME READY STATUS RESTARTS AGE
pod-volume 2/2 Running 0 7m19s
- 进入web容器,在挂载目录下创建一个文件
[root@k8s-master ~]# kubectl exec -it pod-volume -c web -- bash
root@pod-volume:/# cd /var/log/nginx/
root@pod-volume:/var/log/nginx# touch file.log
- 登录 collect容器的挂载目录下可以看到创建的文件
[root@k8s-master ~]# kubectl exec -it pod-volume -c collect -- bash
[root@pod-volume /]# ls -l /var/log/nginx/
total 4
-rw-r--r--. 1 root root 0 Aug 23 03:07 access.log
-rw-r--r--. 1 root root 516 Aug 23 03:07 error.log
-rw-r--r--. 1 root root 0 Aug 23 03:17 file.log
》 这说明web容器和collect容器共享 /var/log/nginx 日志目录
》 通过创建一个pause容器,并将应用容器加入该容器的网络命名空间中,实现了网络共享。通过将valume挂载到应用容器的数据目录中,实现了数据共享。实现这两种共享机制的前提是必须确保pod中所有的容器都在运行在同一节点上,这也说明了为什么pod是最小调度单元