当前位置: 首页 > news >正文

POD内的容器之间的资源共享

概述

摘要:本文通过实践描述并验证了pod内容器如何实现网络、文件、PID、UTC、mount的共享。

pod实战之容器内资源共享与隔离

container容器之间的共享实战

从实际场景说起:有2个容器nginx与wordpress分别运行了紧密耦合且需要共享资源的应用程序。我们希望2两个容器共享网络命名空间,IPC 命名空间,PID 命名空间。

实现这个需求的可以使用2个解决方案:

解决方案一

  1. 先创建一个名为nginx的业务容器,根据docker的底层原理,linux内核中的namespaces组件会为nginx的容器创建独立与宿主的网络、IPC、PID、UTC命名空间。
  2. 再创建业务容器wordpress,同时将wordpress“加入”,属于nginx容器的命名空间。

在这里插入图片描述

该方案实现简单,但是存在一个问题就是,wordpress容器依赖nginx业务容器,一旦nginx容器fail,wordpress容器也将fail.

解决方案二

在这里插入图片描述

为了解决方案一存在的问题,我们可以利用pause容器来解决。pause容器不执行任何业务逻辑,仅仅是为了创建一个独立的命名空间而生,之后再将业务容器
“加入”到pause容器已经创建的命名空。具体步骤如下:

  1. 先创建一个容器:pause的容器,根据docker的底层原理,linux内核中的namespaces组件会为pause的容器创建独立于宿主的网络、IPC、PID、UTC命名空间。pause是一个特殊的容器,里面运行着一个非常简单的进程,它不执行任何功能,基本上是永远“睡觉”的。
  2. 创建业务容器nginx,同时将nginx”加入“,属于pause容器的命名空间。
  3. 再创建业务容器wordpress,同时将wordpress”加入“,属于pause容器的命名空间。

解决方案二的实践

root@ ubuntu1604:~# docker run -d --name pause   pause:3.1
3fd25a34f1b92e3799bbef61b13f88258ea9633b1ffef512e8e7d2f6b5fc199aroot@ ubuntu1604:~# docker  ps |grep pause
3fd25a34f1b9         pause:3.1   "/pause"                 26 seconds ago      Up 25 seconds                           pause
  • –name:指定 pause 容器的名字,pause
root@ ubuntu1604:~# docker run -d --name nginx --net=container:pause --ipc=container:pause --pid=container:pause --ipc=shareable   ubuntu1604
3d043d9a692cb8e3ed1e7f522c8222cc99d0e0c1a44b8b2ca0c4083c308f073froot@ ubuntu1604:~# docker ps |grep nginx
3d043d9a692c         ubuntu1604   "/start.sh"              25 seconds ago      Up 24 seconds                           nginx
  • –net=container:pause:表示创建的容器与另一个容器共享网络命名空间。在这种情况下,容器 “nginx” 会与名为 “pause” 的容器共享网络命名空间,它们可以使用相同的网络配置和接口。
  • –ipc=container:pause:表示创建的容器与另一个容器共享 IPC 命名空间。IPC 命名空间允许容器之间进行进程间通信(Inter-Process Communication),在这里,容器 “nginx” 与名为 “pause” 的容器共享 IPC 命名空间。
  • –pid=container:pause:表示创建的容器与另一个容器共享 PID 命名空间。PID 命名空间允许容器查看和管理其他容器的进程。
  • –ipc=shareable:指示 IPC 命名空间是可共享的,以便其他容器也可以加入到这个共享命名空间中。
root@ ubuntu1604:~# docker run -d --name wordpress --net=container:pause --ipc=container:pause --pid=container:pause --ipc=shareable  ubuntu16.04
efaedd09438fdc2eb903cc2b57301088abf6cd6ee35fcc37f8d0b341802c28b5
  • 查看网络命名空间是否共享
root@ ubuntu1604:~# docker exec -it nginx  /bin/bash
root@3fd25a34f1b9:/work# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group defaultlink/ether 02:42:c0:a8:01:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 192.168.1.2/24 brd 192.168.1.255 scope global eth0valid_lft forever preferred_lft forever
root@3fd25a34f1b9:/work# ip route show
default via 192.168.1.1 dev eth0
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.2root@ ubuntu1604:~# docker exec -it wordpress  /bin/bash
root@3fd25a34f1b9:/work# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group defaultlink/ether 02:42:c0:a8:01:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 192.168.1.2/24 brd 192.168.1.255 scope global eth0valid_lft forever preferred_lft forever
root@3fd25a34f1b9:/work# ip route show
default via 192.168.1.1 dev eth0
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.2

可以看到nginx与wordpress两个容器,IP地址和路由表是一样的,说明它们共用一个网络协议栈(网络命名空间)。

  • 查看PID命名空间是否共享
root@ ubuntu1604:~# docker exec -it nginx  ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.0   1024     4 ?        Ss   17:26   0:00 /pause
root          6  0.0  0.0  19696  3160 ?        Ss   17:28   0:00 /bin/bash /sta
root         25  0.0  0.0  65512  3128 ?        Ss   17:28   0:00 /usr/sbin/sshd
root         34  0.0  0.0  27728  2748 ?        Ss   17:28   0:00 /usr/sbin/cron
root         39  0.0  0.0   6008   664 ?        S    17:28   0:00 sleep 600
root         40  0.0  0.0  19696  3368 ?        Ss   17:29   0:00 /bin/bash /sta
root         68  0.0  0.0  27728  2620 ?        Ss   17:29   0:00 /usr/sbin/cron
root         73  0.0  0.0   6008   668 ?        S    17:29   0:00 sleep 600
root        126  0.0  0.0  36084  3224 pts/0    Rs+  17:34   0:00 ps auxroot@ ubuntu1604:~# docker exec -it wordpress  ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.0   1024     4 ?        Ss   17:26   0:00 /pause
root          6  0.0  0.0  19696  3160 ?        Ss   17:28   0:00 /bin/bash /sta
root         25  0.0  0.0  65512  3128 ?        Ss   17:28   0:00 /usr/sbin/sshd
root         34  0.0  0.0  27728  2748 ?        Ss   17:28   0:00 /usr/sbin/cron
root         39  0.0  0.0   6008   664 ?        S    17:28   0:00 sleep 600
root         40  0.0  0.0  19696  3368 ?        Ss   17:29   0:00 /bin/bash /sta
root         68  0.0  0.0  27728  2620 ?        Ss   17:29   0:00 /usr/sbin/cron
root         73  0.0  0.0   6008   668 ?        S    17:29   0:00 sleep 600
root        121  0.0  0.0  36084  3208 pts/0    Rs+  17:33   0:00 ps aux

可以看到nginx与wordpress两个容器,可以相互看到多方的进程pid。

  • 查看文件系统挂载是否共享
root@ ubuntu1604:~# docker exec -it nginx  df
Filesystem     1K-blocks     Used Available Use% Mounted on
overlay        309505024 38063364 258331752  13% /
tmpfs              65536        0     65536   0% /dev
tmpfs           16336452        0  16336452   0% /sys/fs/cgroup
/dev/vda1      309505024 38063364 258331752  13% /etc/hosts
shm                65536        0     65536   0% /dev/shm
tmpfs           16336452        0  16336452   0% /proc/acpi
tmpfs           16336452        0  16336452   0% /proc/scsi
tmpfs           16336452        0  16336452   0% /sys/firmwareroot@ ubuntu1604:~# docker exec -it wordpress  df
Filesystem     1K-blocks     Used Available Use% Mounted on
overlay        309505024 38063460 258331656  13% /
tmpfs              65536        0     65536   0% /dev
tmpfs           16336452        0  16336452   0% /sys/fs/cgroup
/dev/vda1      309505024 38063460 258331656  13% /etc/hosts
shm                65536        0     65536   0% /dev/shm
tmpfs           16336452        0  16336452   0% /proc/acpi
tmpfs           16336452        0  16336452   0% /proc/scsi
tmpfs           16336452        0  16336452   0% /sys/firmware

可以看到nginx与wordpress两个容器,挂载的目录是一样的。

  • 查看UTC命名空间是否共享
root@ ubuntu1604:~# docker exec -it wordpress  hostname
3fd25a34f1b9
root@ ubuntu1604:~# docker exec -it nginx  hostname
3fd25a34f1b9

可以看到nginx与wordpress两个容器,挂载的主机名是一样的。

总结:

  • 方案二中,由于pause是不运行业务逻辑代码,永远处于”睡觉“状态。就可以"维护"一套独立的命名空间,再将业务容器加入pause的命名空间。

  • 细心的读者可能观察到,这套方案和pod就很类似,恩,没错。kubernetes就是利用pause容器+业务容器来实现一个POD的。

  • 其实pause除了实现 Pod 中多个容器的共享网络与资源隔离的功能之外,pause 容器也会负责管理容器之间的生命周期,保证在 Pod 删除与更新时,容器和资源可以被正确地释放。如果 Pod 中运行的所有其他容器都终止,则 pause 容器自动终止并删除。

    关于pause容器的具体描述后面再展开。

pod内容器之间的共享与隔离

我们知道kubernetes管理的最小单位是pod,而不是容器。一个pod中可以包括一个或多个容器。在实践中,通常一个pod中运行多个容器,将多个紧密耦合且需要共享资源的应用程序封装到一个pod.

实践中根据业务场景的不同,需要考虑pod中多个容器对共享与隔离的需求:

  1. pod内的多个容器,使用的网络是共享的,而且也是必须的。
  2. pod内的多个容器,对于文件系统是有共享的需求的,默认情况下容器之间对文件访问是隔离的。
  3. pod内的多个容器,对于pid也是有共享需求的,默认情况下容器的pid是隔离的,不能相关看到对方容器的pid。
  4. pod内的多个容器,对于hostname(UTC)也是有共享需求的,默认情况下容器的UTC是隔离的,容器有不同的hostname。
  5. pod需要和宿主共享PID,默认pod是无法看到宿主的PID,也是处于安全考虑,默认情况下pod无法与宿主共享PID命名空间。

pod内容器之间网络的共享

当Pod创建多个容器时,容器之间会通过namespace实现了隔离的,之间的网络是隔离的。Pod要解决内部容器之间网络通信的问题其实就要打破namespace的隔离。

那么Kubernetes是怎么解决两个容器之间通信的问题呢?

也即是容器之间看到的网络协议栈是一样的,在创建pod的时候会先创建infra container这个容器(也叫sandbox或pause容器),启动好之后然后再将实际创建的容器加入到infra container容器当中,这个infra容器实现的主要目的是维护了pod的网络,没有跑任何的业务逻辑,只是启动了一个容器罢了。其他容器的创建都让其连接至该容器的网络命名空间当中。这样一来其他容器看到的网络视图就是infra container的网络视图了。一个pod当中所有的容器看到的网络设备,网卡,ip,mac地址都看到的是同一个了,因为在一个网络命名空间。这样就解决了网络共享的问题。实际上pod的ip就是infra container的ip。(类似上面方案二的实践)

记住: 同一个pod内的所有容器共享一个协议栈。

pod内容器之间文件的共享

pod内的容器之间的文件系统,默认是相互隔离的。如果需要实现共享文件或目录,可以两个容器共享一个卷用于他们之间的通信。

root@ ubuntu1604:~# cat pod-blog.yaml
---
apiVersion: v1
kind: Pod
metadata:name: bloglabels:app: blog
spec:restartPolicy: Alwaysvolumes:- name: shared-dataemptyDir: {}containers:containers:- name: nginxvolumeMounts:- name: shared-datamountPath: /sharedirimage: ubuntu16.04- name: wordpressvolumeMounts:- name: shared-datamountPath: /sharedirimage: ubuntu16.04

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

配置文件中的第一个容器运行了一个 nginx 服务器,第二个容器是运行 wordpress 服务器。他们共享卷的挂载路径是 /sharedir

先在第一个容器中共享的目录中创建一个文件/sharedir/blog.txt

root@ ubuntu1604:~# kubectl get pod -owide
NAME   READY   STATUS    RESTARTS   AGE   IP               NODE           NOMINATED NODE   READINESS GATES
blog   2/2     Running   0          10s   192.168.26.100   10.234.12.77   <none>           <none>
root@ ubuntu1604:~# kubectl exec -it blog -c nginx -- bash
root@blog:/work# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay         296G   84G  199G  30% /
tmpfs            64M     0   64M   0% /dev
tmpfs            16G     0   16G   0% /sys/fs/cgroup
/dev/vda1       296G   84G  199G  30% /sharedir
shm              64M     0   64M   0% /dev/shm
tmpfs            16G   12K   16G   1% /run/secrets/kubernetes.io/serviceaccount
root@blog:/work# echo "myblog" >>  /sharedir/blog.txt
root@blog:/work# cat /sharedir/blog.txt
myblog

第二个容器读取/sharedir/blog.txt的内容。

root@ ubuntu1604:~# kubectl exec -it blog -c wordpress -- cat /sharedir/blog.txt
myblog

pod内容器之间的PID的共享

POD内的容器之前,默认的PID是隔离的,无法相互看到或操控。但可以使用 Pod .spec 中的 shareProcessNamespace 字段可以启用进程命名空间共享。shareProcessNamespace的值默认为false,即容器之间不是共享进程命名空间的。调整shareProcessNamespace为true,可以实现容器之间共享进程命名空间

创建POD,指定shareProcessNamespace: true

root@ ubuntu1604:~# cat pod-blog.yaml
---
apiVersion: v1
kind: Pod
metadata:name: bloglabels:app: blog
spec:### 使用 pod.spec.shareProcessNamespace 控制Pod内容器之间的PID共享。shareProcessNamespace的值默认为falseshareProcessNamespace: truerestartPolicy: Alwaysvolumes:- name: shared-dataemptyDir: {}containers:containers:- name: nginxvolumeMounts:- name: shared-datamountPath: /sharedirimage: ubuntu16.04- name: wordpressvolumeMounts:- name: shared-datamountPath: /sharedirimage: ubuntu16.04

观察2个业务容器观察到的PID是一样的。

root@ ubuntu1604:~# kubectl exec -it blog -c nginx --  ps  aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.0   1024     4 ?        Ss   18:13   0:00 /pause
root          6  0.0  0.0  19708  3344 ?        Ss   18:13   0:00 /bin/bash /sta
root         25  0.0  0.0  65512  3080 ?        Ss   18:13   0:00 /usr/sbin/sshd
root         34  0.0  0.0  27728  2704 ?        Ss   18:13   0:00 /usr/sbin/cron
root         40  0.0  0.0  19708  3328 ?        Ss   18:13   0:00 /bin/bash /sta
root         68  0.0  0.0  27728  2700 ?        Ss   18:13   0:00 /usr/sbin/cron
root        102  0.0  0.0   6008   800 ?        S    18:23   0:00 sleep 600
root        103  0.0  0.0   6008   660 ?        S    18:23   0:00 sleep 600
root        119  0.0  0.0  36084  3216 pts/0    Rs+  18:28   0:00 ps aux
root@ ubuntu1604:~# kubectl exec -it blog -c wordpress  --  ps  aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.0   1024     4 ?        Ss   18:13   0:00 /pause
root          6  0.0  0.0  19708  3344 ?        Ss   18:13   0:00 /bin/bash /sta
root         25  0.0  0.0  65512  3080 ?        Ss   18:13   0:00 /usr/sbin/sshd
root         34  0.0  0.0  27728  2704 ?        Ss   18:13   0:00 /usr/sbin/cron
root         40  0.0  0.0  19708  3328 ?        Ss   18:13   0:00 /bin/bash /sta
root         68  0.0  0.0  27728  2700 ?        Ss   18:13   0:00 /usr/sbin/cron
root        102  0.0  0.0   6008   800 ?        S    18:23   0:00 sleep 600
root        103  0.0  0.0   6008   660 ?        S    18:23   0:00 sleep 600
root        124  0.0  0.0  36084  3152 pts/0    Rs+  18:29   0:00 ps aux

注意:这里有一个隐含的信息,是pause, nginx,wordpress三个容器共享进程命名空间。PID 1是pause容器

pod内容器之间共享主机名

POD内的容器之前,默认的UTC是独立的,也就是容器的主机名都不通。但可以使用 Pod .spec 中的 hostname 实现UTC命名空间共享,也就是多个容器共用同样的主机名。

创建yaml文件pod-blog.yaml,添加spec.hostname: sharedhostname实现容器之间共用同样的主机名


---
apiVersion: v1
kind: Pod
metadata:name: bloglabels:app: blog
spec:### 使用 pod.spec.hostname 实现容器共用同一个主机名hostname: sharedhostname### 使用 pod.spec.shareProcessNamespace 控制Pod内容器之间的PID共享。shareProcessNamespace的值默认为falseshareProcessNamespace: truerestartPolicy: Alwaysvolumes:- name: shared-dataemptyDir: {}containers:containers:- name: nginxvolumeMounts:- name: shared-datamountPath: /sharedirimage:  ubuntu1604- name: wordpressvolumeMounts:- name: shared-datamountPath: /sharedirimage:  ubuntu1604
root@ ubuntu1604:~# kubectl exec -it blog -c nginx -- hostname
sharedhostname
root@ ubuntu1604:~# kubectl exec -it blog -c wordpress  -- hostname
sharedhostname

pod与宿主的共享网络命名空间

我们知道pod如果需要使用宿主的网络协议栈,可以使用hostNetwork: true来实现。 由于该场景非常有,所以本次实践略。

pod与宿主的进程命名空间

我们知道pod如果需要使用宿主的网络协议栈,可以使用hostNetwork: true来实现。 有时场景下一个管理性的Pod,也需要与宿主进程命名空间,即看到和控制宿主的进程。这时就可以使用hostPID: true来实现。

创建yaml文件指定hostPID: true

---
apiVersion: v1
kind: Pod
metadata:name: mgr
spec:restartPolicy: AlwayshostPID: truecontainers:- name: nginximage: ubuntu16.04

从容器中查看宿主的内核进程kworker

root@ ubuntu1604:~# kubectl exec -it mgr -- ps aux |grep worker |head
root          4  0.0  0.0      0     0 ?        I<   16:28   0:00 [kworker/0:0H]
root         18  0.0  0.0      0     0 ?        I<   16:28   0:00 [kworker/1:0H]
root         24  0.0  0.0      0     0 ?        I<   16:28   0:00 [kworker/2:0H]
root         30  0.0  0.0      0     0 ?        I<   16:28   0:00 [kworker/3:0H]
root         36  0.0  0.0      0     0 ?        I<   16:28   0:00 [kworker/4:0H]
root         42  0.0  0.0      0     0 ?        I<   16:28   0:00 [kworker/5:0H]
root         48  0.0  0.0      0     0 ?        I<   16:28   0:00 [kworker/6:0H]
root         54  0.0  0.0      0     0 ?        I<   16:28   0:00 [kworker/7:0H]
root         60  0.0  0.0      0     0 ?        I<   16:28   0:00 [kworker/8:0H]
root         66  0.0  0.0      0     0 ?        I<   16:28   0:00 [kworker/9:0H]

参考文档

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

在 Pod 中的容器之间共享进程命名空间

https://cloud.tencent.com/developer/article/2332162

https://blog.csdn.net/qq_34556414/article/details/110083541

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • CLUSTERDOWN Hash slot not served问题复现
  • 【隐私计算】Paillier半同态加密算法
  • node前端开发基本设置
  • rust GUI框架Tauri入门——基于vanilla.js
  • 【C语言】联合体枚举的讲解
  • 02请求响应(简单参数)
  • Java学习Day42:骑龙救!(springMVC)
  • PostMan使用变量
  • 在mac中如何使python3作为默认版本
  • v-for循环中使用‘v-model‘ directives cannot update the iteration variable itself
  • JavaSE基础——第三章 运算符
  • 如何在webots中搭建一个履带机器人
  • 什么是外贸专用路由器?
  • 微信小程序----日期时间选择器(自定义时间精确到分秒)
  • 瑞芯微rv1126 Linux 系统,修改系统时区,包有效方法
  • avalon2.2的VM生成过程
  • ES6--对象的扩展
  • JavaScript DOM 10 - 滚动
  • JavaWeb(学习笔记二)
  • Laravel 中的一个后期静态绑定
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • Mithril.js 入门介绍
  • Mocha测试初探
  • Webpack 4 学习01(基础配置)
  • 关于extract.autodesk.io的一些说明
  • 前端性能优化--懒加载和预加载
  • 如何设计一个比特币钱包服务
  • 深度学习入门:10门免费线上课程推荐
  • 算法-插入排序
  • 移动端唤起键盘时取消position:fixed定位
  • 用jquery写贪吃蛇
  • gunicorn工作原理
  • Mac 上flink的安装与启动
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • ​520就是要宠粉,你的心头书我买单
  • # Redis 入门到精通(八)-- 服务器配置-redis.conf配置与高级数据类型
  • # 透过事物看本质的能力怎么培养?
  • #13 yum、编译安装与sed命令的使用
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • (2)MFC+openGL单文档框架glFrame
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (每日一问)操作系统:常见的 Linux 指令详解
  • (排序详解之 堆排序)
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (十七)Flink 容错机制
  • (一) 初入MySQL 【认识和部署】
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • *Django中的Ajax 纯js的书写样式1
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .Net Core 中间件验签
  • .net 无限分类
  • .Net的C#语言取月份数值对应的MonthName值
  • ?.的用法
  • @converter 只能用mysql吗_python-MySQLConverter对象没有mysql-connector属性’...
  • [04] Android逐帧动画(一)