k8s中的資源管理和調度


k8s中的Resource,目前支持類型:
  • cpu,單位為Core(此處1 Core實際指一個Hyperthread),1 millicore=0.001Core
  • memory,單位Byte
  • storage
  • ephemeral-storage:容器日志、emptyDir、可寫入的容器鏡像層
  • hugepages-<size>:目前屬於Pod級別的資源
  • 自定義資源(如GPU):配置時,指定的數量必須為整數。
目前資源配置主要分成request(需要的數量)和limit(資源的界限)兩種類型。
調度Pod時,調度器只會使用request進行調度(同時會考慮kubelet的--max-pods參數,默認110)
臨時存儲功能(默認不啟動)啟動后Pod掛載的emptyDir不能超過sizeLimit、Container對本地臨時存儲的使用量不能超過其Limit、Pod對本地臨時存儲的使用量不能超過所有Container的Limit之和,否則會被驅逐
巨頁的request必須等於limit,多尺寸的巨頁默認不支持。
自定義資源的request必須等於limit。
 
Pod服務質量(Qos)配置
根據CPU、內存資源的需求,對Pod的服務質量進行分類:
  • Guaranteed:Pod中每個容器都有CPU、內存的request以及limit聲明,且request=limit
  • Burstable:CPU、內存的request≠limit,或者只填寫了其中一種資源
  • BestEffort:沒有任何request和limit
當節點上配額資源不足,kubelet會把一些低優先級的,或者說服務質量要求不高的Pod驅逐掉(先BestEffort再Burstable)。
 
CPU是按request來划分權重的,服務質量要求不高的Pod,request可以填很小的數字或者不填,Pod的權重就會非常低。
kubelet的參數cpu-manager-policy=static時,如果Guaranteed Qos的Pod的CPU的request是整數,會進行綁核;CPU的request不是整數的Guaranteed/Burstable/BestEffort,它們要用的CPU會組成一個CPU share pool,根據不同的權重划分時間片。
 
memory上也會按照不同的Qos划分OOMScore。物理機出現OOM時會優先kill掉OOMScore得分高的Pod。
    Guaranteed:會配置默認的-998的OOMScore;
    Burstable:會根據內存設計的大小和節點的關系(申請資源越多得分越低)來分配 2~999的OOMScore;
    BestEffort:會固定分配1000的OOMScore
 
調度配置
(1)Pod進行Node選擇
在Pod的sepc中指定:
  nodeSelector: <object>
(2)workload進行Node選擇
在workload的spec中通過matchLabels來篩選出一批Pod;通過matchExpressions來決定這批Pod的調度。
  selector:  
    matchLabels: <object>
    matchExpressions: <object>
(3)Node禁止調度
在Node的sepc中指定:
  unschedulable: true
(3)Pod的拓撲調度
在Pod的spec中描述這一組Pod在某個topologyKey上的分布
如果定義了多個,則是並列關系。比如說可以在一個zone級別上,也可以在一個Node級別上。
  topologySpreadConstraints:
    - maxSkew: <integer>
      topologyKey: <string>
      whenUnsatisfiable: <string>
      labelSelector: <object>
topologyKey為zone時,Pod將在zone間均勻分布。沒有key為zone的Node將被忽略(位於這些Node上的Pod不會被計算,新Pod也不會啟動到這些Node上)
maxSkew是最大允許不均衡的數量。如果設置為1,那么Pod將在所有zone間完全均勻分布。
舉例:
假設集群中有三個zone,某個部署的Pod在zone1和zone2中都分配了一個Pod。
計算不均衡數量公式為:Skew = count[topo] - min(count[topo]),由此可以算出三個zone的Skew分別是1、1、0。
如果新Pod分配到zone1/zone2,zone1/zone2的skew將變為2,大於設置的maxSkew=1;如果分配到zone3的話,zone1-zone3的Skew均為0。因此新Pod只能分配到zone3
假設maxSkew為2,如果新Pod分配到zone1/zone2,skew 的值為2 <=maxSkew。因此zone1-zone3都是允許的。
在不均衡的情況下可以設置whenUnsatisfiable:在過濾階段一般設置為DoNotSchedule(不允許被調度),也可以設置為ScheduleAnyway(隨便調度)
 
在kube-scheduler配置文件的profile中可以設置默認的PodTopologySpread:
apiVersion: kubescheduler.config.k8s.io/v1beta1
kind: KubeSchedulerConfiguration
profiles:
  pluginConfig:
    - name: PodTopologySpread
      args:
        defaultConstraints:
          - maxSkew: 1
            topologyKey: topology.kubernetes.io/zone
            whenUnsatisfiable: ScheduleAnyway
Pod沒有配置PodTopologySpread時會自動使用此配置。
配置中沒有labelSelector,會根據service、rs等自動計算。因此Pod必須屬於某個資源對象。
開啟此默認配置時,最好禁用scheduler framework中的SelectorSpread插件。
此時scheduler framework中的PodTopologySpread會使用如下默認配置:
  defaultConstraints:
    - maxSkew: 3
      topologyKey: "kubernetes.io/hostname"
      whenUnsatisfiable: ScheduleAnyway
    - maxSkew: 5
      topologyKey: "topology.kubernetes.io/zone"
      whenUnsatisfiable: ScheduleAnyway

 

(4)Pod親和調度和反親和調度
Exists范圍比In更大。當Operator填了Exists,就不需要再填寫values,會直接禁止調度到帶該key標簽的Pod的節點。即,不管 values是什么值,只要帶了k1這個key標簽的Pod所在節點,都不能調度過去。
 
優先調度和優先反調度時,preferred里面可以是一個list選擇填上多個條件,每對key: kalue有不同的權重。調度器會優先把Pod分配到權重分更高的調度條件節點上去。
 
(5)Node親和調度
NodeSelector其實是一個map結構,在pod的spec.nodeSelector里面直接寫上對node標簽key:value的要求即可。
NodeAffinity的Operator上提供了比 PodAffinity的Operator更豐富的內容。增加了Gt和Lt(數值比較,values只能填數字)。
 
(6)Node標記/容忍
例如上圖綠色部分,給demo-node打了taint后,效果是:新建的Pod沒有專門容忍這個taint,那就沒法調度到這個節點上。
除非如上圖藍色部分,在Pod上打一個key、value、effect完全相同的Pod Tolerations。
 
該特性目前已變為taints:使用cordon命令將節點標記為不可調度,使用drain命令將已經在節點上運行的pod驅逐到其他節點;uncordon命令解鎖節點,使其重新變得可調度
 
(7)優先級搶占調度
比如有一個Node的CPU已經被一個Pod占用了。另一個高優先級Pod來的時候,低優先級的Pod應該把CPU讓給高優先級的Pod使用。低優先級的Pod需要回到等待隊列,或者是業務重新提交。
Kubernetes v1.14后,優先級(PodPriority)和搶占(Preemption)的特點變成了stable。並且默認開啟。

參考資料:

[1] https://kubernetes.io/docs/home/

[2] https://edu.aliyun.com/roadmap/cloudnative

[3] 鄭東旭《Kubernetes源碼剖析》

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM