1. 程式人生 > 實用技巧 >k8s中的資源管理和排程

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。並且預設開啟。