在kubernetes中,每一個POD都有個QoS標記,經過這個Qos標記來對POD進行服務質量管理。QoS的英文全稱爲"Quality of Service",中文名爲"服務質量",它取決於用戶對服務質量的預期,也就是指望的服務質量。對於POD來講,服務質量體如今兩個指標上,一個指標是CPU,另外一個指標是內存。在實際運行過程當中,當NODE節點上內存資源緊張的時候,kubernetes根據POD具備的不一樣QoS標記,採起不一樣的處理策略。線程
在Kubernetes中,POD的QoS服務質量一共有三個級別,以下圖所示:繼承
這三個QoS級別介紹,能夠看下面表格:接口
QoS級別進程 |
QoS介紹內存 |
BestEffort資源 |
POD中的全部容器都沒有指定CPU和內存的requests和limits,那麼這個POD的QoS就是BestEffort級別kubernetes |
Burstablerequests |
POD中只要有一個容器,這個容器requests和limits的設置同其餘容器設置的不一致,那麼這個POD的QoS就是Burstable級別it |
Guaranteed |
POD中全部容器都必須統一設置了limits,而且設置參數都一致,若是有一個容器要設置requests,那麼全部容器都要設置,並設置參數同limits一致,那麼這個POD的QoS就是Guaranteed級別 |
爲了更清楚的瞭解這三個QoS級別,下面咱們舉例說明。
QoS級別 |
QoS配置例子 |
BestEffort |
containers: name: foo resources: name: bar resources: |
Burstable |
containers: name: foo resources: limits: cpu: 10m memory: 1Gi requests: cpu: 10m memory: 1Gi
name: bar |
containers: name: foo resources: limits: memory: 1Gi
name: bar resources: limits: cpu: 100m |
|
containers: name: foo resources: requests: cpu: 10m memory: 1Gi
name: bar |
|
Guaranteed |
containers: name: foo resources: limits: cpu: 10m memory: 1Gi name: bar resources: limits: cpu: 100m memory: 100Mi |
containers: name: foo resources: limits: cpu: 10m memory: 1Gi requests: cpu: 10m memory: 1Gi
name: bar resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 1Gi |
QoS級別決定了kubernetes處理這些POD的方式,咱們之內存資源爲例:
一、當NODE節點上內存資源不夠的時候,QoS級別是BestEffort的POD會最早被kill掉;當NODE節點上內存資源充足的時候,QoS級別是BestEffort的POD可使用NODE節點上剩餘的全部內存資源。
二、當NODE節點上內存資源不夠的時候,若是QoS級別是BestEffort的POD已經都被kill掉了,那麼會查找QoS級別是Burstable的POD,而且這些POD使用的內存已經超出了requests設置的內存值,這些被找到的POD會被kill掉;當NODE節點上內存資源充足的時候,QoS級別是Burstable的POD會按照requests和limits的設置來使用。
三、當NODE節點上內存資源不夠的時候,若是QoS級別是BestEffort和Burstable的POD都已經被kill掉了,那麼會查找QoS級別是Guaranteed的POD,而且這些POD使用的內存已經超出了limits設置的內存值,這些被找到的POD會被kill掉;當NODE節點上內存資源充足的時候,QoS級別是Burstable的POD會按照requests和limits的設置來使用。
從容器的角度出發,爲了限制容器使用的CPU和內存,是經過cgroup來實現的,目前kubernetes的QoS只能管理CPU和內存,因此kubernetes如今也是經過對cgroup的配置來實現QoS管理的。
咱們簡單來介紹下cgroup:
一、來源:
cgroups(Control Groups)最初叫ProcessContainer,由Google工程師(Paul Menage和Rohit Seth)於2006年提出,後來由於Container有多重含義容易引發誤解,就在2007年改名爲Control Groups,並被整合進Linux內核。顧名思義就是把進程放到一個組裏面統一加以控制。
二、官方定義:
cgroups是Linux內核提供的一種機制,這種機制能夠根據特定的行爲,把一系列系統任務及其子任務整合(或分隔)到按資源劃分等級的不一樣組內,從而爲系統資源管理提供一個統一的框架。
三、做用:
資源限制(Resource Limitation):cgroups能夠對進程組使用的資源總額進行限制。如設定應用運行時使用內存的上限,一旦超過這個配額就發出OOM(Out of Memory)。
優先級分配(Prioritization):經過分配的CPU時間片數量及硬盤IO帶寬大小,實際上就至關於控制了進程運行的優先級。
資源統計(Accounting): cgroups能夠統計系統的資源使用量,如CPU使用時長、內存用量等等,這個功能很是適用於計費。
進程控制(Control):cgroups能夠對進程組執行掛起、恢復等操做。
四、特色:
cgroups的API以一個僞文件系統的方式實現,即用戶能夠經過文件操做實現cgroups的組織管理。
cgroups的組織管理操做單元能夠細粒度到線程級別,用戶態代碼也能夠針對系統分配的資源建立和銷燬cgroups,從而實現資源再分配和管理。
全部資源管理的功能都以「 subsystem(子系統)」的方式實現,接口統一。
子進程建立之初與其父進程處於同一個cgroups的控制組。
五、本質:
本質上來講,cgroups是內核附加在程序上的一系列鉤子(hooks),經過程序運行時對資源的調度觸發相應的鉤子以達到資源追蹤和限制的目的。
六、cgroups術語
task(任務):cgroups的術語中,task就表示系統的一個進程。
cgroup(控制組):cgroups 中的資源控制都以cgroup爲單位實現。cgroup表示按某種資源控制標準劃分而成的任務組,包含一個或多個子系統。一個任務能夠加入某個cgroup,也能夠從某個cgroup遷移到另一個cgroup。
subsystem(子系統):cgroups中的subsystem就是一個資源調度控制器(ResourceController)。好比CPU子系統能夠控制CPU時間分配,內存子系統能夠限制cgroup內存使用量。
hierarchy(層級樹):hierarchy由一系列cgroup以一個樹狀結構排列而成,每一個hierarchy經過綁定對應的subsystem進行資源調度。hierarchy中的cgroup節點能夠包含零或多個子節點,子節點繼承父節點的屬性。整個系統能夠有多個hierarchy。
在kubernetes中,咱們能夠看看POD配置中的requests和limits參數是如何同cgroup創建關聯關係,進而實現對POD的資源QoS管理的。
QoS級別 |
QoS配置例子 |
cgroup對應 |
Guaranteed |
kind: Pod metadata: name: Pod1 spec: containers: name: foo resources: limits: cpu: 10m memory: 1Gi name: bar resources: limits: cpu: 100m memory: 2Gi |
/Pod1/cpu.quota = 110m /Pod1/cpu.shares = 110m /Pod2/cpu.quota = 20m /Pod2/cpu.shares = 20m /Pod1/memory.limit_in_bytes = 3Gi /Pod2/memory.limit_in_bytes = 2Gi |
kind: Pod metadata: name: Pod2 spec: containers: name: foo resources: limits: cpu: 20m memory: 2Gi |
||
Burstable |
kind: Pod metadata: name: Pod3 spec: containers: name: foo resources: limits: cpu: 50m memory: 2Gi requests: cpu: 20m memory: 1Gi name: bar resources: limits: cpu: 100m memory: 1Gi |
/Bu/cpu.shares = 30m /Bu/Pod3/cpu.quota = 150m /Bu/Pod3/cpu.shares = 20m /Bu/Pod4/cpu.quota = 20m /Bu/Pod4/cpu.shares = 10m /Bu/memory.limit_in_bytes = Allocatable - 5Gi /Bu/Pod3/memory.limit_in_bytes = 3Gi /Bu/Pod4/memory.limit_in_bytes = 2Gi |
|
kind: Pod metadata: name: Pod4 spec: containers: name: foo resources: limits: cpu: 20m memory: 2Gi requests: cpu: 10m memory: 1Gi |
|
BestEffort |
kind: Pod metadata: name: Pod5 spec: containers: name: foo resources: name: bar resources: |
/BE/cpu.shares = 2 /BE/cpu.quota= not set /BE/memory.limit_in_bytes = Allocatable - 7Gi /BE/Pod5/memory.limit_in_bytes = no limit |
咱們知道了cgroups裏面有hierarchy(層級樹)的概念,那麼咱們來看在kubernetes裏面是如何把POD放在hierarchy(層級樹)上面的:
對於kubernetes來講,經過cgroup就能夠給POD設置QoS級別,當資源不夠使用時,先kill優先級低的POD,在實際使用時,是經過OOM(Out of Memory)分數值來實現的,OOM分數值從0到1000。OOM分數值是根據OOM_ADJ參數計算出來的,對於Guaranteed級別的POD,OOM_ADJ參數設置成了-998,對於BestEffort級別的POD,OOM_ADJ參數設置成了1000,對於Burstable級別的POD,OOM_ADJ參數取值從2到999,對於kube保留的資源,好比kubelet,OOM_ADJ參數設置成了-999。OOM_ADJ參數設置的越大,經過OOM_ADJ參數計算出來的OOM分數越高,OOM分數越高,這個POD的優先級就越低,在出現資源競爭的時候,就越早被kill掉,對於OOM_ADJ參數是-999的表明kubernetes永遠不會由於OOM而被kill掉。以下圖所示: