為什么 Kubernetes 優(yōu)先使用 Systemd 做為 Cgroup Driver?
什么是 cgroup
Cgroup 是一個 Linux 內(nèi)核特性,對一組進程的資源使用(CPU、內(nèi)存、磁盤 I/O 和網(wǎng)絡等)進行限制、審計和隔離。
cgroups(Control Groups) 是 linux 內(nèi)核提供的一種機制,這種機制可以根據(jù)需求把一系列系統(tǒng)任務及其子任務整合 (或分隔) 到按資源劃分等級的不同組內(nèi),從而為系統(tǒng)資源管理提供一個統(tǒng)一的框架。簡單說,cgroups 可以限制、記錄任務組所使用的物理資源。本質(zhì)上來說,cgroups 是內(nèi)核附加在程序上的一系列鉤子 (hook),通過程序運行時對資源的調(diào)度觸發(fā)相應的鉤子以達到資源追蹤和限制的目的。
什么是 cgroupfs
docker 默認的 Cgroup Driver 是 cgroupfs
$ docker info | grep cgroup
Cgroup Driver: cgroupfs
Cgroup 提供了一個原生接口并通過 cgroupfs 提供(從這句話我們可以知道 cgroupfs 就是 Cgroup 的一個接口的封裝)。類似于 procfs 和 sysfs,是一種虛擬文件系統(tǒng)。并且 cgroupfs 是可以掛載的,默認情況下掛載在 /sys/fs/cgroup 目錄。
什么是 Systemd?
Systemd 也是對于 Cgroup 接口的一個封裝。systemd 以 PID1 的形式在系統(tǒng)啟動的時候運行,并提供了一套系統(tǒng)管理守護程序、庫和實用程序,用來控制、管理 Linux 計算機操作系統(tǒng)資源。
為什么使用 systemd 而不是 croupfs
這里引用以下 kubernetes 官方的原話[1]:
?
當某個 Linux 系統(tǒng)發(fā)行版使用 systemd[2] 作為其初始化系統(tǒng)時,初始化進程會生成并使用一個 root 控制組(cgroup),并充當 cgroup 管理器。Systemd 與 cgroup 集成緊密,并將為每個 systemd 單元分配一個 cgroup。你也可以配置容器運行時和 kubelet 使用 cgroupfs。連同 systemd 一起使用 cgroupfs 意味著將有兩個不同的 cgroup 管理器。
單個 cgroup 管理器將簡化分配資源的視圖,并且默認情況下將對可用資源和使用 中的資源具有更一致的視圖。 當有兩個管理器共存于一個系統(tǒng)中時,最終將對這些資源產(chǎn)生兩種視圖。在此領(lǐng)域人們已經(jīng)報告過一些案例,某些節(jié)點配置讓 kubelet 和 docker 使用 cgroupfs,而節(jié)點上運行的其余進程則使用 systemd; 這類節(jié)點在資源壓力下 會變得不穩(wěn)定。
ubuntu 系統(tǒng),debian 系統(tǒng),centos7 系統(tǒng),都是使用 systemd 初始化系統(tǒng)的。systemd 這邊已經(jīng)有一套 cgroup 管理器了,如果容器運行時和 kubelet 使用 cgroupfs,此時就會存在 cgroups 和 systemd 兩種 cgroup 管理器。也就意味著操作系統(tǒng)里面存在兩種資源分配的視圖,當操作系統(tǒng)上存在 CPU,內(nèi)存等等資源不足的時候,操作系統(tǒng)上的進程會變得不穩(wěn)定。
我們可以簡單得理解為一山不要容二虎,一個國家只能有一個國王。
注意事項: 不要嘗試修改集群里面某個節(jié)點的 cgroup 驅(qū)動,如果有需要,最好移除該節(jié)點重新加入。
如何修改 docker 默認的 cgroup 驅(qū)動
增加 "exec-opts": ["native.cgroupdriver=systemd"] 配置 , 重啟 docker 即可
$ cat /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com"
],
"max-concurrent-downloads": 10,
"log-driver": "json-file",
"log-level": "warn",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"data-root": "/var/lib/docker"
}
kubelet 配置 cgroup 驅(qū)動
參考官方[3]
?
說明: 在版本 1.22 中,如果用戶沒有在 KubeletConfiguration 中設置 cgroupDriver 字段, kubeadm init 會將它設置為默認值 systemd。
# kubeadm-config.yaml
kind: ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta3
kubernetesVersion: v1.21.0
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd
然后使用 kubeadm 初始化
$ kubeadm init --config kubeadm-config.yaml