编者按:这篇文章是关于 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
让我们运行以下命令来构建集群:
首先,我们验证集群是否被创建:
其次,引导集群并部署集群联邦控制平面。如果你想跟着操作,可以参照经过相关的步骤 Kelsey Hightower 的教程。
联邦服务( Federation service ) 被分发到联邦 API endpoint ,并指定服务属性。
一旦创建,联邦服务自动执行以下操作:
在集群联邦下的每个集群内创建对应的 Kubernetes service
监视这些服务的健康
在一个公共 DNS 服务商 的平台上管理一组 DNS 记录(如谷歌云 DNS 或 AWS route53 ),从而确保联邦服务的客户端可以在任何时间无缝的定位到一个合适(且健康)的服务。即便在集群、可用区、或地域性的服务发生中断时,也能够保证联邦服务正常访问。
如果 Federation Server 在一个集群中的一个 kubernetes service 副本是健康的,那么在该集群内的 Federation Service 客户端会自动探测到该服务。
如果该集群内的副本运行状态异常,客户端也能够找到临近集群中的一个副本。
Kubernetes 集群联邦可以管理运行在不同云服务商(例如 GCP , AWS )的集群,以及私有部署的集群(例如 OpenStack 平台上)。
你需要做的是在适当的云供应商和 /或位置创建集群,并注册每个集群的 API 端点以及联邦 API 服务器的凭据。
在这个例子中,我们在 4 个区分别创建了一个集群,并在一个可用区部署联邦控制平面 API ,我们将使用它管理服务。结构见下图:
列出联邦内的所有集群:
接下来我们创建一个联邦服务对象
'--context=federation-cluster' 标签表明 kubectl 可以使用适当的证书向联邦 API 端点提交请求。
联邦服务会自动创建,并管理所有集群下 对应的 Kubernetes 服务。
你可以通过检查集群内的每一个来验证,例如:
上面的命令假设你已经为客户端配置了“ gce-asia-east1a ”这个区的上下文环境。
底层服务的名称和命名空间将自动匹配你所创建的联邦服务。
联邦服务的状态也会自动反映底层 Kubernetes 服务的实时状态,例如:
联邦服务的 'LoadBalancer Ingress' 地址对应所有底层 Kubernetes 服务的 'LoadBalancer Ingress' 地址。
为了让服务能够同时在集群内以及跨云服务商均可用,需要为服务配置一个外部可见的 IP 地址。服务类型 Loadbalancer 非常适用于这个场景。
注意:我们配置任何后端 Pods 处理 Service Endpoints 接收到的流量,所以联邦服务认为这些服务是不健康的,因此没有将这些地址添加到联邦服务的 DNS 记录。
为了让底层的服务分片(指每个集群中的 Kubernetes Service ),我们需要为它们添加后端 Pods 。
目前可以通过底层集群的 API 接口实现,将来使用一条命令,联邦服务器就会为你做所有这些事情。
例如,在我们的底层集群中创建后端 Pods :
一旦 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#managedZone
name: 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 300
nginx.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 的工具,例如:
无论你使用什么 DNS 提供商, DNS 查询工具( dig 或 nslookup )都会让你看到联邦创建的记录。
默认情况下, 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 集群联邦处理。
标准的 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 )
给跨集群服务一个尝试,并让我们知道它将如何发展!
原文链接: http://blog.kubernetes.io/2016/07/cross-cluster-services.html