本文主要快速講解Kube.NETes的親和性調(diào)度 和 反親和性調(diào)度,通過理論結(jié)合實際的方式,讓理解更深刻。
首先來個一句話總結(jié):親和性調(diào)度就像關(guān)系親密的閨蜜,你去哪兒我也去哪兒。反親和性調(diào)度就像賭氣的兩個孩子,賭氣永遠不在一起玩兒。更多解釋和實戰(zhàn)詳見下文。花10分鐘看到最后,你肯定會有收獲。
1、調(diào)度Pod的主要方式
Pod調(diào)度到指定Node的方式主要有4種:
-
nodeName調(diào)度:直接在Pod的yaml編排文件中指定 nodeName
,調(diào)度到指定name的節(jié)點上。 -
nodeSelector調(diào)度:直接在Pod的yaml編排文件中指定 nodeSelector
,調(diào)度到帶有指定label
的節(jié)點上。 -
污點(TAInts)和容忍度(Tolerations)調(diào)度:詳見文章《5分鐘搞懂K8S的污點和容忍度(理論+實戰(zhàn))》。主要通過在Node節(jié)點上打污點,然后在Pod的yaml編排文件中配置容忍度,來實現(xiàn)調(diào)度。 -
親和-反親和調(diào)度:見下文講解。
2、為什么需要親和調(diào)度
有了nodeName調(diào)度
、nodeSelector調(diào)度
、污點(Taints)和容忍度(Tolerations)調(diào)度
,為什么還需要親和-反親和調(diào)度
呢?
為了更靈活更復(fù)雜的調(diào)度方式。比如有些場景想把2個Pod 調(diào)度到一臺節(jié)點上,有的場景為了隔離性高可用性想把2個Pod分開到不同節(jié)點上,或者有的場景想把Pod調(diào)度到指定的一些特點節(jié)點上。
3、親和調(diào)度的前置概念(重要)
-
label
在K8S中是非常重要的概念,不管是什么場景,只要和選擇、篩選相關(guān)的,基本是用label
字段來匹配的。 -
親和性和反親和性的調(diào)度,篩選的條件依舊用的是Node的 label
字段。 -
不管是Node親和性調(diào)度,還是Pod親和性調(diào)度,被調(diào)度的主體都是Pod。都是講的Pod根據(jù)親和規(guī)則調(diào)度到某個節(jié)點,或者Pod跟隨別的Pod調(diào)到到某個節(jié)點(比如Pod1跟隨Pod2,Pod2被調(diào)度到B節(jié)點,那么Pod1也被調(diào)度到B節(jié)點)。 -
Node親和性調(diào)度 和 Pod親和性調(diào)度 的配置都是寫在 編排Pod的yaml里。因為被調(diào)度的主體是Pod。 -
Node親和性調(diào)度是指Pod和Node的親密關(guān)系。 -
Pod親和性調(diào)度是指Pod和Pod的親密關(guān)系。 -
硬親和:親和規(guī)則只有一種,必須符合該規(guī)則。 -
軟親和:規(guī)則有多種,每個權(quán)重不同,根據(jù)權(quán)重優(yōu)先級去選擇一個規(guī)則。 -
Node親和性調(diào)度的圖示如下,Pod親和性調(diào)用和Pod反親和性調(diào)用也類似。
4、親和調(diào)度的具體概念
Affinity
的中文意思是親近
,用來表述親和性調(diào)度再合適不過了。
親和性調(diào)度:就好像Node(或者Pod)和Pod是關(guān)系很好的閨蜜,Pod說,“只要符合這種label的Node(Pod)都是我的好閨蜜,閨蜜在哪兒我就去哪兒”。
反親和性調(diào)度:就好像2個Pod是賭氣的2個孩子,互相對著干,一個往東,另一隨便去哪個方向就是不往東,他們不會去到同一個地方。
4.1、記住這3種調(diào)度關(guān)系
親和性調(diào)度 和 反親和性調(diào)度的關(guān)系就3種:
-
node親和調(diào)度:硬親和、軟親和 -
pod親和調(diào)度:硬親和、軟親和 -
pod反親和調(diào)度:硬親和、軟親和
4.2、記住這2種親和表達式
不管是Node親和 還是Pod親和,他們都有2種親和性表達方式:
-
RequiredDuringSchedulingIgnoredDuringExecution:是硬親和的方式,必須滿足指定的規(guī)則才可以把Pod調(diào)度到該Node上。這里注意 Required
這個詞,中文意思必須的
。 -
PreferredDuringSchedulingIgnoredDuringExecution:是軟親和的方式,強調(diào)優(yōu)先滿足某個規(guī)則,然后根據(jù)優(yōu)先的規(guī)則,將Pod調(diào)度到節(jié)點上。這里注意 Preferred
這個詞,中文意思是首選
,用來說明選擇規(guī)則的優(yōu)先級,確實比較合適。
這兩個字段也比較長,我們來做下拆解,將RequiredDuringSchedulingIgnoredDuringExecution拆解為RequiredDuringScheduling
和IgnoredDuringExecution
。
-
RequiredDuringScheduling
:定義的規(guī)則必須強制滿足(Required
)才會把Pod調(diào)度到節(jié)點上。 -
IgnoredDuringExecution
:已經(jīng)在節(jié)點上運行的Pod不需要滿足定義的規(guī)則,即使去除節(jié)點上的某個標(biāo)簽,那些需要節(jié)點包含該標(biāo)簽的Pod依舊會在該節(jié)點上運行。或者這么理解:如果Pod所在的節(jié)點在Pod運行期間標(biāo)簽被刪除了,不再符合該Pod的節(jié)點親和性規(guī)則,那也沒關(guān)系,該Pod 還能繼續(xù)在該節(jié)點上運行。
4.3、表達式中的操作符
親和性表達方式需要用到如下幾個可選的操作符operator
:
-
In:標(biāo)簽的值在某個列表中 -
NotIn:標(biāo)簽的值不在某個列表中 -
Exists:存在某個標(biāo)簽 -
DoesNotExist:不存在某個標(biāo)簽 -
Gt:標(biāo)簽的值大于某個值(字符串比較) -
Lt:標(biāo)簽的值小于某個值(字符串比較)
這些操作符里,雖然沒有排斥某個節(jié)點的功能,但是用這幾個標(biāo)簽也可以變相的實現(xiàn)排斥的功能。
4.4、作用域topologyKey
topologyKey很多地方解釋為拓撲建,很是費解。實際上就是個作用域
的概念。
topologyKey配置了一個label的key,那么存在這個key對應(yīng)的label的所有Node就在同一個作用域里。
5、實戰(zhàn)
理論知識講解完畢,接下來通過實戰(zhàn)加深理解。你可以按照步驟操作實踐。
5.1、nodeName調(diào)度
比如要將Pod調(diào)度到nodeName是k8s-worker-2的節(jié)點上
apiVersion: v1
kind: Pod
metadata:
name: webApp
namespace: demo
labels:
app: webapp
spec:
nodeName: 'k8s-worker-2'
containers:
- name: webapp
image: Nginx
ports:
- containerPort: 80
5.2、nodeSelector調(diào)度
比如要將Pod調(diào)度到具有"special-app"="specialwebapp"的label節(jié)點上。
查看節(jié)點信息:
kubectl describe node k8s-worker-2
Pod的yaml編排文件:
apiVersion: v1
kind: Pod
metadata:
name: webapp
namespace: demo
labels:
app: webapp
spec:
nodeSelector:
# 選擇調(diào)度到具有這個label的節(jié)點
"special-app": "specialwebapp"
containers:
- name: webapp
image: nginx
ports:
- containerPort: 80
查看Pod被調(diào)度到哪臺機器上:
kubectl get pod -n demo -o wide
5.3、Node親和調(diào)度
Node的親和調(diào)度是指,Node和Pod的關(guān)系。
硬親和
定義Pod-Node的硬親和yaml文件:pod_node_required_affinity.yaml
。文件內(nèi)容如下:
apiVersion: v1
kind: Pod
metadata:
name: webapp
namespace: demo
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginx
ports:
- containerPort: 80
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: app
operator: In
values:
- backend
給k8s-worker-3
節(jié)點添加label:
kubectl label node k8s-worker-3 app=backend
查看k8s-worker-3
節(jié)點的label情況:
kubectl get node k8s-worker-3 --show-labels
執(zhí)行上面的yaml部署Pod,可以看到Pod已經(jīng)被調(diào)度到k8s-worker-3
節(jié)點上。
軟親和
軟親和調(diào)度,主要就是加入了多個規(guī)則,每個設(shè)置了權(quán)重,yaml文件如下:
apiVersion: v1
kind: Pod
metadata:
name: webapp
namespace: demo
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginx
ports:
- containerPort: 80
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: app2
operator: Exists
- weight: 20
preference:
matchExpressions:
- key: app
operator: In
values:
- backend2
刪除之前的Pod,刪除之前的k8s-worker-3
節(jié)點的label,再給k8s-worker-2
節(jié)點的增加app2=backend的label。
kubectl delete pod webapp -n demo
kubectl label node k8s-worker-3 app-
kubectl label node k8s-worker-2 app2=backend
部署上面的軟親和yaml文件,可以看到Pod被調(diào)度到了k8s-worker-2
節(jié)點。
5.4、Pod親和調(diào)度
Pod親和調(diào)度,是指Pod和Pod之間的關(guān)系。
硬親和
比如Pod1跟隨Pod2,Pod2被調(diào)度到B節(jié)點,那么Pod1也被調(diào)度到B節(jié)點。
所以這里準(zhǔn)備2個Pod。Pod1使用上面的例子,讓Pod1采用Node硬親和調(diào)度到k8s-worker-3
節(jié)點。然后再部署Pod2,讓它跟隨Pod1,也會被調(diào)度到k8s-worker-3
節(jié)點。
準(zhǔn)備Pod2的yaml編排文件pod_pod_required_affinity.yaml
,如下:
apiVersion: v1
kind: Pod
metadata:
name: webapp-1
namespace: demo
labels:
app: webapp-1
spec:
containers:
- name: webapp
image: nginx
ports:
- containerPort: 80
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- webapp
可以看到Pod2跟隨Pod1,也被調(diào)度到了k8s-worker-3
節(jié)點。
軟親和
軟親和和硬親和類似,只是多了權(quán)重,你可以自行嘗試。
5.5、Pod反親和調(diào)度
反親和的硬親和
接著上面的例子,繼續(xù)準(zhǔn)備Pod3的yaml編排文件,如下:
apiVersion: v1
kind: Pod
metadata:
name: webapp-2
namespace: demo
labels:
app: webapp-2
spec:
containers:
- name: webapp
image: nginx
ports:
- containerPort: 80
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- webapp
使用Pod反親和的方式,讓Pod3和Pod1不會部署在一起。部署完畢后,查看結(jié)果,Pod3因為反親和被調(diào)度到了k8s-worker-2
節(jié)點。
反親和的軟親和
反親和的軟親和 和 硬親和類似,只是多了權(quán)重,你可以自行嘗試。
6、總結(jié)
本文主要快速講解Kubernetes的親和性和反親和性調(diào)度。讀完本文你需要記住以下3點:
-
親和性 和 反親和性的調(diào)度,篩選的條件使用的是Node(Pod)的 label
字段。 -
親和性調(diào)度:就好像Node(Pod)和Pod是關(guān)系很好的閨蜜,Pod說,“只要符合這種label的Node(Pod)都是我的好閨蜜,閨蜜在哪兒我就去哪兒”。 -
反親和性調(diào)度:就好像2個Pod是賭氣的2個孩子,互相對著干,一個往東,另一隨便去哪個方向就是不往東,他們不會去到同一個地方。