昨天搞懂了 K8s 的整體架構,知道 Master Node 和 Worker Node 怎麼分工合作,也看到了那個複雜的流程圖。但是 K8s 不是直接管理 Container,而是管理一個叫 Pod 的東西?今天就來探索 Pod 這個 K8s 的最小單位!
我們使用 Kubernetes 的最終目標是將應用程式以 Container 的方式部署在 Kubernetes Cluster 中的 Worker Node 上。但是 Kubernetes 不會直接在 Worker Node 上部署容器,而是把容器封裝到一個叫 Pod
的 Kubernetes 物件裡。
👉 Pod
就是 Kubernetes 中建置、調度與管理的最小單位。
了解 Pod 是什麼之後,來舉一個最簡單的範例。下圖可以看到假設我們有一個 Python 撰寫的應用程式,把它打包成 Container Instance,並部署到 Cluster 裡的 Worker Node。這個容器會被封裝在一個 Pod 裡:
然而如果存取 Application 的使用者數量增加的話,我們需要新增其他的 Container Instance 來分擔負載。那麼我們要在哪啟動這個 Container Instance 呢?是在同一個 Pod 啟動一個新的 Container Instance 嗎?看到下方動畫很顯然這並不是 K8s 中分擔負載的方式,那麼究竟要怎麼做?
面對更高流量來分散的負載,我們會建立一個全新的 Pod,並且擁有同樣的 Container Instance。而當流量更大的時候,當前的 Worker Node 沒有足夠的容量該怎麼辦?那麼我們就可以部署新的 Pod 在另一個新的 Worker Node,如圖下方動畫就是隨著使用者基數的增加減少,K8s 這邊會進行的 Scale Up 或 Down。
上述例子說明了 Pod 和 Container Instance 通常是一對一的關係,如果需要 Scale Up,就會建立新的 Pod;如果要 Scale Down,則會刪除現有的 Pod,我們不會在既有的 Pod 中新增其他的 Container Instance。
雖然大部分情況下,一個 Pod 裡只會放一個 Container Instance,但其實 Kubernetes 也允許你在同一個 Pod 裡跑多個 Container Instance。但既然同樣的應用程式不會被部署在同一個 Pod,那什麼情況下會需要多容器 Pod?
在某些 scenario 下,除了 Main Container 之外,還會需要 Helper Container 來協助完成特定任務:
在這種 scenario 下,我們希望 Main Container 和 Helper Container 能夠:
localhost
直接通訊接下來我們實際來部署一個 Pod,工具當然還是靠 kubectl
。在 Kubernetes 裡,不管是建立、查看或管理資源,幾乎都要透過它來完成。這邊我們就用大家較為熟悉的 Nginx 當例子:
kubectl run nginx --image=nginx
這行指令會幫我們跑起一個 nginx Pod,映像檔預設會從 Docker Hub 下載下來。當然,如果有 Private 的映像檔來源,例如 Google Cloud Artifact Registry,也可以直接指定。
接著,我們一定會想確認 Pod 的狀態:
kubectl get pods
執行後你會看到 Pod 從 Creating 一路變成 Running / Ready。
如果想看更多細節,可以加上 -o wide
:
kubectl get pods -o wide
這樣就能看到更多欄位,像 IP 就是 Kubernetes 幫 Pod 分配的內部虛擬 IP。同一個 Cluster 裡的其他 Pod 要跟它連線時,就會用這個 IP。另外還有 Node 欄位,可以看到這個 Pod 是跑在哪個 Worker Node 上。如果你有很多 Pod,就能觀察它們是怎麼分散到不同節點去跑的。
再來,如果覺得 get
還不夠詳細,可以用 describe
:
kubectl describe pods
它會列出更完整的資訊,像是狀態細節、事件紀錄、甚至跟哪些 Controller 有關聯。
除了這些常見的指令,其實 kubectl help
還有更多可以探索。不過,指令這麼多要怎麼記呢?我分享我自己記這些指令的方式,其實有個通用的規則:
kubectl [verb] [kind] [object-name]
run
建立、get
查看。nginx
。只要先想清楚「我要對什麼資源,做什麼動作」,就很快能找到對應的指令。
不過到這裡,我們其實都是用 Imperative (命令式) 的方式操作,也就是打一行指令就直接建立 Pod。看似方便,但其實有不少限制:
因此,Kubernetes 更推薦使用 Declarative (聲明式) 的方式。簡單說,就是把想要的狀態(例如 Pod 的名稱、映像檔 (甚至版本)、port 等設定)寫在一個 YAML 檔裡,然後交給 Kubernetes 去「確保」這個狀態被滿足。
這樣做的好處是:
👉 簡單來說:命令式適合學習或快速測試,但在實際專案裡,我們會更依賴聲明式的 YAML。
今天我們了解了 Pod 是 Kubernetes 的最小單位,負責承載並管理容器。接著透過 Single Container Pod 和 Multi-Container Pod 的例子,知道大部分情況下一個 Pod 就是一個 Container,但在某些情境下也會用多容器來搭配協作。最後我們動手用 kubectl
指令實際跑了一個 Nginx Pod,並且比較了 Imperative (命令式) 和 Declarative (聲明式) 兩種操作方式,清楚看到聲明式在專案維護上的優勢。
因此我們明天就要來拆解 YAML 檔的結構,看看裡面有哪些欄位,怎麼去描述一個 Pod,最後再用 YAML 的方式來部署 Pod。
由於我這個文章系列是為了 CKAD 做準備,以開發為主要的目標,因此我不分享我也不會安裝 Kubernetes 🤣🤣。我用的是 kind (Kubernetes in Docker)
來實現 Kubernetes,現在的 Docker 有直接支援安裝 kind
,可以自己選擇 K8s 的版本和要幾個 Node。