天天看點

正确配置Kubelet可一定程度防止K8S叢集雪崩

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

正确配置Kubelet可一定程度防止K8S叢集雪崩

如何配置

  • --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的存在:
正确配置Kubelet可一定程度防止K8S叢集雪崩
  • 在Kubernetes 1.8及1.9版本,Kubelet啟動會檢查以下cgroup subsystem的存在:
正确配置Kubelet可一定程度防止K8S叢集雪崩

對于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來實作。

正确配置Kubelet可一定程度防止K8S叢集雪崩

繼續閱讀