容器與 Pod 有什麼區別和聯絡?這篇文章告訴你

語言: CN / TW / HK

容器本可以成為輕量級虛擬機器的替代品。但是,由於 Docker/OCI 的標準化,最廣泛使用的容器形式是每個容器只有一個程序服務。這種方法有很多優點——增加隔離性、簡化水平擴充套件、更高的可重用性等。但是,它也有一個很大的缺點——正常情況下,虛擬(或物理)機器很少只執行一個服務。

雖然 Docker 試圖提供一些變通方法來建立多服務容器,但 Kubernetes 邁出了更大膽的一步,並選擇了一組稱為 Pod 的內聚容器作為最小的可部署單元。

幾年前,當我偶然發現 Kubernetes 時,我之前的虛擬機器和裸機經驗讓我很快就瞭解了 Pod。

剛開始接觸 Kubernetes 時,你學到的第一件事就是每個 Pod 都有一個唯一的 IP 和主機名,並且在同一個 Pod 中,容器可以通過 localhost 相互通訊。所以,顯而易見,一個 Pod 就像一個微型的伺服器。

但是,過段時間,你會發現 Pod 中的每個容器都有一個隔離的檔案系統,並且從一個容器內部,你看不到在同一 Pod 的其他容器中執行的程序。好吧!也許 Pod 不是一個微型的伺服器,而只是一組具有共享網路堆疊的容器。

但隨後你會了解到,Pod 中的容器可以通過共享記憶體進行通訊!所以,在容器之間,網路名稱空間不是唯一可以共享的東西……

基於最後的發現,所以,我決定深入瞭解:

  • Pod 是如何在底層實現的

  • Pod 和 Container 之間的實際區別是什麼

  • 如何使用 Docker 建立 Pod

在此過程中,我希望它能幫助我鞏固我的 Linux、Docker 和 Kubernetes 技能。

1、探索 Container

OCI 執行時規範並不將容器實現僅限於 Linux 容器,即使用 namespace 和 cgroup 實現的容器。但是,除非另有明確說明,否則本文中的容器一詞指的是這種相當傳統的形式。

設定實驗環境(playground)

在瞭解構成容器的 namespace 和 cgroups 之前,讓我們快速設定一個實驗環境:

$ cat > Vagrantfile <<EOF
# -*- mode: ruby -*-
# vi: set ft=ruby :


Vagrant.configure("2") do |config|
config.vm.box = "debian/buster64"
config.vm.hostname = "docker-host"
config.vm.define "docker-host"
config.vagrant.plugins = ['vagrant-vbguest']


config.vm.provider "virtualbox" do |vb|
vb.cpus = 2
vb.memory = "2048"
end


config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y curl vim
SHELL


config.vm.provision "docker"
end
EOF


$ vagrant up
$ vagrant ssh

最後讓我們啟動一個容器:

$ docker run --name foo --rm -d --memory='512MB' --cpus='0.5' nginx

探索容器的 namespace

首先我們來看一下,當容器啟動後,哪些隔離原語(primitives)被建立了:

# Look up the container in the process tree.
$ ps auxf
USER PID ... COMMAND
...
root 4707 /usr/bin/containerd-shim-runc-v2 -namespace moby -id cc9466b3e...
root 4727 \_ nginx: master process nginx -g daemon off;
systemd+ 4781 \_ nginx: worker process
systemd+ 4782 \_ nginx: worker process


# Find the namespaces used by 4727 process.
$ sudo lsns
NS TYPE NPROCS PID USER COMMAND
...
4026532157 mnt 3 4727 root nginx: master process nginx -g daemon off;
4026532158 uts 3 4727 root nginx: master process nginx -g daemon off;
4026532159 ipc 3 4727 root nginx: master process nginx -g daemon off;
4026532160 pid 3 4727 root nginx: master process nginx -g daemon off;
4026532162 net 3 4727 root nginx: master process nginx -g daemon off;

我們可以看到用於隔離以上容器的名稱空間是以下這些:

  • mnt(掛載): 容器有一個隔離的掛載表。

  • uts(Unix 時間共享): 容器擁有自己的 hostname 和 domain。

  • ipc(程序間通訊): 容器內的程序可以通過系統級 IPC 和同一容器內的其他程序進行通訊。

  • pid(程序 ID): 容器內的程序只能看到在同一容器內或擁有相同的 PID 名稱空間的其他程序。

  • net(網路): 容器擁有自己的網路堆疊。

注意,使用者(user)名稱空間沒有被使用,OCI 執行時規範提及了對使用者名稱空間的支援。不過,雖然 Docker 可以將此名稱空間用於其容器,但由於固有的限制,它預設情況下沒有使用。因此,容器中的 root 使用者很可能是主機系統中的 root 使用者。謹防!

另一個沒有出現在這裡的名稱空間是 cgroup。我花了一段時間才理解 cgroup 名稱空間與 cgroups 機制(mechanism)的不同。Cgroup 名稱空間僅提供一個容器的 cgroup 層次結構的孤立檢視。同樣,Docker 也支援將容器放入私有 cgroup 名稱空間,但預設情況下沒有這麼做。

探索容器的 cgroups

Linux 名稱空間可以讓容器中的程序認為自己是在一個專用的機器上執行。但是,看不到別的程序並不意味著不會受到其他程序的影響。一些耗資源的程序可能會意外的過多消耗宿主機上面共享的資源。

這時候就需要 cgroups 的幫助!

可以通過檢查 cgroup 虛擬檔案系統中的相應子樹來檢視給定程序的 cgroups 限制。Cgroupfs 通常被掛在 /sys/fs/cgroup 目錄,並且程序特定相關的部分可以在 /proc/ /cgroup 中檢視:

PID=$(docker inspect --format '{{.State.Pid}}' foo)


# Check cgroupfs node for the container main process (4727).
$ cat /proc/${PID}/cgroup
11:freezer:/docker/cc9466b3eb67ca374c925794776aad2fd45a34343ab66097a44594b35183dba0
10:blkio:/docker/cc9466b3eb67ca374c925794776aad2fd45a34343ab66097a44594b35183dba0
9:rdma:/
8:pids:/docker/cc9466b3eb67ca374c925794776aad2fd45a34343ab66097a44594b35183dba0
7:devices:/docker/cc9466b3eb67ca374c925794776aad2fd45a34343ab66097a44594b35183dba0
6:cpuset:/docker/cc9466b3eb67ca374c925794776aad2fd45a34343ab66097a44594b35183dba0
5:cpu,cpuacct:/docker/cc9466b3eb67ca374c925794776aad2fd45a34343ab66097a44594b35183dba0
4:memory:/docker/cc9466b3eb67ca374c925794776aad2fd45a34343ab66097a44594b35183dba0
3:net_cls,net_prio:/docker/cc9466b3eb67ca374c925794776aad2fd45a34343ab66097a44594b35183dba0
2:perf_event:/docker/cc9466b3eb67ca374c925794776aad2fd45a34343ab66097a44594b35183dba0
1:name=systemd:/docker/cc9466b3eb67ca374c925794776aad2fd45a34343ab66097a44594b35183dba0
0::/system.slice/containerd.service

似乎 Docker 使用 /docker/ 模式。好吧,不管怎樣:

ID=$(docker inspect --format '{{.Id}}' foo)


# Check the memory limit.
$ cat /sys/fs/cgroup/memory/docker/${ID}/memory.limit_in_bytes
536870912 # Yay! It's the 512MB we requested!


# See the CPU limits.
ls /sys/fs/cgroup/cpu/docker/${ID}

有趣的是在不明確設定任何資源限制的情況下啟動容器都會配置一個 cgroup。實際中我沒有檢查過,但我的猜測是預設情況下,CPU 和 RAM 消耗不受限制,Cgroups 可能用來限制從容器內部對某些裝置的訪問。

這是我在調查後腦海中呈現的容器:

2、探索 Pod

現在,讓我們來看看 Kubernetes Pod。與容器一樣,Pod 的實現可以在不同的 CRI 執行時(runtime)之間變化。例如,當 Kata 容器被用來作為一個支援的執行時類時,某些 Pod 可以就是真實的虛擬機器了!並且正如預期的那樣,基於 VM 的 Pod 與傳統 Linux 容器實現的 Pod 在實現和功能方面會有所不同。

為了保持容器和 Pod 之間公平比較,我們會在使用 ContainerD/Runc 執行時的 Kubernetes 叢集上進行探索。這也是 Docker 在底層執行容器的機制。

設定實驗環境(playground)

這次我們使用基於 VirtualBox driver 和 Containd 執行時的 minikube 來設定實驗環境。要快速安裝 minikube 和 kubectl,我們可以使用 Alex Ellis 編寫的 arkade 工具:

# Install arkade ()
$ curl -sLS http://get.arkade.dev | sh


$ arkade get kubectl minikube


$ minikube start --driver virtualbox --container-runtime containerd

實驗的 Pod,可以按照下面的方式設定:

$ kubectl --context=minikube apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: app
image: docker.io/kennethreitz/httpbin
ports:
- containerPort: 80
resources:
limits:
memory: "256Mi"
- name: sidecar
image: curlimages/curl
command: ["/bin/sleep", "3650d"]
resources:
limits:
memory: "128Mi"
EOF

探索 Pod 的容器

實際的 Pod 檢查應在 Kubernetes 叢集節點上進行:

$ minikube ssh

讓我們看看那裡 Pod 的程序:

$ ps auxf
USER PID ... COMMAND
...
root 4947 \_ containerd-shim -namespace k8s.io -workdir /mnt/sda1/var/lib/containerd/...
root 4966 \_ /pause
root 4981 \_ containerd-shim -namespace k8s.io -workdir /mnt/sda1/var/lib/containerd/...
root 5001 \_ /usr/bin/python3 /usr/local/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent
root 5016 \_ /usr/bin/python3 /usr/local/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent
root 5018 \_ containerd-shim -namespace k8s.io -workdir /mnt/sda1/var/lib/containerd/...
100 5035 \_ /bin/sleep 3650d

基於執行的時間,上述三個程序組很有可能是在 Pod 啟動期間建立。這很有意思,因為在清單檔案中,只有兩個容器,httpbin 和 sleep。

可以使用名為 ctr 的 ContainerD 命令列來交叉檢查上述的發現:

$ sudo ctr --namespace=k8s.io containers ls
CONTAINER IMAGE RUNTIME
...
097d4fe8a7002 docker.io/curlimages/[email protected]:1a220 io.containerd.runtime.v1.linux
...
dfb1cd29ab750 docker.io/kennethreitz/httpbin:latest io.containerd.runtime.v1.linux
...
f0e87a9330466 k8s.gcr.io/pause:3.1 io.containerd.runtime.v1.linux

的確是三個容器被建立了。同時,使用另一個和 CRI 執行時監控的命令列 crictl 檢測發現,僅僅只有兩個容器:

$ sudo crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
097d4fe8a7002 bcb0c26a91c90 About an hour ago Running sidecar 0 f0e87a9330466
dfb1cd29ab750 b138b9264903f About an hour ago Running app 0 f0e87a9330466

但是注意,上述的 POD ID 欄位和 ctr 輸出的 pause:3.1 容器 id 一致。好吧,看上去這個 Pod 是一個輔助容器。所以,它有什麼用呢?

我還沒有注意到在 OCI 執行時規範中有和 Pod 相對應的東西。因此,當我對 Kubernetes API 規範提供的資訊不滿意時,我通常直接進入 Kubernetes Container Runtime 介面(CRI)Protobuf 檔案中查詢相應的資訊:

// kubelet expects any compatible container runtime
// to implement the following gRPC methods:


service RuntimeService {
...
rpc RunPodSandbox(RunPodSandboxRequest) returns (RunPodSandboxResponse) {}
rpc StopPodSandbox(StopPodSandboxRequest) returns (StopPodSandboxResponse) {}
rpc RemovePodSandbox(RemovePodSandboxRequest) returns (RemovePodSandboxResponse) {}
rpc PodSandboxStatus(PodSandboxStatusRequest) returns (PodSandboxStatusResponse) {}
rpc ListPodSandbox(ListPodSandboxRequest) returns (ListPodSandboxResponse) {}


rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse) {}
rpc StartContainer(StartContainerRequest) returns (StartContainerResponse) {}
rpc StopContainer(StopContainerRequest) returns (StopContainerResponse) {}
rpc RemoveContainer(RemoveContainerRequest) returns (RemoveContainerResponse) {}
rpc ListContainers(ListContainersRequest) returns (ListContainersResponse) {}
rpc ContainerStatus(ContainerStatusRequest) returns (ContainerStatusResponse) {}
rpc UpdateContainerResources(UpdateContainerResourcesRequest) returns (UpdateContainerResourcesResponse) {}
rpc ReopenContainerLog(ReopenContainerLogRequest) returns (ReopenContainerLogResponse) {}


// ...
}


message CreateContainerRequest {
// ID of the PodSandbox in which the container should be created.
string pod_sandbox_id = 1;
// Config of the container.
ContainerConfig config = 2;
// Config of the PodSandbox. This is the same config that was passed
// to RunPodSandboxRequest to create the PodSandbox. It is passed again
// here just for easy reference. The PodSandboxConfig is immutable and
// remains the same throughout the lifetime of the pod.
PodSandboxConfig sandbox_config = 3;
}

所以,Pod 實際上就是由沙盒以及在沙盒中執行的容器組成的。沙盒管理 Pod 中所有容器的常用資源,pause 容器會在 RunPodSandbox() 呼叫中被啟動。簡單的網際網路搜尋就發現了該容器僅僅是一個 idle 程序。

探索 Pod 的名稱空間

下面就是叢集節點上的名稱空間:

$ sudo lsns
NS TYPE NPROCS PID USER COMMAND
4026532614 net 4 4966 root /pause
4026532715 mnt 1 4966 root /pause
4026532716 uts 4 4966 root /pause
4026532717 ipc 4 4966 root /pause
4026532718 pid 1 4966 root /pause
4026532719 mnt 2 5001 root /usr/bin/python3 /usr/local/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent
4026532720 pid 2 5001 root /usr/bin/python3 /usr/local/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent
4026532721 mnt 1 5035 100 /bin/sleep 3650d
4026532722 pid 1 5035 100 /bin/sleep 3650d

前面第一部分很像 Docker 容器,pause 容器有五個名稱空間:net、mnt、uts、ipc 以及 pid。但是很明顯,httpbin 和 sleep 容器僅僅有兩個名稱空間:mnt 和 pid。這是怎麼回事?

事實證明,lsns 不是檢查程序名稱空間的最佳工具。相反,要檢查某個程序使用的名稱空間,可以參考 /proc/${pid}/ns 位置:

# httpbin container
sudo ls -l /proc/5001/ns
...
lrwxrwxrwx 1 root root 0 Oct 24 14:05 ipc -> 'ipc:[4026532717]'
lrwxrwxrwx 1 root root 0 Oct 24 14:05 mnt -> 'mnt:[4026532719]'
lrwxrwxrwx 1 root root 0 Oct 24 14:05 net -> 'net:[4026532614]'
lrwxrwxrwx 1 root root 0 Oct 24 14:05 pid -> 'pid:[4026532720]'
lrwxrwxrwx 1 root root 0 Oct 24 14:05 uts -> 'uts:[4026532716]'


# sleep container
sudo ls -l /proc/5035/ns
...
lrwxrwxrwx 1 100 101 0 Oct 24 14:05 ipc -> 'ipc:[4026532717]'
lrwxrwxrwx 1 100 101 0 Oct 24 14:05 mnt -> 'mnt:[4026532721]'
lrwxrwxrwx 1 100 101 0 Oct 24 14:05 net -> 'net:[4026532614]'
lrwxrwxrwx 1 100 101 0 Oct 24 14:05 pid -> 'pid:[4026532722]'
lrwxrwxrwx 1 100 101 0 Oct 24 14:05 uts -> 'uts:[4026532716]'

雖然不太容易去注意到,但 httpbin 和 sleep 容器實際上重用了 pause 容器的 net、uts 和 ipc 名稱空間!

我們可以用 crictl 交叉檢測驗證:

# Inspect httpbin container.
$ sudo crictl inspect dfb1cd29ab750
{
...
"namespaces": [
{
"type": "pid"
},
{
"type": "ipc",
"path": "/proc/4966/ns/ipc"
},
{
"type": "uts",
"path": "/proc/4966/ns/uts"
},
{
"type": "mount"
},
{
"type": "network",
"path": "/proc/4966/ns/net"
}
],
...
}


# Inspect sleep container.
$ sudo crictl inspect 097d4fe8a7002
...

我認為上述發現完美的解釋了同一個 Pod 中容器具有的能力:

  • 能夠互相通訊

    • 通過 localhost 和/或

    • 使用 IPC(共享記憶體,訊息佇列等)

  • 共享 domain 和 hostname

然而,在看過所有這些名稱空間如何在容器之間自由重用之後,我開始懷疑預設邊界可以被打破。實際上,在對 Pod API 規範的更深入閱讀後發現,將 shareProcessNamespace 標誌設定為 true 時,Pod 的容器將擁有四個通用名稱空間,而不是預設的三個。但是有一個更令人震驚的發現——hostIPC、hostNetwork 和 hostPID 標誌可以使容器使用相應主機的名稱空間。

有趣的是,CRI API 規範似乎更加靈活。至少在語法上,它允許將 net、pid 和 ipc 名稱空間限定為 CONTAINER、POD 或 NODE。因此,可以構建一個 Pod 使其容器無法通過 localhost 相互通訊 。

探索 Pod 的 cgroups

Pod 的 cgroups 是什麼樣的?systemd-cgls 可以很好地視覺化 cgroups 層次結構:

$ sudo systemd-cgls
Control group /:
-.slice
├─kubepods
│ ├─burstable
│ │ ├─pod4a8d5c3e-3821-4727-9d20-965febbccfbb
│ │ │ ├─f0e87a93304666766ab139d52f10ff2b8d4a1e6060fc18f74f28e2cb000da8b2
│ │ │ │ └─4966 /pause
│ │ │ ├─dfb1cd29ab750064ae89613cb28963353c3360c2df913995af582aebcc4e85d8
│ │ │ │ ├─5001 /usr/bin/python3 /usr/local/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent
│ │ │ │ └─5016 /usr/bin/python3 /usr/local/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent
│ │ │ └─097d4fe8a7002d69d6c78899dcf6731d313ce8067ae3f736f252f387582e55ad
│ │ │ └─5035 /bin/sleep 3650d
...

所以,Pod 本身有一個父節點(Node),每個容器也可以單獨調整。這符合我的預期,因為在 Pod 清單中,可以為 Pod 中的每個容器單獨設定資源限制。

此刻,我腦海中的 Pod 看起來是這樣的:

3、利用 Docker 實現 Pod

如果 Pod 的底層實現是一組具有共同 cgroup 父級的半融合(emi-fused)容器,是否可以使用 Docker 生產類似 Pod 的構造?

最近我嘗試做了一些類似的事情來讓多個容器監聽同一個套接字,我知道 Docker 可以通過 docker run —network container: 語法來建立一個可以使用已存在的網路名稱空間容器。但我也知道 OCI 執行時規範只定義了 create 和 start 命令。

因此,當你使用 docker exec 在現有容器中執行命令時,實際上是在執行(即 create 然後 start)一個全新的容器,該容器恰好重用了目標容器的所有名稱空間(證明 1[1] 和 2[2])。這讓我非常有信心可以使用標準 Docker 命令生成 Pod。

我們可以使用僅僅安裝了 Docker 的機器作為實驗環境。但是這裡我會使用一個額外的包來簡化使用 cgroups:

$ sudo apt-get install cgroup-tools

首先,讓我們配置一個父 cgroup 條目。為了簡潔起見,我將僅使用 CPU 和記憶體控制器:

sudo cgcreate -g cpu,memory:/pod-foo


# Check if the corresponding folders were created:
ls -l /sys/fs/cgroup/cpu/pod-foo/
ls -l /sys/fs/cgroup/memory/pod-foo/

然後我們建立一個沙盒容器:

$ docker run -d --rm \
--name foo_sandbox \
--cgroup-parent /pod-foo \
--ipc 'shareable' \
alpine sleep infinity

最後,讓我們啟動重用沙盒容器名稱空間的實際容器:

# app (httpbin)
$ docker run -d --rm \
--name app \
--cgroup-parent /pod-foo \
--network container:foo_sandbox \
--ipc container:foo_sandbox \
kennethreitz/httpbin


# sidecar (sleep)
$ docker run -d --rm \
--name sidecar \
--cgroup-parent /pod-foo \
--network container:foo_sandbox \
--ipc container:foo_sandbox \
curlimages/curl sleep 365d

你注意到我省略了哪個名稱空間嗎?沒錯,我不能在容器之間共享 uts 名稱空間。似乎目前在 docker run 命令中沒法實現。嗯,是有點遺憾。但是除開 uts 名稱空間之外,它是成功的!

cgroups 看上去很像 Kubernetes 建立的:

$ sudo systemd-cgls memory
Controller memory; Control group /:
├─pod-foo
│ ├─488d76cade5422b57ab59116f422d8483d435a8449ceda0c9a1888ea774acac7
│ │ ├─27865 /usr/bin/python3 /usr/local/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent
│ │ └─27880 /usr/bin/python3 /usr/local/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent
│ ├─9166a87f9a96a954b10ec012104366da9f1f6680387ef423ee197c61d37f39d7
│ │ └─27977 sleep 365d
│ └─c7b0ec46b16b52c5e1c447b77d67d44d16d78f9a3f93eaeb3a86aa95e08e28b6
│ └─27743 sleep infinity

全域性名稱空間列表看上去也很相似:

$ sudo lsns
NS TYPE NPROCS PID USER COMMAND
...
4026532157 mnt 1 27743 root sleep infinity
4026532158 uts 1 27743 root sleep infinity
4026532159 ipc 4 27743 root sleep infinity
4026532160 pid 1 27743 root sleep infinity
4026532162 net 4 27743 root sleep infinity
4026532218 mnt 2 27865 root /usr/bin/python3 /usr/local/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent
4026532219 uts 2 27865 root /usr/bin/python3 /usr/local/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent
4026532220 pid 2 27865 root /usr/bin/python3 /usr/local/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent
4026532221 mnt 1 27977 _apt sleep 365d
4026532222 uts 1 27977 _apt sleep 365d
4026532223 pid 1 27977 _apt sleep 365d

httpbin 和 sidecar 容器看上去共享了 ipc 和 net 名稱空間:

# app container
$ sudo ls -l /proc/27865/ns
lrwxrwxrwx 1 root root 0 Oct 28 07:56 ipc -> 'ipc:[4026532159]'
lrwxrwxrwx 1 root root 0 Oct 28 07:56 mnt -> 'mnt:[4026532218]'
lrwxrwxrwx 1 root root 0 Oct 28 07:56 net -> 'net:[4026532162]'
lrwxrwxrwx 1 root root 0 Oct 28 07:56 pid -> 'pid:[4026532220]'
lrwxrwxrwx 1 root root 0 Oct 28 07:56 uts -> 'uts:[4026532219]'


# sidecar container
$ sudo ls -l /proc/27977/ns
lrwxrwxrwx 1 _apt systemd-journal 0 Oct 28 07:56 ipc -> 'ipc:[4026532159]'
lrwxrwxrwx 1 _apt systemd-journal 0 Oct 28 07:56 mnt -> 'mnt:[4026532221]'
lrwxrwxrwx 1 _apt systemd-journal 0 Oct 28 07:56 net -> 'net:[4026532162]'
lrwxrwxrwx 1 _apt systemd-journal 0 Oct 28 07:56 pid -> 'pid:[4026532223]'
lrwxrwxrwx 1 _apt systemd-journal 0 Oct 28 07:56 uts -> 'uts:[4026532222]'

4、總結

Container 和 Pod 是相似的。在底層,它們主要依賴 Linux 名稱空間和 cgroup。但是,Pod 不僅僅是一組容器。Pod 是一個自給自足的高階構造。所有 Pod 的容器都執行在同一臺機器(叢集節點)上,它們的生命週期是同步的,並且通過削弱隔離性來簡化容器間的通訊。這使得 Pod 更接近於傳統的 VM,帶回了熟悉的部署模式,如 sidecar 或反向代理。

相關連結:

1、http://github.com/opencontainers/runtime-spec/issues/345
2、http://github.com/opencontainers/runtime-spec/pull/388

5月中旬,GOPS  全球運維大會 2022 · 深圳站,如果你做運維還處於迷茫時,就來 GOPS 吧 ~

BATJ、銀行、證券的技術前沿、數字化轉型,AIOps、MLOps、雲原生、效能度量等相關精彩內容,2022年春天最值得參加的運維大會,就在這裡啦!

<<  滑動檢視下一張圖片  >>

近期好文:

運維常用的35個Linux Shell 指令碼,一定能幫到你!

“高效運維”公眾號誠邀廣大技術人員投稿,

投稿郵箱:[email protected],或新增聯絡人微信:greatops1118.

點個“在看”,一年不宕機