8.k8s叢集排程
一、節點親和性
pod_spec.nodeAffinity
- preferredDuringSchedulingIgnoredDuringExecution: 軟策略
- requiredDuringSchedulingIgnoredDuringExecution: 硬策略
requiredDuringSchedulingIgnoredDuringExecution
apiVersion: v1 kind: Pod metadata: name: affinity labels: app: node-affinity-pod spec: containers: - name: with-node-affinity image: nginx affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: NotIn values: - k8s-node2
preferredDuringSchedulinglgnoredDuringExecution
apiVersion: v1 kind: Pod metadata: name: affinity1 labels: app: node-affinity-pod spec: containers: - name: with-node-affinity image: nginx affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: source operator: In values: - k8s-node1
合體
apiVersion: v1 kind: Pod metadata: name: affinity labels: app: node-affinity-pod spec: containers: - name: with-node-affinity image: nginx affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kunernetes.io/hostname operator; NotIn values: - k8s-node2 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: source operator: In values: - qikqiak
鍵值運算關係
- In:label 的值在某個列表中
- NotIn:label的值不在某個列表中
- Gt:label的值大於某個值
- It:label的值小於某個值
- Exists: 某個label存在
- DoesNotExist: 某個label不存在
注意:如果nodeSelectorTerms下面有多個選項的話,滿足任何一個條件就可以了; 如果matchExpressions有多個選項的話,則必須同時滿足這些條件才能正常排程 POD
Pod親和性
pod.spec.affinity.podAffinity/podAntiAffinity
- preferredDuringSchedulingIgnoredDuringExecution: 軟策略
- requiredDuringSchedulingIgnoredDuringExecution: 硬策略
apiVersion: v1
kind: Pod
metadata:
name: pod-3
labels:
app: pod-3
spec:
containers:
- name: pod-3
image: nginx
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- pod-1
topologyKey: kubernetes.io/hostname
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
perator: In
values:
- pod-2
topologyKey: kubernetes.io/hostname
親和性、反親和性排程策略比較如下:
排程策略 | 匹配標籤 | 操作符 | 拓撲域支援 | 排程目標 |
---|---|---|---|---|
nodeAffinity | 主機 | In,NotIn,Exists,DoesNotExist,Gt,Lt | 否 | 指定主機 |
podAffinity | POD | In,NotIn,Exists,DoesNotExist | 是 | POD與指定POD同一拓撲域 |
podAnitAffinity | POD | In,NotIn,Exists,DoesNotExist | 是 | POD與指定POD不在同一拓撲域 |
二、汙點和容忍
Taint和Toleration
節點親和性,是pod的一種屬(偏好或硬性要求),它邊pod被吸引到一類特定的節點。Taint則相反,它便節點 能夠排斥一類特定的pod
Taint和toeration相互配合 , 可以用來避免pod被分配到不合適的節點上, 每個節點上都可以應用一個或多個taint, 這表示對於那些不能容忍這些taint的pod , 是不會被該節點接受的 , 如果將toleration應用於pod上, 則表示這些pod可以(但不要求)被排程到具有匹配taint的節點上
如果你能容忍這個汙點,代表你兩能發生故事 。
汙點(Taint)
1.汙點(Taint)的組成
使用kubectl taint 命令可以給某個Node節點設定汙點, Node被設定上汙點之後就和Pod之間存在了一種相斥的關係 , 可以讓Node拒絕Pod的排程執行 , 甚至將Node已經存在的Pod驅逐出去
每個汙點的組成如下:
key=value:effect
每個汙點有一個key和value作為汙點的標籤, 其中value可以為空, effect描述汙點的作用 。當前taint effect支援如下三個選項
- NoSchedule: 表示k8s將不會將Pod排程到具有該汙點的Node上
- PreferNoSchedule: 表示k8s將盡量避免將Pod排程到具有該汙點的Node上
- NoExecute: 表示k8s將不會將Pod排程到具有該汙點的Node上, 同時會將Node上已經存在的Pod驅逐出去 。
2.汙點的設定, 檢視和去除
#設定汙點
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes k8s-master03 check=haha:NoExecute
#節點說明中, 查詢Taints欄位
#檢視汙點
kubectl describe nodes 節點名稱
kubectl describe nodes k8s-master03
#去除汙點
kubectl taint nodes node1 key1:NoSchedule-
kubectl taint nodes k8s-master03 check:NoExecute-
容忍(Tolerations)
設定了汙點的Node將根據taint的effect: NoSchedule, PreferNoSchedule, NoExecute和Pod之間產生互斥的關係 , Pod將在一定程度上不會被排程到Node上 。 但我們可以在Pod上設定容忍(Toleration),意思是設定了容忍的Pod將可以容忍汙點的存在 , 可以排程到存在汙點的Node上
pod.spec.tolerations
tolerations:
- key: "key1"
operator: "Equa1"
value: "value1"
effect: "NoSchedule"
tolerationSeconds: 3600
- key: "key1"
operator: "Equa1"
value: "value1"
effect: "NoExecute"
- key: "key2"
operator: "Exists"
effect: "NoSchedule"
- 其中key,value,effect要與Node上設定的taint保持一致
- operator的值為Exists將會忽略value值
- tolerationSeconds用於描述當Pod需要被驅逐時可以在Pod上繼續保留執行的時間
1.當不指定key值時 , 表示容忍所有的汙點key:
tolerations:
- operator: "Exists"
2.當不指定effect值時 , 表示容忍所有的汙點作用
tolerations:
- key: "key"
operator: "Exists"
3.有多個Master存在時 , 防止資源浪費, 可以如下設定
kubectl taint nodes Node-Name node-role.kubernetes.io/master=:PreferNoSchedule
三、固定節點排程
1.Pod.spec.nodeName將Pod直接排程到指定的Node節點上, 會跳過Scheduler的排程策略, 該匹配規則是強制匹配
apiVersion: apps/v1
kind: Deployment
metadata:
name: myweb
spec:
replicas: 7
selector:
matchLabels:
app: myweb
template:
metadata:
labels:
app: myweb
spec:
nodeName: k8s-master01
containers:
- name: myweb
image: nginx
ports:
- containerPort: 80
2.Pod.spec.nodeSelector: 通過kubernetes的label-selector機制選擇節點, 由排程器排程策略匹配label, 而後排程pod到目標節點, 該匹配規則屬於強制約束
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myweb
spec:
replicas: 2
template:
metadata:
labels:
app: myweb
spec:
nodeSelector
disk: ssd
containers:
- name: myweb
image: nginx
ports:
- containerPort: 80
打標籤在k8s-master02上打標籤
kubectl label node k8s-master02 disk=ssd
kubectl get nodes --show-labels
為k8s-master01增加標籤
kubectl label node k8s-master01 disk=ssd
修改deployment副本數
kubectl edit deployment myweb
四、排程過程說明
簡介
Scheduler是kubernetes的排程器 , 主要的任務是把定義的pod分配到叢集的節點上 , 聽起來非常簡單 ,但有很多要考慮的問題:
- 公平: 如何保證每個節點都能被分配資源
- 資源高效利用:叢集所有資源最大化被使用
- 效率:排程的效能要好, 能夠儘快地對大批量的pod完成排程工作
- 靈活:允許使用者根據自己的需求控制排程的邏輯
Sheduler是作為單獨的程式執行的 , 啟動之後會一直堅挺API Server, 獲取PodSpec.NodeName為空的pod,對每個pod都會建立一個binding,表明該pod應該放到哪個節點上
排程過程
排程分為幾個部分: 首先是過濾不滿足條件的節點, 這個過程稱為predicate;然後對通過的節點按照優先順序排序, 這個是priority;最後從中選擇優先順序最高的節點。 如果中間任何一步驟有錯誤, 就直接返回錯誤
Predicate有一系列的演算法可以使用:
- PodFitsResources: 節點上剩餘的資源是否大於pod請求的資源
- PodFitsHost: 如果pod指定了NodeName, 檢查節點名稱是否和NodeName匹配
- PodFitsHostPorts:節點上已經使用的port是否和pod申請的port衝突
- PodSelectorMatches:過濾掉和pod指定的label不匹配的節點
- NoDiskConflict:已經mount的volume和pod指定的volume不衝突, 除非它們都是隻讀
如果在predicate過程中沒有合適的節點, pod會一直在pending狀態, 不斷重試排程, 直到有節點滿足掉件。 經過這個步驟, 如果有多個節點滿足條件, 就繼續priorities過程;按照優先順序大小對節點排序
優先順序由一系列鍵值對組成, 鍵是該優先順序頂的名稱, 值是它的權重(該項的重要性)。 這些優先順序選項包括:
- LeastRequestedPriority: 通過計算CPU和Memory的使用率來決定權重, 使用率越低權重越高。 換句話說, 這個優先順序指標傾向於資源使用比例更低的節點
- BalancedResourceAllocation:節點上CPU和Memory使用率越接近, 權重越高 。 這個應該和上面的一起使用, 不應該單獨使用。
- ImageLocalityPriority:傾向於已經有要使用映象的節點, 映象總大小值越大, 權重越高通過演算法對所有的優先順序專案和權重進行計算, 得出最終的結果
自定義排程器
除了kubernetes自帶的排程器, 你也可以編寫自己的排程器 。 通過spec:schedlername引數指定排程器的名字, 可以為pod選擇某個排程器進行排程。 比如下面的pod選擇my-scheduler進行排程, 而不是預設的default-scheduler:
apiVersion: v1
kind: Pod
metadata:
name: annotation-second-scheduler
labels:
name: multischeduler-example
spec:
schedulername: my-scheduler
containers:
- name: pod-with-second-annotation-container
image: nginx