kubelet 預留system、kube資源
Kubernetes 的節點可以按照 Capacity 調度。默認情況下 pod 能夠使用節點全部可用容量。這是個問題,因為節點自己通常運行了不少驅動 OS 和 Kubernetes 的系統守護進程(system daemons)。除非為這些系統守護進程留出資源,否則它們將與 pod 爭奪資源並導致節點資源短缺問題。
kubelet 公開了一個名為 Node Allocatable 的特性,有助於為系統守護進程預留計算資源。Kubernetes 推薦集群管理員按照每個節點上的工作負載密度配置 Node Allocatable。
Node Allocatable
Node Capacity
---------------------------
| kube-reserved |
|-------------------------|
| system-reserved |
|-------------------------|
| eviction-threshold |
|-------------------------|
| |
| allocatable |
| (available for pods) |
| |
| |
---------------------------
Kubernetes 節點上的 Allocatable 被定義為 pod 可用計算資源量。調度器不會超額申請 Allocatable。目前支持 CPU, memory 和 storage 這幾個參數。
Node Allocatable 暴露為 API 中 v1.Node 對象的一部分,也是 CLI 中 kubectl describe node 的一部分。
在 kubelet 中,可以為兩類系統守護進程預留資源。
啟用 QoS 和 Pod 級別的 cgroups
為了恰當的在節點范圍實施 node allocatable,您必須通過 --cgroups-per-qos 標志啟用新的 cgroup 層次結構。這個標志是默認啟用的。啟用后,kubelet 將在其管理的 cgroup 層次結構中創建所有終端用戶的 pod。
配置 cgroup 驅動
kubelet 支持在主機上使用 cgroup 驅動操作 cgroup 層次結構。驅動通過 --cgroup-driver 標志配置。
支持的參數值如下:
- cgroupfs 是默認的驅動,在主機上直接操作 cgroup 文件系統以對 cgroup 沙箱進行管理。
- systemd 是可選的驅動,使用 init 系統支持的資源的瞬時切片管理 cgroup 沙箱。
取決於相關容器運行時(container runtime)的配置,操作員可能需要選擇一個特定的 cgroup 驅動來保證系統正常運行。例如如果操作員使用 docker 運行時提供的 cgroup 驅動時,必須配置 kubelet 使用 systemd cgroup 驅動。
Kube Reserved
- Kubelet Flag: --kube-reserved=[cpu=100m][,][memory=100Mi][,][storage=1Gi]
- Kubelet Flag: --kube-reserved-cgroup=
kube-reserved 是為了給諸如 kubelet、container runtime、node problem detector 等 kubernetes 系統守護進程爭取資源預留。這並不代表要給以 pod 形式運行的系統守護進程保留資源。kube-reserved 通常是節點上的一個 pod 密度(pod density) 功能。 這個性能儀表盤 從 pod 密度的多個層面展示了 kubelet 和 docker engine 的 cpu 和 memory使用情況。
要選擇性的在系統守護進程上執行 kube-reserved,需要把 kubelet 的 --kube-reserved-cgroup 標志的值設置為 kube 守護進程的父控制組。
推薦將 kubernetes 系統守護進程放置於頂級控制組之下(例如 systemd 機器上的 runtime.slice)。理想情況下每個系統守護進程都應該在其自己的子控制組中運行。請參考這篇文檔,獲取更過關於推薦控制組層次結構的細節。
請注意,如果 --kube-reserved-cgroup 不存在,Kubelet 將不會創建它。如果指定了一個無效的 cgroup,Kubelet 將會失敗。
系統預留值(System Reserved)
- Kubelet Flag: --system-reserved=[cpu=100mi][,][memory=100Mi][,][storage=1Gi]
- Kubelet Flag: --system-reserved-cgroup=
system-reserved 用於為諸如 sshd、udev 等系統守護進程爭取資源預留。system-reserved 也應該為 kernel 預留 內存,因為目前 kernel 使用的內存並不記在 Kubernetes 的 pod 上。同時還推薦為用戶登錄會話預留資源(systemd 體系中的 user.slice)。
要想在系統守護進程上可選地執行 system-reserved,請指定 --system-reserved-cgroup kubelet 標志的值為 OS 系統守護進程的父級控制組。
推薦將 OS 系統守護進程放在一個頂級控制組之下(例如 systemd 機器上的system.slice)。
請注意,如果 --system-reserved-cgroup 不存在,Kubelet 不會創建它。如果指定了無效的 cgroup,Kubelet 將會失敗。
驅逐閾值(Eviction Thresholds)
- Kubelet Flag: --eviction-hard=[memory.available<500Mi]
節點級別的內存壓力將導致系統內存不足(System OOMs),這將影響到整個節點及其上運行的所有 pod。節點可以暫時離線直到內存已經回收為止。為了防止(或減少可能性)系統內存不足,kubelet 提供了 資源不足(Out of Resource) 管理。驅逐(Eviction)操作只支持 memory 和 storage。通過 --eviction-hard 標志預留一些內存后,當節點上的可用內存降至保留值以下時,kubelet 將嘗試 驅逐 pod。假設,如果節點上不存在系統守護進程,pod 將不能使用超過 capacity-eviction-hard 的資源。因此,為驅逐而預留的資源對 pod 是不可用的。
執行節點 Allocatable
- Kubelet Flag: --enforce-node-allocatable=pods[,][system-reserved][,][kube-reserved]
調度器將 Allocatable 按 pod 的可用 capacity 對待。
kubelet 默認在 pod 中執行 Allocatable。無論何時,如果所有 pod 的總用量超過了 Allocatable,驅逐 pod 的措施將被執行。有關驅逐策略的更多細節可以在 這里 找到。請通過設置 kubelet --enforce-node-allocatable 標志值為 pods 控制這個措施。
可選的,通過在相同標志中同時指定 kube-reserved 和 system-reserved 值能夠使 kubelet 執行 kube-reserved 和 system-reserved。請注意,要想執行 kube-reserved 或者 system-reserved時,需要分別指定 --kube-reserved-cgroup 或者 --system-reserved-cgroup。
一般原則
系統守護進程期望被按照類似 Guaranteed pod 一樣對待。系統守護進程可以在其范圍控制組中爆發式增長,您需要將這個行為作為 kubernetes 部署的一部分進行管理。例如,kubelet 應該有它自己的控制組並和容器運行時(container runtime)共享 Kube-reserved 資源。然而,如果執行了 kube-reserved,則 kubelet 不能突然爆發並耗盡節點的所有可用資源。
在執行 system-reserved 預留操作時請加倍小心,因為它可能導致節點上的關鍵系統服務 CPU 資源短缺或因為內存不足(OOM)而被終止。
- 在 pods 上執行 Allocatable 作為開始。
- 一旦足夠用於追蹤系統守護進程的監控和告警的機制到位,請嘗試基於用量探索(usage heuristics)方式執行 kube-reserved。
- 隨着時間推進,如果絕對必要,可以執行 system-reserved。
隨着時間的增長以及越來越多特性的加入,kube 系統守護進程對資源的需求可能也會增加。以后 kubernetes 項目將嘗試減少對節點系統守護進程的利用,但目前那並不是優先事項。所以,請期待在將來的發布中將 Allocatable 容量降低。
示例場景
這是一個用於說明節點 Allocatable 計算方式的示例:
- 節點擁有 32Gi 內存,16 核 CPU 和 100Gi 存儲
- --kube-reserved 設置為 cpu=1,memory=2Gi,storage=1Gi
- --system-reserved 設置為 cpu=500m,memory=1Gi,storage=1Gi
- --eviction-hard 設置為 memory.available<500Mi,nodefs.available<10%
在這個場景下,Allocatable 將會是 14.5 CPUs、28.5Gi 內存以及 98Gi 存儲。調度器保證這個節點上的所有 pod 請求的內存總量不超過 28.5Gi,存儲不超過 88Gi。當 pod 的內存使用總量超過 28.5Gi 或者磁盤使用總量超過 88Gi 時,Kubelet 將會驅逐它們。如果節點上的所有進程都盡可能多的使用 CPU,則 pod 加起來不能使用超過 14.5 CPUs 的資源。
當沒有執行 kube-reserved 和/或 system-reserved 且系統守護進程使用量超過其預留時,如果節點內存用量高於 31.5Gi 或存儲大於 90Gi,kubelet 將會驅逐 pod。
可用特性
截至 Kubernetes 1.2 版本,已經可以可選的指定 kube-reserved 和 system-reserved 預留。當在相同的發布中都可用時,調度器將轉為使用 Allocatable 替代 Capacity。
截至 Kubernetes 1.6 版本,eviction-thresholds 是通過計算 Allocatable 進行考慮。要使用舊版本的行為,請設置 --experimental-allocatable-ignore-eviction kubelet 標志為 true。
截至 Kubernetes 1.6 版本,kubelet 使用控制組在 pod 上執行 Allocatable。要使用舊版本行為,請取消設置 --enforce-node-allocatable kubelet 標志。請注意,除非 --kube-reserved 或者 --system-reserved 或者 --eviction-hard 標志沒有默認參數,否則 Allocatable 的實施不會影響已經存在的 deployment。
截至 Kubernetes 1.6 版本,kubelet 在 pod 自己的 cgroup 沙箱中啟動它們,這個 cgroup 沙箱在 kubelet 管理的 cgroup 層次結構中的一個獨占部分中。在從前一個版本升級 kubelet之前,要求操作員 drain 節點,以保證 pod 及其關聯的容器在 cgroup 層次結構中合適的部分中啟動。