寫這篇想要分享的重點:
深入理解 Kubernetes 為什麼不直接拿 Container 作為最小調度單位,並掌握 Pod 的底層資源共享機制、生命週期狀態(Status),以及如何透過指令快速生成結構正確的 YAML 設定檔。這篇想要講什麼:
- 為什麼是 Pod 而非 Container?(共享 Network Namespace 與 Volume 機制)。
- Pod 的生命週期與常見狀態解讀(Pending, Running, CrashLoopBackOff)。
- Pod YAML 基礎四大區塊與 Imperative 快捷指令生成技巧。
為何要寫這篇:
前三天我們搞懂了 Control Plane、Worker Node 架構以及底層 Container Runtime 的演進。今天我們介紹 K8s 最重要的工作組件——Pod,這是每一位 DevOps 與雲端工程師一定都要碰到的組件。
Namespace (Linux): 命名空間 / 隔離空間
Network Namespace: 網路命名空間
Sidecar Pattern: Sidecar 模式 / 邊車模式
Declarative / Imperative: 宣告式(聲明式) / 命令式(指令式)
pull: 拉取
許多初學者剛接觸 K8s 時最常問:「既然 Docker 已經有 Container 了,為什麼 K8s 還要多包一層 Pod?」
答案在於:現實中的應用程式往往需要『緊密耦合(Tightly Coupled)』的彈性互動運作。
+-----------------------------------------------------------------------+
| POD (獨立運作的專案小組 / 獨立工作桌) |
| |
| - 共享 IP 位址 (例如: 10.244.1.15) |
| - 共享 Loopback (localhost 互相通訊) |
| - 共享 Volume (公用硬碟 / 資料共用區) |
| |
| +--------------------------+ +-----------------------------+ |
| | Main Container | | Sidecar Container | |
| | (主要工程師: Nginx Web) | | (助理工程師: Log Collector) | |
| | 負責主要業務邏輯 (Port 80) | | 負責收集與搬運 Log | |
| +--------------------------+ +-----------------------------+ |
| |
+-----------------------------------------------------------------------+
💡 一個Pod裡面可以跑多個Containers!
如果把容器想像成「單一員工」,那 Pod 就是「為了同一個目標組成的專案小組」。K8s 永遠是把整個專案小組(Pod)一起打包放到同一台機器上。
共用網路(Network Namespace):
共用儲存(Volume):
智慧工廠比喻:
如果 Container 是廠房裡的單一機件,Pod 就是一組完整整合好的標準生產機台。廠長(
kubelet)在派工時,永遠是把整個機台一起搬到合適的工作間(Worker Node)。主機件(Main Container)與附帶的監測感測器(Sidecar Container)共用同一個電源插座(共享 IP/Port)與內部運料管道(共享 Volume),確保機件之間合作無間。
當你透過 K8s 跑起來 Pod 時,Pod 會經歷一系列的生命週期狀態(Phase)。學會看懂 kubectl get pods 輸出的 Status 是現場除錯的第一步:
+-----------+ 綁定 Node +-----------+ 拉取 Image +-----------+
| Pending | -----------------> | Container | -----------------> | Running |
| (等待排程) | | Creating | | (正常運作) |
+-----------+ +-----------+ +-----------+
| |
| 資源不足 / Taints 阻擋 | 應用程式 Crash
v v
+-----------+ +--------------------+
| Failed / | | CrashLoopBackOff |
| Unknown | | (重複掛掉與重啟) |
+-----------+ +--------------------+
Pending:API Server 已接收到請求並寫入 etcd,但 kube-scheduler 還沒找到合適的 Node 指派給它,或是 kubelet 正準備開始拉取 Image。
ContainerCreating:Node 已選定,kubelet 正透過 CRI 指揮 containerd 拉取 Image、建立網路與設定掛載。
Running:Pod 已經成功綁定到 Node 上了,且裡面的 Container 都已被成功建立並至少有一個正在運行中。
CrashLoopBackOff:最常見的異常狀態,容器啟動後因為某些原因不斷崩潰(Crash)退出,K8s 觸發重啟機制後再次掛掉,導致重啟間隔時間被不斷拉長(Back-off)。
在 K8s 中,我們習慣用 YAML 檔案 來宣告預期狀態(Desired State)。不管是任何 K8s 物件,YAML 一定包含以下四大結構:
apiVersion: v1 # 1. API 版本(這個物件屬於哪個 API 群組)
kind: Pod # 2. 物件類型(Pod, Service, Deployment...)
metadata: # 3. metadata(大家都只用英文講他), (囊括: 名稱、標籤 Namespace、Label)
name: my-web-pod
labels:
app: web
spec: # 4. 規格細節(最多設定都放這邊)
containers:
- name: nginx-container
image: nginx:1.25
ports:
- containerPort: 80
apiVersion:指定這個物件在 K8s API 中的版本(例如 Pod 是 v1,Deployment 是 apps/v1)。kind:告訴 K8s 你現在要建立的是什麼種類的物件。metadata:用來識別該物件的資料,包含 name(名稱)、namespace(所屬命名空間)與 labels(用來做篩選的比對標籤)。spec:最重要的一區! 宣告這個物件的「預期狀態」,如要跑什麼 Image、開什麼 Port、環境變數與資源限制(Limits/Requests)。在日常維運,手敲 YAML 容易出錯(特別是 YAML 嚴格要求的縮排)。常用以下指令快速產生 YAML 範本:
# 產生一個名為 nginx-pod 的 Pod YAML 檔(--dry-run=client: 不實際建立物件)
kubectl run nginx-pod --image=nginx:1.25 --dry-run=client -o yaml > pod.yaml
--dry-run=client:告訴 API Server 只在 Client 端測試驗證,不要真正發送到叢集建立。-o yaml:將預計產生的物件以標準 YAML 格式輸出到 Terminal,配合 > 即可直接存成yaml檔案。output:
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx-pod
name: nginx-pod
spec:
containers:
- image: nginx:1.25
name: nginx-pod
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
這樣就可以快速生成一個yaml範本然後再修改裡面內容就好了
本篇總結:
Pod 是 K8s 最小的作業組件,透過讓容器共用 Network Namespace 與 Volume,解決了多容器緊密耦合的情境;學會解讀 Pod 生命週期狀態(如 Pending 與 CrashLoopBackOff),並熟練四大 YAML 架構與快捷指令生成,是進入 K8s 實務開發的基石。
下一篇預告:
掌握了基礎 Pod 部署與 YAML 撰寫後,明天 Day 05 我們將深入剖析 【指令】聲明式 vs 命令式:Imperative vs Declarative 操作哲學!重點比較 kubectl run/create 與 kubectl apply 的差異、Three-way Merge 合併機制,以及如何善用 kubectl explain 技巧
Pending(排程排不下去/資源不夠)、Running(正常運作)、CrashLoopBackOff(程式出錯或環境變數設定錯誤導致重啟循環)。apiVersion(API 版本)、kind(物件種類)、metadata(名稱與 Label)、spec(核心規格宣告)。kubectl run ... --dry-run=client -o yaml 快速長出標準 YAML 範本,省去手打縮排的時間。