Pod、Node、Scheduler:Kubernetes 叢集的三個原子
· tech
上一篇講了 K8s 的靈魂:你宣告期望,reconcile loop 不斷把現實拉過去。但那句「我要 3 個」——3 個什麼?落在哪台機器上?誰決定放哪? 這篇把叢集最基本的三個原子講清楚:Pod、Node、Scheduler。
Pod:最小單位,而且不是「容器」
第一個反直覺的點:K8s 排程與伸縮的最小單位不是容器,是 Pod。 一個 Pod 包住一個(或少數幾個)容器,讓它們同生共死、共享網路與儲存:
為什麼要多這層包裝?因為有些容器天生該綁在一起 —— 例如主服務 + 一個幫它收 log 或當代理的 sidecar,它們要共用網路、一起被排程、一起生死。但別過度用:多數 Pod 就是一個容器。 記住這句話就好:容器是「跑什麼」,Pod 是 K8s 真正搬動、複製、排程的單位。
Node:一台機器
Node 就是一台真正的機器(雲上多半是一台 VM)。上一篇提過叢集分兩半:
- Control Plane(大腦):決定要跑什麼、排到哪、持續修正落差。
- Worker Node(工人):真正跑你 Pod 的機器。每台上面有個 kubelet,負責照顧本機的 Pod、回報狀態給大腦。
所以「我要 3 個 Pod」的實際樣子,就是這 3 個 Pod 被分配到某幾台 Node 上跑。而決定「哪個 Pod 去哪台 Node」的,是第三個原子。
Scheduler:決定 Pod 落哪台
當 reconcile loop 要補一個新 Pod,這個 Pod 一開始是 Pending(還沒有 Node)。Scheduler 的工作,就是幫它挑一台落腳:
過濾與評分背後的旋鈕——requests/limits、node 親和性、taint/toleration——是後面控制「誰跑在哪」的關鍵,這個系列之後會專門一篇講。這裡先知道:Pod 落在哪台不是隨機,是 Scheduler 依資源與規則算出來的。
關鍵心態:Pod 是短命的
最後一個一定要現在就建立的觀念:Pod 是用完即丟的。 它掛掉、被重排、滾動更新換新版時,舊的 Pod 直接消失,reconcile loop 開一個全新的 Pod 補上——新 Pod 有新的 IP。
這代表:你永遠不該記住某個 Pod 的 IP、也別把狀態存在 Pod 裡。 Pod 是牛,不是寵物——壞了就換一頭,不是抱著醫。這帶出兩個之後的主題:既然 Pod 的 IP 會變,別的服務怎麼穩定找到它?(→ Service,系列第 4 篇);Pod 沒了資料就沒了,那資料庫這種有狀態的怎麼辦?(→ Volume 與 StatefulSet,第 6 篇)。
反思
「Pod 不是容器」這個區分,想通就順了
我剛學 K8s 時卡最久的,就是「明明是跑容器,為什麼要多一個 Pod?」後來想通:Pod 是 K8s 的排程單位,容器是執行單位。 K8s 要搬動、複製、放置的是 Pod;至於 Pod 裡放一個還是幾個容器,是「這些東西要不要同生共死」的設計選擇。九成情況一個 Pod 一個容器,別為了炫技硬塞 sidecar。把「單位」這件事分清楚,後面 Deployment 管 Pod、Service 指向 Pod、排程排的是 Pod——全部一次順起來。
Pod 短命是特性,不是 bug
「Pod 隨時會消失、IP 會變」聽起來很不安,但這其實是 K8s 自我修復的前提,不是缺陷。正因為 Pod 被當成可拋棄的,壞了才能無痛換一個。這跟我在 Spark、Spark on K8s 那幾篇反覆講的「executor 用完即刪」是同一種思維——把運算單位當成牛而非寵物。一旦接受這點,你就不會去做「記住某個 Pod」這種注定會痛的事,而會轉去用 K8s 給你的穩定抽象(Service、Volume)。
Scheduler 幫你想「放哪」,但你可以介入
預設 Scheduler 會自動挑一台裝得下的 node,多數時候你不用管。但當你有「這批 Pod 要跑在高記憶體機器」「別跟那個吵鄰居擠同一台」這種需求時,requests、affinity、taint 這些旋鈕就是你介入的方式——我在 Airflow + Spark on K8s 那篇用它把 Airflow 核心釘在穩定 node、把 Spark executor 丟去便宜的 spot node,就是這個道理。先讓 Scheduler 自動幫你放,真的有需求再出手調——這也是我對所有 K8s 進階功能的態度:預設夠用,別為了用而用。