kubernetes系列(十五) - 叢集排程
阿新 • • 發佈:2020-07-11
- [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: