9. 老闆2年不加薪,我用篇文章加了2K

全棧小劉發表於2020-10-22

1.1 排程器簡介

SchedulerKubernetes的排程器,主要的任務是把定義的 pod分配到叢集的節點上,需要考慮以下問題:

  • 公平:如何保證每個節點都能被分配資源
  • 資源高效利用:叢集所有資源最大化被使用
  • 效率:排程的效能要好,能夠儘快地對大批量的 pod完成排程工作
  • 靈活:允許使用者根據自己的需求控制排程的邏輯

Scheduler是作為單獨的程式執行的,啟動之後會一直連線 apiserver獲取 PodSpec.NodeName為空的 pod,對每個 pod都會建立一個 binding,表明該 pod應該放到哪個節點上。

1.2 排程過程

排程分為幾個部分:

Predicate有一系列的演算法可以使用:

  • PodFitsResources:節點上剩餘的資源是否大於 pod請求的資源
  • PodFitsHost:如果 pod指定了 NodeName,檢查節點名稱是否和 NodeName匹配
  • PodFitsHostPorts:節點上已經使用的 port是否和 pod申請的 port衝突
  • PodSelectorMatches:過濾掉和 pod指定的 label不匹配的節點
  • NoDiskConflict:已經 mountvolumepod指定的 volume不衝突,除非它們都是隻讀

如果在 predicate過程中沒有合適的節點, pod會一直在 pending狀態(等待),不斷重試排程,直到有節點滿足條件。

經過這個步驟,如果有多個節點滿足條件,就繼續 priorities過程:按照優先順序大小對節點排序。優先順序由一系列鍵值對組成,鍵是該優先順序項的名稱,值是它的權重,這些優先順序選項包括:

  • LeastRequestedPriority:通過計算 CPUMemory的使用率來決定權重,使用率越低權重越高。換句話說,這個優先順序指標傾向於資源使用比例更低的節點
  • BalancedResourceAllocation:節點上 CPUMemory使用率越接近,權重越高。這個應該和上面的一起使用,不應該單獨使用
  • ImageLocalityPriority:傾向於已經有要使用映象的節點,映象總大小值越大,權重越高

通過演算法對所有的優先順序專案和權重進行計算,得出最終的結果。

1.3 自定義排程器

除了 K8S自帶的排程器,可以自定義排程器。通過 spec:schedulername引數指定排程器的名字,可以為 pod選擇某個排程器進行排程。比如下面的 pod選擇 my-scheduler進行排程,而不是預設的 default-scheduler

apiVersion: v1
kind: Pod
metadata:
  name: annotation-second-scheduler
  labels:
    name: multischeduler-example
spec:
  schedulername: my-scheduler
  containers:
 - name: pod-with-second-annotation-container
    image: gcr.io/google_containers/pause:2.0

2.1 Node 親和性

spec.affinity.nodeAffinity

  • preferredDuringSchedulingIgnoredDuringExecution(優先執行計劃):軟策略
  • requiredDuringSchedulingIgnoredDuringExecution(要求執行計劃):硬策略

鍵值運算關係:

鍵說明Inlabel 的值在某個列表中NotInlabel 的值不在某個列表中Gtlabel 的值大於某個值Ltlabel 的值小於某個值Exists某個 label 存在DoesNotExist某個 label 不存在

軟策略:

[root@master schedule]
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: hub.hc.com/library/myapp:v1
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - worker3
[root@master schedule]
NAME                      READY   STATUS    RESTARTS   AGE   IP            NODE      NOMINATED NODE   READINESS GATES
affinity                 1/1     Running   0          39s   10.244.2.92   worker2   <none>           <none>

硬策略:

[root@master schedule]
apiVersion: v1
kind: Pod
metadata:
  name: affinity2
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: hub.hc.com/library/myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - worker3

[root@master schedule]
NAME                      READY   STATUS    RESTARTS   AGE   IP            NODE      NOMINATED NODE   READINESS GATES
affinity2                  0/1     Pending   0          23s   <none>        <none>    <none>           <none>

[root@master schedule]
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  49s   default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.

2.2 Pod 親和性

spec.affinity.podAffinity/podAntiAffinity

  • preferredDuringSchedulingIgnoredDuringExecution(優先執行計劃):軟策略
  • requiredDuringSchedulingIgnoredDuringExecution(要求執行計劃):硬策略
[root@master schedule]
apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  labels:
    app: pod-2
spec:
  containers:
  - name: pod-2
    image: hub.hc.com/library/myapp:v1
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - pod-1
        topologyKey: kubernetes.io/hostname
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - pod-2
          topologyKey: kubernetes.io/hostname

[root@master schedule]
pod-2                     0/1     Pending   0          4s      <none>        <none>    <none>           <none>

[root@master schedule]
NAME                      READY   STATUS    RESTARTS   AGE     IP            NODE      NOMINATED NODE   READINESS GATES
pod-1                     1/1     Running   0          5s      10.244.2.94   worker2   <none>           <none>

親和性/反親和性排程策略比較如下:

排程策略匹配標籤操作符拓撲域支援排程目標nodeAffinity主機In, NotIn, Exists,DoesNotExist, Gt, Lt否指定主機podAffinityPODIn, NotIn, Exists,DoesNotExist是POD與指定POD同一拓撲域podAnitAffinityPODIn, NotIn, Exists,DoesNotExist是POD與指定POD不在同一拓撲域

2.3 Taint 和 Toleration

節點親和性,是 pod的一種屬性(偏好或硬性要求),它使 pod被吸引到一類特定的節點。 Taint則相反,它使節點能夠排斥一類特定的 pod

Tainttoleration相互配合,可以用來避免 pod被分配到不合適的節點上。每個節點上都可以應用一個或多個 taint,這表示對於那些不能容忍這些 taintpod,是不會被該節點接受的。如果將 toleration應用於 pod上,則表示這些 pod可以(但不要求)被排程到具有匹配 taint的節點上。

①汙點 (Taint) 的組成

使用 kubectl taint命令可以給某個 Node節點設定汙點, Node被設定上汙點之後就和 Pod之間存在了一種相斥的關係,可以讓 Node拒絕 Pod的排程執行,甚至將 Node已經存在的 Pod驅逐出去每個汙點的組成如下: key=value:effect

每個汙點有一個 keyvalue作為汙點的標籤,其中 value可以為空, effect描述汙點的作用。當前 taint effect支援如下三個選項:

  • NoScheduleK8S將不會將 Pod排程到具有該汙點的 Node
  • PreferNoScheduleK8S將盡量避免將 Pod排程到具有該汙點的 Node
  • NoExecuteK8S將不會將 Pod排程到具有該汙點的 Node上,同時會將 Node上已經存在的 Pod驅逐出去

② 汙點的設定、檢視和去除


kubectl describe node node-name

kubectl taint nodes node1 key1=value1:effect

kubectl taint nodes node1 key1=value1:effect

設定了汙點的 Node將根據 tainteffectPod之間產生互斥的關係, Pod將在一定程度上不會被排程到 Node上。但我們可以在 Pod上設定容忍 (Toleration) ,設定了容忍的 Pod將可以容忍汙點的存在,可以被排程到存在汙點的 Node上。

** toleration 的配置:**

spec:
  tolerations:
    - key: "key1"
      operator: "Equal"
      value: "value1"
      effect: "NoSchedule"
      tolerationSeconds: 3600
    - key: "key1"
      operator: "Equal"
      value: "value1"
      effect: "NoExecute"
    - key: "key2"
      operator: "Exists"
      effect: "NoSchedule"

說明:

  • 其中 keyvauleeffect要與 Node上設定的 taint保持一致
  • operator的值為 Exists將會忽略 value
  • tolerationSeconds:當 Pod需要被驅逐時可以在 Pod上繼續保留執行的時間

① 當不指定 key值時,表示容忍所有的汙點 key

tolerations:
 - operator: "Exists"

② 當不指定 effect值時,表示容忍所有的汙點作用

tolerations:
 - key: "key"
operator: "Exists"

③ 有多個 Master存在時,防止資源浪費,可以如下設定

kubectl taint nodes Node-Name node-role.kubernetes.io/master=:PreferNoSchedule

2.4 指定排程節點

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: myweb
spec:
  replicas: 7
  template:
    metadata:
      labels:
        app: myweb
    spec:
      nodeName: worker1
      nodeSelector:
	    type: theSelected
      containers:
      - name: myweb
        image: hub.hc.com/library/myapp:v1
        ports:
        - containerPort: 80

說明:

  • spec.nodeName:將 Pod直接排程到指定的 Node節點上,會跳過 Scheduler的排程策略,該匹配規則是強制匹配
  • spec.nodeSelector:通過 K8Slabel-selector機制選擇節點,由排程器排程策略匹配 label,而後排程 Pod到目標節點,該匹配規則屬於強制約束
  • Node打標籤: kubect; label node worker1 type=theSelected

相關文章