Try   HackMD

整理 Pod 的十種方式

早安,這是一個關於 Kubernetes 的文章,如果你不知道 Kubernetes 是什麼,建議先去看一下官方文件,另外本文會搭配 GKE 使用。

方法一 什麼都不管,雜成一鍋粥

  1. 說明:把所有的 pod 都放在同一個 node 或 node pool 裡,自動擴展開起來,方便又省事
  2. 優點:方便快速,菜雞工程師都這麼幹
  3. 缺點:混亂

方法二 指定 node pool (指定 node)

  1. 說明:

    1. 如果用的不是 GKE,可能沒有 node pool,如果是拿一般機器建,可能是直接指定 node
    2. GKE 直接指定 node 的風險很高,因為 GKE 很常莫名回收掉你的機器,建議指定 node pool
  2. 方式:

    ​​​​nodeSelector:
    ​​​​	cloud.google.com/gke-nodepool: pool-backend
    ​​​​
    
  3. 優點:

    1. 容易操作
    2. 很好預測 GKE 的行為
    3. 可以指定特定的服務使用特定規格的機器
  4. 缺點

    1. 不能將 pod 的 replica 分散
    2. 如果要為每個服務細分機器規格,那口袋要有點深度

方法三 設定互斥(強互斥)

  1. 說明:

    1. 文件好像是寫「親和性」與「反親和性」
    2. 要求特定 Pod 不要跟某些 label 的 Pod 放在同一個 node
  2. 方式

    ​​​​affinity:
    ​​​​    podAntiAffinity:
    ​​​​      requiredDuringSchedulingIgnoredDuringExecution:
    ​​​​        - labelSelector:
    ​​​​            matchExpressions:
    ​​​​              - key: "app.kubernetes.io/name"
    ​​​​                operator: In
    ​​​​                values:
    ​​​​                  - backend
    ​​​​          topologyKey: "kubernetes.io/hostname"
    
  3. 優點:

    1. 可以拆散 pod 的 replica 讓他們分佈在不同的 node 上
    2. 也可以拆散某些服務,讓他們不會一起出現在同一個 node 上
  4. 缺點

    1. code 又臭又長,設定當下要讀十分鐘的文件,三個月後的自己可能都看不懂
    2. 多個互斥疊加的時候,不好預測會發生什麼事
      1. 想像一下:你在安排員旅房間,只有兩間雙人房。A 討厭 B ,B 跟 D 互相討厭,C 討厭所有人,A 先住進房間 1 。接下來要怎麼安排。
    3. node 可能會不夠用
      1. 假設機器只有 2 臺,但是 Pod A 有 3 個 replica ,且 Pod A 彼此不能在同一臺機器。第 3 個 Pod A 就會起不來

方法四 設定相吸(強相吸)

  1. 說明:

    1. 可以互斥,就可以相吸,這個是互斥的相反
    2. 優缺點亦同,不多做解說
  2. 方式

    ​​​​podAffinity:
    ​​​​      requiredDuringSchedulingIgnoredDuringExecution:
    ​​​​        - labelSelector:
    ​​​​            matchExpressions:
    ​​​​              - key: app
    ​​​​                operator: In
    ​​​​                values:
    ​​​​                  - backend
    ​​​​          topologyKey: "kubernetes.io/hostname"
    

方法五 驅逐多餘的 pod(汙點與容忍)

  1. 說明:

    1. 為 node 設下結界,把它看不上的 pod 通通驅逐
    2. 可以讓某個 node 不能佈署它指定的 pod
    3. 可以佈署在上面的 pod 一定是被 node 選中的 pod
  2. 方式

    1. GKE 的話,要在 GKE 的頁面上設定,而且是以 node pool 為單位(當然,你也可以用 terraform 或 gcloud 設定)

    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

    1. 如果要讓 Pod 可以被佈署到這臺 node 上,就要在 pod 上寫

      ​​​​​​​​tolerations:
      ​​​​​​​​- key: "job"
      ​​​​​​​​  operator: "Equal"
      ​​​​​​​​  value: "true"
      ​​​​​​​​  effect: "NoSchedule"
      
  3. 優點

    1. 不用再為每個 pod 都設定上 nodeSelector ,也不用擔心有迷途的 pod 誤入特定 node
    2. 簡單就可以掌握一臺機器會出現哪些 pod
  4. 缺點

    1. GKE 的話,設定界面在 GKE 上,三年後的自己可能會忘記當時設定了什麼
    2. 不符合直覺,而且很隱晦。第一次看到的人可能不會知道原來某臺機器不接受其他的 pod

方法六 勉強互斥(弱互斥)

  1. 說明:

    1. 雖然我討厭你,但是在不得已的情況下,我們還是可以住在一起 — by Pod A 對 Pod B 的告白
    2. 設定上,Kubernetes 會優先選擇符合條件的 node,但是沒有符合條件,還是會佈署
  2. 方式

    ​​​​podAntiAffinity:
    ​​​​  preferredDuringSchedulingIgnoredDuringExecution:
    ​​​​    - weight: 100
    ​​​​      podAffinityTerm:
    ​​​​        labelSelector:
    ​​​​          matchLabels:
    ​​​​            app.kubernetes.io/name: backend
    ​​​​        topologyKey: kubernetes.io/hostname
    
  3. 優點

    1. 就算 node 不夠用,也不用擔心 pod 會建立不起來
    2. 為互斥增加了彈性
  4. 缺點

    1. 他的 code 跟設定互斥的 code 長得超像
    2. 存在模糊地帶,更不容易預測 pod 的分佈

方法七 勉強相吸(弱相吸)

  1. 說明:
    1. 有互斥,就有相吸,這段是來充字數的
    2. 優缺點亦同,不多做解說

方法八 調整濃度(拓撲傳播約束)

  1. 說明:

    1. 跟勉強互斥自己的 replica 設定雷同,你可以設定特地 pod 在多個 nodes 間的濃度
  2. 方式

    ​​​​topologySpreadConstraints:
    ​​​​  - maxSkew: 1
    ​​​​    topologyKey: kubernetes.io/hostname
    ​​​​    whenUnsatisfiable: DoNotSchedule
    ​​​​    labelSelector:
    ​​​​    - matchLabels:
    ​​​​        app: nginx
    
    1. maxSkew 表示能容忍的 pod 數量差異,設定為 1 代表只容忍差異為 1 個 pod
    2. whenUnsatisfiable 設定當不滿條件下,要如何行動,DoNotSchedule 代表保持 Pending (意同相斥),ScheduleAnyway 代表管他的,就是要佈署(意同勉強相斥)
  3. 優點

    1. 為勉強互斥又增加更多的彈性
  4. 缺點

    1. 預測 Pod 的分佈越來越像在通靈了

方法九 組合拳

  1. 說明:
    • 例如:把方法二的指定 node 跟方法五的驅逐多餘的 pod,一起用的話,就可以製造一臺專屬某個 pod 的 node ,而且那個 pod 不會像變了心的女友一樣,突然就跑到別的 node 串門子
  2. 優點:
    1. 靈活性高,是個一般人,都會想到這麼做
  3. 缺點:
    1. 複雜度變大,管理成本變高

方法十 還是把那些藩籬通通打掉吧

  1. 說明:
    1. 當你費盡心思,結合上面的方法,把所有的 pod 都安排的妥妥當當,明明白白,結果因為機器開太多,所以帳單爆炸貴。老闆詢問:我們要不要把一些 pod 整併到其中一臺 node 裡?
    2. 當你好不容易把 pod 整併進去,但是某天一個斷電,那個 node 剛好死掉,然後服務就掛了。老闆詢問:我們還是開兩臺 node 互相 cover 好了。
    3. 當你好不容易把 pod 設定好 replica 然後把互斥設定都處理好了。老闆詢問:這兩個服務的資源競爭很嚴重,好像會互相影響,要不要把他們分開來?
    4. 歷史總是輪迴的,讓我們回到說明 1
    5. 最後,我們到底為什麼要設定這些東西,把 pod 從東邊搬到西邊,再搬到東邊呢?混在一起做撒尿牛丸不好嗎?
    6. 於是你把阻斷 pod 在 node 間穿梭的高牆推倒,只留下一個 node pool ,並且設定自動擴展
  2. 優點:方便快速,大神工程師都這麼幹
  3. 缺點:混亂(什麼混亂,這是美學 (´ _ > `) ,沒看過下面這張圖嗎?)