kubernetes的調度機制

k8s的調度機制

scheduler組件

k8s調度器會將pod調度到資源知足要求而且評分最高的node上。咱們可使用多種規則好比:1.設置cpu、內存的使用要求;2.增長node的label,並經過pod.Spec.NodeSelector進行強匹配;3.直接設置pod的nodeName,跳過調度直接下發。node

k8s 1.2加入了一個實驗性的功能:affinity。意爲親和性。這個特性的設計初衷是爲了替代nodeSelector,並擴展更強大的調度策略。nginx

調度器的工做機制是這樣的:
1、預備工做
一、緩存全部的node節點,記錄他們的規格:cpu、內存、磁盤空間、gpu顯卡數等;
二、緩存全部運行中的pod,按照pod所在的node進行區分,統計每一個node上的pod request了多少資源。request是pod的QoS配置,能夠參考以前的文章
三、list & watch pod資源,當檢查到有新的Pending狀態的pod出現,就將它加入到調度隊列中。
四、調度器的worker組件從隊列中取出pod進行調度。算法

2、調度過程
一、先將當前全部的node放入隊列;
二、執行predicates算法,對隊列中的node進行篩選。這裏算法檢查了一些pod運行的必要條件,包括port不衝突、cpu和內存資源QoS(若是有的話)必須知足、掛載volume(若是有的話)類型必須匹配、nodeSelector規則必須匹配、硬性的affinity規則(下文會提到)必須匹配、node的狀態(condition)必須正常,taint_toleration硬規則(下文會提到)等等。
二、執行priorities算法,對隊列中剩餘的node進行評分,這裏有許多評分項,各個項目有各自的權重:總體cpu,內存資源的平衡性、node上是否有存在要求的鏡像、同rs的pod是否有調度、node affinity的軟規則、taint_toleration軟規則(下文會提到)等等。
三、最終評分最高的node會被選出。即代碼中suggestedHost, err := sched.schedule(pod)一句(plugin/pkg/scheduler/scheduler.go)的返回值。
四、調度器執行assume方法,該方法在pod調度到node以前,就以「該pod運行在目標node上」 爲場景更新調度器緩存中的node 信息,也即預備工做中的一、2兩點。這麼作是爲了讓pod在真正調度到node上時,調度器也能夠同時作後續其餘pod的調度工做。
五、調度器執行bind方法,該方法建立一個Binding資源,apiserver檢查到建立該資源時,會主動更新pod的nodeName字段。完成調度。segmentfault

nodeSelector

舉例:api

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd

上面這個pod會且僅會被調度到帶有disktype: ssd這個label的node上。這是一種強規則,沒有妥協,必須遵照。緩存

affinity 和 anti-affinity

  • 有親和性規則,那麼反親和性規則確定也要有。
  • 親和性規則實現了更豐富的規則表達方式。而且包含了nodeSelector的硬規則和另外一種軟規則。
  • 軟規則是一種優先規則,若是沒有符合這個優先規則的節點,它仍然會被進行調度。

node親和性

node親和性和nodeSelector相似,經過label進行可調度node的過濾,如今有兩種node親和性:requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecutiondom

requiredDuringSchedulingIgnoredDuringExecution

強規則。和nodeSelector徹底相同,以label進行強制的約束。須要指出的是:目前,若是一個node在運行時label發生了變化,變化後和其上運行的pod的requiredDuringSchedulingIgnoredDuringExecution 再也不匹配,這個node上的pod也不會被驅逐,這個功能會在之後被改進,屆時會增長一種類型RequiredDuringSchedulingRequiredDuringExecution ui

preferredDuringSchedulingIgnoredDuringExecution

軟規則。舉例來講:咱們要將某個容器儘量地調度到可用域X中,但若是不存在這個可用域或者可用域沒法再運行pod,調度器也容許這個pod被調度到其餘可用域。google

如下是一個包含了強規則和軟規則的案例:spa

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/e2e-az-name
            operator: In
            values:
            - e2e-az1
            - e2e-az2
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: gcr.io/google_containers/pause:2.0

該案例代表,這個pod只容許被調度到帶有kubernetes.io/e2e-az-name=e2e-az1或e2e-az2的label的node上,也即只容許被調度到e2e-az1或者e2e-az2兩個可用域中;另外,pod要儘可能調度到包含another-node-label-key的值爲another-node-label-value的node上。

matchExpressions結構記錄各類表達式,一個表達式包含key,operator,values,分別表示關鍵字、關鍵字匹配關係、關鍵字匹配值。匹配關係包括:In,NotIn,Exists,DoesNotExist,Gt,LtNotInDoesNotExist是node anti-affinity的一種表現。

若是一個pod的描述信息中同時包含了nodeSelectornodeAffinity,那麼調度時兩個規則都要知足。

若是一個nodeAffinity中包含了多條nodeSelectorTerms, 調度器只須要知足其中一條; 若是一個 nodeSelectorTerms中記錄了多條matchExpressions,那麼調度器要知足全部的matchExpressions

inter-pod affinity 和 anti-affinity

這兩個特性都包含在1.4版本中,上面的親和性是node親和性,這個就是pod親和性,簡而言之,要把pod調度到某個node上,這個node上已有的pod能知足、或儘可能知足某些條件。這個特性用pod.spec.affinity.podAffinitypod.spec.affinity.podAntiAffinity來表示。

pod親和性的規則能夠這麼表示:
這個pod應該(或者不該該)運行在節點X上,X上必須已經運行了一個或多個知足規則Y的pod。規則Y的表達方式相似於一個labelSelector並關聯了一個namespace列表:namespaces(若沒有則表示「allnamespaces」),X多是node或一個az,咱們經過字段topologyKey來規劃X,即全部的X都要知足topologyKey相同,通常topologyKey是一個label的key。

爲何要有namespace列表?由於和node不一樣,pod是有分namespace的,所以pod的label也是有分namespace的。在這種狀況下,規則Y必需要指明本身這個規則要適用於哪些namespace。好比node上運行的是hy這個namespace下的pod,即使pod的label和規則Y的nodeSelector都相同,咱們也視爲不符合規則。

和node親和性同樣,pod親和性也包含兩個(硬規則和軟規則):

  • requiredDuringSchedulingIgnoredDuringExecution: 硬規則。
  • preferredDuringSchedulingIgnoredDuringExecution

舉個例子:

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: failure-domain.beta.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: gcr.io/google_containers/pause:2.0

上面的pod模板使用了podAffinity的硬規則和podAntiAffinity的軟規則。

  • podAffinity規則中topologyKey是zone,也就是可用域,說明這條規則能夠規劃處調度到的域,首先,node上必須至少有一個running狀態的pod包含key爲security,value爲S1的label。只要知足這個條件,那麼這個node和其同一個域(擁有相同的failure-domain.beta.kubernetes.io/zone 爲key,且值相同的label)的node均會被調度。
  • podAntiAffinity規則中topologyKey是hostname,代表該規則約定了某種node儘可能不會被調度到,這種node上已經運行了包含key爲security,value爲S2的label的pod。
  • 假如如今有node a,b,c,其中a和b擁有相同的zone,且b上運行了一個pod,這個pod有一個label,key爲security,value爲S1。那麼咱們建立如上的一個親和性規則的3副本時,三個副本都會被調度到a或者b上。假如b上同時運行了一個pod,這個pod有一個label,key爲security,value爲S2,那麼全部的副本都會調度到node a上。

taint toleration

node 能夠被打上污點標記,並配置污點容忍策略。而pod的描述信息中若是包含了相同的污點容忍策略,就能夠被調度到這個node上,反之則不可、或儘可能不容許。

硬性規則

給node a 打上污點 name=huang, 策略爲不可調度:
kubectl taint nodes a name=huang:NoSchedule
若我建立的pod中包含以下描述:

tolerations:
- key: "name"
  operator: "Equal"
  value: "huang"
  effect: "NoSchedule"

則這個pod能夠容忍有這類污點的node,便可以調度到node a,固然,也能夠用以下的描述:

tolerations:
- key: "name"
  operator: "Exist"
  effect: "NoSchedule"

相似的硬性規則體如今effect字段中,還有NoExecute,它比NoSchedule更嚴格,不止pod不能調度上去,node上原有的pod若是不能容忍污點,就會被驅逐(eviction),配合字段tolerationSeconds能夠規定這些會被驅逐的pod能在node上呆多久。

軟規則

除了NoExecuteNoSchedule,還有一條軟規則:PreferNoSchedule.配置effect=PreferNoSchedule後,沒有相關污點策略的pod會儘可能避免調度到該node上。

相關文章
相關標籤/搜索