K8S 的節點上的資源會被 pod 和系統進程所使用,若是默認什麼都不配置,那麼節點上的所有資源都是能夠分配給pod使用的,系統進程自己沒有保障,這樣作很危險:node
節點資源主要分爲兩類:git
oom 分數:github
因此,OOM 的優先級以下:docker
BestEffort Pod > Burstable Pod > 其它進程 > Guaranteed Pod > kubelet/docker 等 > sshd 等進程
所以須要對節點的內存等資源進行配置,以保證節點核心進程運行正常。bash
節點資源的配置通常分爲 2 種:服務器
allocatable的值即對應 describe node 時看到的allocatable容量,pod 調度的上限ssh
計算公式:節點上可配置值 = 總量 - 預留值 - 驅逐閾值 Allocatable = Capacity - Reserved(kube+system) - Eviction Threshold
以上配置均在kubelet 中添加,涉及的參數有:google
--enforce-node-allocatable=pods,kube-reserved,system-reserved --kube-reserved-cgroup=/system.slice/kubelet.service --system-reserved-cgroup=/system.slice --kube-reserved=cpu=200m,memory=250Mi --system-reserved=cpu=200m,memory=250Mi --eviction-hard=memory.available<5%,nodefs.available<10%,imagefs.available<10% --eviction-soft=memory.available<10%,nodefs.available<15%,imagefs.available<15% --eviction-soft-grace-period=memory.available=2m,nodefs.available=2m,imagefs.available=2m --eviction-max-pod-grace-period=30 --eviction-minimum-reclaim=memory.available=0Mi,nodefs.available=500Mi,imagefs.available=500Mi
配置的含義以下:spa
(1)--enforce-node-allocatable3d
含義:指定kubelet爲哪些進程作硬限制,可選的值有: * pods * kube-reserved * system-reserve 這個參數開啓並指定pods後kubelet會爲全部pod的總cgroup作資源限制(經過cgroup中的kubepods.limit_in_bytes),限制爲公式計算出的allocatable的大小。 假如想爲系統進程和k8s進程也作cgroup級別的硬限制,還能夠在限制列表中再加system-reserved和kube-reserved,同時還要分別加上--kube-reserved-cgroup和--system-reserved-cgroup以指定分別限制在哪一個cgroup裏。
配置:--enforce-node-allocatable=pods,kube-reserved,system-reserved
(2)設置k8s組件的cgroup
含義:這個參數用來指定k8s系統組件所使用的cgroup。 注意,這裏指定的cgroup及其子系統須要預先建立好,kubelet並不會爲你自動建立好。
配置:--kube-reserved-cgroup=/system.slice/kubelet.service
(3)設置系統守護進程的cgroup
含義:這個參數用來指定系統守護進程所使用的cgroup。 注意,這裏指定的cgroup及其子系統須要預先建立好,kubelet並不會爲你自動建立好。
配置:--system-reserved-cgroup=/system.slice
(4)配置 k8s組件預留資源的大小,CPU、Mem
指定爲k8s系統組件(kubelet、kube-proxy、dockerd等)預留的資源量, 如:--kube-reserved=cpu=1,memory=2Gi,ephemeral-storage=1Gi。 這裏的kube-reserved只爲非pod形式啓動的kube組件預留資源,假如組件要是以static pod(kubeadm)形式啓動的,那並不在這個kube-reserved管理並限制的cgroup中,而是在kubepod這個cgroup中。 (ephemeral storage須要kubelet開啓feature-gates,預留的是臨時存儲空間(log,EmptyDir),生產環境建議先不使用) ephemeral-storage是kubernetes1.8開始引入的一個資源限制的對象,kubernetes 1.10版本中kubelet默認已經打開的了,到目前1.11仍是beta階段,主要是用於對本地臨時存儲使用空間大小的限制,如對pod的empty dir、/var/lib/kubelet、日誌、容器可讀寫層的使用大小的限制。
(5)配置 系統守護進程預留資源的大小(預留的值須要根據機器上容器的密度作一個合理的值)
含義:爲系統守護進程(sshd, udev等)預留的資源量, 如:--system-reserved=cpu=500m,memory=1Gi,ephemeral-storage=1Gi。 注意,除了考慮爲系統進程預留的量以外,還應該爲kernel和用戶登陸會話預留一些內存。
配置:--system-reserved=cpu=200m,memory=250Mi
(6)配置 驅逐pod的硬閾值
含義:設置進行pod驅逐的閾值,這個參數只支持內存和磁盤。 經過--eviction-hard標誌預留一些內存後,當節點上的可用內存降至保留值如下時, kubelet 將會對pod進行驅逐。
配置:--eviction-hard=memory.available<5%,nodefs.available<10%,imagefs.available<10%
(7)配置 驅逐pod的軟閾值
--eviction-soft=memory.available<10%,nodefs.available<15%,imagefs.available<15%
(8)定義達到軟閾值以後,持續時間超過多久才進行驅逐
--eviction-soft-grace-period=memory.available=2m,nodefs.available=2m,imagefs.available=2m
(9)驅逐pod前最大等待時間=min(pod.Spec.TerminationGracePeriodSeconds, eviction-max-pod-grace-period),單位爲秒
--eviction-max-pod-grace-period=30
(10)至少回收的資源量
--eviction-minimum-reclaim=memory.available=0Mi,nodefs.available=500Mi,imagefs.available=500Mi
以上配置均爲百分比,舉例:
以2核4GB內存40GB磁盤空間的配置爲例,Allocatable是1.6 CPU,3.3Gi 內存,25Gi磁盤。當pod的總內存消耗大於3.3Gi或者磁盤消耗大於25Gi時,會根據相應策略驅逐pod。
kubelet 利用metric的值做爲決策依據來觸發驅逐行爲,下面內容來自於 Kubelet summary API。
一旦超出閾值,就會觸發 kubelet 進行資源回收的動做(區別於軟驅逐,有寬限期),指標以下:
例如若是一個 Node 有 10Gi 內存,咱們但願在可用內存不足 1Gi 時進行驅逐,就能夠選取下面的一種方式來定義驅逐閾值:
能夠配置百分比或者實際值,可是操做符只能使用小於號,即<
軟閾值須要和一個寬限期參數協同工做。當系統資源消耗達到軟閾值時,這一情況的持續時間超過了寬限期以前,Kubelet 不會觸發任何動做。若是沒有定義寬限期,Kubelet 會拒絕啓動。
另外還能夠定義一個 Pod 結束的寬限期。若是定義了這一寬限期,那麼 Kubelet 會使用 pod.Spec.TerminationGracePeriodSeconds 和最大寬限期這兩個值之間較小的那個(進行寬限),若是沒有指定的話,kubelet 會不留寬限當即殺死 Pod。
軟閾值的定義包括如下幾個參數:
Housekeeping interval 參數定義一個時間間隔,Kubelet 每隔這一段就會對驅逐閾值進行評估。
若是觸發了硬閾值,或者符合軟閾值的時間持續了與其對應的寬限期,Kubelet 就會認爲當前節點壓力太大,下面的節點狀態定義描述了這種對應關係。
Kubelet 會持續報告節點狀態的更新過程,這一頻率由參數 —node-status-update-frequency 指定,缺省狀況下取值爲 10s。
若是一個節點的情況在軟閾值的上下波動,可是又不會超過他的寬限期,將會致使該節點的狀態持續的在是否之間徘徊,最終會影響下降調度的決策過程。
要防止這種情況,下面的標誌能夠用來通知 Kubelet,在脫離pressure以前,必須等待。
eviction-pressure-transition-period
定義了在脫離pressure狀態以前要等待的時間
Kubelet 在把pressure狀態設置爲 False 以前,會確認在週期以內,該節點沒有達到閾值
若是達到了驅逐閾值,而且超出了寬限期,那麼 Kubelet 會開始回收超出限量的資源,直到回到閾值之內。
Kubelet 在驅逐用戶 Pod 以前,會嘗試回收節點級別的資源。若是服務器爲容器定義了獨立的 imagefs,他的回收過程會有所不一樣。
有 Imagefs
若是 nodefs 文件系統到達了驅逐閾值,kubelet 會按照下面的順序來清理空間:
若是 imagefs 文件系統到達了驅逐閾值,kubelet 會按照下面的順序來清理空間:
沒有 Imagefs
若是 nodefs 文件系統到達了驅逐閾值,kubelet 會按照下面的順序來清理空間。
Kubelet 會按照下面的標準對 Pod 的驅逐行爲進行評判:
接下來,Pod 按照下面的順序進行驅逐(QOS):
參考 POD的QOS:服務質量等級
Guaranteed Pod 不會由於其餘 Pod 的資源被驅逐。若是系統進程(例如 kubelet、docker、journald 等)消耗了超出 system-reserved 或者 kube-reserved 的資源,並且這一節點上只運行了 Guaranteed Pod,那麼爲了保證節點的穩定性並下降異常請求對其餘 Guaranteed Pod 的影響,必須選擇一個 Guaranteed Pod 進行驅逐。
本地磁盤是一個 BestEffort 資源。若有必要,kubelet 會在 DiskPressure 的狀況下,kubelet 會按照 QoS 進行評估。若是 Kubelet 斷定缺少 inode 資源,就會經過驅逐最低 QoS 的 Pod 的方式來回收 inodes。若是 kubelet 斷定缺少磁盤空間,就會經過在相同 QoS 的 Pods 中,選擇消耗最多磁盤空間的 Pod 進行驅逐。
有 Imagefs
沒有 Imagefs
例以下面的配置:
--eviction-hard=memory.available<500Mi,nodefs.available<1Gi,imagefs.available<100Gi --eviction-minimum-reclaim="memory.available=0Mi,nodefs.available=500Mi,imagefs.available=2Gi"
缺省狀況下,全部資源的 eviction-minimum-reclaim 爲 0。
在節點資源緊缺的狀況下,調度器將再也不繼續向此節點部署新的 Pod
若是節點在 Kubelet 可以回收內存以前,遭遇到了系統的 OOM (內存不足),節點就依賴 oom_killer 進行響應了。
kubelet 根據 Pod 的 QoS 爲每一個容器設置了一個 oom_score_adj 值。
若是 kubelet 沒法在系統 OOM 以前回收足夠的內存,oom_killer 就會根據根據內存使用比率來計算 oom_score,得出結果和 oom_score_adj 相加,最後得分最高的 Pod 會被首先驅逐。
跟 Pod 驅逐不一樣,若是一個 Pod 的容器被 OOM 殺掉,他是可能被 kubelet 根據 RestartPolicy 重啓的。
由於 DaemonSet 中的 Pod 會當即重建到同一個節點,因此 Kubelet 不該驅逐 DaemonSet 中的 Pod。
可是目前 Kubelet 沒法分辨一個 Pod 是否由 DaemonSet 建立。若是Kubelet 可以識別這一點,那麼就能夠先從驅逐候選列表中過濾掉 DaemonSet 的 Pod。
通常來講,強烈建議 DaemonSet 不要建立 BestEffort Pod,而是使用 Guaranteed Pod,來避免進入驅逐候選列表。
Kubelet 目前從 cAdvisor 定時獲取內存使用情況統計。若是內存使用在這個時間段內發生了快速增加,Kubelet 就沒法觀察到 MemoryPressure,可能會觸發 OOMKiller。咱們正在嘗試將這一過程集成到 memcg 通知 API 中,來下降這一延遲,而不是讓內核首先發現這一狀況。
若是用戶不是但願得到終極使用率,而是做爲一個過量使用的衡量方式,對付這一個問題的較爲可靠的方式就是設置驅逐閾值爲 75% 容量。這樣就提升了避開 OOM 的能力,提升了驅逐的標準,有助於集羣狀態的平衡。
這也是由於狀態蒐集的時間差致使的。將來會加入功能,讓根容器的統計頻率和其餘容器分別開來(https://github.com/google/cad...)。
目前不可能知道一個容器消耗了多少 inode。若是 Kubelet 覺察到了 inode 耗盡,他會利用 QoS 對 Pod 進行驅逐評估。在 cadvisor 中有一個 issue,來跟蹤容器的 inode 消耗,這樣咱們就能利用 inode 進行評估了。例如若是咱們知道一個容器建立了大量的 0 字節文件,就會優先驅逐這一 Pod
一、資源預留須要設置,pod 的 limit 也要設置。
二、cpu是可壓縮資源,內存、磁盤資源是不可壓縮資源。內存必定要預留,CPU能夠根據實際狀況來調整
三、預留多少合適:根據集羣規模設置階梯,以下(GKE建議):
Allocatable = Capacity - Reserved - Eviction Threshold
對於內存資源:
對於 CPU 資源:
對於磁盤資源(不是正式特性,僅供參考):
效果:查看節點的可分配資源:
kubectl describe node [NODE_NAME] | grep Allocatable -B 4 -A 3
--eviction-hard=memory.available<5%,nodefs.available<10%,imagefs.available<10% --eviction-soft=memory.available<10%,nodefs.available<15%,imagefs.available<15% --eviction-soft-grace-period=memory.available=2m,nodefs.available=2m,imagefs.available=2m --eviction-max-pod-grace-period=30 --eviction-minimum-reclaim=memory.available=0Mi,nodefs.available=500Mi,imagefs.available=500Mi
原文連接:http://www.xuyasong.com/?p=1725