我们在进行生产环境部署时得到的一个明确的需求,是 Kubernetes 用户希望服务部署能够 zone、跨区域、跨集群甚至跨云边界(译者:如跨云供应商)。相比单集群多 zone 部署,跨集群服务提供按地域分布,支持混合云、多云场景,提升高可用等级。客户希望服务能够跨一到多个集群(可能是本地或者远程集群),并希望这些集群无论内部或外部都有一致稳定的连接。 |
在 Kubernetes 1.3 版本, 我们希望降低跨集群跨地区服务部署相关的管理和运营难度. 本文介绍如何实现此目标.
注意: 虽然本文示例使用谷歌容器引擎 (GKE) 来提供 Kubernetes 集群, 您可以在任何的其他环境部署 Kubernetes.
我们正式开始. 第一步是在谷歌的四个云平台地区通过 GKE 创建 Kubernetes 集群.
- asia-east1-b
- europe-west1-b
- us-east1-b
- us-central1-b
我们通过下面的命令 https://www.linuxcool.com/ 创建集群:
- gcloud container clusters create gce-asia-east1 --scopes cloud-platform --zone asia-east1-b
- gcloud container clusters create gce-europe-west1 --scopes cloud-platform --zone=europe-west1-b
- gcloud container clusters create gce-us-east1 --scopes cloud-platform --zone=us-east1-b
- gcloud container clusters create gce-us-central1 --scopes cloud-platform --zone=us-central1-b
验证创建的集群
- gcloud container clusters list
- NAME ZONE MASTER_VERSION MASTER_IP NUM_NODES STATUS
- gce-asia-east1 asia-east1-b 1.2.4 104.XXX.XXX.XXX 3 RUNNING
- gce-europe-west1 europe-west1-b 1.2.4 130.XXX.XX.XX 3 RUNNING
- gce-us-central1 us-central1-b 1.2.4 104.XXX.XXX.XX 3 RUNNING
- gce-us-east1 us-east1-b 1.2.4 104.XXX.XX.XXX 3 RUNNING
下一步是起动集群并在创建的其中一个集群中部署联邦控制模块(Control Plane). 您可以参考和依照 Kelsey Hightower 的示例进行这步配置.
联邦服务
从联邦 API 获取信息, 因此您可以通过联邦 API 制定服务属性.
当服务创建后, 联邦服务自动进行如下操作:
在联邦中注册的所有 Kubernetes 集群中创建服务;
监控服务碎片 (以及它们所在集群) 的健康状况;
在公共 DNS 提供商上面创建 DNS 记录(如谷歌 Cloud DNS, 或者 AWS Route 53), 以此确定你的服务客户端能够在任何时候无缝的获得相关的健康服务终端, 即使当集群, 可用区或者地区出现服务中断的情况时.
在注册到联邦的 Kubernetes 集群中的服务客户端, 当联邦服务在本地集群碎片工作正常时, 会优先使用本地服务碎片, 否则会在最近的其他集群中选取健康的服务碎片.
Kubernetes 集群联邦能够联合不同的云供应商 (比如 GCP,AWS) 以及私有云(如 OpenStack). 您只需在相应的云供应商和位置创建您的集群, 并且将每个集群的 API Server 地址和证书信息注册到联邦集群中.
在我们的示例中, 我们在四个区域创建了集群, 并且在其中的一个集群中部署了联邦控制模块, 我们会用这个环境来部署我们的服务. 具体请参考下图.
创建联邦服务
我们先查看联邦中所有注册好的集群:
- kubectl --context=federation-cluster get clusters
- NAME STATUS VERSION AGE
- gce-asia-east1 Ready 1m
- gce-europe-west1 Ready 57s
- gce-us-central1 Ready 47s
- gce-us-east1 Ready 34s
创建联邦服务:
kubectl --context=federation-cluster create -f services/nginx.YAML
--context=federation-cluster 参数通知 kubectl 把带相关证书信息的请求提交至联邦 API 服务器. 联邦服务会自动在联邦中所有集群创建相应的 Kubernetes 服务.
你可以通过检查每一个集群中的服务进行验证, 比如:
- kubectl --context=gce-asia-east1a get svc nginx
- NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
- nginx 10.63.250.98 104.199.136.89 80/TCP 9m
上面的命令 https://www.linuxcool.com/ 假设你有一个名为 gce-asia-east1a 的 kubectl 的上下文设置, 并且你有集群部署在这个区(zone).Kubernetes 服务的名字和名空间自动与你上面创建的集群服务一致.
联邦服务状态会实时体现 Kubernetes 对应的服务状态, 例如:
- kubectl --context=federation-cluster describe services nginx
- Name: nginx
- Namespace: default
- Labels: run=nginx
- Selector: run=nginx
- Type: LoadBalancer
- IP:
- LoadBalancer Ingress: 104.XXX.XX.XXX, 104.XXX.XX.XXX, 104.XXX.XX.XXX, 104.XXX.XXX.XX
- Port: http 80/TCP
- Endpoints: <none>
- Session Affinity: None
- No events.
联邦服务的 LoadBalancer Ingress 地址会汇总所有注册的 Kubernetes 集群服务的 LoadBalancer Ingress 地址. 为了让同一联邦服务在不通集群之间以及不同云供应商之间的网络正确工作, 你的服务需要有外部可见的 IP 地址, 比如 Loadbalancer 是常见的服务类型.
请注意我们还没有部署任何后台 Pod 来接收指向这些地址的网络流量(比如服务终端), 所以此时联邦服务还不会认为这些服务碎片是健康的, 所以联邦服务对应的 DNS 记录也尚未创建.
增加后台 Pod
为了渲染底层服务碎片的健康状况, 我们需要为服务增加后台 Pod. 目前需要通过直接操作底层集群的 API Server 来完成(为节省您的时间, 未来我们可以通过一条命令在联邦服务器中创建). 例如我们在底层集群中创建后台 Pod:
- for CLUSTER in asia-east1-a europe-west1-a us-east1-a us-central1-a
- do
- kubectl --context=$CLUSTER run nginx --image=nginx:1.11.1-alpine --port=80
- done
验证公共 DNS 记录
一旦 Pod 开始成功启动并开始监听连接, 每个集群 (通过健康检查) 会汇报服务的健康终端至集群联邦. 集群联邦会依次认为这些服务碎片是健康的, 并且创建相应的公共 DNS 记录. 你可以使用你喜欢的 DNS 供应商的接口来验证. 比如, 如果你使用谷歌 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 工具, 例如:
- $AWS route53 list-hosted-zones
- $AWS route53 list-resource-record-sets --hosted-zone-id Z3ECL0L9QLOVBX
不管您使用什么 DNS 供应商, 您可以使用 DNS 查询工具 (例如'dig' 或者'nslookup') 来查看联邦为您创建的 DNS 记录.
从联邦集群内部的 pod 发现联邦服务
默认情况下, Kubernetes 集群有内置的本地域名服务器(KubeDNS), 并且有智能的 DNS 搜索路径确保针对 "myservice","myservice.mynamespace","bobsservice.othernamespace" 等等被您运行在 Pod 中的的应用软件自动扩展和解析至相应的本地集群中的服务 IP.
通过引入联邦服务以及跨集群服务发现, 这个概念被扩展至全局, 覆盖您联邦中所有的集群. 为了利用这个扩展带来的便利性, 您只需使用稍微不同的服务名 (比如, myservice.mynamespace.myfederation) 进行解析.
使用不同的 DNS 名同时避免了您现有的服务在您没有做明确的配置和选择情况下, 意外的被解析到不同区 (zone) 或地域 (region) 网络, 导致额外的网络费用或延迟.
因此, 使用我们上面的 NGINX 服务, 以及刚刚介绍的联邦服务 DNS 名, 我们构想一个示例: 在可用性区域 us-central1-a 的集群中的 pod 需要访问我们的 NGINX 服务. 与其使用传统的本地集群 DNS 名 ("nginx.mynamespace", 自动扩展为 "nginx.mynamespace.svc.cluster.local"), 现在可以使用联邦服务名 "nginx.mynamespace.myfederation". 此名称会被自动扩展和解析至我的 Nginx 服务最近的健康节点, 无论它在世界的哪里. 如果本地集群存在健康服务碎片, 那么本地集群 IP 地址 (通常是 10.x.y.z) 会被返回(被集群本地 KubeDNS). 这与非联邦服务解析完全一致.
如果服务在本地集群不存在(或者服务存在但本地没有健康的后台 pod),DNS 查询会自动扩充至 `"nginx.mynamespace.myfederation.svc.us-central1-a.example.com". 实际的行为是查找离当前可用性区域最近的服务碎片的外部 IP. 该扩展被 KubeDNS 自动触发执行, 返回相关的 CNAME 记录. 这会遍历上面示例中的 DNS 记录, 直到找到本地 us-central1 区域联邦服务的外部 IP.
通过明确指定 DNS 名, 直接指向非本地可用区域 (AZ) 和地域 (region) 的服务碎片, 而不依赖于自动 DNS 扩展, 是可行的. 例如,
"nginx.mynamespace.myfederation.svc.europe-west1.example.com" 会被解析至位于欧洲的所有健康服务碎片, 即使通过 nslookup 解析出的服务位于美国, 并无论在美国是否有该服务的健康碎片. 这对远程监控和其它类似应用很有用.
从联邦集群外部发现联邦服务
对于外部客户端, 前文描述的 DNS 自动扩展已不适用. 外部客户端需要指定联邦服务的全名(FQDN), 可以是区域, 地域或全局名. 为方便起见, 最好为您的服务手工创建 CNAME 记录, 比如:
- eu.nginx.acme.com CNAME nginx.mynamespace.myfederation.svc.europe-west1.example.com.
- us.nginx.acme.com CNAME nginx.mynamespace.myfederation.svc.us-central1.example.com.
- nginx.acme.com CNAME nginx.mynamespace.myfederation.svc.example.com.
这样您的客户端可以一直使用左侧的短名形式, 并且会被自动解析到它所在大陆的最近的健康节点上. 集群联邦会帮您处理服务的 failover.
处理后台 Pod 和整个集群的失败情况
标准 Kubernetes 服务集群 IP 已经确保无响应的 Pod 会被及时从服务中移除. Kubernetes 联邦集群系统自动监控集群以及联邦服务所有碎片对应的终端的健康状况, 并按需增加和删除服务碎片.
因为 DNS 缓存造成的延迟 (缓存超时, 或者联邦服务 DNS 记录 TTL 默认设置为三分钟, 但可以调节) 可能需要这么长时间才能在某集群或服务碎片出现问题时, 正确将客户端, 请求 failover 到可用集群上. 然而, 因为每个服务终端可以返回多个 ip 地址,(如上面的 us-central1, 有三个选择) 很多客户端会返回其中一个可选地址.
来源: http://www.bubuko.com/infodetail-3023956.html