一直在關注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-O
,containerd-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