跨集群服务——如何利用Kubernetes 1.3实现跨区高可用

时间:2024-03-30 14:19:29

摘要:编者按:这篇文章是关于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

让我们运行以下命令来构建集群:

跨集群服务——如何利用Kubernetes 1.3实现跨区高可用

首先,我们验证集群是否被创建:

跨集群服务——如何利用Kubernetes 1.3实现跨区高可用
跨集群服务——如何利用Kubernetes 1.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 ,我们将使用它管理服务。结构见下图:

跨集群服务——如何利用Kubernetes 1.3实现跨区高可用


创建联邦服务

列出联邦内的所有集群:

跨集群服务——如何利用Kubernetes 1.3实现跨区高可用

接下来我们创建一个联邦服务对象

跨集群服务——如何利用Kubernetes 1.3实现跨区高可用

'--context=federation-cluster' 标签表明 kubectl可以使用适当的证书向联邦API端点提交请求。

联邦服务会自动创建,并管理所有集群下 对应的Kubernetes服务。

你可以通过检查集群内的每一个来验证,例如:

跨集群服务——如何利用Kubernetes 1.3实现跨区高可用

上面的命令假设你已经为客户端配置了“gce-asia-east1a”这个区的上下文环境。

底层服务的名称和命名空间将自动匹配你所创建的联邦服务。

联邦服务的状态也会自动反映底层 Kubernetes服务的实时状态,例如:

跨集群服务——如何利用Kubernetes 1.3实现跨区高可用

联邦服务的 'LoadBalancer Ingress' 地址对应所有底层Kubernetes服务的 'LoadBalancer Ingress' 地址。

为了让服务能够同时在集群内以及跨云服务商均可用,需要为服务配置一个外部可见的IP地址。服务类型 Loadbalancer 非常适用于这个场景。

注意:我们配置任何后端Pods 处理 Service Endpoints接收到的流量,所以联邦服务认为这些服务是不健康的,因此没有将这些地址添加到联邦服务的DNS记录。

增加后端Pods

为了让底层的服务分片(指每个集群中的Kubernetes Service),我们需要为它们添加后端Pods。

目前可以通过底层集群的API 接口实现,将来使用一条命令,联邦服务器就会为你做所有这些事情。

例如,在我们的底层集群中创建后端Pods:

跨集群服务——如何利用Kubernetes 1.3实现跨区高可用

验证公共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的工具,例如:

跨集群服务——如何利用Kubernetes 1.3实现跨区高可用

无论你使用什么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记录,例如:

跨集群服务——如何利用Kubernetes 1.3实现跨区高可用

这样客户端就可以随时使用左边的短域名,并能被自动路由到最近最健康的服务分片。所有故障都交给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)