1. 程式人生 > >跨叢集服務——如何利用Kubernetes 1.3實現跨區高可用

跨叢集服務——如何利用Kubernetes 1.3實現跨區高可用

編者按:這篇文章是關於Kubernetes 1.3新功能的一系列深入文章的一部分。本文是第七篇。

使用者使用Kubernetes 對生產環境上的部署進行彈性伸縮,同時我們聽到一個明確的聲音:希望跨區域、跨資料中心、跨叢集和跨雲服務商來部署服務。

跨叢集服務能夠分佈在不同的地理位置,使得混合和多雲成為可能,相對於單一叢集多可用區部署,更好地保證高可用。

客戶希望他們的服務能跨越一個或多個(可能是遠端)叢集,不管從叢集的內部和外部訪問這些服務,都有一致的體驗。

在Kubernetes 1.3中,我們的目標是在管理地理位置上分散的多叢集服務時,儘量減少管理開銷。這篇文章解釋瞭如何做到這一點。

注:例子中,我們利用谷歌容器引擎(GKE)提供的Kubernetes叢集,在該平臺上,你可以把Kubernetes部署到想要的地區。

那我們就開始吧。第一步是建立,使用GKE在4個可用區內建立Kubernetes叢集。

●   asia-east1-b

●   europe-west1-b

●   us-east1-b

●   us-central1-b

讓我們執行以下命令來構建叢集:

跨叢集1

首先,我們驗證叢集是否被建立:

跨叢集2
跨叢集3

其次,引導叢集並部署叢集聯邦控制平面。如果你想跟著操作,可以參照經過相關的步驟Kelsey Hightower的教程。

聯邦服務

聯邦服務(Federation service) 被分發到聯邦API endpoint,並指定服務屬性。

一旦建立,聯邦服務自動執行以下操作:

1.  在叢集聯邦下的每個叢集內建立對應的Kubernetes service

2.  監視這些服務的健康

3.  在一個公共DNS服務商 的平臺上管理一組DNS記錄(如谷歌雲DNS或AWS route53),從而確保聯邦服務的客戶端可以在任何時間無縫的定位到一個合適(且健康)的服務。即便在叢集、可用區、或地域性的服務發生中斷時,也能夠保證聯邦服務正常訪問。

如果Federation Server在一個叢集中的一個kubernetes service副本是健康的,那麼在該叢集內的Federation Service 客戶端會自動探測到該服務。

如果該叢集內的副本執行狀態異常,客戶端也能夠找到臨近叢集中的一個副本。

Kubernetes叢集聯邦可以管理執行在不同雲服務商(例如GCP,AWS)的叢集,以及私有部署的叢集(例如OpenStack平臺上)。

你需要做的是在適當的雲供應商和/或位置建立叢集,並註冊每個叢集的API端點以及聯邦API伺服器的憑據。

在這個例子中,我們在4個區分別建立了一個叢集,並在一個可用區部署聯邦控制平面 API ,我們將使用它管理服務。結構見下圖:

跨叢集4

建立聯邦服務

列出聯邦內的所有叢集:

跨叢集5

接下來我們建立一個聯邦服務物件

跨叢集6

'--context=federation-cluster' 標籤表明 kubectl可以使用適當的證書向聯邦API端點提交請求。

聯邦服務會自動建立,並管理所有叢集下 對應的Kubernetes服務。

你可以通過檢查叢集內的每一個來驗證,例如:

跨叢集7

上面的命令假設你已經為客戶端配置了“gce-asia-east1a”這個區的上下文環境。

底層服務的名稱和名稱空間將自動匹配你所建立的聯邦服務。

聯邦服務的狀態也會自動反映底層 Kubernetes服務的實時狀態,例如:

跨叢集8

聯邦服務的 'LoadBalancer Ingress' 地址對應所有底層Kubernetes服務的 'LoadBalancer Ingress' 地址。

為了讓服務能夠同時在叢集內以及跨雲服務商均可用,需要為服務配置一個外部可見的IP地址。服務型別 Loadbalancer 非常適用於這個場景。

注意:我們配置任何後端Pods 處理 Service Endpoints接收到的流量,所以聯邦服務認為這些服務是不健康的,因此沒有將這些地址新增到聯邦服務的DNS記錄。

增加後端Pods

為了讓底層的服務分片(指每個叢集中的Kubernetes Service),我們需要為它們新增後端Pods。

目前可以通過底層叢集的API 介面實現,將來使用一條命令,聯邦伺服器就會為你做所有這些事情。

例如,在我們的底層叢集中建立後端Pods:

跨叢集9

驗證公共DNS記錄

 一旦 Pods成功啟動並開始監聽連線,Kubernetes的健康檢查機制會把它認定為對應Service的一個健康的endpoint。

然後,叢集聯邦將認定每個叢集中的服務分片是健康的,並將其新增到公共DNS記錄。

你可以向DNS提供商驗證這一點。例如,如果你的聯邦使用Google Cloud DNS以及管理DNS域 'example.com'來配置:

$ gcloud dns managed-zones describe example-dot-com 

creationTime: '2016-06-26T18:18:39.229Z'description: Example domain for Kubernetes Cluster Federation
dnsName: example.com.
id: '3229332181334243121'kind: dns#managedZonename: example-dot-com
nameServers:
- ns-cloud-a1.googledomains.com.
- ns-cloud-a2.googledomains.com.
- ns-cloud-a3.googledomains.com.
- ns-cloud-a4.googledomains.com.

$ gcloud dns record-sets list --zone example-dot-com

NAME                                                                                                 TYPE      TTL     DATA
example.com.                                                                                       NS     21600  ns-cloud-e1.googledomains.com., ns-cloud-e2.googledomains.com.
example.com.                                                                                      SOA     21600 ns-cloud-e1.googledomains.com. cloud-dns-hostmaster.google.com. 1 21600 3600 1209600 300nginx.mynamespace.myfederation.svc.example.com.                            A     180     104.XXX.XXX.XXX, 130.XXX.XX.XXX, 104.XXX.XX.XXX, 104.XXX.XXX.XX
nginx.mynamespace.myfederation.svc.us-central1-a.example.com.     A     180     104.XXX.XXX.XXX
nginx.mynamespace.myfederation.svc.us-central1.example.com.
nginx.mynamespace.myfederation.svc.us-central1.example.com.         A    180     104.XXX.XXX.XXX, 104.XXX.XXX.XXX, 104.XXX.XXX.XXX
nginx.mynamespace.myfederation.svc.asia-east1-a.example.com.       A    180     130.XXX.XX.XXX
nginx.mynamespace.myfederation.svc.asia-east1.example.com.
nginx.mynamespace.myfederation.svc.asia-east1.example.com.           A    180     130.XXX.XX.XXX, 130.XXX.XX.XXX
nginx.mynamespace.myfederation.svc.europe-west1.example.com.  CNAME    180   nginx.mynamespace.myfederation.svc.example.com.
... etc.

注意:如果你的聯邦使用AWS route53,你可以用一個等價的AWS的工具,例如:

跨叢集10

無論你使用什麼DNS提供商,DNS查詢工具(dig 或 nslookup )都會讓你看到聯邦建立的記錄。

從聯邦叢集 pods 中發現聯邦服務

 預設情況下,Kubernetes叢集預配置了本地叢集DNS伺服器('KubeDNS'),以及智慧化構建DNS搜尋路徑來確保如“myservice”的DNS查詢。

"myservice.mynamespace", "bobsservice.othernamespace" 等通過執行在Pods內的軟體自動擴充套件,從而解析到本叢集內的適當服務IP。

引入聯邦服務和跨叢集服務發現後,這個概念延伸到聯邦服務,即全域性有效。

為了便於全域性使用,我們使用了一個略有不同的DNS名稱(例如myservice.mynamespace.myfederation)來解析聯邦服務。

使用不同的DNS名稱也避免了現有應用流量在未明確配置的情況下在跨區域或跨地域的網路流動,帶來額外的網路費用或延遲。

因此,使用上面的NGINX 例項服務以及描述過的聯邦服務DNS名稱。

我們考慮一個例子:在us-central1-a可用區域的nginx Pod需要聯絡Nginx service。

按照傳統的方式,Pod會找到本地叢集中對應service的DNS名稱("nginx.mynamespace", 可以自動拓展到"nginx.mynamespace.svc.cluster.local")。

現在,新的方式要強大得多。它可以使用該服務對應的聯邦DNS名稱,即"nginx.mynamespace.myfederation"。

聯邦DNS會被自動擴充套件並解析到最近的健康 NGINX service(服務分片),這個service可能在世界的任何地方。

如果一個健康的服務分片存在於本地叢集,將使用service的本地(通常為10.x.y.z)IP( 通過本地KubeDNS)。

這相當於非聯邦服務解決方案,即一個傳統的單叢集解決方案。

如果本地叢集中不存在對應的Service(或者存在,但沒有健康的後端pods),DNS查詢自動擴充套件到"nginx.mynamespace.myfederation.svc.us-central1-a.example.com"。

在背後,系統會在最近的可用區查詢對應的service。域名擴充套件由KubeDNS 自動執行,並返回相關的CNAME記錄。

所以在上面的例子,KubeDNS會遍歷DNS記錄的多個層級,遍歷到本地( us-central1 區域)聯邦服務的外部IP時結束。

如果顯式地指定DNS名稱,那麼系統將不使用域名自動擴充套件,而是會直接解析到對應可用區的服務分片。

例如"nginx.mynamespace.myfederation.svc.europe-west1.example.com"將被解析到歐洲所有的健康服務分片。

即使提起查詢操作的Pod在美國,也不管美國是否有健康的服務分片。這對遠端監控和類似的應用都很有用。

在聯邦叢集外部的客戶端中發現聯邦服務

對於外部客戶端,就無法使用DNS自動擴充套件了。

外部客戶端需要指定一個合法的DNS名稱(一個全球可訪問的名稱)。

方便起見,可以你的服務中手動配置額外的靜態CNAME記錄,例如:

跨叢集11

這樣客戶端就可以隨時使用左邊的短域名,並能被自動路由到最近最健康的服務分片。所有故障都交給Kubernetes叢集聯邦處理。

後臺Pods以及整叢集的故障處理

標準的Kubernetes服務叢集IP能確保將不響應的Pod endpoint 自動從低延遲的服務中移除。

類似的概念,Kubernetes叢集聯邦能夠自動監控叢集和聯邦服務背後的kubernetes service endpoints,按需新增和移除服務分片。

由於DNS快取延遲(快取超時,聯邦服務DNS的TTL預設是 3分鐘,但可以調整),災難性故障的情況下, 讓所有客戶端故障切換到到另一個叢集可能需要很長時間。然而,鑑於每個區域的Kubernetes Service endpoint 均有多個IP(例如以上的 us-central1有三個),只要進行適當的配置,很多客戶端都能夠在很短時間內切換到其中一個替代的IP.

社群

 我們希望聽到Kubernetes跨叢集服務的反饋。您可以加入以下社群:

●   GitHub上的文章問題或功能要求 (https://github.com/kubernetes/kubernetes/tree/master/federation)

●   在Slack的聯邦渠道加入我們(https://kubernetes.slack.com/?redir=%2Fmessages%2Fsig-federation)

●   參與叢集聯邦SIG (https://groups.google.com/forum/#!forum/kubernetes-sig-federation)