本文已超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
Kubernetes 1.27:StatefulSet 啟動序數簡化遷移
Kubernetes v1.26 為 StatefulSets 引入了一個新的 alpha 級功能,用於控制 Pod 副本的序號編號。從 Kubernetes v1.27 開始,此功能現在為 beta 版。序號可以從任意非負數開始。此部落格文章將討論如何使用此功能。
背景
StatefulSets 序號為 pod 副本提供循序識別碼。當使用 OrderedReady
Pod 管理時,Pod 是從序號索引 0
到 N-1
建立的。
在現今的 Kubernetes 中,跨叢集協調 StatefulSet 遷移具有挑戰性。備份和還原解決方案存在,但這些方案需要應用程式在遷移之前縮減到零個副本。在當今完全連線的世界中,即使是計畫性的應用程式停機時間也可能無法讓您達到業務目標。您可以使用 串聯刪除 或 On Delete 來遷移個別 pod,但是這容易出錯且難以管理。當您的 Pod 失敗或被逐出時,您會失去 StatefulSet 控制器的自我修復優勢。
Kubernetes v1.26 使 StatefulSet 能夠負責範圍 {0..N-1} 內的序號範圍(序號 0、1、... 到 N-1)。有了它,您可以縮減來源叢集中的範圍 {0..k-1},並擴展目的地叢集中的互補範圍 {k..N-1},同時保持應用程式可用性。這使您能夠在跨叢集協調遷移時,保留最多一個語義(表示在 StatefulSet 中最多只有一個具有給定身分識別的 Pod 執行)和 滾動更新 行為。
為何我會想要使用此功能?
假設您在一個叢集中執行 StatefulSet,並且需要將其遷移到另一個叢集。有很多原因會讓您需要這樣做
- 擴展性:您的 StatefulSet 已擴展得太大,超出叢集的負荷,並已開始擾亂叢集中其他工作負載的服務品質。
- 隔離:您正在多個使用者存取的叢集中執行 StatefulSet,而命名空間隔離不足以滿足需求。
- 叢集組態:您想要將 StatefulSet 移動到不同的叢集,以使用目前叢集上不可用的某些環境。
- 控制平面升級:您想要將 StatefulSet 移動到執行升級控制平面的叢集,並且無法處理就地控制平面升級的風險或停機時間。
我該如何使用它?
在叢集上啟用 StatefulSetStartOrdinal
功能閘道,並建立具有自訂 .spec.ordinals.start
的 StatefulSet。
試用看看
在此示範中,我將使用新的機制將 StatefulSet 從一個 Kubernetes 叢集遷移到另一個叢集。將使用 redis-cluster Bitnami Helm chart 安裝 Redis。
所需工具
先決條件
為此,我需要兩個 Kubernetes 叢集,它們都可以存取共用網路和儲存空間;我已將我的叢集命名為 source
和 destination
。具體來說,我需要
- 在兩個叢集上都啟用
StatefulSetStartOrdinal
功能閘道。 kubectl
的用戶端組態,讓我能夠以管理員身分存取這兩個叢集。- 在兩個叢集上都安裝相同的
StorageClass
,並設定為兩個叢集的預設 StorageClass。此StorageClass
應佈建可從任一或兩個叢集存取的底層儲存空間。 - 允許 pod 與任一叢集中的 Pod 互相傳送和接收封包的平面網路拓撲。如果您在雲端供應商上建立叢集,則此組態可能稱為私有雲或私有網路。
在兩個叢集上建立示範命名空間
kubectl create ns kep-3335
在來源叢集中部署具有六個副本的 Redis 叢集
helm repo add bitnami https://charts.bitnami.com/bitnami helm install redis --namespace kep-3335 \ bitnami/redis-cluster \ --set persistence.size=1Gi \ --set cluster.nodes=6
檢查來源叢集中的複製狀態
kubectl exec -it redis-redis-cluster-0 -- /bin/bash -c \ "redis-cli -c -h redis-redis-cluster -a $(kubectl get secret redis-redis-cluster -o jsonpath="{.data.redis-password}" | base64 -d) CLUSTER NODES;"
2ce30362c188aabc06f3eee5d92892d95b1da5c3 10.104.0.14:6379@16379 myself,master - 0 1669764411000 3 connected 10923-16383 7743661f60b6b17b5c71d083260419588b4f2451 10.104.0.16:6379@16379 slave 2ce30362c188aabc06f3eee5d92892d95b1da5c3 0 1669764410000 3 connected 961f35e37c4eea507cfe12f96e3bfd694b9c21d4 10.104.0.18:6379@16379 slave a8765caed08f3e185cef22bd09edf409dc2bcc61 0 1669764411000 1 connected 7136e37d8864db983f334b85d2b094be47c830e5 10.104.0.15:6379@16379 slave 2cff613d763b22c180cd40668da8e452edef3fc8 0 1669764412595 2 connected a8765caed08f3e185cef22bd09edf409dc2bcc61 10.104.0.19:6379@16379 master - 0 1669764411592 1 connected 0-5460 2cff613d763b22c180cd40668da8e452edef3fc8 10.104.0.17:6379@16379 master - 0 1669764410000 2 connected 5461-10922
在目的地叢集中部署具有零個副本的 Redis 叢集
helm install redis --namespace kep-3335 \ bitnami/redis-cluster \ --set persistence.size=1Gi \ --set cluster.nodes=0 \ --set redis.extraEnvVars\[0\].name=REDIS_NODES,redis.extraEnvVars\[0\].value="redis-redis-cluster-headless.kep-3335.svc.cluster.local" \ --set existingSecret=redis-redis-cluster
將來源叢集中的
redis-redis-cluster
StatefulSet 縮減 1 個副本,以移除副本redis-redis-cluster-5
kubectl patch sts redis-redis-cluster -p '{"spec": {"replicas": 5}}'
將相依性從來源叢集遷移到目的地叢集
以下命令將資源從
source
複製到destination
。已移除與destination
叢集無關的詳細資訊(例如:uid
、resourceVersion
、status
)。來源叢集的步驟
注意:如果使用組態為
reclaimPolicy: Delete
的StorageClass
,您應在刪除之前使用reclaimPolicy: Retain
修補source
中的 PV,以保留destination
中使用的底層儲存空間。請參閱 變更 PersistentVolume 的回收策略 以取得更多詳細資訊。kubectl get pvc redis-data-redis-redis-cluster-5 -o yaml | yq 'del(.metadata.uid, .metadata.resourceVersion, .metadata.annotations, .metadata.finalizers, .status)' > /tmp/pvc-redis-data-redis-redis-cluster-5.yaml kubectl get pv $(yq '.spec.volumeName' /tmp/pvc-redis-data-redis-redis-cluster-5.yaml) -o yaml | yq 'del(.metadata.uid, .metadata.resourceVersion, .metadata.annotations, .metadata.finalizers, .spec.claimRef, .status)' > /tmp/pv-redis-data-redis-redis-cluster-5.yaml kubectl get secret redis-redis-cluster -o yaml | yq 'del(.metadata.uid, .metadata.resourceVersion)' > /tmp/secret-redis-redis-cluster.yaml
目的地叢集的步驟
注意:對於 PV/PVC,此程序僅在您的 PV 使用的底層儲存系統可以支援複製到
destination
時才有效。與特定節點或拓撲相關聯的儲存空間可能不受支援。此外,某些儲存系統可能會在 PV 物件外部儲存有關磁碟區的其他 metadata,並且可能需要更專業的順序來匯入磁碟區。kubectl create -f /tmp/pv-redis-data-redis-redis-cluster-5.yaml kubectl create -f /tmp/pvc-redis-data-redis-redis-cluster-5.yaml kubectl create -f /tmp/secret-redis-redis-cluster.yaml
將目的地叢集中的
redis-redis-cluster
StatefulSet 擴展 1 個副本,起始序號為 5kubectl patch sts redis-redis-cluster -p '{"spec": {"ordinals": {"start": 5}, "replicas": 1}}'
檢查目的地叢集中的複製狀態
kubectl exec -it redis-redis-cluster-5 -- /bin/bash -c \ "redis-cli -c -h redis-redis-cluster -a $(kubectl get secret redis-redis-cluster -o jsonpath="{.data.redis-password}" | base64 -d) CLUSTER NODES;"
我應該會看到新的副本(標記為
myself
)已加入 Redis 叢集(IP 位址屬於與來源叢集中的副本不同的 CIDR 區塊)。2cff613d763b22c180cd40668da8e452edef3fc8 10.104.0.17:6379@16379 master - 0 1669766684000 2 connected 5461-10922 7136e37d8864db983f334b85d2b094be47c830e5 10.108.0.22:6379@16379 myself,slave 2cff613d763b22c180cd40668da8e452edef3fc8 0 1669766685609 2 connected 2ce30362c188aabc06f3eee5d92892d95b1da5c3 10.104.0.14:6379@16379 master - 0 1669766684000 3 connected 10923-16383 961f35e37c4eea507cfe12f96e3bfd694b9c21d4 10.104.0.18:6379@16379 slave a8765caed08f3e185cef22bd09edf409dc2bcc61 0 1669766683600 1 connected a8765caed08f3e185cef22bd09edf409dc2bcc61 10.104.0.19:6379@16379 master - 0 1669766685000 1 connected 0-5460 7743661f60b6b17b5c71d083260419588b4f2451 10.104.0.16:6379@16379 slave 2ce30362c188aabc06f3eee5d92892d95b1da5c3 0 1669766686613 3 connected
針對其餘副本重複步驟 #5 到 #7,直到來源叢集中的 Redis StatefulSet 縮減為 0,並且目的地叢集中的 Redis StatefulSet 運作正常且總共有 6 個副本。
下一步?
此功能為將 StatefulSet 分割到多個叢集提供了一個建構區塊,但並未規定應如何遷移 StatefulSet 的機制。遷移需要協調 StatefulSet 副本,以及協調儲存和網路層。這取決於 StatefulSet 安裝的應用程式的儲存和連線需求。此外,許多 StatefulSet 由 operator 管理,這為遷移增加了另一層複雜性。
如果您有興趣建構增強功能以使這些流程更輕鬆,請加入 SIG Multicluster 以做出貢獻!