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

news/2024/12/22 0:13:27/

概述

摘要:本文通过实践描述并验证了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


http://www.ppmy.cn/news/1527298.html

相关文章

【与C++的邂逅】--- string容器使用

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 与C的邂逅 本篇博客我们将来了解string容器本身以及接口的使用。 string是串&#xff0c;本质是一个字符数组&#xff0c;可以对其进行增删查改。 &am…

机器学习--逻辑回归

逻辑回归 前情提要&#xff1a;线性回归 关于分类 C l a s s i f i c a t i o n Classification Classification 在逻辑回归中&#xff0c;我们只讨论 y ∈ { 0 , 1 } y\in\{0, 1\} y∈{0,1} 的情况。其中 1 1 1 表示 p o s i t i v e c l a s s positive \; class posit…

Vue主题色实现

主题色实现 情境 配置平台支持多个主题色的选择&#xff0c;用户可通过在配置平台选择项目主题色。前端项目在骨架屏加载页面获取配置信息&#xff0c;设置项目主题色&#xff0c;实现同个项目不同主题色渲染的需求 实现 1.定义主题色变量 不同主题色根据不同js文件划分定…

‌移动管家手机智能控制汽车系统

‌ 手机可以通过下载特定的应用程序来控制汽车系统&#xff0c;实现远程启动、锁/解锁车门、调节车内温度等功能。‌ ‌ 手机智能控制汽车系统主要通过下载并安装特定的APP来实现。‌ 首先&#xff0c;用户需要确定自己的手机系统是安卓还是苹果版&#xff0c;然后前往应用…

HTML+CSS - 网页布局之多列布局定位

1. 多列布局 CSS中多列布局处理文本内容&#xff0c;特别适合对于长段落或者大量文本进行自动分栏显示 类似于grid分布&#xff0c;但相较之下更加简洁明了 基本语法 <div class"container"><p>这是一些示例文本&#xff0c;当我们使用 column-count…

Python 中常见的数据结构(三)

Python 中常见的数据结构&#xff08;三&#xff09; 9. Heap&#xff08;堆&#xff09; 堆是一种特殊的树形数据结构&#xff0c;Python 中&#xff0c;可以使用 heapq 模块创建一个堆&#xff0c;例如&#xff1a; import heapq numbers [1, 3, 5, 7, 9] heap [] for n…

async Lifetimes

async Lifetimes (Jin Qing’s Column, Sep., 2024) From: https://rust-lang.github.io/async-book/03_async_await/01_chapter.html The Future’s lifetime is bounded by the parameter’s. // This function: async fn borrow_x(x: &u8) -> u8 { *x }// Is equ…

手机、平板电脑编程———未来之窗行业应用跨平台架构

一、平板编程优点 1. 便携性强 - 可以随时随地携带平板进行编程&#xff0c;不受地点限制&#xff0c;方便在旅行、出差或休息时间进行学习和开发。 2. 直观的触摸操作 - 利用触摸屏幕进行代码编辑、缩放、拖动等操作&#xff0c;提供了一种直观和自然的交互方式。 …