原文連接:Kubernetes Pod 驅逐詳解node
在 Kubernetes 中,Pod 使用的資源最重要的是 CPU、內存和磁盤 IO,這些資源能夠被分爲可壓縮資源(CPU)和不可壓縮資源(內存,磁盤 IO)。可壓縮資源不可能致使 Pod 被驅逐,由於當 Pod 的 CPU 使用量不少時,系統能夠經過從新分配權重來限制 Pod 的 CPU 使用。而對於不可壓縮資源來講,若是資源不足,也就沒法繼續申請資源(內存用完就是用完了),此時 Kubernetes 會從該節點上驅逐必定數量的 Pod,以保證該節點上有充足的資源。docker
當不可壓縮資源不足時,Kubernetes 是經過 kubelet
來驅逐 Pod 的。kubelet 也不是隨機驅逐的,它有本身的一套驅逐機制,每一個計算節點的 kubelet 都會經過抓取 cAdvisor
的指標來監控節點的資源使用量,下面咱們來具體分析每種狀況。微信
更多精彩內容請關注微信公衆號:雲原生實驗室post
下面是 kubelet 默認的關於節點存儲的驅逐觸發條件:.net
當 imagefs
使用量達到閾值時,kubelet 會嘗試刪除不使用的鏡像來清理磁盤空間。code
當 nodefs
使用量達到閾值時,kubelet 就會拒絕在該節點上運行新 Pod,並向 API Server 註冊一個 DiskPressure condition。而後 kubelet 會嘗試刪除死亡的 Pod 和容器來回收磁盤空間,若是此時 nodefs
使用量仍然沒有低於閾值,kubelet 就會開始驅逐 Pod。從 Kubernetes 1.9 開始,kubelet 驅逐 Pod 的過程當中不會參考 Pod 的 QoS,只是根據 Pod 的 nodefs 使用量來進行排名,並選取使用量最多的 Pod 進行驅逐。因此即便 QoS 等級爲 Guaranteed
的 Pod 在這個階段也有可能被驅逐(例如 nodefs 使用量最大)。若是驅逐的是 Daemonset
,kubelet 會阻止該 Pod 重啓,直到 nodefs 使用量超過閾值。排序
若是一個 Pod 中有多個容器,kubelet 會根據 Pod 中全部容器的 nodefs 使用量之和來進行排名。即全部容器的
container_fs_usage_bytes
指標值之和。事件
舉個栗子,假設某計算節點上運行着一系列已知 QoS 等級和 nodefs 使用量的 Pod:內存
Pod Name | Pod QoS | nodefs usage |
---|---|---|
A | Best Effort | 800M |
B | Guaranteed | 1.3G |
C | Burstable | 1.2G |
D | Burstable | 700M |
E | Best Effort | 500M |
F | Guaranteed | 1G |
當 nodefs 的使用量超過閾值時,kubelet 會根據 Pod 的 nodefs 使用量來對 Pod 進行排名,首先驅逐使用量最多的 Pod。排名以下圖所示:ci
Pod Name | Pod QoS | nodefs usage |
---|---|---|
B | Guaranteed | 1.3G |
C | Burstable | 1.2G |
F | Guaranteed | 1G |
A | Best Effort | 800M |
D | Burstable | 700M |
E | Best Effort | 500M |
能夠看到在本例中,QoS 等級爲 Guaranteed
的 Pod 最早被驅逐。
下面是 kubelet 默認的關於節點內存資源的驅逐觸發條件:
當內存使用量超過閾值時,kubelet 就會向 API Server 註冊一個 MemoryPressure condition,此時 kubelet 不會接受新的 QoS 等級爲 Best Effort
的 Pod 在該節點上運行,並按照如下順序來驅逐 Pod:
request
指定的值request
指定的值之差。按照這個順序,能夠確保 QoS 等級爲 Guaranteed
的 Pod 不會在 QoS 等級爲 Best Effort
的 Pod 以前被驅逐,但不能保證它不會在 QoS 等級爲 Burstable
的 Pod 以前被驅逐。
若是一個 Pod 中有多個容器,kubelet 會根據 Pod 中全部容器相對於 request 的內存使用量與之和來進行排名。即全部容器的 (
container_memory_usage_bytes
指標值與container_resource_requests_memory_bytes
指標值的差)之和。
繼續舉例,假設某計算節點上運行着一系列已知 QoS 等級和內存使用量的 Pod:
Pod Name | Pod QoS | Memory requested | Memory limits | Memory usage |
---|---|---|---|---|
A | Best Effort | 0 | 0 | 700M |
B | Guaranteed | 2Gi | 2Gi | 1.9G |
C | Burstable | 1Gi | 2Gi | 1.8G |
D | Burstable | 1Gi | 2Gi | 800M |
E | Best Effort | 0 | 0 | 300M |
F | Guaranteed | 2Gi | 2Gi | 1G |
當節點的內存使用量超過閾值時,kubelet 會根據 Pod 相對於 request
的內存使用量來對 Pod 進行排名。排名以下所示:
Pod Name | Pod QoS | Memory requested | Memory limits | Memory usage | 內存相對使用量 |
---|---|---|---|---|---|
C | Burstable | 1Gi | 2Gi | 1.8G | 800M |
A | Best Effort | 0 | 0 | 700M | 700M |
E | Best Effort | 0 | 0 | 300M | 300M |
B | Guaranteed | 2Gi | 2Gi | 1.9G | -100M |
D | Burstable | 1Gi | 2Gi | 800M | -200M |
F | Guaranteed | 2Gi | 2Gi | 1G | -1G |
能夠看到在本例中,能夠看到在本例中,QoS 等級爲 Guaranteed
的 Pod 在 QoS 等級爲 Burstable
的 Pod 以前被驅逐。
當內存資源不足時,kubelet 在驅逐 Pod 時只會考慮 requests 和 Pod 的內存使用量,不會考慮 limits。
由於 kubelet 默認每 10
秒抓取一次 cAdvisor 的監控數據,因此有可能在 kubelet 驅逐 Pod 回收內存以前發生內存使用量激增的狀況,這時就有可能觸發內核 OOM killer。這時刪除容器的權利就由kubelet 轉交到內核 OOM killer 手裏,但 kubelet 仍然會起到必定的決定做用,它會根據 Pod 的 QoS 來設置其 oom_score_adj
值:
QoS | oom_score_adj |
---|---|
Guaranteed | -998 |
Burstable | min(max(2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999) |
pod-infra-container | -998 |
kubelet, docker daemon, systemd service | -999 |
若是該節點在 kubelet 經過驅逐 Pod 回收內存以前觸發了 OOM 事件,OOM killer 就會採起行動來下降系統的壓力,它會根據下面的公式來計算 oom_score
的值:
容器使用的內存佔系統內存的百分比 + oom_score_adj = oom_score
OOM killer 會殺掉 oom_score_adj
值最高的容器,若是有多個容器的 oom_score_adj
值相同,就會殺掉內存使用量最多的容器(實際上是由於內存使用量最多的容器的 oom_score 值最高)。關於 OOM 的更多內容請參考:Kubernetes 內存資源限制實戰。
假設某節點運行着 4 個 Pod,且每一個 Pod 中只有一個容器。每一個 QoS 類型爲 Burstable
的 Pod 配置的內存 requests 是 4Gi
,節點的內存大小爲 30Gi
。每一個 Pod 的 oom_score_adj
值以下所示:
Pod Name | Pod QoS | oom_score_adj |
---|---|---|
A | Best Effort | 1000 |
B | Guaranteed | -998 |
C | Burstable | 867(根據上面的公式計算) |
D | Best Effort | 1000 |
當調用 OOM killer 時,它首先選擇 oom_score_adj
值最高的容器(1000),這裏有兩個容器的 oom_score_adj
值都是 1000,OOM killer 最終會選擇內存使用量最多的容器。
如今你應該理解了 kubelet 驅逐 Pod 的原理和過程,若是你在部署應用時設置了恰當的參數,知道了全部的可能性,你就能更好地掌控你的集羣。