天天看點

運維實戰 容器部分 Kubernetes排程需求簡介具體排程方法Taints

運維實戰 容器部分 Kubernetes排程

  • 需求簡介
  • 具體排程方法
    • nodeName
    • nodeSelector
    • 親和與反親和
      • 節點親和
      • Pod親和
  • Taints
    • Taints設定的取值
    • Tolerations相關設定

需求簡介

  • 生産環境有對

    Pod

    排程規劃的真實需求, 比如端口沖突的業務不能部署在同一實體機如何實作, 比如某些業務盡可能部署在同一實體機如何實作
  • 排程器通過

    K8S

    watch

    機制來發現叢集中新建立且尚未被排程到

    Node

    上的

    Pod

    . 排程器會将發現的每一個未排程的

    Pod

    排程到一個合适的

    Node

    上來運作.
  • 叢集預設使用

    kube-scheduler

    作為排程器, 可以自行編寫排程元件替換原有的

    kube-scheduler

  • 也可以在資源清單中指定使用的排程政策
  • 做排程配置設定時需要考慮許多要素, 如: 單獨和整體的資源請求, 硬體/軟體/政策限制, 親和以及反親和要求, 資料局限性, 負載間的幹擾等等

具體排程方法

nodeName

  • nodeName

    是最簡單的節點限制方法, 通常來說不推薦使用
  • 通過在資源清單中指定

    Node

    ,

    Pod

    會被自動部署到該

    Node

    上, 但如果

    Node

    不存在, 叢集也會嘗試這麼做, 因而導緻

    Pending

局限性

  • 指定的節點不存在時不會隻能解決
  • 節點存在, 但不滿足實體需求(如資源/空間不足), 排程也會失敗
  • 在生産環境中

    Node

    的名稱并不總是穩定/可預測的
  • nodeName.yaml

    檔案内容
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeName: server3
           
  • 測試結果
[[email protected] Schedule]# kubectl apply -f nodeName.yaml 
Pod/nginx created
[[email protected] Schedule]# kubectl get Pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          10s   10.244.141.226   server3   <none>           <none>
           
  • 如果叢集中沒有符合條件的

    Node

    , 比如上面的

    server3

    改成

    server10

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeName: server10
           
  • 則會出現排程失敗, 并不會隻能解決
  • 因為叢集中不存在

    server10

    而你又要求排程到

    server10

    上, 就會一直

    Pending

[[email protected] Schedule]# kubectl delete Pod nginx 
Pod "nginx" deleted
[[email protected] Schedule]# kubectl get Pod -o wide
No resources found in default namespace.
[[email protected] Schedule]# kubectl apply -f nodeName.yaml 
Pod/nginx created
[[email protected] Schedule]# kubectl get Pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP       NODE       NOMINATED NODE   READINESS GATES
nginx   0/1     Pending   0          1s    <none>   server10   <none>           <none>
           

nodeSelector

想必你也注意到了,

nodeName

并不能指定一類機器, 而隻能指定固定機器

如果我們想定義一類具有同樣特點的機器, 如這些機器都使用固态硬碟, 可以通過對節點打

tag

的方式來實作

與之對應,

nodeSelector

是通過

tag

進行排程篩選的機制, 也是節點選擇限制的最簡單推薦形式

  • nodeSelector.yaml

    檔案内容
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd
           
  • 測試流程
[[email protected] Schedule]# kubectl apply -f nodeSelector.yaml 
Pod/nginx created
[[email protected] Schedule]# kubectl get Pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
nginx   0/1     Pending   0          9s    <none>   <none>   <none>           <none>
           
  • 此時, 所有結點上都沒有

    disktype: ssd

    标簽是以

    Pending

  • server3

    附加

    disktype=ssd

    的标簽後, 排程正确實作
[[email protected] Schedule]# kubectl label nodes server3 disktype=ssd
node/server3 labeled
[[email protected] Schedule]# kubectl get Pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          67s   10.244.141.227   server3   <none>           <none>
           

親和與反親和

  • 實作了 “硬要求” 和 “軟需求” 并存, 如"必須滿足A, 盡量滿足B(B不滿足也可以)"這類需求, 這極大擴充了表達限制的類型
  • 親和和反親和不止支援節點标簽, 也支援

    Pod

    标簽, 如

    B服務

    隻能放在

    A服務

    不存在的

    Node

    上這種需求

節點親和

參數 含義
requiredDuringSchedulingIgnoredDuringExecution 必須滿足
preferredDuringSchedulingIgnoredDuringExecution 傾向滿足

雖然這個參數很長, 但實際上是由兩部分構成的, 前半部分表示

軟/硬

後半部分的

IgnoreDuringExecution

表示如果在

Pod

運作期間

Node

的标簽發生變化, 導緻親和性政策不能滿足, 則繼續運作目前的

Pod

, 而不直接驅離

nodeaffinity

還支援多種規則比對條件的配置

參數 含義
In

label

的值在清單内
NotIn

label

的值不在清單内
Gt

label

的值大于設定的值, 不支援

Pod

親和性
Lt

label

的值小于設定的值, 不支援

Pod

親和性
Exists 設定的

label

存在
DoesNotExist 設定的

label

不存在
  • 測試用

    node-affinity.yaml

    檔案内容
apiVersion: v1
kind: Pod
metadata:
  name: node-affinity
spec:
  containers:
  - name: nginx
    image: nginx
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
           nodeSelectorTerms:
           - matchExpressions:
             - key: disktype
               operator: In
               values:
                 - ssd
           
  • 這裡的需求是 滿足

    disktype=ssd

    的節點,

    key

    +

    operator

    +

    values

    共同完成了這一指名
  • 測試流程, 可以看到測試用的

    node-affinity

    被排程到了

    server3

[[email protected] Schedule]# kubectl apply -f nodeAffinity_required.yaml 
Pod/node-affinity created
[[email protected] Schedule]# kubectl get Pod -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
node-affinity   1/1     Running   0          5s    10.244.141.228   server3   <none>           <none>
           

傾向滿足

的案例

apiVersion: v1
kind: Pod
metadata:
  name: node-affinity
spec:
  containers:
  - name: nginx
    image: nginx
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
           nodeSelectorTerms:
           - matchExpressions:
             - key: kubernetes.io/hostname
               operator: NotIn
               values:
               - server3
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd     
           

在這個資源清單中存在兩條要求:

  • 必須滿足 不能排程到

    server3

  • 傾向滿足

    Node

    包含

    disktype=ssd

    tag

這樣, 即使

server4

上并沒有這個

tag

, 也可以排程到

server4

上了

Pod親和

  • PodAffinity

    主要解決

    Pod

    可以和哪些

    Pod

    部署在同一個拓撲域中的問題(拓撲域用主機标簽實作, 可以是單個主機, 也可以是多個主機組成的

    cluster

    ,

    zone

    等.) 與之效能相反的

    PodAntiAffinity

    主要解決

    Pod

    不能和哪些

    Pod

    部署在同一個拓撲域中的問題. 它們處理的是

    Kubernetes

    叢集内部

    Pod

    Pod

    之間的關系.
  • Pod

    間親和與反親和在與更進階别的集合(例如

    ReplicaSets

    ,

    StatefulSets

    ,

    Deployments

    等)一起使用時, 它們可能更加有用. 可以輕松配置一組應位于相同定義拓撲(例如, 節點)中的工作負載.
  • Pod

    間親和與反親和需要大量的處理, 這可能會顯著減慢大規模叢集中的排程. \

測試樣例

  • 建立一個自主的包含

    nginx

    服務的

    Pod

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
           
  • 建立一個包含

    Pod

    親和需求的資源清單
apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  containers:
  - name: mysql
    image: mysql
    env:
     - name: "MYSQL_ROOT_PASSWORD"
       value: "westos"
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - nginx
        topologyKey: kubernetes.io/hostname
           
[[email protected] Schedule]# kubectl apply -f nodeName.yaml
Pod/nginx created
[[email protected] Schedule]# kubectl get Pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATESnginx   1/1     Running   0          11s   10.244.141.230   server3   <none>           <none>

[[email protected] Schedule]# kubectl apply -f PodAffinity.yaml
Pod/demo created
[[email protected] Schedule]# kubectl get Pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATESdemo    1/1     Running   0          6s    10.244.22.25     server4   <none>           <none> nginx   
 1/1     Running   0          54s   10.244.141.230   server3   <none>           <none>
           

可以看到, 兩個

Pod

分别被排程到了2個不同的

Node

Taints

NodeAffinity

節點親和性的目的是讓

Pod

可以按照我們的需求排程到一個或一類

Node

上;

Taints

與之相反, 它能讓

Node

拒絕運作

Pod

, 甚至驅離已經在該

Node

上運作的

Pod

Taints

(污點)是

Node

的一個屬性, 設定了

Taints

後,

K8S

叢集就不會把

Pod

排程到這個

Node

上了

如果想讓

Pod

排程到有

Taints

的節點, 就需要給

Pod

設定

Tolerations

(容忍)屬性

主節點上天生具有

Taints

, 是以才有了預設不會排程到主節點上的說法

  • 相關指令
##為node1增加一個NoSchedule(不允許排程)的污點
kubectl taint nodes node1 key=value:NoSchedule

##查詢server1上的污點情況
kubectl describe nodes  server1 |grep Taints

##删除node1上的NoSchedule(不允許排程)污點屬性
$ kubectl taint nodes node1 key:NoSchedule-
           
  • 一個标準的

    Deployment

    控制器部署

    nginx

    的清單
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
           
  • 主節點預設不允許排程
[[email protected] Schedule]# kubectl describe nodes  server2 |grep TaintsTaints:
node-role.kubernetes.io/master:NoSchedule
           
  • 為Server4增加驅離屬性
[[email protected] Schedule]# kubectl taint node server4 key1=v1:NoExecute
node/server4 tainted
[[email protected] Schedule]# kubectl get Pod -o wide
           
  • 如果設定正确, 你将隻會在

    server3

    上看到

    Pod

    , 因為

    server2

    server4

    都不能用于部署
  • 增加容忍設定的版本
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
      tolerations:
      - key: "key1"
        operator: "Equal"
        value: "v1"
        effect: "NoExecute"
           

Taints設定的取值

參數 含義
NoSchedule 不會被排程到标記節點
PreferNoSchedule NoSchedule 的軟政策版本
NoExecute 不會排程到标記節點, 并且該節點内的

Pod

如無對應的

Tolerate

設定還會被驅逐

Tolerations相關設定

Tolerations

中定義的

key

,

value

,

effect

, 要與

node

上設定的

taint

保持一緻, 但并不是都要填寫

  • operator

    Exists

    時, 可以省略

    value

  • operator

    Equal

    時,

    key

    value

    之間的關系必須相等
  • 如果不指定

    operator

    屬性, 則預設值為

    Equal

  • 當不指定

    key

    , 再配合

    Exists

    就能比對所有的

    key

    value

    , 可以容忍所有污點
  • 當不指定

    effect

    , 則比對所有的

    effect

tolerations:
  - key: "key"
    operator: "Equal"
    value: "value"
    effect: "NoSchedule"
對滿足key=value 且污點政策為NoSchedule的節點進行容忍

tolerations:
  - operator: "Exists"
    effect: "NoSchedule"
容忍所有污點并不驅離
           

繼續閱讀