iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0
Kubernetes

Kubernetes學習心得分享系列 第 5

Day 05:【指令】聲明式 vs 命令式:Imperative vs Declarative 操作

  • 分享至 

  • xImage
  •  

前言

寫這篇想要分享的重點:
釐清 Kubernetes 的作業方式——「聲明式(Declarative)管理」,理解它與「命令式(Imperative)操作」的差別,並掌握 kubectl run/createkubectl apply 的使用時機,以及好用的 kubectl explain

這篇想要講什麼:

  1. 命令式 (Imperative) vs 聲明式 (Declarative) 的差異與時機選擇。
  2. kubectl createkubectl apply 的底層行為差異(包含 last-applied-configuration 機制)。
  3. 實做技巧:利用 kubectl explain 速查 YAML 欄位定義。

為何要寫這篇:
許多熟悉 Linux / Docker 的工程師,剛開始常把 kubectl 當成一般的 bash 指令在用。理解 K8s 的聲明式作業方法,才能真正體會到 GitOps 與基礎設施即程式碼(IaC)的強大優勢。


名詞對應

Imperative: 命令式 / 指令式
Declarative: 宣告式 / 聲明式
Idempotent: 冪等性
Three-way Merge: 三方合併
GitOps: GitOps / Git 自動化維運


1. 命令式 (Imperative) vs 聲明式 (Declarative)

在自動化維運的世界裡,這兩種哲學代表了完全不同的管理邏輯:

+-----------------------------------------------------------------------+
|  命令式 (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 runkubectl createkubectl scale 直播指令。
    • 缺點:缺乏版本控制(Git History)、難以追蹤修改紀錄、且指令不具備冪等性(Non-idempotent)—例如重複下 kubectl create 會直接跳出 AlreadyExists 錯誤。
  • 聲明式(Declarative - 告訴系統「結果要怎樣 What」)

    • 作法:撰寫 YAML 檔案,並透過 kubectl apply -f manifest.yaml 進行部署。
    • 優點:具備冪等性(Idempotent),重複執行一百次結果都相同;檔案可以放進 Git 版控(GitOps),並由 K8s 的 Controller 24 小時不斷修正現狀以符合聲明。

智慧工廠比喻:
命令式就像老闆每天跑進廠房對廠長說:「去拿一台 Nginx 機台進來!改 Port 80!再貼上標籤!」如果重複下發指令,廠長會很困惑或直接打槍你。
聲明式則是老闆直接弄一份「廠房SOP(YAML)」貼在牆上。廠長(kubelet)與稽核員(Controller)會自己看SOP,發現現場少一台就自動補,發現不一樣就自動修,照本宣科。


2. kubectl create vs. kubectl apply 實際做了什麼

許多人剛學 K8s 時會混用 createapply,但兩者在 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)

  1. Last-applied-configuration:上次 apply 時,紀錄在物件 Annotation 中的原始宣告。
  2. Current Live State:目前運作中、在 etcd 裡的真實狀態(可能含有動態分配的 IP 或其他 Controller 加上的系統資訊)。
  3. New File Manifest:你這次準備 apply 的最新 YAML 內容。

kubectl 會計算這三者的差異(Diff),只對有被更動的欄位發送 Patch 請求,這樣既能實現版控更新,又不會破壞 Controller 動態寫入的系統欄位!


3. 實務使用時機與 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

  • 特點:它會直接向你當前的 API Server 查詢該版本的 Schema,回傳完整的欄位型態(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 時實際發生了什麼事情,敬請期待!

Takeaway

  • Imperative vs. Declarative:命令式是一步一步教著做(適合快速除錯);聲明式是宣告預期狀態(適合正式部署與 GitOps)。
  • kubectl apply 的優勢:具備冪等性,並透過 Three-way Merge 計算 Last-applied、Live State 與 New File 的差異進行增量 Patch。
  • 最佳實務搭配:使用 kubectl run/create ... --dry-run=client -o yaml 快速抓出框架,再透過 kubectl apply -f 進行長期宣告式維護。
  • Terminal 辭典:忘記 YAML 欄位結構時,利用 kubectl explain pod.spec.containers.... 即可快速查文件。

上一篇
Day 04:【核心】最小部署單位:Pod 的概念與 YAML 撰寫基礎
下一篇
Day 06:【排程】 節點分配與手動調度控制
系列文
Kubernetes學習心得分享6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言