Kubelet Node Allocatable
- Kubelet Node Allocatable用來為Kube元件和System程序預留資源,進而保證當節點出現滿負荷時也能保證Kube和System程序有足夠的資源。
- 目前支援cpu, memory, ephemeral-storage三種資源預留。
- Node Capacity是Node的所有硬體資源,kube-reserved是給kube元件預留的資源,system-reserved是給System程序預留的資源, eviction-threshold是kubelet eviction的門檻值設定,allocatable才是真正scheduler排程Pod時的參考值(保證Node上所有Pods的request resource不超過Allocatable)。
-
Node Allocatable Resource = Node Capacity - Kube-reserved - system-reserved - eviction-threshold
如何配置
- --enforce-node-allocatable,預設為pods,要為kube元件和System程序預留資源,則需要設定為
。pods,kube-reserved,system-reserve
- --cgroups-per-qos,Enabling QoS and Pod level cgroups,預設開啟。開啟後,kubelet會将管理所有workload Pods的cgroups。
- --cgroup-driver,預設為cgroupfs,另一可選項為systemd。取決于容器運作時使用的cgroup driver,kubelet與其保持一緻。比如你配置docker使用systemd cgroup driver,那麼kubelet也需要配置--cgroup-driver=systemd。
- --kube-reserved,用于配置為kube元件(kubelet,kube-proxy,dockerd等)預留的資源量,比如—kube-reserved=cpu=1000m,memory=8Gi,ephemeral-storage=16Gi。
- --kube-reserved-cgroup,如果你設定了--kube-reserved,那麼請一定要設定對應的cgroup,并且該cgroup目錄要事先建立好,否則kubelet将不會自動建立導緻kubelet啟動失敗。比如設定為kube-reserved-cgroup=/kubelet.service 。
- --system-reserved,用于配置為System程序預留的資源量,比如—system-reserved=cpu=500m,memory=4Gi,ephemeral-storage=4Gi。
- --system-reserved-cgroup,如果你設定了--system-reserved,那麼請一定要設定對應的cgroup,并且該cgroup目錄要事先建立好,否則kubelet将不會自動建立導緻kubelet啟動失敗。比如設定為system-reserved-cgroup=/system.slice。
- --eviction-hard,用來配置kubelet的hard eviction條件,隻支援memory和ephemeral-storage兩種不可壓縮資源。當出現MemoryPressure時,Scheduler不會排程新的Best-Effort QoS Pods到此節點。當出現DiskPressure時,Scheduler不會排程任何新Pods到此節點。關于Kubelet Eviction的更多解讀,請參考我的相關博文。
- Kubelet Node Allocatable的代碼很簡單,主要在
,感興趣的同學自己去走讀一遍。pkg/kubelet/cm/node_container_manager.go
關于如何規劃Node的Cgroup結構,請參考官方建議: recommended-cgroups-setup
Sample
以如下的kubelet資源預留為例,Node Capacity為memory=32Gi, cpu=16, ephemeral-storage=100Gi,我們對kubelet進行如下配置:
--enforce-node-allocatable=pods,kube-reserved,system-reserved
--kube-reserved-cgroup=/kubelet.service
--system-reserved-cgroup=/system.slice
--kube-reserved=cpu=1,memory=2Gi,ephemeral-storage=1Gi
--system-reserved=cpu=500m,memory=1Gi,ephemeral-storage=1Gi
--eviction-hard=memory.available<500Mi,nodefs.available<10%
NodeAllocatable = NodeCapacity - Kube-reserved - system-reserved - eviction-threshold =
cpu=14.5,memory=28.5Gi,ephemeral-storage=98Gi.
Scheduler會確定Node上所有的Pod Resource Request不超過NodeAllocatable。Pods所使用的memory和storage之和超過NodeAllocatable後就會觸發kubelet Evict Pods。
我踩的坑
kube-reserved-cgroup及system-reserved-cgroup配置
最開始,我隻對kubelet做了如下配置--kube-reserved, --system-reserved,我就以為kubelet會自動給kube和system建立對應的Cgroup,并設定對應的cpu share, memory limit等,然後高枕無憂了。
然而實際上并非如此,直到線上上有一次某個TensorFlow worker的問題,無限制的使用節點的cpu,導緻節點上cpu usage持續100%運作,并且壓榨到了kubelet元件的cpu使用,導緻kubelet與APIServer的心跳斷了,這個節點便Not Ready了。
接着,Kubernetes會在其他某個最優的Ready Node上啟動這個貪婪的worker,進而把這個節點的cpu也跑滿了,節點Not Ready了。
如此就出現了叢集雪崩,叢集内的Nodes逐個的Not Ready了,後果非常嚴重。
把kublet加上如下配置後,即可保證在Node高負荷時,也能保證當kubelet需要cpu時至少能有
--kube-reserved
設定的cpu cores可用。
--enforce-node-allocatable=pods,kube-reserved,system-reserved
--kube-reserved-cgroup=/kubelet.service
--system-reserved-cgroup=/system.slice
注意,因為kube-reserved設定的cpu其實最終是寫到kube-reserved-cgroup下面的cpu shares。了解cpu shares的同學知道,隻有當叢集的cpu跑滿需要搶占時才會起作用,是以你會看到Node的cpu usage還是有可能跑到100%的,但是不要緊,kubelet等元件并沒有收到影響,如果kubelet此時需要更多的cpu,那麼它就能搶到更多的時間片,最多可以搶到kube-reserved設定的cpu nums。
Kubernetes會檢查的cgroup subsystem
- 在Kubernetes 1.7版本,Kubelet啟動會檢查以下cgroup subsystem的存在:
- 在Kubernetes 1.8及1.9版本,Kubelet啟動會檢查以下cgroup subsystem的存在:
對于Centos系統,cpuset和hugetlb subsystem是預設沒有初始化system.slice,是以需要手動建立,否則會報
Failed to start ContainerManager Failed to enforce System Reserved Cgroup Limits on "/system.slice": "/system.slice" cgroup does not exist
的錯誤日志。
我們可以通過在kubelet service中配置ExecStartPre來實作。