Kubernetes(k8s)親和性調(diào)度

一般情況下我們部署的 Pod 是通過集群的自動調(diào)度策略來選擇節(jié)點的只搁,默認情況下調(diào)度器考慮的是資源足夠,并且負載盡量平均突诬,但是有的時候我們需要能夠更加細粒度的去控制 Pod 的調(diào)度,比如我們內(nèi)部的一些服務(wù) gitlab 之類的也是跑在Kubernetes集群上的,我們就不希望對外的一些服務(wù)和內(nèi)部的服務(wù)跑在同一個節(jié)點上了葵第,擔(dān)心內(nèi)部服務(wù)對外部的服務(wù)產(chǎn)生影響;但是有的時候我們的服務(wù)之間交流比較頻繁合溺,又希望能夠?qū)⑦@兩個服務(wù)的 Pod 調(diào)度到同一個的節(jié)點上卒密。這就需要用到 Kubernetes 里面的一個概念:親和性和反親和性。

親和性有分成節(jié)點親和性(nodeAffinity)和 Pod 親和性(podAffinity)棠赛。

nodeSelector

在了解親和性之前哮奇,我們先來了解一個非常常用的調(diào)度方式:nodeSelector膛腐。我們知道label是kubernetes中一個非常重要的概念,用戶可以非常靈活的利用 label 來管理集群中的資源鼎俘,比如最常見的一個就是 service 通過匹配 label 去匹配 Pod 資源哲身,而 Pod 的調(diào)度也可以根據(jù)節(jié)點的 label 來進行調(diào)度。

我們可以通過下面的命令查看我們的 node 的 label:

$ kubectl get nodes --show-labels
NAME      STATUS    ROLES     AGE       VERSION   LABELS
master    Ready     master    147d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=
node02    Ready     <none>    67d       v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,course=k8s,kubernetes.io/hostname=node02
node03    Ready     <none>    127d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,jnlp=haimaxy,kubernetes.io/hostname=node03

現(xiàn)在我們先給節(jié)點node02增加一個com=youdianzhishi的標簽贸伐,命令如下:

$ kubectl label nodes node02 com=youdianzhishi
node "node02" labeled

我們可以通過上面的--show-labels參數(shù)可以查看上述標簽是否生效勘天。當 node 被打上了相關(guān)標簽后,在調(diào)度的時候就可以使用這些標簽了捉邢,只需要在 Pod 的spec字段中添加nodeSelector字段脯丝,里面是我們需要被調(diào)度的節(jié)點的 label 即可。比如伏伐,下面的 Pod 我們要強制調(diào)度到 node02 這個節(jié)點上去巾钉,我們就可以使用 nodeSelector 來表示了:(node-selector-demo.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 命令查看調(diào)度結(jié)果:

$ kubectl create -f node-selector-demo.yaml
pod "test-busybox" created
$ kubectl describe pod test-busybox
Name:         test-busybox
Namespace:    default
Node:         node02/10.151.30.63
......
QoS Class:       BestEffort
Node-Selectors:  com=youdianzhishi
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  SuccessfulMountVolume  55s   kubelet, node02    MountVolume.SetUp succeeded for volume "default-token-n9w2d"
  Normal  Scheduled              54s   default-scheduler  Successfully assigned test-busybox to node02
  Normal  Pulling                54s   kubelet, node02    pulling image "busybox"
  Normal  Pulled                 40s   kubelet, node02    Successfully pulled image "busybox"
  Normal  Created                40s   kubelet, node02    Created container
  Normal  Started                40s   kubelet, node02    Started container

可以看到 Events 下面的信息,我們的 Pod 通過默認的 default-scheduler 調(diào)度器被綁定到了node02節(jié)點秘案。不過需要注意的是nodeSelector屬于強制性的砰苍,如果我們的目標節(jié)點沒有可用的資源,我們的 Pod 就會一直處于 Pending 狀態(tài)阱高,這就是nodeSelector的用法赚导。

通過上面的例子我們可以感受到nodeSelector的方式比較直觀,但是還夠靈活赤惊,控制粒度偏大吼旧,接下來我們再和大家了解下更加靈活的方式:節(jié)點親和性(nodeAffinity)。

親和性和反親和性調(diào)度

之前了解了 kubernetes 調(diào)度器的一個調(diào)度流程未舟,我們知道默認的調(diào)度器在使用的時候圈暗,經(jīng)過了 predicates 和 priorities 兩個階段,但是在實際的生產(chǎn)環(huán)境中裕膀,往往我們需要根據(jù)自己的一些實際需求來控制 pod 的調(diào)度员串,這就需要用到 nodeAffinity(節(jié)點親和性)、podAffinity(pod 親和性) 以及 podAntiAffinity(pod 反親和性)昼扛。

親和性調(diào)度可以分成軟策略和硬策略兩種方式:

軟策略就是如果你沒有滿足調(diào)度要求的節(jié)點的話寸齐,pod 就會忽略這條規(guī)則,繼續(xù)完成調(diào)度過程抄谐,說白了就是滿足條件最好了渺鹦,沒有的話也無所謂了的策略
硬策略就比較強硬了箫爷,如果沒有滿足條件的節(jié)點的話痊夭,就不斷重試直到滿足條件為止,簡單說就是你必須滿足我的要求过咬,不然我就不干的策略浦箱。
對于親和性和反親和性都有這兩種規(guī)則可以設(shè)置: preferredDuringSchedulingIgnoredDuringExecution和requiredDuringSchedulingIgnoredDuringExecution吸耿,前面的就是軟策略殴边,后面的就是硬策略。

nodeAffinity

節(jié)點親和性主要是用來控制 pod 要部署在哪些主機上珍语,以及不能部署在哪些主機上的锤岸。它可以進行一些簡單的邏輯組合了,不只是簡單的相等匹配板乙。

比如現(xiàn)在我們用一個 Deployment 來管理3個 pod 副本是偷,現(xiàn)在我們來控制下這些 pod 的調(diào)度,如下例子:(node-affinity-demo.yaml)

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: affinity
  labels:
    app: affinity
spec:
  replicas: 3
  revisionHistoryLimit: 15
  template:
    metadata:
      labels:
        app: affinity
        role: test
    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:
                - node03
          preferredDuringSchedulingIgnoredDuringExecution:  # 軟策略
          - weight: 1
            preference:
              matchExpressions:
              - key: com
                operator: In
                values:
                - youdianzhishi

上面這個 pod 首先是要求不能運行在 node03 這個節(jié)點上募逞,如果有個節(jié)點滿足com=youdianzhishi的話就優(yōu)先調(diào)度到這個節(jié)點上蛋铆。

下面是我們測試的節(jié)點列表信息:

$ 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     <none>    74d       v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,com=youdianzhishi,course=k8s,kubernetes.io/hostname=node02
node03    Ready     <none>    134d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,jnlp=haimaxy,kubernetes.io/hostname=node03

可以看到 node02 節(jié)點有com=youdianzhishi這樣的 label,按要求會優(yōu)先調(diào)度到這個節(jié)點來的放接,現(xiàn)在我們來創(chuàng)建這個 pod刺啦,然后使用descirbe命令查看具體的調(diào)度情況是否滿足我們的要求。

$ kubectl create -f node-affinity-demo.yaml
deployment.apps "affinity" created
$ kubectl get pods -l app=affinity -o wide
NAME                        READY     STATUS    RESTARTS   AGE       IP             NODE
affinity-7b4c946854-5gfln   1/1       Running   0          47s       10.244.4.214   node02
affinity-7b4c946854-l8b47   1/1       Running   0          47s       10.244.4.215   node02
affinity-7b4c946854-r86p5   1/1       Running   0          47s       10.244.4.213   node02

從結(jié)果可以看出 pod 都被部署到了 node02纠脾,其他節(jié)點上沒有部署 pod玛瘸,這里的匹配邏輯是 label 的值在某個列表中,現(xiàn)在Kubernetes提供的操作符有下面的幾種:

In:label 的值在某個列表中
NotIn:label 的值不在某個列表中
Gt:label 的值大于某個值
Lt:label 的值小于某個值
Exists:某個 label 存在
DoesNotExist:某個 label 不存在
如果nodeSelectorTerms下面有多個選項的話苟蹈,滿足任何一個條件就可以了糊渊;如果matchExpressions有多個選項的話,則必須同時滿足這些條件才能正常調(diào)度 POD慧脱。

podAffinity

pod 親和性主要解決 pod 可以和哪些 pod 部署在同一個拓撲域中的問題(其中拓撲域用主機標簽實現(xiàn)渺绒,可以是單個主機,也可以是多個主機組成的 cluster菱鸥、zone 等等)宗兼,而 pod 反親和性主要是解決 pod 不能和哪些 pod 部署在同一個拓撲域中的問題,它們都是處理的 pod 與 pod 之間的關(guān)系氮采,比如一個 pod 在一個節(jié)點上了殷绍,那么我這個也得在這個節(jié)點,或者你這個 pod 在節(jié)點上了扳抽,那么我就不想和你待在同一個節(jié)點上篡帕。

由于我們這里只有一個集群,并沒有區(qū)域或者機房的概念贸呢,所以我們這里直接使用主機名來作為拓撲域,把 pod 創(chuàng)建在同一個主機上面拢军。

$ 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     <none>    74d       v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,com=youdianzhishi,course=k8s,kubernetes.io/hostname=node02
node03    Ready     <none>    134d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,jnlp=haimaxy,kubernetes.io/hostname=node03

同樣楞陷,還是針對上面的資源對象,我們來測試下 pod 的親和性:(pod-affinity-demo.yaml)

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: affinity
  labels:
    app: affinity
spec:
  replicas: 3
  revisionHistoryLimit: 15
  template:
    metadata:
      labels:
        app: affinity
        role: test
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
          name: nginxweb
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - busybox-pod
            topologyKey: kubernetes.io/hostname

上面這個例子中的 pod 需要調(diào)度到某個指定的主機上茉唉,至少有一個節(jié)點上運行了這樣的 pod:這個 pod 有一個app=busybox-pod的 label固蛾。

我們查看有標簽app=busybox-pod的 pod 列表:

$ kubectl get pods -o wide -l app=busybox-pod
NAME           READY     STATUS    RESTARTS   AGE       IP             NODE
test-busybox   1/1       Running   164        7d        10.244.4.205   node02

我們看到這個 pod 運行在了 node02 的節(jié)點上面结执,所以按照上面的親和性來說,上面我們部署的3個 pod 副本也應(yīng)該運行在 node02 節(jié)點上:

$ kubectl get pods -o wide -l app=affinity
NAME                        READY     STATUS    RESTARTS   AGE       IP             NODE
affinity-564f9d7db9-lzzvq   1/1       Running   0          3m        10.244.4.216   node02
affinity-564f9d7db9-p79cq   1/1       Running   0          3m        10.244.4.217   node02
affinity-564f9d7db9-spfzs   1/1       Running   0          3m        10.244.4.218   node02

如果我們把上面的 test-busybox 和 affinity 這個 Deployment 都刪除艾凯,然后重新創(chuàng)建 affinity 這個資源献幔,看看能不能正常調(diào)度呢:

$ kubectl delete -f node-selector-demo.yaml
pod "test-busybox" deleted
$ kubectl delete -f pod-affinity-demo.yaml
deployment.apps "affinity" deleted
$ kubectl create -f pod-affinity-demo.yaml
deployment.apps "affinity" created
$ kubectl get pods -o wide -l app=affinity
NAME                        READY     STATUS    RESTARTS   AGE       IP        NODE
affinity-564f9d7db9-fbc8w   0/1       Pending   0          2m        <none>    <none>
affinity-564f9d7db9-n8gcf   0/1       Pending   0          2m        <none>    <none>
affinity-564f9d7db9-qc7x6   0/1       Pending   0          2m        <none>    <none>

我們可以看到處于Pending狀態(tài)了,這是因為現(xiàn)在沒有一個節(jié)點上面擁有busybox-pod這個 label 的 pod趾诗,而上面我們的調(diào)度使用的是硬策略蜡感,所以就沒辦法進行調(diào)度了,大家可以去嘗試下重新將 test-busybox 這個 pod 調(diào)度到 node03 這個節(jié)點上恃泪,看看上面的 affinity 的3個副本會不會也被調(diào)度到 node03 這個節(jié)點上去郑兴?

我們這個地方使用的是kubernetes.io/hostname這個拓撲域,意思就是我們當前調(diào)度的 pod 要和目標的 pod 處于同一個主機上面贝乎,因為要處于同一個拓撲域下面情连,為了說明這個問題,我們把拓撲域改成beta.kubernetes.io/os览效,同樣的我們當前調(diào)度的 pod 要和目標的 pod 處于同一個拓撲域中却舀,目標的 pod 是不是擁有beta.kubernetes.io/os=linux的標簽,而我們這里3個節(jié)點都有這樣的標簽锤灿,這也就意味著我們3個節(jié)點都在同一個拓撲域中禁筏,所以我們這里的 pod 可能會被調(diào)度到任何一個節(jié)點:

$ kubectl get pods -o wide
NAME                                      READY     STATUS      RESTARTS   AGE       IP             NODE
affinity-7d86749984-glkhz                 1/1       Running     0          3m        10.244.2.16    node03
affinity-7d86749984-h4fb9                 1/1       Running     0          3m        10.244.4.219   node02
affinity-7d86749984-tj7k2                 1/1       Running     0          3m        10.244.2.14    node03
podAntiAffinity

這就是 pod 親和性的用法,而 pod 反親和性則是反著來的衡招,比如一個節(jié)點上運行了某個 pod篱昔,那么我們的 pod 則希望被調(diào)度到其他節(jié)點上去,同樣我們把上面的 podAffinity 直接改成 podAntiAffinity始腾,(pod-antiaffinity-demo.yaml)

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: affinity
  labels:
    app: affinity
spec:
  replicas: 3
  revisionHistoryLimit: 15
  template:
    metadata:
      labels:
        app: affinity
        role: test
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
          name: nginxweb
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - busybox-pod
            topologyKey: kubernetes.io/hostname

這里的意思就是如果一個節(jié)點上面有一個app=busybox-pod這樣的 pod 的話州刽,那么我們的 pod 就別調(diào)度到這個節(jié)點上面來,上面我們把app=busybox-pod這個 pod 固定到了 node03 這個節(jié)點上面來浪箭,所以正常來說我們這里的 pod 不會出現(xiàn)在 node03 節(jié)點上:

$ kubectl create -f pod-antiaffinity-demo.yaml
deployment.apps "affinity" created
$ kubectl get pods -o wide
NAME                                      READY     STATUS      RESTARTS   AGE       IP             NODE
affinity-bcbd8854f-br8z8                  1/1       Running     0          5s        10.244.4.222   node02
affinity-bcbd8854f-cdffh                  1/1       Running     0          5s        10.244.4.223   node02
affinity-bcbd8854f-htb52                  1/1       Running     0          5s        10.244.4.224   node02
test-busybox                              1/1       Running     0          23m       10.244.2.10    node03

這就是 pod 反親和性的用法穗椅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市奶栖,隨后出現(xiàn)的幾起案子匹表,更是在濱河造成了極大的恐慌,老刑警劉巖宣鄙,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袍镀,死亡現(xiàn)場離奇詭異,居然都是意外死亡冻晤,警方通過查閱死者的電腦和手機苇羡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鼻弧,“玉大人设江,你說我怎么就攤上這事锦茁。” “怎么了叉存?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵码俩,是天一觀的道長。 經(jīng)常有香客問我歼捏,道長稿存,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任甫菠,我火速辦了婚禮挠铲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘寂诱。我一直安慰自己拂苹,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布痰洒。 她就那樣靜靜地躺著瓢棒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丘喻。 梳的紋絲不亂的頭發(fā)上脯宿,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機與錄音泉粉,去河邊找鬼连霉。 笑死,一個胖子當著我的面吹牛嗡靡,可吹牛的內(nèi)容都是我干的跺撼。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼讨彼,長吁一口氣:“原來是場噩夢啊……” “哼歉井!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起哈误,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤哩至,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蜜自,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菩貌,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年袁辈,在試婚紗的時候發(fā)現(xiàn)自己被綠了菜谣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡晚缩,死狀恐怖尾膊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荞彼,我是刑警寧澤冈敛,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站鸣皂,受9級特大地震影響抓谴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寞缝,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一癌压、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧荆陆,春花似錦滩届、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至浓体,卻和暖如春泡挺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背命浴。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工娄猫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人生闲。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓媳溺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親跪腹。 傳聞我的和親對象是個殘疾皇子褂删,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容