這篇文章已超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
使用 Kubernetes 全新多區域叢集(又名「Ubernetes Lite」)建構高可用性應用程式
編輯註記: 這是 Kubernetes 1.2 新功能 系列深入文章的第三篇
簡介
Kubernetes 最常被要求的功能之一,就是在多個區域中執行應用程式的能力。這是有充分理由的 — 開發人員需要跨多個網域部署應用程式,以在單一區域中斷時提高可用性。
Kubernetes 1.2 在兩週前發布,新增了在多個故障區域(GCP 簡稱為「區域」,Amazon 稱為「可用區域」,在此我們將其稱為「區域」)中執行單一叢集的功能。這是更廣泛努力的第一步,目的是將多個 Kubernetes 叢集聯合在一起(有時以暱稱「Ubernetes」稱之)。這個初始版本(稱為「Ubernetes Lite」)透過將應用程式分散到單一雲端供應商內的多個區域,來提高應用程式的可用性。
多區域叢集經過刻意簡化,而且在設計上非常容易使用 — 不需要 Kubernetes API 變更,也不需要應用程式變更。您只需將現有的 Kubernetes 應用程式部署到新型多區域叢集中,您的應用程式就會自動具備區域故障的復原能力。
現在進入一些細節...
Ubernetes Lite 的運作方式是透過標籤來利用 Kubernetes 平台的可擴展性。如今,當節點啟動時,標籤會新增到系統中的每個節點。透過 Ubernetes Lite,系統已擴展為也新增關於節點執行所在區域的資訊。有了這些資訊,排程器就可以針對應用程式實例的放置做出明智的決策。
具體來說,排程器已分散 Pod,以盡量減少任何單一節點故障的影響。透過 Ubernetes Lite,藉由 SelectorSpreadPriority
,排程器將盡最大努力跨區域分散放置。我們應注意,如果叢集中的區域是異質的(例如,不同數量的節點或不同類型的節點),您可能無法實現跨區域平均分散 Pod。如果需要,您可以使用同質區域(相同數量和類型的節點)來降低不均勻分散的可能性。
這種改良的標籤也適用於儲存。當建立持久性磁碟區時,PersistentVolumeLabel
許可控制器會自動將區域標籤新增到其中。然後排程器(透過 VolumeZonePredicate
述詞)將確保聲明給定磁碟區的 Pod 僅放置在與該磁碟區相同的區域中,因為磁碟區無法跨區域附加。
逐步解說
我們現在將逐步解說如何在 Google Compute Engine (GCE) 和 Amazon EC2 上,使用 Kubernetes 隨附的預設 kube-up 指令碼來設定和使用多區域叢集。雖然我們重點介紹 GCE 和 EC2,但此功能適用於任何 Kubernetes 1.2 部署,您可以在叢集設定期間進行變更。此功能也將在 Google Container Engine (GKE) 中很快推出。
啟動您的叢集
為 Kubernetes 建立多區域部署與單區域叢集相同,但您需要傳遞環境變數("MULTIZONE”
)來告知叢集管理多個區域。我們先從在 GCE 和/或 EC2 上建立多區域感知叢集開始。
GCE
curl -sS https://get.k8s.io | MULTIZONE=true KUBERNETES_PROVIDER=gce
KUBE_GCE_ZONE=us-central1-a NUM_NODES=3 bash
EC2
curl -sS https://get.k8s.io | MULTIZONE=true KUBERNETES_PROVIDER=aws
KUBE_AWS_ZONE=us-west-2a NUM_NODES=3 bash
在此指令的結尾,您將啟動一個叢集,該叢集已準備好管理在多個區域中執行的節點。您也將啟動 NUM_NODES
個節點和叢集的控制平面(即 Kubernetes master),全部都在 KUBE_{GCE,AWS}_ZONE
指定的區域中。在 Ubernetes Lite 的未來迭代中,我們將支援 HA 控制平面,其中 master 元件會在多個區域中複寫。在那之前,如果執行 master 的區域發生故障,master 將變得不可用。但是,在所有區域中執行的容器將繼續執行,並在故障時由 Kubelet 重新啟動,因此應用程式本身將能容忍此類區域故障。
節點已加上標籤
若要查看新增到節點的其他 metadata,只需檢視叢集的所有標籤(此處的範例是在 GCE 上)
$ kubectl get nodes --show-labels
NAME STATUS AGE LABELS
kubernetes-master Ready,SchedulingDisabled 6m
beta.kubernetes.io/instance-type=n1-standard-1,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kub
ernetes.io/hostname=kubernetes-master
kubernetes-minion-87j9 Ready 6m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kub
ernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv Ready 6m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kub
ernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q Ready 6m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kub
ernetes.io/hostname=kubernetes-minion-a12q
排程器將在其排程決策中使用附加到每個節點的標籤(區域使用 failure-domain.beta.kubernetes.io/region,區域使用 failure-domain.beta.kubernetes.io/zone)。
在第二個區域中新增更多節點
讓我們將另一組節點新增到現有的叢集,但在不同的區域(GCE 為 us-central1-b,EC2 為 us-west-2b)中執行。我們再次執行 kube-up,但透過指定 KUBE_USE_EXISTING_MASTER=1
,kube-up 將不會建立新的 master,而是會重複使用先前建立的 master。
GCE
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=gce
KUBE_GCE_ZONE=us-central1-b NUM_NODES=3 kubernetes/cluster/kube-up.sh
在 EC2 上,我們也需要指定額外子網路的網路 CIDR,以及 master 內部 IP 位址
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=aws
KUBE_AWS_ZONE=us-west-2b NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.1.0/24
MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh
再次檢視節點;將會啟動並標記另外 3 個節點(此處的範例是在 GCE 上)
$ kubectl get nodes --show-labels
NAME STATUS AGE LABELS
kubernetes-master Ready,SchedulingDisabled 16m
beta.kubernetes.io/instance-type=n1-standard-1,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kub
ernetes.io/hostname=kubernetes-master
kubernetes-minion-281d Ready 2m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kub
ernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-87j9 Ready 16m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kub
ernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv Ready 16m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kub
ernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q Ready 17m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kub
ernetes.io/hostname=kubernetes-minion-a12q
kubernetes-minion-pp2f Ready 2m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kub
ernetes.io/hostname=kubernetes-minion-pp2f
kubernetes-minion-wf8i Ready 2m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kub
ernetes.io/hostname=kubernetes-minion-wf8i
讓我們再新增一個區域
GCE
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=gce
KUBE_GCE_ZONE=us-central1-f NUM_NODES=3 kubernetes/cluster/kube-up.sh
EC2
KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=aws
KUBE_AWS_ZONE=us-west-2c NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.2.0/24
MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh
驗證您現在在 3 個區域中都有節點
kubectl get nodes --show-labels
高可用性應用程式,指日可待。
部署多區域應用程式
建立 guestbook-go 範例,其中包含大小為 3 的 ReplicationController,執行簡單的 Web 應用程式。從此處下載所有檔案,並執行以下指令(指令假設您將它們下載到名為「guestbook-go」的目錄)
kubectl create -f guestbook-go/
您完成了!您的應用程式現在已分散到所有 3 個區域。使用以下指令向自己證明
$ kubectl describe pod -l app=guestbook | grep Node
Node: kubernetes-minion-9vlv/10.240.0.5
Node: kubernetes-minion-281d/10.240.0.8
Node: kubernetes-minion-olsh/10.240.0.11
$ kubectl get node kubernetes-minion-9vlv kubernetes-minion-281d
kubernetes-minion-olsh --show-labels
NAME STATUS AGE LABELS
kubernetes-minion-9vlv Ready 34m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-a,kub
ernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-281d Ready 20m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-b,kub
ernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-olsh Ready 3m
beta.kubernetes.io/instance-type=n1-standard-2,failure-domain.beta.kubernetes.
io/region=us-central1,failure-domain.beta.kubernetes.io/zone=us-central1-f,kub
ernetes.io/hostname=kubernetes-minion-olsh
此外,負載平衡器會自動跨叢集中的所有區域;guestbook-go 範例包含負載平衡服務範例
$ kubectl describe service guestbook | grep LoadBalancer.Ingress
LoadBalancer Ingress: 130.211.126.21
ip=130.211.126.21
$ curl -s http://${ip}:3000/env | grep HOSTNAME
"HOSTNAME": "guestbook-44sep",
$ (for i in `seq 20`; do curl -s http://${ip}:3000/env | grep HOSTNAME; done)
| sort | uniq
"HOSTNAME": "guestbook-44sep",
"HOSTNAME": "guestbook-hum5n",
"HOSTNAME": "guestbook-ppm40",
負載平衡器正確地鎖定所有 Pod,即使它們位於多個區域中。
關閉叢集
完成後,清除
GCE
KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true
KUBE_GCE_ZONE=us-central1-f kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true
KUBE_GCE_ZONE=us-central1-b kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-a
kubernetes/cluster/kube-down.sh
EC2
KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2c
kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2b
kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2a
kubernetes/cluster/kube-down.sh
結論
Kubernetes 的核心理念是抽象化執行高可用性分散式應用程式的複雜性。正如您在此處所見,除了在叢集啟動時進行少量工作外,跨多個故障網域啟動應用程式實例的所有複雜性,都不需要應用程式開發人員進行額外的工作,這才是應有的狀態。而我們才剛開始!
請加入我們的社群,協助我們建構 Kubernetes 的未來!有很多種參與方式。如果您對擴充性特別感興趣,您會對以下內容感興趣
- 我們的 federation Slack 頻道
- Federation「特別興趣小組」,每週四太平洋時間上午 9:30 在 SIG-Federation Hangout 線上會議 舉行會議
當然,如需有關專案的更多資訊,請前往 www.kubernetes.io