kubernetes 調度

pod 分配給特定的node節點

目的:在一般業務場景,有些pod需要運行在特定的物理節點上,可以通過kubernetes的nodeSelector、nodeName安排pod到指定的節點上運行。

# 採用nodeselect節點選擇器的方法:
# 為 test-nodelete-2節點打上標籤。
$ kubectl label nodes test-nodelete-2 disk=ssd
node/test-nodelete-2 labeled
$ kubectl get node --show-labels 
NAME              STATUS   ROLES    AGE   VERSION   LABELS
test-nodelete-1   Ready    <none>   14d   v1.20.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=ingress,kubernetes.io/arch=amd64,kubernetes.io/hostname=test-nodelete-1,kubernetes.io/os=linux
test-nodelete-2   Ready    <none>   14d   v1.20.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disk=ssd,ingress=ingress,kubernetes.io/arch=amd64,kubernetes.io/hostname=test-nodelete-2,kubernetes.io/os=linux
test-nodelete-3   Ready    <none>   14d   v1.20.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=ingress,kubernetes.io/arch=amd64,kubernetes.io/hostname=test-nodelete-3,kubernetes.io/os=linux

$ cat > nodeschedule.yaml  << EOF
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-select
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disk: ssd
EOF

# 採用nodeName的方法:
# 如果不用節點選擇器,直接用指定節點名,可以無視Taints,可以被調度。但會被NoExcute Taint影響, 如果節點存在NoExcute, 那將不能運行在該節點上。
$ cat  > nodeName.yaml << EOF
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-app
spec:
  nodeName: test-nodelete-2 # schedule pod to specific node
  containers:
  - name: nginx-web
    image: nginx
    imagePullPolicy: IfNotPresent
EOF

Taints(污點) and Tolerations(容忍)

目的:Taints 是允許node節點排斥一組pod。Tolerations 允許程式調度pod到具有污點的 node節點上。Tolerations 允許調度但不保證調度。taints和Tolerations一起工作,以確保 Pod 不會被調度到不合適的節點上。一個或多個taints應用於一個節點;這標誌著該節點不接受任何不容忍污點的 pod。
NoSchedule: 設置為不調度到該節點
PreferNoSchedule: 設置為盡量不調度到該節點
NoExecute: 設置為不調度到該節點和驅逐原來該節點已有存量的pod

# 向節點添加污點 
$ kubectl taint nodes node1 key1=value1:NoSchedule
# 解釋:在 node1上設置一個污點。污點具有鍵key1、值value1和污點效果NoSchedule。node1這意味著除非具有匹配的容限,否則任何 pod 都無法調度到node1節點。

# 去除節點污點
$ kubectl taint nodes node1 key1=value1:NoSchedule-

# 節點加上taints為NoSchedule,pod資源是不會調度到node1節點。
$ kubectl taint nodes node1 key1=value1:NoSchedule
$ cat > taints.yaml  << EOF
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-taints
  labels:
    env: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
EOF

# 為 pod 指定一個tolerations(容忍度)。以下兩個容忍「匹配」由kubectl taint上面的行創建的污點(key1=value1:NoSchedule),因此具有容忍的 pod 都可以調度到node1節點。
$ cat > taints-and-tolerations.yaml << EOF
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-taints-tolerations
  labels:
    env: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  tolerations:
  - key: "key1"
    value: "value1"
    operator: "Equal"
    effect: "NoSchedule"
EOF

# 當operator為Equal時,key和value都要匹配到上述taints指定的key1=value1,key和value都滿足條件即可以容忍該污點,pod運行在node1節點上。
# 當operator為Exists時,key或value其中一個匹配到上述taints指定的key1=value1,滿足條件即可以容忍該污點,pod運行在node1節點上。
  tolerations:
  - key: "key1"
    value: "value1"
    operator: "Equal"
    effect: "NoSchedule"

# 如果NoExecute被添加到一個節點,那麼任何不容忍該 taint 的 pod 將立即被驅逐,而容忍該 taint 的 pod 將永遠不會被驅逐。NoExecute效果的容忍可以指定一個可選`tolerationSeconds`欄位,該欄位指示在添加污點後 pod 將保持綁定到節點的時間。
$ kubectl taint nodes node1 execute=yes:NoExecute
  - key: "execute"
    value: "yes"
    effect: "NoExecute"
    # tolerationSeconds: 3600

Node Affinity

nodeSelector是將 Pod 約束到具有特定標籤的節點的最簡單方法。Affinity 和 anti-affinity 擴展了您可以定義的約束類型。如果同時指定nodeSelector和nodeAffinity,則必須同時滿足兩者才能將 Pod 調度到節點上。.

  • 親和/反親和語言更具表現力。nodeSelector僅選擇具有所有指定標籤的節點。Affinity/anti-affinity 讓您可以更好地控制選擇邏輯。
  • 您可以指示一條規則是soft或preferred,這樣即使找不到匹配的節點,調度程式仍然會調度 Pod。
  • 您可以使用在該節點上運行的其他 Pod 上的標籤來約束 Pod,而不僅僅是節點標籤,這允許您定義哪些 Pod 可以在一個節點上共存的規則。

節點親和性(Node Affinity)在概念上類似於nodeSelector,允許您根據節點標籤限制您的 Pod 可以調度的節點。有兩種類型的節點親和性:

  • requiredDuringSchedulingIgnoredDuringExecution:除非滿足規則,否則調度程式無法調度 Pod。此函數類似於nodeSelector,但具有更具表現力的語法。
  • preferredDuringSchedulingIgnoredDuringExecution: 調度器嘗試尋找符合規則的節點。如果匹配的節點不可用,調度程式仍會繼續調度 Pod運行。
    # 注意:上述類型中,IgnoredDuringExecution表示如果 Kubernetes 調度 Pod 後節點標籤發生變化,則 Pod 繼續運行.
$  cat > nodeAffinity.yaml << EOF
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-nodeaffinity
  labels:
    env: nodeaffinity
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: "test-nodelete-3"
            operator: In
            values: 
            - "yes"
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: "disk"
            operator: In
            values:
            - "ssd"
  tolerations:
  - key: "active"
    operator: "Exists"
    effect: "NoSchedule"
EOF

# requiredDuringSchedulingIgnoredDuringExecution規則解釋:
# 該node節點必須具有帶有鍵的標籤為test-nodelete-3,並且該標籤的值必須是:yes

# preferredDuringSchedulingIgnoredDuringExecution規則解釋:
# 調度器嘗試尋找帶有鍵為disk,值為ssd的node節點。如果匹配的節點不可用,調度程式仍會繼續調度 Pod運行。

# tolerations(容忍)規則解釋:
# 容忍程式調度pod到具有污點(taints)node節點上, 污點鍵為active的node。

# operator欄位指定 Kubernetes 在解釋規則時使用的邏輯運算符。您可以使用In、NotIn、Exists、DoesNotExist和 Gt、Lt。NotIn和DoesNotExist允許您定義節點反親和行為。

pod 親和性(affinity)和pod反親和性(antiaffinity)

pod 親和性和反親和性根據節點上已經運行的 Pod 的標籤, 而不是根據node節點標籤來限制 pod調度到節點上。
注意:Pod 親和性和反親和性需要大量資源處理調度,這會在大型集群中的減慢調度速度。不建議在超過數百個節點的集群中使用它。

$ cat > pod-affinity.yaml << EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-pod-affinity
spec:
  replicas: 3
  selector:
    matchLabels:
      podaffinity: app 
  template:
    metadata:
      labels:
        podaffinity: app
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: "env"
                operator: In
                values: 
                - "nginx"
            topologyKey: "kubernetes.io/hostname"
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: "app"
                  operator: In           
                  values: 
                  - "web"
              topologyKey: "kubernetes.io/hostname"
      tolerations:
      - key: "active"
        operator: "Exists"
        effect: "NoSchedule"
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 8088
EOF

# requiredDuringSchedulingIgnoredDuringExecution 親和性規則解釋:
# 當一個或多個node節點上的Pod 具有env=nginx標籤, 且pod都位於同一區域或同一類伺服器時,調度程式才能將 Pod 調度到節點上 。更準確地說,調度程式必須將 Pod 放置在具有 topologyKey="kubernetes.io/hostname"標籤的node節點上,且該區域node節點有一個或多個node節點 的Pod 具有env=nginx標籤。

# preferredDuringSchedulingIgnoredDuringExecution 反親和性解釋:
# 表示調度程式應盡量避免將 Pod 調度到一個或多個node節點上的Pod具有app=web標籤的node節點上,更準確地說,具有topologyKey="kubernetes.io/hostname"標籤的node節點上,調度程式必免將pod運行在該區域node節點的pod具有app=web標籤的節點上。

# tolerations(容忍)規則解釋:
# 容忍程式調度pod到具有污點(taints)node節點上, 污點鍵為active的node。


# Pod親和性(podAffinity)規則告訴調度程式將每個副本放置在具有app=web標籤的 Pod 的節點上。Pod 反親和性(podAntiAffinity)規則告訴調度器避免調度到具有env=nginx標籤的 Pod 的節點上。
$ cat > nginx-pod-affinity.yaml  << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-web
spec:
  selector:
    matchLabels:
      app: store
  replicas: 3
  template:
    metadata:
      labels:
        app: store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web
            topologyKey: "kubernetes.io/hostname"
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: env
                operator: In
                values:
                - nginx
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: nginx-server
        image: nginx
EOF

參考文獻

kubernetes官方文檔