十三. k8s--調度器

k8s調度器

Scheduler調度器作爲Kubernetes三大核心組件之一, 承載着整個集羣資源的調度功能,其根據特定調度算法和策略,將Pod調度到最優工做節點上,從而更合理與充分的利用集羣計算資源。 其做用是根據特定的調度算法和策略將Pod調度到指定的計算節點(Node)上,其作爲單獨的程序運行,啓動以後會一直監聽API Server,獲取PodSpec.NodeName爲空的Pod,對每一個Pod都會建立一個綁定。
默認狀況下,k8s的調度器採用擴散策略,將同一集羣內部的pod對象調度到不一樣的Node節點,以保證資源的均衡利用。
完成調度操做的步驟:節點預選(Predicate)、節點優先級排序(Priority)、節點擇優(Select)

  1. 首先用戶經過 Kubernetes 客戶端 Kubectl 提交建立 Pod 的 Yaml 的文件,向Kubernetes 系統發起資源請求,該資源請求被提交到
  2. Kubernetes 系統中,用戶經過命令行工具 Kubectl 向 Kubernetes 集羣即 APIServer 用 的方式發送「POST」請求,即建立 Pod 的請求。
  3. APIServer 接收到請求後把建立 Pod 的信息存儲到 Etcd 中,從集羣運行那一刻起,資源調度系統 Scheduler 就會定時去監控 APIServer
  4. 經過 APIServer 獲得建立 Pod 的信息,Scheduler 採用 watch 機制,一旦 Etcd 存儲 Pod 信息成功便會當即通知APIServer,
  5. APIServer會當即把Pod建立的消息通知Scheduler,Scheduler發現 Pod 的屬性中 Dest Node 爲空時(Dest Node=」」)便會當即觸發調度流程進行調度。
  6. 而這一個建立Pod對象,在調度的過程中有3個階段:節點預選、節點優選、節點選定,從而篩選出最佳的節點
    • 節點預選:基於一系列的預選規則對每一個節點進行檢查,將那些不符合條件的節點過濾,從而完成節點的預選
    • 節點優選:對預選出的節點進行優先級排序,以便選出最合適運行Pod對象的節點
    • 節點選定:從優先級排序結果中挑選出優先級最高的節點運行Pod,當這類節點多於1個時,則進行隨機選擇
Predicates是強制性規則,用來形容主機匹配Pod所須要的資源,若是沒有任何主機知足該Predicates, 則該Pod會被掛起,直到有主機可以知足。

k8s的調用工做方式

Kubernetes調度器做爲集羣的大腦,在如何提升集羣的資源利用率、保證集羣中服務的穩定運行中也會變得愈來愈重要Kubernetes的資源分爲兩種屬性。node

  1. 可壓縮資源(例如CPU循環,Disk I/O帶寬)都是能夠被限制和被回收的,對於一個Pod來講能夠下降這些資源的使用量而不去殺掉Pod。python

  2. 不可壓縮資源(例如內存、硬盤空間)通常來講不殺掉Pod就無法回收。將來Kubernetes會加入更多資源,如網絡帶寬,存儲IOPS的支持。算法

經常使用預選策略

預選策略 做用
CheckNodeCondition 檢查是否能夠在節點報告磁盤、網絡不可用或未準備好時將Pod調度其上
HostName 若是Pod對象擁有spec.hostname屬性,則檢查節點名稱字符串是否和該屬性值匹配。
PodFitsHostPorts Pod的spec.hostPort屬性時,檢查端口是否被佔用
MatchNodeSelector Pod的spec.nodeSelector屬性時,檢查節點標籤
NoDiskConflict Pod請求的存儲卷在此節點是否可用
PodFitsResources 檢查節點上的資源(CPU、內存)可用性是否知足Pod對象的運行需求。
PodToleratesNodeTaints Pod的spec.tolerations屬性,僅關注NoSchedule和NoExecute兩個效用標識的污點
PodToleratesNodeNoExecuteTaints Pod的spec.tolerations屬性,是否能接納節點的NoExecute類型污點
CheckNodeLabelPresence 僅檢查節點上指定的全部標籤的存在性
CheckServiceAffinity 將相同Service的Pod對象放置在同一個或同一類節點上以提升效率
MaxEBSVolumeCount 檢查節點已掛載的EBS存儲卷數量是否超過設置的最大值,默認爲39
MaxGCEPDVolumeCount 檢查節點上已掛載的GCE PD 存儲卷數量是否超過最大值,默認爲16
MaxAzureDiskVolumeCount 檢查節點上已掛載的Azure Disk存儲卷數量是否超過最大值,默認爲16
CheckVolumeBinding 檢查節點上已綁定和未綁定的PVC是否知足需求
NoVolumeZoneConflict 在給定區域zone限制下,檢查此節點部署的Pod對象是否存在存儲卷衝突
CheckNodeMemoryPressure 若給定節點已報告內存資源壓力過大,檢查當前Pod是否可調度至該節點
CheckPodePIDPressure 檢查節點PID資源壓力
CheckNodeDiskPressure 檢查節點磁盤資源壓力
MatchInterPodAffinity 檢查節點是否知足Pod對象親和性或反親和性條件

經常使用優先函數

函數名稱 詳細說明
LeastRequestedPriority 節點的優先級就由節點空閒資源與節點總容量的比值,即由(總容量-節點上Pod的容量總和-新Pod的容量)/總容量)來決定。
CPU和內存具備相同權重,資源空閒比越高的節點得分越高。
cpu((capacity – sum(requested)) * 10 / capacity) + memory((capacity – sum(requested)) * 10 / capacity) / 2
BalancedResourceAllocation CPU和內存使用率越接近的節點權重越高,該策略不能單獨使用,必須和LeastRequestedPriority組合使用,儘可能選擇在部署Pod後各項資源更均衡的機器。
若是請求的資源(CPU或者內存)大於節點的capacity,那麼該節點永遠不會被調度到。
InterPodAffinityPriority 經過迭代 weightedPodAffinityTerm 的元素計算和,而且若是對該節點知足相應的PodAffinityTerm,則將 「weight」 加到和中,具備最高和的節點是最優選的。
SelectorSpreadPriority 爲了更好的容災,對同屬於一個service、replication controller或者replica的多個Pod副本,儘可能調度到多個不一樣的節點上。
若是指定了區域,調度器則會盡可能把Pod分散在不一樣區域的不一樣節點上。當一個Pod的被調度時,會先查找Pod對於的service或者replication controller,
而後查找service或replication controller中已存在的Pod,運行Pod越少的節點的得分越高。
NodeAffinityPriority 親和性機制。Node Selectors(調度時將pod限定在指定節點上),
支持多種操做符(In, NotIn, Exists, DoesNotExist, Gt, Lt),而不限於對節點labels的精確匹配。
另外支持兩種類型的選擇器,一種是「hard(requiredDuringSchedulingIgnoredDuringExecution)」選擇器,
它保證所選的主機必須知足全部Pod對主機的規則要求。
這種選擇器更像是以前的nodeselector,在nodeselector的基礎上增長了更合適的表現語法。
另外一種是「soft(preferresDuringSchedulingIgnoredDuringExecution)」選擇器,
它做爲對調度器的提示,調度器會盡可能但不保證知足NodeSelector的全部要求。
NodePreferAvoidPodsPriority(權重1W) 若是 節點的 Anotation 沒有設置 key-value:scheduler. alpha.kubernetes.io/ preferAvoidPods = "...",則節點對該 policy 的得分就是10分,
加上權重10000,那麼該node對該policy的得分至少10W分。若是Node的Anotation設置了,
scheduler.alpha.kubernetes.io/preferAvoidPods = "..." ,若是該 pod 對應的 Controller 是 ReplicationController 或 ReplicaSet,
則該 node 對該 policy 的得分就是0分。
TaintTolerationPriority 使用 Pod 中 tolerationList 與 節點 Taint 進行匹配,配對成功的項越多,則得分越低。
ImageLocalityPriority 根據Node上是否存在一個pod的容器運行所需鏡像大小對優先級打分,分值爲0-10。遍歷所有Node,
若是某個Node上pod容器所需的鏡像一個都不存在,分值爲0;
若是Node上存在Pod容器部分所需鏡像,則根據這些鏡像的大小來決定分值,鏡像越大,分值就越高;若是Node上存在pod所需所有鏡像,分值爲10。
EqualPriority 是一個優先級函數,它給予全部節點相等權重。
MostRequestedPriority 在 ClusterAutoscalerProvider 中,替換 LeastRequestedPriority,給使用多資源的節點,更高的優先級。
計算公式爲:
(cpu(10 sum(requested) / capacity) + memory(10 sum(requested) / capacity)) / 2

節點親和調度

節點親和性規則:硬親和性 required 、軟親和性 preferred。centos

  • 硬親和性規則不知足時,Pod會置於Pending狀態,軟親和性規則不知足時,會選擇一個不匹配的節點
  • 當節點標籤改變而再也不符合此節點親和性規則時,不會將Pod從該節點移出,僅對新建的Pod對象生效

節點硬親和性

  • 方式一:Pod使用 spec.nodeSelector (基於等值關係)
  • 方式二:Pod使用 spec.affinity 支持matchExpressions屬性 (複雜標籤選擇機制)
# 調度至 zone = foo 的節點
kubectl label nodes kube-node1 zone=foo
apiVersion: v1
kind: Pod
metadata:
  name: with-required-nodeaffinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:  # 定義硬親和性
        nodeSelectorTerms:
        - matchExpressions:
          - {key: zone,operator: In,values: ["foo"]}
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
可有多個nodeSelectorTerms,相互間爲邏輯或關係
同個nodeSelectorTerms下可有多個matchExpressions,各matchExpressions間爲邏輯與關係
同個matchExpressions下可有多條標籤選擇規則,相互間爲邏輯與關係
節點親和性僅是節點預選策略中的一項,其餘預選策略依然生效

節點軟親和性

  • 柔性控制邏輯,當條件不知足時,能接受被編排於其餘不符合條件的節點之上
  • 權重 weight 定義優先級,1-100 值越大優先級越高
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy-with-node-affinity
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      name: myapp-pod
      labels:
        app: myapp
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 60
            preference:
              matchExpressions:
              - {key: zone, operator: In, values: ["foo"]}
          - weight: 30
            preference:
              matchExpressions:
              - {key: ssd, operator: Exists, values: []}
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1

Pod資源親和調度

  • Pod對象間親和性,將一些Pod對象組織在相近的位置(同一節點、機架、區域、地區)
  • Pod對象間反親和性,將一些Pod在運行位置上隔開

調度器將第一個Pod放置於任何位置,而後與其有親和或反親和關係的Pod據此動態完成位置編排
# 基於MatchInterPodAffinity預選策略完成節點預選,基於InterPodAffinityPriority優選函數進行各節點的優選級評估api

位置拓撲,定義"同一位置"tomcat

Pod硬親和調度

Pod親和性描述一個Pod與具備某特徵的現存Pod運行位置的依賴關係;即須要事先存在被依賴的Pod對象網絡

# 被依賴Pod
kubectl run tomcat -l app=tomcat --image tomcat:alpine
kubectl explain pod.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.topologyKey
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:  # 硬親和調度
      - labelSelector:
          matchExpressions:
          - {key: app, operator: In, values: ["tomcat"]}  # 選擇被依賴Pod
        topologyKey: kubernetes.io/hostname  # 根據挑選出的Pod全部節點的hostname做爲同一位置的斷定
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
調度器先基於標籤選擇器查詢擁有匹配標籤的全部被依賴Pod,再獲取它們所屬節點的topologyKey指示的屬性的標籤值,再查詢全部擁有匹配這些標籤值的全部節點,從而完成節點預選,再根據優選函數計算節點優先級,挑選出運行新建Pod的節點
若節點標籤在運行時發生更改,再也不知足Pod親和性規則時,該Pod會繼續運行;即僅對親建的Pod生效

Pod軟親和調度

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-with-preferred-pod-affinity
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      name: myapp
      labels:
        app: myapp
    spec:
      affinity:
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 80
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - {key: app, operator: In, values: ["cache"]}
              topologyKey: zone
          - weight: 20
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - {key: app, operator: In, values: ["db"]}
              topologyKey: zone
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1

Pod反親和調度

Pod反親和調度用於分散同一類應用,調度至不一樣的區域、機架或節點等
spec.affinity.podAffinity替換爲 spec.affinity.podAntiAffinityapp

反親和調度也分爲柔性約束和強制約束ide

apiVersion: v1
kind: Pod
metadata:
    name: pod-first
    labels: 
        app: myapp
        tier: fronted
spec:
    containers:
    - name: myapp
      image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
    name: pod-second
    labels:
        app: backend
        tier: db
spec:
    containers:
    - name: busybox
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh", "-c", "sleep 3600"]
    affinity:
      podAntiAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
            - {key: app, operator: In, values: ["myapp"]}
          topologyKey: zone

污點和容忍度

污點 taints 是定義在節點上的鍵值型屬性數據,用於讓節點拒絕將Pod調度運行於其上,除非Pod有接納節點污點的容忍度容忍度 tolerations 是定義在Pod上的鍵值屬性數據,用於配置可容忍的污點,且調度器將Pod調度至其能容忍該節點污點的節點上或沒有污點的節點上

使用PodToleratesNodeTaints預選策略和TaintTolerationPriority優選函數完成該機制

  • 節點親和性使得Pod對象被吸引到一類特定的節點 (nodeSelector和affinity)
  • 污點提供讓節點排斥特定Pod對象的能力

定義污點和容忍度

污點定義於nodes.spec.taints容忍度定義於pods.spec.tolerations
語法: key=value:effect

effect定義排斥等級:

  • NoSchedule,不能容忍,節點現存Pod不受影響
  • PreferNoSchedule,柔性約束,節點現存Pod不受影響
  • NoExecute,不能容忍,當污點變更時,Pod對象會被驅逐

在Pod上定義容忍度時:

  1. 等值比較 容忍度與污點在key、value、effect三者徹底匹配
  2. 存在性判斷 key、effect徹底匹配,value使用空值

一個節點可配置多個污點,一個Pod也可有多個容忍度

管理節點的污點

同一個鍵值數據,effect不一樣,也屬於不一樣的污點

添加污點:

kubectl taint node <node-name> <key>=<value>:<effect>

查看污點:

kubectl get nodes <nodename> -o go-template={{.spec.taints}}

刪除污點:

kubectl taint node <node-name> <key>[:<effect>]-
kubectl patch nodes <node-name> -p '{"spec":{"taints":[]}}'

kubectl taint node kube-node1 node-type=production:NoSchedule
kubectl get nodes kube-node1 -o go-template={{.spec.taints}}
# 刪除key爲node-type,effect爲NoSchedule的污點
kubectl taint node kube-node1 node-type:NoSchedule-

# 刪除key爲node-type的全部污點
kubectl taint node kube-node1 node-type-

# 刪除全部污點
kubectl patch nodes kube-node1 -p '{"spec":{"taints":[]}}'

Pod對象容忍度

spec.tolerations字段添加
tolerationSeconds用於定義延遲驅逐Pod的時長

# 等值判斷
tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600
 
# 存在性判斷
tolerations:
- key: "key1"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 3600
上面兩個例子表示若是某個Node存在key1=value1的污點或者存在key1的污點,Pod將不會調度到這樣的節點。
apiVersion: v1
kind: Deployment
metadata:
    name: myapp-deploy
    namespace: default
spec:
    replicas: 3
    selector:
        matchLabels:
            app: myapp
            release: canary
    template:
        metadata:
            labels:
                app: myapp
                release: canary
        spec:
            containers:
            - name: myapp
            image: ikubernetes/myapp:v1
            ports:
            - name: http
              containerPort: 80
            tolerations:
            - key: "node-type"
              operator: "Equal"
              value: "production":
              effect: "NoExecute"
              tolerationSeconds: 3600

問題節點標識

自動爲節點添加污點信息,使用NoExecute效用標識,會驅逐現有Pod
K8s核心組件一般都容忍此類污點

node.kubernetes.io/not-ready 節點進入NotReady狀態時自動添加
node.alpha.kubernetes.io/unreachable 節點進入NotReachable狀態時自動添加
node.kubernetes.io/out-of-disk 節點進入OutOfDisk狀態時自動添加
node.kubernetes.io/memory-pressure 節點內存資源面臨壓力
node.kubernetes.io/disk-pressure 節點磁盤面臨壓力
node.kubernetes.io/network-unavailable 節點網絡不可用
node.cloudprovider.kubernetes.io/uninitialized kubelet由外部雲環境程序啓動時,自動添加,待到去控制器初始化此節點時再將其刪除

Pod優選級和搶佔式調度

優選級,Pod對象的重要程度
優選級會影響節點上Pod的調度順序和驅逐次序
一個Pod對象沒法被調度時,調度器會嘗試搶佔(驅逐)較低優先級的Pod對象,以即可以調度當前Pod

Pod優選級和搶佔機制默認處於禁用狀態
啓用:同時爲kube-apiserver、kube-scheduler、kubelet程序的 --feature-gates 添加 PodPriority=true
使用:
事先建立優先級類別,並在建立Pod資源時經過 priorityClassName屬性指定所屬的優選級類別

參考連接

https://pdf.us/2019/04/08/3222.html

https://www.cnblogs.com/centos-python/articles/10884738.html

相關文章
相關標籤/搜索