k8s的親和度
nodeSelector
k8s非常常用的一個調度方式:nodeSelector
label 設置好的標簽
用戶可以靈活的利用label來管理集群中的資源,比如常見的service對象通過label去匹配pod資源,而pod的調度也可以根據節點的label來進行調度
查看node的label命令
$ kubectl get nodes --show-labels
給隨便一個節點增加標簽
$ kubectl label nodes ydzs-node2 com=youdianzhishi
node/ydzs-node2 labeled
增加好之后可以用過上面的 kubectl get nodes --show-lales
來查看新增的label
具體yaml文件展示
apiVersion: v1
kind: Pod
metadata:
labels:
app: busybox-pod
name: test-busybox
spec:
containers:
- command:
- sleep
- "3600"
image: busybox
imagePullPolicy: Always
name: test-busybox
nodeSelector:
com: youdianzhishi
通過describe命令查看調度結果
$ kubectl apply -f pod-selector-demo.yaml
pod/test-busybox created
$ kubectl describe pod test-busybox #查看描述,來看pod調度到了哪台機器
我們可以看到 Events 下面的信息,我們的 Pod 通過默認的 default-scheduler 調度器被綁定到了 ydzs-node2 節點。不過需要注意的是nodeSelector 屬於強制性的,如果我們的目標節點沒有可用的資源,我們的 Pod 就會一直處於 Pending 狀態。
通過上面的例子我們可以感受到 nodeSelector 的方式比較直觀,但是還夠靈活,控制粒度偏大,接下來我們再和大家了解下更加靈活的方式:節點親和性(nodeAffinity)。
親和性和反親和性調度
默認的調度器在使用的時候,經過了predicate和priorities兩個階段,但是在實際的生產環境中,會用到nodeAffinity(節點親和性)、podAffinity(pod 親和性) 以及 podAntiAffinity(pod 反親和性)
親和性調度可以分成軟策略和硬策略兩種方式
軟策略就是如果現在沒有滿足調度要求的節點的話,pod就會忽略這條規則,繼續完成調度的過程,說白了就是滿足條件最好了,沒有的話也無所謂
硬策略就比較強硬了,是如果沒有滿足條件的節點的話,就不斷重試直到滿足條件為止,簡單說就是你必須滿足我的要求,不然就不干了
對於親和性和反親和性都有這兩種規則可以設置:preferredDuringSchedulingIgnoredDuringExecution 和requiredDuringSchedulingIgnoredDuringExecution,前面的就是軟策略,后面的就是硬策略
節點親和性
節點親和性(nodeAffinity)主要是用來控制 Pod 要部署在哪些節點上,以及不能部署在哪些節點上的,它可以進行一些簡單的邏輯組合了,不只是簡單的相等匹配。
比如現在我們用一個 Deployment 來管理8個 Pod 副本,現在我們來控制下這些 Pod 的調度,如下例子:(node-affinity-demo.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-affinity
labels:
app: node-affinity
spec:
replicas: 8
selector:
matchLabels:
app: node-affinity
template:
metadata:
labels:
app: node-affinity
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
name: nginxweb
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬策略
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- ydzs-node3
preferredDuringSchedulingIgnoredDuringExecution: # 軟策略
- weight: 1
preference:
matchExpressions:
- key: com
operator: In
values:
- youdianzhishi
其實最終還是要根據label標簽來進行設置的,yaml文件當中
污點和容忍
污點與容忍¶
對於 nodeAffinity 無論是硬策略還是軟策略方式,都是調度 Pod 到預期節點上,而污點(Taints)恰好與之相反,如果一個節點標記為 Taints ,除非 Pod 也被標識為可以容忍污點節點,否則該 Taints 節點不會被調度 Pod。
比如用戶希望把 Master 節點保留給 Kubernetes 系統組件使用,或者把一組具有特殊資源預留給某些 Pod,則污點就很有用了,Pod 不會再被調度到 taint 標記過的節點。我們使用 kubeadm 搭建的集群默認就給 master 節點添加了一個污點標記,所以我們看到我們平時的 Pod 都沒有被調度到 master 上去:
$ kubectl describe node ydzs-master
Name: ydzs-master
Roles: master
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=ydzs-master
kubernetes.io/os=linux
node-role.kubernetes.io/master=
......
Taints: node-role.kubernetes.io/master:NoSchedule
Unschedulable: false
......
我們可以使用上面的命令查看 master 節點的信息,其中有一條關於 Taints 的信息:node-role.kubernetes.io/master:NoSchedule,就表示master 節點打了一個污點的標記,其中影響的參數是 NoSchedule,表示 Pod 不會被調度到標記為 taints 的節點,除了 NoSchedule 外,還有另外兩個選項:
PreferNoSchedule:NoSchedule 的軟策略版本,表示盡量不調度到污點節點上去
NoExecute:該選項意味着一旦 Taint 生效,如該節點內正在運行的 Pod 沒有對應容忍(Tolerate)設置,則會直接被逐出
污點 taint 標記節點的命令如下:
$ kubectl taint nodes ydzs-node2 test=node2:NoSchedule
node "ydzs-node2" tainted
上面的命名將 ydzs-node2 節點標記為了污點,影響策略是 NoSchedule,只會影響新的 Pod 調度,如果仍然希望某個 Pod 調度到 taint 節點上,則必須在 Spec 中做出 Toleration 定義,才能調度到該節點,比如現在我們想要將一個 Pod 調度到 master 節點:(taint-demo.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
name: taint
labels:
app: taint
spec:
replicas: 3
selector:
matchLabels:
app: taint
template:
metadata:
labels:
app: taint
spec:
containers:
- name: nginx
image: nginx
ports:
- name: http
containerPort: 80
tolerations:
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"
由於 master 節點被標記為了污點,所以我們這里要想 Pod 能夠調度到改節點去,就需要增加容忍的聲明:
tolerations:
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"
然后創建上面的資源,查看結果:
$ kubectl apply -f taint-demo.yaml
deployment.apps "taint" created
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
......
taint-845d8bb4fb-57mhm 1/1 Running 0 1m 10.244.4.247 ydzs-node2
taint-845d8bb4fb-bbvmp 1/1 Running 0 1m 10.244.0.33 ydzs-master
taint-845d8bb4fb-zb78x 1/1 Running 0 1m 10.244.4.246 ydzs-node2
......
我們可以看到有一個 Pod 副本被調度到了 master 節點,這就是容忍的使用方法。
對於 tolerations 屬性的寫法,其中的 key、value、effect 與 Node 的 Taint 設置需保持一致, 還有以下幾點說明:
如果 operator 的值是 Exists,則 value 屬性可省略
如果 operator 的值是 Equal,則表示其 key 與 value 之間的關系是 equal(等於)
如果不指定 operator 屬性,則默認值為 Equal
另外,還有兩個特殊值:
空的 key 如果再配合 Exists 就能匹配所有的 key 與 value,也就是是能容忍所有節點的所有 Taints
空的 effect 匹配所有的 effect
最后如果我們要取消節點的污點標記,可以使用下面的命令:
$ kubectl taint nodes ydzs-node2 test-
node "ydzs-node2" untainted