k8s搭配containerd


一直在關注Kubernetes動態,眼看着1.20 版本要發布了,抱着好奇的心理去Github看看這個版本更新了啥?結果在棄用位置發現了一個焦點,說要“棄用對Docker支持”

Kubelet 中對 Docker 支持被棄用,並將在以后的版本中刪除。

目前Kubelet 使用一個名為 dockershim 的模塊,該模塊實現了對Docker的 CRI 支持,后續版本將刪除dockershim

每一個容器運行時都需要自己實現一個 CRI shim,即完成對 CRI 這個抽象接口的具體實現。這樣容器運行時就可以接收來自 Kubelet 的請求。

從上圖可以看出,新增的 CRI shim 是 Kubelet 和容器運行時之間的交互紐帶,Kubelet 只需要跟 CRI shim 進行交互。Kubelet 調用 CRI shim 的接口,CRI shim 響應請求后會調用底層的運行容器時,完成對容器的相關操作。

這里我們需要將 Kubelet、CRI shim 以及容器運行時都部署在同一個節點上。一般來說,大多數的容器運行時都默認實現了 CRI 的接口,比如containerd。

名詞的解釋

https://blog.csdn.net/weixin_40864891/article/details/86655846

CRI:容器運行時接口 container runtime interface,CRI 中定義了容器和鏡像兩個接口

實現了這兩個接口目前主流的是:

CRI-O:   相關介紹: https://linux.cn/article-9015-1.html

Containerd: 相關介紹 :https://segmentfault.com/a/1190000023618092

其主要的作用:

  • 針對容器操作的接口,包括容器的創建、啟動和停止等
  • 針對鏡像的操作,拉去、刪除鏡像等
  • 針對 podsandbox(容器沙箱環境)
  • 以上全是接口

OCI 中定義了兩個標准:

容器運行時標准 和 容器鏡像標准,實現了這一標准的主流是:

runc(也即我們日常說的 Docker,因為是docker 開源出來的)

Kata-Container  介紹文章 https://segmentfault.com/a/1190000021845002?utm_medium=referral&utm_source=tuicool

主要作用,制作容器:

  • 容器鏡像制作內容,即 ImageSpec
  • 容器需要接收哪些指令,即 runtimeSpec

Dockershim 作用:把外部收到的請求轉化成 Docker Daemon 能聽懂的請求,讓 Docker Daemon 執行創建、刪除等容器操作。

 

 

 組件介紹:

  • docker:命令行管理工具

  • dockerd:Docker守護進程,負責與docker client交互;

  • containerd:負責鏡像管理和容器管理的守護進程,containerd是一個標准的容器運行時,可以獨立管理容器生命周期,也就是即使不運行dockerd,容器也能正常工作;
  • containerd-shim:是一個真實運行的容器的載體,每啟動一個容器都會起一個新的shim的一個進程;
  • runC:一個命令行工具,根據OCI標准來創建和運行容器。

當我們執行docker run創建一個容器時,大致流程:

1.docker工具向dockerd守護進程發送創建容器請求;

2.dockerd收到請求后再向containerd請求創建一個容器;

3.containerd收到請求后並不會直接創建容器,而讓shim創建容器;

4.docker-shim又調用runC創建容器(准備容器所需的namespace和cgroups就退出了),docker-shim就作為了該容器進程的父進程,負責收集容器狀態並上報給containerd。

通過上面來看,Docker Daemon 和 dockershim 看上去就是兩個不干活的東西,Kubelet 為啥不直接調用 containerd 呢?其實和容器歷程有關,這里不在闡述。

有興趣可以看張磊老師的博客https://time.geekbang.org/column/intro/100015201

盡管現在已經有 CRI-Ocontainerd-plugin 這樣更精簡輕量的 Runtime 架構,但 dockershim 這一套作為經受了最多生產環境考驗的方案,迄今為止仍是 Kubernetes 默認的 Runtime 實現

   

 

 

 

 

可以看出,調用鏈還是很復雜的,多層封裝和調用,導致性能降低、提升故障率、不易排查,我想這也是棄用對Docker支持的主要原因吧!

如果把容器運行時換成containerd,如圖所示

 

 

 

 

 

可見,Containerd 調用鏈更短,組件更少,占用節點資源也比較少

containerd 1.1 版本已經內置了對 CRI 的實現,比直接使用 Docker 的性能要高很多。

如果使用containerd我們就需要配置

kubelet 的 --container-runtime 參數為 remote,

設置 --container-runtime-endpoint 為對應的容器運行時的監聽地址

比如:

--container-runtime=remote 
--container-runtime-endpoint=unix:///run/containerd/containerd.sock 

我這邊用的是centos8的系統,所以需要安裝containerd 和runc  相關的軟件包

dnf install runc -y 

https://github.com/containerd/containerd

wget  https://github.com/containerd/containerd/releases/download/v1.3.9/containerd-1.3.9-linux-amd64.tar.gz

tar -zxvf containerd-1.3.9-linux-amd64.tar.gz 

cd bin/

cp * /usr/bin/

mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml

 

這里重點修改一下 Cgroup

說明一下Cgroup drivers:systemd cgroupfs 區別

 那么 systemd 和 cgroupfs 這兩種驅動有什么區別呢?

1. systemd cgroup driver 是 systemd 本身提供了一個 cgroup 的管理方式,使用systemd 做 cgroup 驅動的話,所有的 cgroup 操作都必須通過 systemd 的接口來完成,不能手動更改 cgroup 的文件

2. cgroupfs 驅動就比較直接,比如說要限制內存是多少、要用 CPU share 為多少?直接把 pid 寫入對應的一個 cgroup 文件,然后把對應需要限制的資源也寫入相應的 memory cgroup 文件和 CPU 的 cgroup 文件就可以了

所以可以看出來 systemd 更加安全,因為不能手動去更改 cgroup 文件,當然我們也推薦使用 systemd 驅動來管理 cgroup。

 

 

 

 

同時未必保證修改kubelet 

cgroupDriver: systemd

 

通過systemd-cgls命令我們可以看到systemd工作的進程PID是1,而目錄/sys/fs/cgroup/systemd是systemd維護的自己使用的非subsystem的cgroups層級結構

查考文檔:

https://blog.csdn.net/avatar_2009/article/details/109603870

https://github.com/containerd/containerd/issues/4900

https://www.pianshen.com/article/89821412857/


cat <<EOF > /etc/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target

[Service]
ExecStartPre=/sbin/modprobe overlay
ExecStartPre=/sbin/modprobe br_netfilter
ExecStart=/usr/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
OOMScoreAdjust=-999
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
[Install]
WantedBy=multi-user.target
EOF
systemctl enable containerd
systemctl restart containerd
systemctl status containerd

安裝完成,就可以使用ctr客戶端工具測試

containerd 相比於docker , 多了namespace概念, 每個image和container 都會在各自的namespace下可見
默認k8s使用的鏡像都放置到 k8s.io 這個名稱空間,使用離線鏡像盡量導入到這個名詞空間

https://github.com/containerd/containerd/blob/master/docs/namespaces.md

私用倉庫的調用用戶名和密碼認證方式是:

ctr i pull -u "devops:xxxx" harbor.xxx.net/devops/pause:3.2

如果不想一直輸入密碼,可以增加配置文件

 vim /etc/containerd/config.toml

ctr -n k8s.io images ls 

ctr --namespace=k8s.io i tag harbor.xxx.net/devops/pause:3.2 k8s.gcr.io/pause:3.2

crictl是一個命令行接口,用於與CRI兼容的容器運行時

https://kubernetes.io/zh/docs/tasks/debug-application-cluster/crictl/

需要安裝相應的工具包

cat <<EOF > /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

使用K8S 離線包:

crictl pull --creds devops:xxxx  harbor.xxx.net/devops/pause:3.2 

 

 看到的鏡像一個和ctr -n k8s.io i ls  看到的鏡像是一樣的

目前官網支持的幾種容器運行時的安裝方式:

https://kubernetes.io/zh/docs/setup/production-environment/container-runtimes/#containerd

 

 

 

雖然未來 Kubelet 刪除 dockershim 支持,但並不說明 Docker 馬上就不能在 Kubernetes 中使用,目前容器市場 Docker 還是占用很大的比例。這中間會有一個過渡期,大家可以關注 Containerd 或者 Podman。Centos8 開始,倉庫源默認容器已經從 Docker 切換為 Podman

參考文章:

https://blog.51cto.com/juestnow/2440775

https://www.infoq.cn/article/odslclsjvo8bnx*mbrbk

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM