自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Kubernetes中的Pause容器到底是干嘛的

云計算 云原生
那為啥使用 kubectl create 或 kubectl apply 等命令創(chuàng)建Pod時,通常不會顯式地看到Pause容器。這是因為Pause容器是由Kubernetes自動創(chuàng)建和管理的,通常不需要用戶手動操作或關(guān)注。它是Pod的一個隱式組成部分,用于維護Pod的基礎(chǔ)設(shè)施和容器之間的網(wǎng)絡隔離。

引言

Kubernetes出現(xiàn)的報錯如下:

Failed to create pod sandbox: rpc error: code = Unknown desc = failed to get sandbox image "k8s.gcr.io/pause:3.5": failed to pull image "k8s.gcr.io/pause:3.5": failed to pull and unpack image "k8s.gcr.io/pause:3.5": failed to resolve reference "k8s.gcr.io/pause:3.5": failed to do request: Head "https://k8s.gcr.io/v2/pause/manifests/3.5": x509: certificate signed by unknown authority

k8s.gcr.io 這個地址是需要連外網(wǎng)才可以拉取到,導致 pause 鏡像拉不下來,Pod無法啟動。以前都沒關(guān)注過 pause 這個容器,它是啥,做什么用的,怎么在 Pod 里沒看到過他,本文將帶你了解 pause 容器。

Pause容器是個啥

在Kubernetes中,Pod是最小的調(diào)度單元,但它的內(nèi)部結(jié)構(gòu)卻充滿了許多復雜的機制,其中之一就是Pause容器。盡管Pause容器看似不起眼,但它在整個Kubernetes集群中發(fā)揮了至關(guān)重要的作用。我們在 kubernetes 的 node 節(jié)點,執(zhí)行 docker ps,可以發(fā)現(xiàn)每個 node 上都運行了一個 pause進程的容器,具體如下:

[root@localhost ~]# docker ps |grep traefik
66032431a20e   2ae1addee1b2                                                     "/entrypoint.sh --gl…"   30 hours ago     Up 30 hours               k8s_traefik_traefik-68b9ccfc77-x8sqg_traefik_aa5b97bf-3db8-4b92-89a7-1fe551645e6a_0
10d393461904   registry.aliyuncs.com/google_containers/pause:3.5                "/pause"                 30 hours ago     Up 30 hours               k8s_POD_traefik-68b9ccfc77-x8sqg_traefik_aa5b97bf-3db8-4b92-89a7-1fe551645e6a_0

會發(fā)現(xiàn)有很多 pause 容器運行于服務器上面,容器命名也很規(guī)范,然后每次啟動一個容器,都會伴隨一個pause這樣的容器啟動。那它究竟是干啥子的?它就是 Pause 容器,又叫 Infra 容器。我們在部署完 kubernetes 集群后,查看 kubelet 進程,可以看到配置中有這樣一個參數(shù):

[root@localhost ~]# ps -ef|grep kubelet
root      8675     1 10 Sep18 ?        03:15:07 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.5

pause 容器使用的鏡像為 registry.aliyuncs.com/google_containers/pause:3.5  該鏡像非常小,只有 683kB,由于它總是處于 Pause (暫時)狀態(tài),所以取名叫 pause

[root@localhost ~]# docker images|grep pause
registry.aliyuncs.com/google_containers/pause                     3.5        ed210e3e4a5b   2 years ago     683kB

想了解該 pause 容器的構(gòu)成(代碼是用 C 語言寫的)的可以去官方倉庫上一看究竟:https://github.com/kubernetes/kubernetes/tree/master/build/pause

Pause容器的作用

  1. 網(wǎng)絡命名空間隔離:Pod是Kubernetes中最小的調(diào)度單元,可以包含一個或多個容器。為了實現(xiàn)容器之間的網(wǎng)絡隔離,每個Pod都有自己獨立的網(wǎng)絡命名空間。Pause容器負責創(chuàng)建并維護這個網(wǎng)絡命名空間,其他容器共享這個網(wǎng)絡命名空間,使它們能夠相互通信,而不會與其他Pod中的容器發(fā)生沖突。
  2. 進程隔離:Pause容器保持一個輕量級的進程運行,即使Pod中的其他容器都停止了。這個進程實際上不執(zhí)行任何有用的工作,但它的存在確保了Pod不會在沒有容器運行的情況下被刪除。當其他容器停止時,Pause容器仍在運行,以維持Pod的生命周期。
  3. 資源隔離:盡管Pause容器通常不分配大量的CPU和內(nèi)存資源,但它可以配置以使用一些資源。這有助于確保即使Pod中沒有其他容器運行時,Kubernetes仍然可以監(jiān)控和管理Pod的資源使用情況。這也有助于防止Pod被其他具有相同資源要求的Pod占用。
  4. IP地址維護:Pause容器負責維護Pod的IP地址。Pod的IP地址通常是動態(tài)分配的,但由于Pause容器一直在運行,它可以維護Pod的IP地址,以便其他容器可以通過該地址進行通信。這有助于確保Pod的IP地址在整個Pod的生命周期內(nèi)保持一致。
  5. 生命周期管理:Pause容器的生命周期與Pod的生命周期相同。當Pod創(chuàng)建時,Pause容器被創(chuàng)建;當Pod刪除時,Pause容器也會被刪除。這確保了Pod的整個生命周期都由Kubernetes進行管理,包括創(chuàng)建、擴展、縮放和刪除。

Pause容器工作原理

一個 Pod 可以由一組容器組成的,這些容器之間共享存儲和網(wǎng)絡資源,那么網(wǎng)絡資源是如何共享的呢?下面是個例子:

圖片圖片

比如說現(xiàn)在有一個 Pod,其中包含了一個容器 A 和一個容器 B,它們兩個就要共享 Network Namespace。在 Kubernetes 里的解法是這樣的:它會在每個 Pod 里,額外起一個 Infra container 小容器來共享整個 Pod 的 Network Namespace。Infra container 是一個非常小的鏡像,大概 683kB,是一個C語言寫的、永遠處于“暫停”狀態(tài)的容器。由于有了這樣一個 Infra container 之后,其他所有容器都會通過 Join Namespace 的方式加入到 Infra container 的 Network Namespace 中。所以說一個 Pod 里面的所有容器,它們看到的網(wǎng)絡視圖可以說是完全一樣的。即:它們看到的網(wǎng)絡設(shè)備、IP地址、Mac地址等等,跟網(wǎng)絡相關(guān)的信息,其實全是一份,這一份都來自于 Pod 第一次創(chuàng)建的這個 Infra container。這就是 Pod 解決網(wǎng)絡共享的一個解法。在 Pod 里面,一定有一個 IP 地址,是這個 Pod 的 Network Namespace 對應的地址,也是這個 Infra container 的 IP 地址。所以大家看到的都是一份,而其他所有網(wǎng)絡資源,都是一個 Pod 一份,并且被 Pod 中的所有容器共享。這就是 Pod 的網(wǎng)絡實現(xiàn)方式。由于需要有一個相當于說中間的容器存在,所以整個 Pod 里面,必然是 Infra container 第一個啟動。并且整個 Pod 的生命周期是等同于 Infra container 的生命周期的,與容器 A 和 B 是無關(guān)的。這是非常重要的一個設(shè)計。kubernetes的pause容器主要為每個業(yè)務容器提供兩個核心功能:

  • 第一,它提供整個pod的Linux命名空間的基礎(chǔ)。
  • 第二,啟用PID命名空間,它在每個pod中都作為PID為1的進程,并回收僵尸進程。

手工模擬Pod

我們已經(jīng)知道,一個 Pod 從表面上來看至少由一個容器組成,而實際上一個 Pod 至少要有包含兩個容器,一個是應用容器,一個是 pause 容器。運行一個pause容器:

[root@localhost ~]# docker run -d --name pause -p 8080:80 registry.aliyuncs.com/google_containers/pause:3.5
fd315974f5d1a5f52ca47c5dc31aea3774cebf90c88ce065cc9e9ea2f52c103c
  • --name:指定 pause 容器的名字,pause
  • -p 8080:80:將宿主機的 8080 端口映射到容器的 80 端口

運行一個nginx容器,代理 127.0.0.1:8888 springboot應用程序

# 準備nginx配置文件
[root@k8s001 ~]# cat <<EOF >> nginx.conf
error_log stderr;
events { worker_connections  1024; }
http {
    server {
        listen 80 default_server;
        server_name www.kubesre.com;
        location / {
            proxy_pass http://127.0.0.1:8888;
        }
    }
}
EOF
 
# 創(chuàng)建nginx容器
[root@localhost ~]# docker run -d --name nginx -v `pwd`/nginx.conf:/etc/nginx/nginx.conf --net=container:pause --ipc=container:pause --pid=container:pause --ipc=shareable nginx
fa9f858adae826ad536178747e00fffc829c7baf98c3bc29e945230abbf2a5cb
  • --net=container:pause:用于與另一個容器共享網(wǎng)絡命名空間。在這種情況下,容器 "nginx" 會與名為 "pause" 的容器共享網(wǎng)絡命名空間,它們可以使用相同的網(wǎng)絡配置和接口。
  • --ipc=container:pause:用于與另一個容器共享 IPC 命名空間。IPC 命名空間允許容器之間進行進程間通信(Inter-Process Communication),在這里,容器 "nginx" 與名為 "pause" 的容器共享 IPC 命名空間。
  • --pid=container:pause:用于與另一個容器共享 PID 命名空間。PID 命名空間允許容器查看和管理其他容器的進程。
  • --ipc=shareable:指示 IPC 命名空間是可共享的,以便其他容器也可以加入到這個共享命名空間中。

創(chuàng)建一個應用容器 springboot

[root@localhost ~]# docker run -d --name springboot --net=container:pause --ipc=container:pause --pid=container:pause --ipc=shareable registry.cn-shanghai.aliyuncs.com/kubesre02/springboot
e33cfa3cebd5aafa714ca6ef0f6a16be52a282c64b8d24b2d98890ccf02c436a

到這里,我們就純手工模擬出了一個符合 K8S Pod 模型的 “Pod” ,只是它并不由 K8S 進行管理。驗證,查看運行的容器

[root@localhost ]~# docker ps | grep -E "pause|nginx|springboot"
4f877cdcba5d   registry.cn-shanghai.aliyuncs.com/kubesre02/springboot   "java -jar /app.jar"     3 seconds ago   Up 2 seconds                                               springboot
e541dc010fb3   nginx                                                    "/docker-entrypoint.…"   19 hours ago    Up 19 hours                                                nginx
09f94a052d50   registry.aliyuncs.com/google_containers/pause:3.5        "/pause"                 19 hours ago    Up 19 hours    0.0.0.0:8080->80/tcp, :::8080->80/tcp       pause

通過瀏覽器訪問 http://ip:8080 端口

[root@localhost ~]# curl http://localhost:8080
Hello Docker World

從上面的步驟可見:

  • pause容器將內(nèi)部80端口映射到宿主機8080端口。
  • pause容器在宿主機上設(shè)置好網(wǎng)絡namespace后,nginx容器加入到該網(wǎng)絡的namespace中。
  • nginx容器啟動的時候指定了-net=container:pause。
  • springboot 容器啟動時,同樣方式加入到該網(wǎng)絡的namespace中。
  • 這樣三個容器共享了網(wǎng)絡,互相之間就可以使用localhost直接通信。
  • --ipc=container:pause,--pid=container:pause就是三個容器的ipc和pid處于同一個namespace中,init進程為pause。

這里,我們進入springboot 容器內(nèi)部查看:

[root@localhost ~]# /tmp/test# docker exec -it springboot sh
/ # ps aux
PID   USER     TIME   COMMAND
    1 65535      0:00 /pause
  205 root       0:22 java -jar /app.jar
  240 root       0:00 nginx: master process nginx -g daemon off;
  261 101        0:00 nginx: worker process
  263 root       0:00 sh
  269 root       0:00 ps aux

在springboot 容器中可以看到pause和nginx容器的進程,并且pause容器的PID為1,而在kubernetes中容器的PID=1的進程則為容器本身的業(yè)務進程。

如果沒有 K8S 的 Pod ,啟動一個 業(yè)務容器,你需要手動創(chuàng)建三個容器,當你想銷毀這個服務時,同樣需要刪除三個容器。而有了 K8S 的 Pod,這三個容器在邏輯上就是一個整體,創(chuàng)建 Pod 就會自動創(chuàng)建三個容器,刪除 Pod 就會刪除三個容器,從管理上來講,方便了不少。

這正是 Pod 存在的一個根本意義所在。

如何回收僵尸進程

在Linux中,PID命名空間中的進程是一個樹型結(jié)構(gòu),每個進程有一個父進程。在樹的根上只有一個進程沒有真正的父進程。這是init進程,其PID為1。

僵尸進程是指已經(jīng)停止運行但它們的進程表條目仍然存在的進程,在UNIX系統(tǒng)中,一個子進程結(jié)束了,但是它的父進程沒有等待(調(diào)用wait/waitpid)它,那么它將變成一個僵尸進程。

僵尸進程是怎么產(chǎn)生的?

出現(xiàn)僵尸進程的一種情況是:父進程編寫得很糟糕,省略了wait調(diào)用,或者父進程意外崩潰在子進程之前死亡,而新的父進程沒有調(diào)用wait。當一個進程的父進程在子進程之前死亡時,操作系統(tǒng)將該子進程分配給init進程或PID 1的進程。即init進程接納子進程并成為其父進程。這意味著,現(xiàn)在當子進程退出時,新的父進程(init)必須調(diào)用wait來獲取它的退出碼,否則它的進程表條目將永遠保留下來,成為僵死進程。

在Kubernetes pod中,容器的運行方式與上述基本相同,但是為每個pod創(chuàng)建了一個特殊的pause容器。

這個pause容器運行了一個非常簡單的進程,它不執(zhí)行任何函數(shù),本質(zhì)上永遠休眠,其源碼實現(xiàn):

/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
 
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
 
static void sigdown(int signo) {
  psignal(signo, "Shutting down, got signal");
  exit(0);
}
 
static void sigreap(int signo) {
  while (waitpid(-1, NULL, WNOHANG) > 0);
}
 
int main() {
  if (getpid() != 1)
    /* Not an error because pause sees use outside of infra containers. */
    fprintf(stderr, "Warning: pause should be the first process\n");
 
  if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
    return 1;
  if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
    return 2;
  if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap,
                                             .sa_flags = SA_NOCLDSTOP},
                NULL) < 0)
    return 3;
 
  for (;;)
    pause();
  fprintf(stderr, "Error: infinite loop terminated\n");
  return 42;
}

從上述代碼種我們可以發(fā)現(xiàn),pause容器不僅僅調(diào)用pause()使進程休眠,還擁有另外一個重要的功能:

它假定自己為PID 1的角色,當僵尸進程被其父進程孤立時,會被pause容器進行收養(yǎng),通過調(diào)用wait來獲取僵尸進程。這樣一來就不會在Kubernetes pod的PID命名空間中堆積僵尸進程了。

那為啥使用 kubectl create 或 kubectl apply 等命令創(chuàng)建Pod時,通常不會顯式地看到Pause容器。這是因為Pause容器是由Kubernetes自動創(chuàng)建和管理的,通常不需要用戶手動操作或關(guān)注。它是Pod的一個隱式組成部分,用于維護Pod的基礎(chǔ)設(shè)施和容器之間的網(wǎng)絡隔離。

不難想到,這其中的過程是非常復雜的。而且我們還沒有深入探討如何去監(jiān)控和管理這些容器的生命周期。但是不用擔心,我們不需要這么復雜的去管理我們的容器,因為kubernetes已經(jīng)都為我們做好了。

責任編輯:武曉燕 來源: 云原生運維圈
相關(guān)推薦

2022-02-16 20:04:08

容器KubernetesShim

2022-04-10 19:26:07

TypeScript類型語法

2024-08-26 14:23:56

2024-02-22 08:00:00

SoraOpenAI

2022-08-08 08:00:00

人工智能機器學習計算機應用

2024-07-12 15:08:23

Python@wraps函數(shù)

2020-10-25 20:05:29

Pythonyield開發(fā)

2024-03-15 08:06:58

MySQLJOIN命令

2022-05-24 17:00:41

區(qū)塊鏈IT比特幣

2022-04-15 08:54:39

PythonAsync代碼

2018-07-30 11:27:12

云服務

2022-07-11 08:33:51

容器技術(shù)Docker

2015-10-09 11:01:07

iPhone原創(chuàng)鎖定

2020-12-28 08:18:55

安全代碼線程

2024-05-11 09:41:45

線程安全代碼

2024-01-16 23:30:46

?fractionsPython分數(shù)

2018-05-03 15:03:09

內(nèi)存虛擬化空間

2020-08-19 07:48:11

云計算亞馬遜搜索

2010-04-02 16:46:43

云計算

2021-08-13 05:47:48

通信設(shè)計院通信行業(yè)設(shè)計院
點贊
收藏

51CTO技術(shù)棧公眾號