還記得 Day 01 我們用 kubeadm 建立了 Kubernetes v1.34 叢集嗎?
當時特別保留了一個 minor version 的升級空間,就是為了在系列最後實際走一次 Kubernetes 的升級流程。
Kubernetes 大約每年會釋出三個 minor version,因此叢集版本也需要持續維護。
當某個版本進入 EOL 之後,就不再獲得官方的 Security Update 與 Bug Fix。因此,叢集升級不是單純為了追求新功能,更重要的是維持安全性、穩定性與版本支援。
今天我們會使用 kubeadm,將目前的 Kubernetes v1.34 叢集升級到 v1.35,完整走過 Control Plane 與 Worker Node 的升級流程。
今天內容涵蓋:
本篇延續 Day 01 的環境(1 Master + 2 Worker,Debian,v1.34.0),升級目標為 v1.35.0。

⚠️ 升級順序要先 Control Plane,再 Worker
kubeadm 升級時,應先升級 Control Plane Node,再逐一升級 Worker Node。
其中 kubelet 的版本不應高於 kube-apiserver,否則會超出 Kubernetes 支援的版本偏差範圍。
v1.34 → v1.35 ✅v1.34 → v1.36 ❌升級前先確認目前叢集狀態:
kube-system 內的重要 Pod 正常運行# 確認目前版本
kubectl version
kubeadm version
# 確認所有 Node 狀態
kubectl get nodes
# 確認系統 Pod
kubectl get pods -n kube-system

執行節點:僅在 master 上執行
Day 01 使用的是 Kubernetes v1.34 Repository,現在要把套件來源切換到 v1.35:
# 更新 GPG 金鑰
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key | \
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 更新 Repository
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /" | \
sudo tee /etc/apt/sources.list.d/kubernetes.list
# 更新套件索引
sudo apt-get update
先解除 kubeadm 的版本鎖定:
sudo apt-mark unhold kubeadm
查看目前 Repository 中可以安裝的版本:
apt-cache madison kubeadm
確認目標版本後再安裝:
sudo apt-get install -y kubeadm=1.35.0-1.1
重新鎖定 kubeadm:
sudo apt-mark hold kubeadm
最後確認版本:
kubeadm version

應該會看到:
GitVersion:"v1.35.0"
💡 本篇先將 kubeadm 升級到
v1.35.0。同一個v1.35minor version 之後仍可能有更新的 Patch Release,實際可用版本請以apt-cache madison kubeadm與後續的kubeadm upgrade plan結果為準。
在真正修改 Control Plane 之前,先讓 kubeadm 檢查目前叢集是否符合升級條件:
sudo kubeadm upgrade plan
💡
kubeadm upgrade plan做了什麼?它會檢查目前叢集狀態,並列出:
- 可以升級的 Kubernetes 版本
- Control Plane 元件的目前版本與目標版本
- kubelet 等需要後續手動升級的元件
- 升級前需要處理的問題
upgrade plan只會進行檢查,不會真正修改叢集。
你應該會看到類似下面的結果:

從這次輸出可以看到,目前 v1.35 系列可用的升級目標已經到:
v1.35.2
💡 為什麼前面 kubeadm 是 v1.35.0,這裡卻顯示 v1.35.2?
v1.35.0和v1.35.2都屬於 Kubernetesv1.35minor version,只是 Patch Version 不同。
kubeadm upgrade plan會依目前可用的版本資訊,顯示同一個 minor version 中可升級的 Patch Version。因此看到
v1.35.2並不代表前面的v1.35.0安裝有問題,而是代表v1.35系列已經有更新的 Patch Release 可用。
⚠️ 遇到 CoreDNS Migration 檢查錯誤
如果出現:
[ERROR CoreDNSUnsupportedPlugins] [ERROR CoreDNSMigration]代表 kubeadm 無法正常完成 CoreDNS 的升級相容性檢查。
建議先確認目前的 CoreDNS Image 與 Corefile 設定,而不是直接忽略錯誤。
如果只是 Lab 環境,並且已經了解可能的影響,可以將指定的 Preflight Error 降為 Warning:
sudo kubeadm upgrade plan \ --ignore-preflight-errors=CoreDNSUnsupportedPlugins,CoreDNSMigration後續執行
kubeadm upgrade apply時,如果仍出現相同檢查,也需要加入相同參數。
確認升級計畫沒有問題後,就可以正式升級 Control Plane。
如果 Step 3 沒有遇到 CoreDNS 相關錯誤:
sudo kubeadm upgrade apply v1.35.0
如果前面的 upgrade plan 因 CoreDNS Migration 檢查失敗,而你已經確認要在 Lab 環境中略過:
sudo kubeadm upgrade apply v1.35.0 \
--ignore-preflight-errors=CoreDNSUnsupportedPlugins,CoreDNSMigration
⚠️ Preflight 設定要保持一致
kubeadm upgrade apply也會再次執行升級前檢查。如果 Step 3 是使用
--ignore-preflight-errors才通過,這裡也需要帶上相同的參數。
執行後,kubeadm 會升級 Control Plane 相關元件,例如:
kube-apiserver
kube-controller-manager
kube-scheduler
kube-proxy
💡 升級過程中會發生什麼?
kubeadm 會更新 Control Plane 的設定與 Static Pod Manifest。
當
/etc/kubernetes/manifests/中的檔案發生變化後,kubelet 會偵測並重新建立對應的 Control Plane Pod。

看到類似下面的訊息:
[upgrade] SUCCESS! A control plane node of your cluster was upgraded to "v1.35.0".
就代表這台 Control Plane Node 已成功完成升級。
💡 本篇實作與截圖固定使用
v1.35.0。前一步kubeadm upgrade plan顯示的v1.35.2,代表同一個v1.35minor version 中已有較新的 Patch Release 可用。
⚠️ 注意
kubeadm upgrade apply會升級 Control Plane 相關元件,但kubelet和kubectl仍需要另外升級。
先解除版本鎖定:
sudo apt-mark unhold kubelet kubectl
升級到 v1.35.0:
sudo apt-get install -y \
kubelet=1.35.0-1.1 \
kubectl=1.35.0-1.1
重新鎖定版本:
sudo apt-mark hold kubelet kubectl
重新載入 systemd 設定並重啟 kubelet:
sudo systemctl daemon-reload
sudo systemctl restart kubelet
先確認 Node 版本:
kubectl get nodes
再確認 kube-system 內的 Pod 是否正常:
kubectl get pods -n kube-system
此時應該會看到:

這是正常的。
目前只有 Control Plane Node 完成升級,Worker Node 還維持在 v1.34.0,接下來再逐一升級 Worker Node。
⚙️ 執行方式:逐一升級每個 Worker Node
Worker Node 的升級流程需要在 Control Plane Node 與 Worker Node 之間交替操作,請注意每個步驟的執行位置。
# 在 master 上執行
kubectl drain node1 \
--ignore-daemonsets \
--delete-emptydir-data
💡
kubectl drain做了什麼?
- 將 Node 標記為
SchedulingDisabled,避免新的 Pod 被排程到這台 Node- 驅逐可以被驅逐的 Pod
- 由 Deployment、ReplicaSet、StatefulSet 等 Controller 管理的工作負載,會依照期望狀態在其他可用 Node 上重新建立
參數說明:
--ignore-daemonsets:略過 DaemonSet 管理的 Pod,例如calico-node、kube-proxy--delete-emptydir-data:允許刪除使用emptyDir的 Pod;其中的暫存資料會一起消失
確認 node1 已停止接收新的 Pod:
kubectl get nodes
此時 node1 應該會顯示:

SSH 到 node1 後,先把 Kubernetes Package Repository 切換到 v1.35:
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key | \
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /" | \
sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
接著升級 kubeadm:
sudo apt-mark unhold kubeadm
sudo apt-get install -y kubeadm=1.35.0-1.1
sudo apt-mark hold kubeadm
在 node1 上執行:
sudo kubeadm upgrade node

💡
upgrade apply和upgrade node有什麼差別?
kubeadm upgrade apply:用於第一台 Control Plane Node,負責升級整個叢集的 Control Plane 設定與相關元件kubeadm upgrade node:用於其他節點對 Worker Node 來說,
kubeadm upgrade node主要會讀取叢集設定,並更新這台 Node 的 kubelet configuration。如果是在額外的 Control Plane Node 上執行,則還會更新該節點的 Control Plane Static Pod Manifest。
解除版本鎖定:
sudo apt-mark unhold kubelet kubectl
升級 kubelet 和 kubectl:
sudo apt-get install -y \
kubelet=1.35.0-1.1 \
kubectl=1.35.0-1.1
重新鎖定版本:
sudo apt-mark hold kubelet kubectl
重新載入 systemd 並重啟 kubelet:
sudo systemctl daemon-reload
sudo systemctl restart kubelet
在 master 上執行,讓 node1 重新接受 Pod 排程:
kubectl uncordon node1
接著確認節點狀態與版本:
kubectl get nodes

node1的VERSION應該已經變成v1.35.0,STATUS則恢復為Ready。接著對
node2重複 Step 7~11,直到所有 Worker Node 都完成升級。

| 問題 | 原因與處理方式 |
|---|---|
drain 卡住 |
可能受到 PodDisruptionBudget、local storage 或 unmanaged Pod 影響,先查看錯誤訊息再決定是否使用 --delete-emptydir-data 或 --force |
kubeadm upgrade plan 找不到目標版本 |
確認 apt Repository 已切換到 v1.35,並重新執行 apt-get update |
| 升級後 kubelet 無法啟動 | 使用 systemctl status kubelet、journalctl -u kubelet 查看錯誤,並確認 kubelet 版本與設定 |
Node 長時間停在 NotReady |
檢查 kubelet、Container Runtime 與 CNI 狀態,確認升級後相關元件是否正常 |
⚠️ 如果遇到
CoreDNSUnsupportedPlugins或CoreDNSMigration,建議先確認 CoreDNS Image 與 Corefile 設定。只有在 Lab 環境、且已了解影響時,再考慮使用--ignore-preflight-errors。
今天完成了 Kubernetes 叢集從 v1.34 升級到 v1.35 的完整流程,回顧幾個重點:
| 學到的東西 | 一句話總結 |
|---|---|
| 升級順序 | 先升級 Control Plane,再逐一升級 Worker Node |
| 版本跨度 | kubeadm 一次只能升一個 minor version,跨多個版本需要逐版升級 |
| drain / uncordon | 升級 Worker 前先排空節點,完成後再恢復排程,降低工作負載中斷風險 |
| upgrade apply vs node | 第一台 Control Plane 使用 upgrade apply,其餘 Node 使用 upgrade node |
| kubelet 要手動升級 | kubeadm upgrade 不會自動升級 kubelet,需要另外更新套件並重新啟動 |
| daemon-reload | 升級 kubelet 後重新載入 systemd 設定,再重新啟動 kubelet |
💡 實務小提醒
在生產環境中,升級前應先備份 etcd、確認 PodDisruptionBudget 與工作負載副本配置,並盡量安排在低流量時段執行。
如果是多 Control Plane 的 HA 架構,第一台 Control Plane 使用
kubeadm upgrade apply,其餘 Control Plane Node 則使用kubeadm upgrade node。