天天看點

k8s驅逐pian(1)-k8s QoS與pod驅逐

QoS是Quality of Service的縮寫,即服務品質。每個pod屬于某一個QoS分類,而Kubernetes會根據pod的QoS級别來決定pod的排程、搶占排程和驅逐優先級,而且pod的QoS級别也影響oomkiller對殺死程序的選擇。

概述

QoS是

Quality of Service

的縮寫,即服務品質。每個pod屬于某一個QoS分類,而Kubernetes會根據pod的QoS級别來決定pod的排程、搶占排程和驅逐優先級,而且pod的QoS級别也影響oomkiller對殺死程序的選擇。

pod QoS級别

QoS主要分為

Guaranteed

Burstable

Best-Effort

三個級别,優先級從高到低。

怎麼決定某個pod屬于哪個QoS分類呢?根據pod yaml中的cpu和記憶體資源定義決定。

Guaranteed

同時滿足以下情形的pod屬于Guaranteed級别:

(1)pod中的所有容器都設定了cpu的request、limit值;

(2)pod中每個容器的cpu的request值與limit值都相等;

(1)pod中的所有容器都設定了記憶體的request、limit值;

(2)pod中每個容器的記憶體的request值與limit值都相等;

...
containers:
  - name: test-a
    resources:
      limits:
        cpu: 10m
        memory: 1Gi
      requests:
        cpu: 10m
        memory: 1Gi
...
  - name: test-b
    resources:
      limits:
        cpu: 100m
        memory: 100Mi
      requests:
        cpu: 100m
        memory: 100Mi
...
           

Burstable

同時滿足以下情形的pod屬于

Burstable

級别:

(1)pod不符合

Guaranteed

的QoS級别标準;

(2)pod中至少有一個容器設定了記憶體或cpu的request或limit值;

...
containers:
  - name: test-a
...
  - name: test-b
    resources:
      limits:
        memory: 200Mi
      requests:
        memory: 100Mi
...
           

Best-Effort

同時滿足以下情形的pod屬于

Best-Effort

級别:

(1)pod中的所有容器都沒有設定記憶體的request與limit;

(2)pod中的所有容器都沒有設定cpu的request與limit;

...
containers:
  - name: test-a
...
  - name: test-b
...
           

kubelet驅逐pod順序

kubelet不使用pod的QoS級别來确定驅逐順序,但注意,

Guaranteed

級别QoS的pod不會被驅逐。

當node節點記憶體資源不足時,會觸發kubelet的節點壓力驅逐,pod驅逐順序選擇如下(排在前面的優先被驅逐):

(1)先根據pod的記憶體使用量是否超過記憶體request排序,超過的排在前面;

(2)再根據pod的priority值大小排序,值小的排在前面;

(3)最後根據pod記憶體request值減去pod的記憶體使用量的值,得到值小的排在前面;

關于pod的priority

通過

pod.spec.priorityClassName

pod.spec.priority

可為pod設定priority值大小,另外,

Guaranteed

級别QoS的pod也會間接設定priority值;

pod的priority值大小會影響kubelet驅逐pod的順序,還會影響kube-scheduler對于pod排程、搶占排程的優先級順序:

(1)當kubelet驅逐pod時,pod其他條件相同的情況下,priority值越小的越容易被驅逐;

(2)priority值越大,kube-scheduler對于pod排程的優先級越高;

(3)當pod因資源不足而排程失敗時,kube-scheduler會搶占排程該pod,即将priority值比它小的pod驅逐掉,然後将該pod排程上去;

詳細内容請檢視官方文檔:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/pod-priority-preemption/

OOM killer機制

當kubelet沒來得及觸發pod驅逐,使得節點記憶體耗盡時,将觸發節點上的

OOM killer

機制;

Linux上有個機制叫

OOM killer

Out Of Memory kille

r),這個機制會在系統記憶體耗盡的情況下發揮作用,即根據一定的算法規則,選擇性的殺死一些程序,以釋放部分記憶體,讓系統繼續穩定運作。

如何選擇殺死哪個程序

當發生oomkill時,

OOM killer

給程序打分,得到

oom_score

,然後優先把

oom_score

最大的程序先殺死;

oom_score

怎麼計算獲得呢?

oom_score

=

oom_score_adj

+

程序記憶體占用大小

oom_score_adj

則是可以人工給每個程序設定的,進而讓使用者通過設定程序的

oom_score_adj

值來影響

OOM killer

殺死程序的選擇;

oom_score_adj

的值設定為-1000時,表示該程序将不會被

OOM killer

殺死,但如果設定的值不是-1000,那這個程序還是會參與打分,會受

oom_score_adj

以及程序記憶體占用大小的影響,需要注意的是,即使

oom_score_adj

的值設定的很小,比如-999,但當你的程序占用記憶體很大時,該程序同樣有很大的機率會被殺死;

pod中容器程序的oom_score_adj

對于

Guaranteed

級别的pod,其

oom_score_adj

的值被設定為-998,對于

Best-Effort

級别的pod,其

oom_score_adj

的值被設定為1000,對于

Burstable

級别的pod,其

oom_score_adj

的取值為2到999。

怎麼避免OOM Killer殺死某個業務程序?

(1)将程序

oom_score_adj

的值設定為-1000;

(2)關閉

OOM killer

機制;

pod搶占排程

pod搶占排程機制,解決的是 Pod 排程失敗時該怎麼辦的問題。

正常情況下,當一個 pod 排程失敗後,就會被暫時 “擱置” 處于 pending 狀态,直到 pod 被更新或者叢集狀态發生變化,排程器才會對這個 pod 進行重新排程。

但是有的時候,我們希望給pod分等級,即分優先級。當一個高優先級的 Pod 排程失敗後,該 Pod 并不會被“擱置”,而是會“擠走”某個 Node 上的一些低優先級的 Pod(請求apiserver,删除pod),這樣一來就可以保證高優先級 Pod 會優先排程成功。

這裡所講的優先級就是前面提到的pod的priority值大小。

關于pod優先級,具體請參考:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/pod-priority-preemption/

搶占發生的原因,一定是一個高優先級的 pod 排程失敗,我們稱這個 pod 為“搶占者”,稱被搶占的 pod 為“犧牲者”(victims)。

繼續閱讀