【k8s】——NodeSelector/Taints/Affinity 使用說明

一、前言

     1、 NodeSelector:如果需要限制Pod到指定的Node上運行,則可以給Node打標籤並給Pod配置NodeSelector。

      2、NodeAffinity節點親和性,是Pod上定義的一種屬性,使Pod能夠按我們的要求調度到某個Node上,而Taints則恰恰相反,它可以讓Node拒絕運行Pod,甚至驅逐Pod。Taints(污點)是Node的一個屬性,設置了Taints(污點)後,因爲有了污點,所以Kubernetes是不會將Pod調度到這個Node上的,於是Kubernetes就給Pod設置了個屬性Tolerations(容忍),只要Pod能夠容忍Node上的污點,那麼Kubernetes就會忽略Node上的污點,就能夠(不是必須)把Pod調度過去。因此 Taints(污點)通常與Tolerations(容忍)配合使用。Taints 和 tolerations 用於保證 Pod 不被調度到不合適的 Node 上,Taint應用於Node上,而toleration則應用於Pod上(Toleration是可選的)

     3、 Affinity 翻譯成中文是“親和性”,它對應的是 Anti-Affinity,我們翻譯成“互斥”。這兩個詞比較形象,可以把 pod 選擇 node 的過程類比成磁鐵的吸引和互斥,不同的是除了簡單的正負極之外,pod 和 node 的吸引和互斥是可以靈活配置的。

二、NodeSelector

2.1 給節點打標籤

# get node的name
$ kubectl get nodes

# 設置Label
$ kubectl label nodes <node-name> <label-key>=<label-value>
# 例如
$ kubectl label nodes node1 disktype=ssd

# 查看Node的Label
$ kubectl get nodes --show-labels

# 刪除Node的label
$ kubectl label node <node-name> <label-key>-

2.2 給Pod設置NodeSelector

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd    # 對應Node的Label

三、Taint

3.1 實驗環境

      實驗環境是三節點的集羣,採用kubeadm部署,部署請參考我的另一篇文章

3.2 實驗流程

1、給節點打上污點

node打上污點(可以想象成一個標籤),pod如果不定義容忍這個污點,那麼pod就不會被調度器分配到這個node

匹配規則:

一個 toleration 和一個 taint 相“匹配”是指它們有一樣的 key 和 effect ,並且:

如果 operator 是 Exists (此時 toleration 不能指定 value

如果 operator 是 Equal ,則它們的 value 應該相等

特殊情況:

如果一個 toleration 的 key 爲空且 operator 爲 Exists ,表示這個 toleration 與任意的 key 、 value 和 effect 都匹配,即這個 toleration 能容忍任意 taint。

  • tolerations:
  • - operator: "Exists"

如果一個 toleration 的 effect 爲空,則 key 值與之相同的相匹配 taint 的 effect 可以是任意值。

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

一個節點可以設置多個taint,一個pod也可以設置多個toleration。Kubernetes 處理多個 taint 和 toleration 的過程就像一個過濾器:從一個節點的所有 taint 開始遍歷,過濾掉那些 pod 中存在與之相匹配的 toleration 的 taint。餘下未被過濾的 taint 的 effect 值決定了 pod 是否會被分配到該節點,特別是以下情況:

  • 如果未被過濾的 taint 中存在一個以上 effect 值爲 NoSchedule 的 taint,則 Kubernetes 不會將 pod 分配到該節點。
  • 如果未被過濾的 taint 中不存在 effect 值爲 NoSchedule 的 taint,但是存在 effect 值爲 PreferNoSchedule 的 taint,則 Kubernetes 會嘗試將 pod 分配到該節點。
  • 如果未被過濾的 taint 中存在一個以上 effect 值爲 NoExecute 的 taint,則 Kubernetes 不會將 pod 分配到該節點(如果 pod 還未在節點上運行),或者將 pod 從該節點驅逐(如果 pod 已經在節點上運行)。

目前支持的 taint 類型(也被稱爲effect):

NoSchedule:K8S的node添加這個effect類型污點,新的不能容忍的pod不能再調度過來,但是老的運行在node上不受影響

NoExecute:K8S的node添加這個effect類型污點,新的不能容忍的pod不能調度過來,老的pod也會被驅逐

PreferNoSchedule:儘量不要調度到該節點,但pod會嘗試將pod分配到該節點

effect 值 NoExecute ,它會影響已經在節點上運行的 pod,即根據策略對Pod進行驅逐。

  • 如果 pod 不能忍受effect 值爲 NoExecute 的 taint,那麼 pod 將馬上被驅逐
  • 如果 pod 能夠忍受effect 值爲 NoExecute 的 taint,但是在 toleration 定義中沒有指定 tolerationSeconds,則 pod 還會一直在這個節點上運行。
  • 如果 pod 能夠忍受effect 值爲 NoExecute 的 taint,而且指定了 tolerationSeconds,則 pod 還能在這個節點上繼續運行這個指定的時間長度。
# 查詢節點名字
$ kubectl get nodes
NAME    STATUS   ROLES    AGE   VERSION
node1   Ready    master   28d   v1.15.4
node2   Ready    <none>   28d   v1.15.4
node3   Ready    <none>   28d   v1.15.4

# 給node1節點打上key值爲project,value值爲ops,驅逐模式爲NoSchedule
$ kubectl taint node node1 project=ops:NoSchedule

# 給node2節點打上key值爲project,value值爲ops,驅逐模式爲NoSchedule
$ kubectl taint node node2 project=ops:NoSchedule

# 給node3節點打上key值爲project,value值爲ops,驅逐模式爲NoSchedule
$ kubectl taint node node3 project=ops:NoSchedule

2、deployment設置容忍

apiVersion: apps/v1Beta1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 1
    selector:
      matchLabels:
        app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        images: nginx:laste
        ports:
        - containerPort: 80
    tolerations:
    - key: "project"
      operator: "Equal"
      value: "ops"
      effect: "NoSchedule"

      可以看到 如果pod打上這個污點,那麼這個pod就會分配到這個node1,其他pod未打污點無法分配,並且old的pod也被驅趕出這個node。

     有時候在master節點上也安裝了docker,但是又不想讓master既作爲主節點又做爲node節點,避免讓pod調度到master上,方法如下:

# master節點名稱爲node1
$ kubectl taint node node1 node-role.kubernetes.io/master=node1:NoSchedule

四、親和性

Affinity 翻譯成中文是“親和性”,它對應的是 Anti-Affinity,我們翻譯成“互斥”。這兩個詞比較形象,可以把 pod 選擇 node 的過程類比成磁鐵的吸引和互斥,不同的是除了簡單的正負極之外,pod 和 node 的吸引和互斥是可以靈活配置的。

Affinity的優點:

  • 匹配有更多的邏輯組合,不只是字符串的完全相等
  • 調度分成軟策略(soft)和硬策略(hard),在軟策略下,如果沒有滿足調度條件的節點,pod會忽略這條規則,繼續完成調度。

目前主要的node affinity:

  • requiredDuringSchedulingIgnoredDuringExecution
    表示pod必須部署到滿足條件的節點上,如果沒有滿足條件的節點,就不停重試。其中IgnoreDuringExecution表示pod部署之後運行的時候,如果節點標籤發生了變化,不再滿足pod指定的條件,pod也會繼續運行。

  • requiredDuringSchedulingRequiredDuringExecution
    表示pod必須部署到滿足條件的節點上,如果沒有滿足條件的節點,就不停重試。其中RequiredDuringExecution表示pod部署之後運行的時候,如果節點標籤發生了變化,不再滿足pod指定的條件,則重新選擇符合要求的節點。

  • preferredDuringSchedulingIgnoredDuringExecution
    表示優先部署到滿足條件的節點上,如果沒有滿足條件的節點,就忽略這些條件,按照正常邏輯部署。

  • preferredDuringSchedulingRequiredDuringExecution
    表示優先部署到滿足條件的節點上,如果沒有滿足條件的節點,就忽略這些條件,按照正常邏輯部署。其中RequiredDuringExecution表示如果後面節點標籤發生了變化,滿足了條件,則重新調度到滿足條件的節點。

軟策略和硬策略的區分是有用處的,硬策略適用於 pod 必須運行在某種節點,否則會出現問題的情況,比如集羣中節點的架構不同,而運行的服務必須依賴某種架構提供的功能;軟策略不同,它適用於滿不滿足條件都能工作,但是滿足條件更好的情況,比如服務最好運行在某個區域,減少網絡傳輸等。這種區分是用戶的具體需求決定的,並沒有絕對的技術依賴。

下面是一個官方的示例:

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 同時定義了 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution 兩種 nodeAffinity。第一個要求 pod 運行在特定 AZ 的節點上,第二個希望節點最好有對應的 another-node-label-key:another-node-label-value 標籤。

這裏的匹配邏輯是label在某個列表中,可選的操作符有:

  • In: label的值在某個列表中
  • NotIn:label的值不在某個列表中
  • Exists:某個label存在
  • DoesNotExist:某個label不存在
  • Gt:label的值大於某個值(字符串比較)
  • Lt:label的值小於某個值(字符串比較)

如果nodeAffinity中nodeSelector有多個選項,節點滿足任何一個條件即可;如果matchExpressions有多個選項,則節點必須同時滿足這些選項才能運行pod 。

需要說明的是,node並沒有anti-affinity這種東西,因爲NotIn和DoesNotExist能提供類似的功能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章