1. 程式人生 > >kubernetes系列(十五) - 叢集排程

kubernetes系列(十五) - 叢集排程

- [1. 叢集排程簡介](#head1) - [2. 排程過程](#head2) - [2.1 排程過程概覽](#head3) - [2.2 Predicate(預選)](#head4) - [2.3 Priorities(優選)](#head5) - [3. 排程的親和性](#head6) - [3.1 node親和性](#head7) - [3.1.1 node親和性簡介](#head8) - [3.1.2 node親和性硬策略示例](#head9) - [3.1.3 node親和性軟策略示例](#head10) - [3.2 pod親和性](#head11) - [3.2.1 pod親和性/反親和性簡介](#head12) - [3.2.2 pod親和性/反親和性示例](#head13) - [3.3 親和性/反親和性排程策略比較](#head14) - [4. Taint(汙點)和Toleration(容忍)](#head15) - [4.1 Taint和和Toleration簡介](#head16) - [4.2 Taint(汙點)](#head17) - [4.2.1 Taint的組成](#head18) - [4.2.2 Taint的設定、檢視和去除](#head19) - [4.3 Toleration(容忍)](#head20) - [4.3.1 Toleration簡介](#head21) - [4.3.2 Toleration的資源清單配置](#head22) - [5. 指定排程節點](#head23) ## 1. 叢集排程簡介 `Scheduler`是`kubernetes`中的排程器元件,主要的任務是把定義的pod分配到叢集的節點上。聽起來非常簡單,但有很多要考慮的問題: - **公平**: 如何保證每個節點都能被分配 - **資源資源高效利用**: 叢集所有資源最大化被使用 - **效率**: 排程的效能要好,能夠儘快地對大批量的pod完成排程工作 - **靈活**: 允許使用者根據自己的需求控制排程的邏輯 `Sheduler`是作為單獨的程式執行的(如果是`kubeadm`則是以pod形式執行的),啟動之後會一直和`APIServer`持續連線,獲取`PodSpec.NodeName`為空的pod,對每個pod都會建立一個`binding`,表明該 pod 應該放到哪個節點上 > 這裡的`PodSpec.NodeName`不為空的pod,說明我們手動指定了這個pod應該部署在哪個node上,所以這種情況`Sheduler`就不需要參與進來了 ---- ## 2. 排程過程 ### 2.1 排程過程概覽 排程過程分為兩部分,如果中間任何一步驟有錯誤,直接返回錯誤: 1. `predicate`(預選): 首先是過濾掉不滿足條件的節點 2. `priority`(優選): 然後從中選擇優先順序最高的節點 ### 2.2 Predicate(預選) `Predicate`有一系列的演算法可以使用:  - **PodFitsResources**: 節點上剩餘的資源是否大於pod請求的資源 - **Podfitshost**: 如果pod指定了NodeName,檢查節點名稱是否和NodeName相匹配 - **PodFfitsHostPorts**: 節點上已經使用的port是否和 pod申請的port衝突 - **PodSelectorMatches**: 過濾掉和 pod指定的label不匹配的節點 - **NoDiskConflict**: 已經mount的volume和 pod指定的volume不衝突,除非它們都是隻讀 **注意:** 如果在`predicate`過程中沒有合適的節點。pod會一直在`pending`狀態,不斷重試排程,直到有節點滿足條件。經過這個步驟,如果有多個節點滿足條件,就繼續`priorities`過程 ### 2.3 Priorities(優選) `Priorities`是按照優先順序大小對節點排序 優先順序由一系列鍵值對組成,鍵是該優先順序項的名稱,值是它的權重(該項的重要性)。這些優先順序選項包括: - **LeastRequestedPriority**:通過計算CPU和 Memory的使用率來決定權重,使用率越低權重越高。換句話說,這個優先順序指標傾向於資源使用比例更低的節點 - **BalancedResourceA1location**:節點上CPU和Memory 使用率越接近,權重越高。這個應該和上面的一起使用,不應該單獨使用 - **ImageLocalityPriority**:傾向於已經有要使用映象的節點,映象總大小值越大,權重越高 通過演算法對所有的優先順序專案和權重進行計算,得出最終的結果 ---- ## 3. 排程的親和性 ### 3.1 node親和性 #### 3.1.1 node親和性簡介 簡單來理解就是,指定排程到的`node`,`nodeAffinity`又分為兩種: `pod.spec.nodeAffinity`: - `preferredDuringSchedulinglgnoredDuringExecution`:軟策略【我想要去這個節點】 - `requiredDuringschedulinglgnoredDuringExecution`:硬策略【我一定要去這個節點】 #### 3.1.2 node親和性硬策略示例 ```yaml apiVersion: v1 kind: Pod metadata: name: affinity labels: app: node-affinity-pod spec: containers: - name: with-node-affinity image: lzw5399/tocgenerator affinity: # 指定親和性為node親和性 nodeAffinity: # 指定為硬策略 requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: # key就是node的label # 這句話代表當前pod一定不能分配到k8s-node02節點上 - matchExpressions: - key: kubernetes.io/hostname operator: NotIn values: - k8s-node02 ``` - 關於`- key: kubernetes.io/hostname`,可以通過以下方式檢視node的label ```shell $ kubectl get nodes --show-labels NAME STATUS ROLES AGE VERSION LABELS master Ready master 154d v1.10.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master= node02 Ready 74d v1.10.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,com=youdianzhishi,course=k8s,kubernetes.io/hostname=node02 node03 Ready 134d v1.10.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,jnlp=haimaxy,kubernetes.io/hostname=node03 ``` #### 3.1.3 node親和性軟策略示例 ```yaml apiVersion: v1 kind: Pod metadata: name: affinity labels: app: node-affinity-pod spec: containers: - name: with-node-affinity image: lzw5399/tocgenerator affinity: # 宣告節點親和性為軟策略 nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: # 當前策略權重為1 - weight: 1 preference: # [最好]能分配到label為source=k8s-node03的節點上 matchExpressions: - key: source operator: In values: - k8s-node03 ``` ### 3.2 pod親和性 #### 3.2.1 pod親和性/反親和性簡介 pod親和性主要解決pod可以和哪些pod部署在同一個**拓撲域**中的問題 > 拓撲域: 用主機標籤實現,可以是單個主機,或者具有同個label的多個主機,也可以是多個主機組成的 cluster、zone 等等 所以簡單來說: 比如一個 pod 在一個節點上了,那麼我這個也得在這個節點,或者你這個 pod 在節點上了,那麼我就不想和你待在同一個節點上 pod親和性/反親和性又分為兩種: `pod.spec.affinity.podAffinity/podAntiAffinity`: - `preferredDuringSchedulinglgnoredDuringExecution`:軟策略 - `requiredDuringSchedulinglgnoredDuringExecution`:硬策略 #### 3.2.2 pod親和性/反親和性示例 ```yaml apiVersion: v1 kind: Pod metadata: name: pod-3 labels: app: pod-3 spec: containers: - name: pod-3 image: hub.coreqi.cn/library/myapp:v1 affinity: # 配置一條pod親和性策略 podAffinity: # 配置為硬策略 requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - pod-1 topologyKey: kubernetes.io/hostname # 配置一條pod反親和性策略 podAntiAffinity: # 配置為軟策略 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - pod-2 topologyKey: kubernetes.io/hostname ``` ### 3.3 親和性/反親和性排程策略比較 排程策略 | 匹配標籤 | 操作符| 拓撲域支援 | 排程目標 ---|---|---|---|--- nodeAffinity | 主機 | IN, NotIn, Exists, DoesNotExist, Gt, Lt | 否 | 指定主機 podAffinity | POD | IN, NotIn, Exists, DoesNotExist | 是 | POD與指定POD同一拓撲域 podAntiAffinity | POD | IN, NotIn, Exists, DoesNotExist | 是 | POD與指定POD不在同一拓撲域 ---- ## 4. Taint(汙點)和Toleration(容忍) ### 4.1 Taint和和Toleration簡介 `節點親和性`是pod的一種屬性(偏好或硬性要求),它使pod被吸引到一類特定的節點。`Taint`則相反,它使節點能夠排斥一類特定的pod。 `Taint`和`toleration`相互配合,可以用來避免pod被分配到不合適的節點上。**每個節點上都可以應用一個或多個taint**,這表示對於那些不能容忍這些taint的pod,是不會被該節點接受的。如果將toleration 應用於pod上,則表示這些pod 可以(但不要求)被排程到具有匹配 taint 的節點上。 > 如果沒有特別配置toleration,預設是不容忍所有汙點的 ### 4.2 Taint(汙點) #### 4.2.1 Taint的組成 汙點的value是可選項,即汙點有兩種組成形式 ``` key-value:effect key:effect ``` **effect** effect描述汙點的作用, 當前支援三種策略: - `NoSchedu1e`:表示k8s將不會將Pod 排程到具有該汙點的Node上 - `PreferNoSchedu1e`:表示k8s將盡量避免將Pod排程到具有該汙點的 Node上 - `NoExecute`:表示k8s將不會將 Pod排程到具有該汙點的Node上,**同時會將Node上已經存在的 Pod 驅逐出去** #### 4.2.2 Taint的設定、檢視和去除 1. 設定汙點 ```shell # value不為空的格式 kubectl taint nodes node1 key1=value1:NoSchedule # value為空的格式 kubectl taint nodes node1 key1:NoExecute ``` 2. 汙點的檢視 ```shell # 通過describe node檢視Taints屬性 kubectl describe node nodename ``` ![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggn3la02iqj30dk014aa6.jpg) 3. 汙點的去除 - 通過describe檢視汙點,然後把汙點複製出來,按照如下格式在最後加一個`-`就好了 ```shell # 去除如上截圖的一個汙點 kubectl taint nodes node1 haha-233:NoSchedule- ``` ### 4.3 Toleration(容忍) #### 4.3.1 Toleration簡介 設定了汙點的Node將根據`taint`的`effect`:`NoSchedule`、`PreferNoSchedule`、`NoExecute` 和 Pod之間產生**互斥**的關係,Pod將在一定程度上不會被排程到Node上 **但我們可以在Pod上設定容忍(Toleration)**。意思是設定了容忍的Pod將可以容忍汙點的存在,可以被排程到存在汙點的Node上 > 可以被排程不代表一定會被排程,只是儲存了可能性 #### 4.3.2 Toleration的資源清單配置 **如下是`pod.spec.tolerations`部分:** ```yaml tolerations: # 容忍key1-value1:NoSchedule的汙點 # 且需要被驅逐時,可以再呆3600秒 - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule" # 用於描述當Pod需要被驅逐時可以在 Pod上繼續保留執行的時間 tolerationSeconds: 3600 # 容忍key1-value1:NoExecute的汙點 - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute" # 容忍key2:NoSchedule的汙點 - key:"key2" operator: "Exists" effect: "NoSchedule" ``` **注意點** 1. `key`,`value`, `effect`要與Node上設定的 taint保持一致 2. `operator`的值為`Exists`將會忽略value值 3. 如不指定`operator`,則預設為`equal` 4. `tolerationSeconds`用於描述當Pod**需要被驅逐時**可以在 Pod上繼續保留執行的時間 **騷操作** 1. 當不指定key值時,表示容忍所有的汙點key ```yaml tolerations: - operator: "Exists" ``` 2. 當不指定`effect`時,表示容忍所有的汙點作用 ```yaml tolerations: - key: "key" operator: "Exists" ``` 3. 有多個`Master`存在時,防止資源浪費,可以如下設定 ```shell kubectl taint nodes Node-Name node-role.kubernetes.io/master=:PreferNoSchedule ``` ---- ## 5. 指定排程節點 通過指定`Pod.spec.nodeName`將Pod直接排程到指定的Node節點上 - 會跳過Scheduler的排程策略 - 該匹配規則是強制匹配 ```yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: myweb spec: replicas: 7 template: metadata: labels: app: myweb spec: # 直接指定node名稱 nodeName: k8s-node01 containers: - name: myweb image: lzw5399/tocgenerator ports: - containerPort: