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是最小调度单元

posted @ 2024-08-22 20:20  Hello_worlds  阅读(24)  评论(0编辑  收藏  举报