寫這篇想要分享的重點:
釐清 Kubernetes 的作業方式——「聲明式(Declarative)管理」,理解它與「命令式(Imperative)操作」的差別,並掌握kubectl run/create與kubectl apply的使用時機,以及好用的kubectl explain。這篇想要講什麼:
- 命令式 (Imperative) vs 聲明式 (Declarative) 的差異與時機選擇。
kubectl create與kubectl apply的底層行為差異(包含last-applied-configuration機制)。- 實做技巧:利用
kubectl explain速查 YAML 欄位定義。為何要寫這篇:
許多熟悉 Linux / Docker 的工程師,剛開始常把kubectl當成一般的 bash 指令在用。理解 K8s 的聲明式作業方法,才能真正體會到 GitOps 與基礎設施即程式碼(IaC)的強大優勢。
Imperative: 命令式 / 指令式
Declarative: 宣告式 / 聲明式
Idempotent: 冪等性
Three-way Merge: 三方合併
GitOps: GitOps / Git 自動化維運
在自動化維運的世界裡,這兩種哲學代表了完全不同的管理邏輯:
+-----------------------------------------------------------------------+
| 命令式 (Imperative) |
| 「工程師下達具體步驟」 |
| 1. 建立一個 Pod |
| 2. 把它的 Image 改為 Nginx 1.25 |
| 3. 開啟 Port 80 |
+-----------------------------------------------------------------------+
vs
+-----------------------------------------------------------------------+
| 聲明式 (Declarative) |
| 「工程師只宣告預期狀態 (Desired State)」 |
| - 我不管你怎麼做,這座 Cluster 裡面最終必須要有一個名為 Nginx 的 Pod, |
| Image 是 1.25,開 Port 80。 |
+-----------------------------------------------------------------------+
命令式(Imperative - 告訴系統「怎麼做 How」):
kubectl run、kubectl create 或 kubectl scale 直播指令。kubectl create 會直接跳出 AlreadyExists 錯誤。聲明式(Declarative - 告訴系統「結果要怎樣 What」):
kubectl apply -f manifest.yaml 進行部署。智慧工廠比喻:
命令式就像老闆每天跑進廠房對廠長說:「去拿一台 Nginx 機台進來!改 Port 80!再貼上標籤!」如果重複下發指令,廠長會很困惑或直接打槍你。
聲明式則是老闆直接弄一份「廠房SOP(YAML)」貼在牆上。廠長(kubelet)與稽核員(Controller)會自己看SOP,發現現場少一台就自動補,發現不一樣就自動修,照本宣科。
kubectl create vs. kubectl apply 實際做了什麼許多人剛學 K8s 時會混用 create 與 apply,但兩者在 K8s 底層的處理機制完全不同:
+-----------------------------+
| kubectl create -f |
| (只適合第一次建立物件) |
+--------------+--------------+
| 再次執行
v
[ Error: AlreadyExists ]
vs
+-----------------------------+
| kubectl apply -f |
| (適合第一次與後續維護) |
+--------------+--------------+
| 再次執行
v
[ Three-way Merge 比對 ]
|
+-----------+-----------+
| |
v v
(若有變更: Configured) (若無變更: Unchanged)
kubectl apply 的神奇機制:三方合併 (Three-way Merge)當你下達 kubectl apply -f pod.yaml 時,K8s 並不是直接拿新檔案蓋掉舊檔案,而是進行 三方比對(Three-way Merge):
etcd 裡的真實狀態(可能含有動態分配的 IP 或其他 Controller 加上的系統資訊)。kubectl 會計算這三者的差異(Diff),只對有被更動的欄位發送 Patch 請求,這樣既能實現版控更新,又不會破壞 Controller 動態寫入的系統欄位!
kubectl explain 技巧雖然聲明式(Declarative)是維運的主流,但並不代表命令式(Imperative)毫無用處。
| 操作方式 | 常用指令 | 適合情境 |
|---|---|---|
| Imperative(命令式) | kubectl run, kubectl expose, kubectl exec |
臨時現場故障除錯、快速測試網路連線、快速長出 YAML 範本 (就像前面演練的快速生一個yaml出來) |
| Declarative(聲明式) | kubectl apply -f <file/dir>, kubectl delete -f |
正式環境部署、GitOps 流水線、長期維護的專案 |
kubectl explain在寫 YAML 檔時,我們常常忘記某個欄位到底該寫在哪一層(例如 livenessProbe 是在 spec 還是 containers 下面?格式是 List 還是 Object?)。
不用上官網查 Docs,直接在 Terminal 敲下 kubectl explain:
# 查閱 Pod 下面 spec 的完整結構
kubectl explain pod.spec
# 深入查閱 Pod 容器內 livenessProbe 的語法細節
kubectl explain pod.spec.containers.livenessProbe
string / integer / []object)與詳細說明。配合 --recursive 參數甚至能印出整個樹狀結構!KIND: Pod
VERSION: v1
FIELD: livenessProbe <Probe>
DESCRIPTION:
Periodic probe of container liveness. Initiated by the kubelet.
Cannot be updated. More info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
FIELDS:
exec <ExecAction>
One and only one of the supplying attributes must be set.
httpGet <HTTPGetAction>
Custom handler for making HTTP requests.
...
本篇總結:
Kubernetes 以聲明式(Declarative)管理為核心,讓工程師透過宣告預期狀態(YAML)實現自動修復與冪等性部署;實務上應善用 Imperative 指令快速產生範本與除錯,配合 kubectl apply 進行日常維護,並以 kubectl explain 快速查閱 API 規格。
下一篇預告:
釐清了聲明式與命令式的特性後,明天 Day 06:【排程】節點分配與手動調度控制 我們將正式跨入排程領域!將探討 kube-scheduler 的背後運作邏輯(從 Filtering 到 Scoring),教你如何系統化除錯惡夢之 Pending 狀態,並一探透過 nodeName 與 Labels / Selectors 將應用程式發送到指定 Worker Node 時實際發生了什麼事情,敬請期待!
kubectl apply 的優勢:具備冪等性,並透過 Three-way Merge 計算 Last-applied、Live State 與 New File 的差異進行增量 Patch。kubectl run/create ... --dry-run=client -o yaml 快速抓出框架,再透過 kubectl apply -f 進行長期宣告式維護。kubectl explain pod.spec.containers.... 即可快速查文件。