EKS 升級概述
Amazon EKS 叢集升級是維護 Kubernetes 環境安全性和穩定性的重要工作。AWS 會定期發布新版本的 Kubernetes,每個版本通常支援約 14 個月。升級叢集可以獲得最新的功能、安全修補和效能改進。
升級路徑說明
EKS 叢集升級必須按照版本順序進行,不支援跨版本升級。例如,從 1.27 升級到 1.29 必須先升級到 1.28,再升級到 1.29。
1
2
3
4
5
6
7
8
9
10
| # 查看目前叢集版本
aws eks describe-cluster \
--name my-eks-cluster \
--query "cluster.version" \
--output text
# 查看可用的 Kubernetes 版本
aws eks describe-addon-versions \
--query "addons[].addonVersions[].compatibilities[].clusterVersion" \
--output text | tr '\t' '\n' | sort -u
|
升級元件順序
建議的升級順序如下:
- 控制平面(Control Plane)
- 核心附加元件(Add-ons)
- 節點群組(Node Groups)
- 應用程式相容性驗證
升級前準備工作
備份叢集資源
在升級前,務必備份所有重要的 Kubernetes 資源:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| # 建立備份目錄
mkdir -p eks-backup/$(date +%Y%m%d)
cd eks-backup/$(date +%Y%m%d)
# 備份所有 namespace
kubectl get namespaces -o yaml > namespaces.yaml
# 備份所有 deployments
kubectl get deployments --all-namespaces -o yaml > deployments.yaml
# 備份所有 services
kubectl get services --all-namespaces -o yaml > services.yaml
# 備份所有 configmaps
kubectl get configmaps --all-namespaces -o yaml > configmaps.yaml
# 備份所有 secrets
kubectl get secrets --all-namespaces -o yaml > secrets.yaml
# 備份 persistent volumes
kubectl get pv -o yaml > persistent-volumes.yaml
kubectl get pvc --all-namespaces -o yaml > persistent-volume-claims.yaml
# 使用 Velero 進行完整備份(推薦)
velero backup create pre-upgrade-backup --include-namespaces '*'
|
檢視叢集現況
1
2
3
4
5
6
7
8
9
10
11
| # 查看叢集基本資訊
aws eks describe-cluster --name my-eks-cluster --output table
# 列出所有節點群組
aws eks list-nodegroups --cluster-name my-eks-cluster
# 查看節點狀態
kubectl get nodes -o wide
# 查看所有 pod 狀態
kubectl get pods --all-namespaces -o wide | grep -v Running
|
檢查叢集相容性
檢查 API 棄用項目
Kubernetes 每個版本都會棄用某些 API,升級前需要確認應用程式沒有使用已棄用的 API:
1
2
3
4
5
6
7
8
9
10
11
| # 安裝 pluto 工具檢查棄用 API
wget https://github.com/FairwindsOps/pluto/releases/download/v5.18.0/pluto_5.18.0_linux_amd64.tar.gz
tar -xzf pluto_5.18.0_linux_amd64.tar.gz
sudo mv pluto /usr/local/bin/
# 檢查叢集中的棄用 API
pluto detect-helm -o wide
pluto detect-files -d ./manifests -o wide
# 檢查特定版本的棄用項目
pluto detect-helm --target-versions k8s=v1.29.0
|
檢查 Add-ons 相容性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 列出目前安裝的 add-ons
aws eks list-addons --cluster-name my-eks-cluster
# 查看每個 add-on 的版本資訊
for addon in $(aws eks list-addons --cluster-name my-eks-cluster --query 'addons[]' --output text); do
echo "=== $addon ==="
aws eks describe-addon \
--cluster-name my-eks-cluster \
--addon-name $addon \
--query 'addon.{name:addonName,version:addonVersion,status:status}'
done
# 查看目標版本支援的 add-on 版本
aws eks describe-addon-versions \
--kubernetes-version 1.29 \
--addon-name vpc-cni \
--query 'addons[].addonVersions[].addonVersion'
|
檢查 Pod Disruption Budgets
1
2
3
4
5
| # 列出所有 PDB
kubectl get pdb --all-namespaces
# 檢查 PDB 設定是否允許節點排程
kubectl describe pdb -n kube-system
|
升級控制平面
使用 AWS CLI 升級
1
2
3
4
5
6
7
8
9
10
11
12
| # 開始升級控制平面(此操作約需 20-30 分鐘)
aws eks update-cluster-version \
--name my-eks-cluster \
--kubernetes-version 1.29
# 追蹤升級進度
aws eks describe-update \
--name my-eks-cluster \
--update-id <update-id>
# 持續監控升級狀態
watch -n 30 "aws eks describe-cluster --name my-eks-cluster --query 'cluster.{status:status,version:version}'"
|
使用 eksctl 升級
1
2
3
4
5
6
7
8
| # 使用 eksctl 升級控制平面
eksctl upgrade cluster \
--name my-eks-cluster \
--version 1.29 \
--approve
# 檢查升級狀態
eksctl get cluster --name my-eks-cluster
|
驗證控制平面升級
1
2
3
4
5
6
7
8
| # 確認控制平面版本
kubectl version --short
# 檢查 API server 健康狀態
kubectl get --raw='/healthz'
# 驗證核心元件運作正常
kubectl get pods -n kube-system
|
升級 Node Groups
升級 Managed Node Groups
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # 列出節點群組及其版本
aws eks list-nodegroups --cluster-name my-eks-cluster
# 查看節點群組詳細資訊
aws eks describe-nodegroup \
--cluster-name my-eks-cluster \
--nodegroup-name standard-workers
# 升級節點群組
aws eks update-nodegroup-version \
--cluster-name my-eks-cluster \
--nodegroup-name standard-workers \
--kubernetes-version 1.29
# 監控升級進度
aws eks describe-nodegroup \
--cluster-name my-eks-cluster \
--nodegroup-name standard-workers \
--query 'nodegroup.{status:status,version:version}'
|
使用 eksctl 升級節點群組
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 升級所有 managed node groups
eksctl upgrade nodegroup \
--cluster my-eks-cluster \
--name standard-workers \
--kubernetes-version 1.29
# 或建立新的節點群組並遷移工作負載
eksctl create nodegroup \
--cluster my-eks-cluster \
--name standard-workers-v129 \
--node-type t3.medium \
--nodes 3 \
--nodes-min 1 \
--nodes-max 5 \
--version 1.29
|
節點滾動更新策略
1
2
3
4
5
6
7
8
9
10
11
12
| # 設定節點群組更新策略
aws eks update-nodegroup-config \
--cluster-name my-eks-cluster \
--nodegroup-name standard-workers \
--update-config maxUnavailable=1
# 手動排空節點(如需精細控制)
kubectl cordon <node-name>
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
# 確認 pod 已遷移
kubectl get pods -o wide --all-namespaces | grep <node-name>
|
升級 Add-ons
升級 VPC CNI
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 查看目前版本
aws eks describe-addon \
--cluster-name my-eks-cluster \
--addon-name vpc-cni
# 取得建議版本
aws eks describe-addon-versions \
--kubernetes-version 1.29 \
--addon-name vpc-cni \
--query 'addons[0].addonVersions[0].addonVersion' \
--output text
# 升級 VPC CNI
aws eks update-addon \
--cluster-name my-eks-cluster \
--addon-name vpc-cni \
--addon-version v1.16.0-eksbuild.1 \
--resolve-conflicts OVERWRITE
|
升級 CoreDNS
1
2
3
4
5
6
7
8
9
10
11
12
| # 查看目前 CoreDNS 版本
kubectl get deployment coredns -n kube-system -o jsonpath='{.spec.template.spec.containers[0].image}'
# 升級 CoreDNS
aws eks update-addon \
--cluster-name my-eks-cluster \
--addon-name coredns \
--addon-version v1.11.1-eksbuild.4 \
--resolve-conflicts OVERWRITE
# 驗證升級
kubectl rollout status deployment/coredns -n kube-system
|
升級 kube-proxy
1
2
3
4
5
6
7
8
9
10
11
12
| # 查看目前版本
kubectl get daemonset kube-proxy -n kube-system -o jsonpath='{.spec.template.spec.containers[0].image}'
# 升級 kube-proxy
aws eks update-addon \
--cluster-name my-eks-cluster \
--addon-name kube-proxy \
--addon-version v1.29.0-eksbuild.1 \
--resolve-conflicts OVERWRITE
# 驗證升級
kubectl rollout status daemonset/kube-proxy -n kube-system
|
批次升級所有 Add-ons
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| #!/bin/bash
CLUSTER_NAME="my-eks-cluster"
K8S_VERSION="1.29"
# 取得所有 add-ons
ADDONS=$(aws eks list-addons --cluster-name $CLUSTER_NAME --query 'addons[]' --output text)
for ADDON in $ADDONS; do
echo "升級 $ADDON..."
# 取得建議版本
RECOMMENDED_VERSION=$(aws eks describe-addon-versions \
--kubernetes-version $K8S_VERSION \
--addon-name $ADDON \
--query 'addons[0].addonVersions[0].addonVersion' \
--output text)
# 執行升級
aws eks update-addon \
--cluster-name $CLUSTER_NAME \
--addon-name $ADDON \
--addon-version $RECOMMENDED_VERSION \
--resolve-conflicts OVERWRITE
echo "$ADDON 升級至 $RECOMMENDED_VERSION"
done
|
升級後驗證
叢集健康檢查
1
2
3
4
5
6
7
8
9
10
11
12
| # 檢查所有節點狀態
kubectl get nodes -o wide
# 確認所有節點版本一致
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.nodeInfo.kubeletVersion}{"\n"}{end}'
# 檢查核心元件健康
kubectl get componentstatuses
kubectl get pods -n kube-system
# 檢查所有 pod 狀態
kubectl get pods --all-namespaces | grep -v Running | grep -v Completed
|
應用程式驗證
1
2
3
4
5
6
7
8
9
10
11
| # 檢查所有 deployment 狀態
kubectl get deployments --all-namespaces
# 檢查所有 service endpoints
kubectl get endpoints --all-namespaces
# 測試 DNS 解析
kubectl run test-dns --image=busybox:1.28 --rm -it --restart=Never -- nslookup kubernetes.default
# 測試網路連通性
kubectl run test-network --image=busybox:1.28 --rm -it --restart=Never -- wget -qO- http://kubernetes.default.svc.cluster.local/healthz
|
效能基準測試
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 部署效能測試 pod
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: performance-test
spec:
containers:
- name: test
image: alpine
command: ["sleep", "3600"]
EOF
# 執行基本效能測試
kubectl exec -it performance-test -- sh -c "time wget -qO- http://kubernetes.default.svc.cluster.local/healthz"
# 清理測試資源
kubectl delete pod performance-test
|
回滾策略
控制平面回滾
EKS 控制平面升級後無法直接回滾,需要透過以下方式處理:
1
2
3
4
5
6
7
8
9
10
11
| # 方法一:建立新叢集並遷移
# 1. 建立舊版本的新叢集
eksctl create cluster \
--name my-eks-cluster-rollback \
--version 1.28 \
--region ap-northeast-1
# 2. 從備份還原資源
velero restore create --from-backup pre-upgrade-backup
# 3. 更新 DNS 或負載平衡器指向新叢集
|
節點群組回滾
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # 建立舊版本節點群組
eksctl create nodegroup \
--cluster my-eks-cluster \
--name standard-workers-rollback \
--node-type t3.medium \
--nodes 3 \
--version 1.28
# 排空新版本節點
kubectl cordon -l eks.amazonaws.com/nodegroup=standard-workers-v129
kubectl drain -l eks.amazonaws.com/nodegroup=standard-workers-v129 --ignore-daemonsets --delete-emptydir-data
# 刪除新版本節點群組
eksctl delete nodegroup \
--cluster my-eks-cluster \
--name standard-workers-v129
|
Add-ons 回滾
1
2
3
4
5
6
7
8
9
10
11
| # 回滾 add-on 到先前版本
aws eks update-addon \
--cluster-name my-eks-cluster \
--addon-name vpc-cni \
--addon-version v1.15.0-eksbuild.2 \
--resolve-conflicts OVERWRITE
# 驗證回滾狀態
aws eks describe-addon \
--cluster-name my-eks-cluster \
--addon-name vpc-cni
|
最佳實踐
升級規劃建議
- 環境分層升級:先在開發環境測試,再升級測試環境,最後升級生產環境
- 維護時段:選擇業務低峰期進行升級
- 監控告警:升級期間加強監控,設定適當的告警閾值
- 文件記錄:詳細記錄升級步驟和遇到的問題
自動化升級腳本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
| #!/bin/bash
set -e
CLUSTER_NAME="my-eks-cluster"
TARGET_VERSION="1.29"
NODEGROUPS=$(aws eks list-nodegroups --cluster-name $CLUSTER_NAME --query 'nodegroups[]' --output text)
echo "開始升級 $CLUSTER_NAME 至 Kubernetes $TARGET_VERSION"
# 步驟 1:升級控制平面
echo "升級控制平面..."
aws eks update-cluster-version \
--name $CLUSTER_NAME \
--kubernetes-version $TARGET_VERSION
# 等待控制平面升級完成
while true; do
STATUS=$(aws eks describe-cluster --name $CLUSTER_NAME --query 'cluster.status' --output text)
if [ "$STATUS" = "ACTIVE" ]; then
break
fi
echo "等待控制平面升級完成... 狀態: $STATUS"
sleep 60
done
# 步驟 2:升級 add-ons
echo "升級 add-ons..."
for ADDON in vpc-cni coredns kube-proxy; do
RECOMMENDED_VERSION=$(aws eks describe-addon-versions \
--kubernetes-version $TARGET_VERSION \
--addon-name $ADDON \
--query 'addons[0].addonVersions[0].addonVersion' \
--output text)
aws eks update-addon \
--cluster-name $CLUSTER_NAME \
--addon-name $ADDON \
--addon-version $RECOMMENDED_VERSION \
--resolve-conflicts OVERWRITE
done
# 步驟 3:升級節點群組
echo "升級節點群組..."
for NODEGROUP in $NODEGROUPS; do
echo "升級節點群組: $NODEGROUP"
aws eks update-nodegroup-version \
--cluster-name $CLUSTER_NAME \
--nodegroup-name $NODEGROUP \
--kubernetes-version $TARGET_VERSION
done
echo "升級完成!"
|
升級檢查清單
參考資料