本文发布已超过一年。较早的文章可能包含过时内容。请检查页面信息自发布以来是否已不再正确。
Kubernetes 1.5 中的集群 Federation
编者注:本文是一系列关于 Kubernetes 1.5 新特性深度文章的一部分
在最新的 Kubernetes 1.5 版本中,您会注意到对集群 Federation 的支持正在成熟。这项功能是在 Kubernetes 1.3 中引入的,而 1.5 版本包含了一系列新特性,包括更简单的设置体验以及更接近支持所有 Kubernetes API 对象的进展。
引入了一个名为 'kubefed' 的新命令行工具,使 Cluster Federation 的入门变得更加简单。此外,还增加了对 Federated DaemonSets、Deployments 和 ConfigMaps 的 alpha 级别支持。总而言之:
- DaemonSets 是 Kubernetes 的部署规则,它保证给定的 Pod 始终存在于每个节点上,随着新节点添加到集群中(更多信息)。
- Deployments 描述了 Replica Sets 的期望状态(更多信息)。
- ConfigMaps 是应用于 Replica Sets 的变量(通过外部化参数极大地提高了镜像的可重用性 - 更多信息)。 Federated DaemonSets 、 Federated Deployments 、 Federated ConfigMaps 将这些基本概念的特性提升到了新的水平。例如,Federated DaemonSets 保证 Pod 部署在所有新加入集群的每个节点上。
但“Federation”究竟是什么?让我们通过它满足的需求来解释。想象一个在全球运营的服务。自然地,所有用户都期望获得相同的服务质量,无论他们位于亚洲、欧洲还是美国。这意味着服务必须对每个位置的请求做出同等快速的响应。这听起来很简单,但背后涉及大量的逻辑。这正是 Kubernetes Cluster Federation 旨在实现的目标。
它是如何工作的?其中一个 Kubernetes 集群必须通过运行 Federation Control Plane 成为主控。实际上,这是一个控制器,它监控其他集群的健康状况,并提供一个单一的管理入口点。这个入口点表现得像一个典型的 Kubernetes 集群。它允许创建 Replica Sets、Deployments、Services,但 Federation 控制平面会将这些资源传递到底层集群。这意味着如果我们请求 Federation 控制平面创建一个包含 1000 个副本的 Replica Set,它会将请求分散到所有底层集群。如果我们有 5 个集群,那么默认情况下每个集群将分得 200 个副本。
这本身就是一个强大的机制。但这还不止于此。还可以创建一个 Federated Ingress。实际上,这是一个全局的应用层负载均衡器。由于它了解应用层,因此可以实现“更智能”的负载均衡——例如,通过考虑客户端和服务器的地理位置,并以最优方式在它们之间路由流量。
总而言之,通过 Kubernetes Cluster Federation,我们可以简化所有集群的管理(单一访问点),同时优化全球的内容交付。在接下来的章节中,我们将展示它是如何工作的。
创建 Federation Plane
在本练习中,我们将联合几个集群。为了方便,所有命令已分组到 此处 提供的 6 个脚本中:
- 0-settings.sh
- 1-create.sh
- 2-getcredentials.sh
- 3-initfed.sh
- 4-joinfed.sh
- 5-destroy.sh 首先我们需要定义几个变量 (0-settings.sh)
$ cat 0-settings.sh && . 0-settings.sh
# this project create 3 clusters in 3 zones. FED\_HOST\_CLUSTER points to the one, which will be used to deploy federation control plane
export FED\_HOST\_CLUSTER=us-east1-b
# Google Cloud project name
export FED\_PROJECT=\<YOUR PROJECT e.g. company-project\>
# DNS suffix for this federation. Federated Service DNS names are published with this suffix. This must be a real domain name that you control and is programmable by one of the DNS providers (Google Cloud DNS or AWS Route53)
export FED\_DNS\_ZONE=\<YOUR DNS SUFFIX e.g. example.com\>
并获取 kubectl 和 kubefed 二进制文件。(安装说明请参考 此处 和 此处 的指南)。
现在设置已准备好,可以使用 gcloud container clusters create 创建几个 Google Container Engine (GKE) 集群 (1-create.sh)。在本例中,一个在美国,一个在欧洲,一个在亚洲。
$ cat 1-create.sh && . 1-create.sh
gcloud container clusters create gce-us-east1-b --project=${FED\_PROJECT} --zone=us-east1-b --scopes cloud-platform,storage-ro,logging-write,monitoring-write,service-control,service-management,https://www.googleapis.com/auth/ndev.clouddns.readwrite
gcloud container clusters create gce-europe-west1-b --project=${FED\_PROJECT} --zone=europe-west1-b --scopes cloud-platform,storage-ro,logging-write,monitoring-write,service-control,service-management,https://www.googleapis.com/auth/ndev.clouddns.readwrite
gcloud container clusters create gce-asia-east1-a --project=${FED\_PROJECT} --zone=asia-east1-a --scopes cloud-platform,storage-ro,logging-write,monitoring-write,service-control,service-management,https://www.googleapis.com/auth/ndev.clouddns.readwrite
下一步是使用 gcloud -q container clusters get-credentials 获取 kubectl 配置 (2-getcredentials.sh)。这些配置将用于指示 kubectl 命令的当前上下文。
$ cat 2-getcredentials.sh && . 2-getcredentials.sh
gcloud -q container clusters get-credentials gce-us-east1-b --zone=us-east1-b --project=${FED\_PROJECT}
gcloud -q container clusters get-credentials gce-europe-west1-b --zone=europe-west1-b --project=${FED\_PROJECT}
gcloud -q container clusters get-credentials gce-asia-east1-a --zone=asia-east1-a --project=${FED\_PROJECT}
让我们验证一下设置
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
\*
gke\_container-solutions\_europe-west1-b\_gce-europe-west1-b
gke\_container-solutions\_europe-west1-b\_gce-europe-west1-b
gke\_container-solutions\_europe-west1-b\_gce-europe-west1-b
gke\_container-solutions\_us-east1-b\_gce-us-east1-b
gke\_container-solutions\_us-east1-b\_gce-us-east1-b
gke\_container-solutions\_us-east1-b\_gce-us-east1-b
gke\_container-solutions\_asia-east1-a\_gce-asia-east1-a
gke\_container-solutions\_asia-east1-a\_gce-asia-east1-a
gke\_container-solutions\_asia-east1-a\_gce-asia-east1-a
我们有 3 个集群。其中一个,由 FED_HOST_CLUSTER 环境变量指示,将用于运行 Federation 平面。为此,我们将使用 kubefed init federation 命令 (3-initfed.sh)。
$ cat 3-initfed.sh && . 3-initfed.sh
kubefed init federation --host-cluster-context=gke\_${FED\_PROJECT}\_${FED\_HOST\_CLUSTER}\_gce-${FED\_HOST\_CLUSTER} --dns-zone-name=${FED\_DNS\_ZONE}
执行上述命令后,您会注意到出现了一个新的 kubectl 上下文
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
...
federation
federation
federation 上下文将成为我们的管理入口点。现在是时候加入集群了 (4-joinfed.sh)
$ cat 4-joinfed.sh && . 4-joinfed.sh
kubefed --context=federation join cluster-europe-west1-b --cluster-context=gke\_${FED\_PROJECT}\_europe-west1-b\_gce-europe-west1-b --host-cluster-context=gke\_${FED\_PROJECT}\_${FED\_HOST\_CLUSTER}\_gce-${FED\_HOST\_CLUSTER}
kubefed --context=federation join cluster-asia-east1-a --cluster-context=gke\_${FED\_PROJECT}\_asia-east1-a\_gce-asia-east1-a --host-cluster-context=gke\_${FED\_PROJECT}\_${FED\_HOST\_CLUSTER}\_gce-${FED\_HOST\_CLUSTER}
kubefed --context=federation join cluster-us-east1-b --cluster-context=gke\_${FED\_PROJECT}\_us-east1-b\_gce-us-east1-b --host-cluster-context=gke\_${FED\_PROJECT}\_${FED\_HOST\_CLUSTER}\_gce-${FED\_HOST\_CLUSTER}
请注意,这里使用集群 gce-us-east1-b 来运行 federation 控制平面,同时也作为一个工作集群。这种循环依赖有助于更有效地利用资源,可以使用 kubectl --context=federation get clusters 命令进行验证
$ kubectl --context=federation get clusters
NAME STATUS AGE
cluster-asia-east1-a Ready 7s
cluster-europe-west1-b Ready 10s
cluster-us-east1-b Ready 10s
我们准备好了。
使用 Federation 运行应用
在我们的仓库中,您将找到如何构建一个 Docker 镜像的说明,该镜像包含一个 Web 服务,用于显示容器的主机名和 Google Cloud Platform (GCP) 区域。
输出示例可能如下所示
{"hostname":"k8shserver-6we2u","zone":"europe-west1-b"}
现在我们将部署 Replica Set (k8shserver.yaml)
$ kubectl --context=federation create -f rs/k8shserver
和一个 Federated Service (k8shserver.yaml)
$ kubectl --context=federation create -f service/k8shserver
如您所见,这两个命令引用了“federation”上下文,即 federation 控制平面。几分钟后,您会发现底层集群正在运行 Replica Set 和 Service。
创建 Ingress
Service 准备好后,我们可以创建 Ingress - 全局负载均衡器。命令如下所示:
kubectl --context=federation create -f ingress/k8shserver.yaml
文件内容指向我们在上一步创建的 Service
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: k8shserver
spec:
backend:
serviceName: k8shserver
servicePort: 80
几分钟后,我们应该会得到一个全局 IP 地址
$ kubectl --context=federation get ingress
NAME HOSTS ADDRESS PORTS AGE
k8shserver \* 130.211.40.125 80 20m
实际上,以下命令的响应结果
$ curl 130.211.40.125
取决于客户端的位置。在美国,预期结果会是这样:
{"hostname":"k8shserver-w56n4","zone":"us-east1-b"}
而在欧洲,我们可能会得到:
{"hostname":"k8shserver-z31p1","zone":"eu-west1-b"}
有关我们已描述的所有内容的额外详情,请参阅此问题。
演示
总结
Cluster Federation 正在积极开发中,并且尚未完全通用可用(GA)。有些 API 处于 beta 阶段,有些则处于 alpha 阶段。有些功能尚缺失,例如跨云负载均衡不受支持(federated ingress 目前仅在 Google Cloud Platform 上工作,因为它依赖于 GCP HTTP(S) 负载均衡)。
然而,随着功能的成熟,它将成为所有面向全球市场但目前无法承担 Netflix 或 Amazon 等公司使用的复杂管理技术的公司的推动者。这就是为什么我们密切关注这项技术,希望它能尽快实现其承诺。
PS:完成后,记得销毁您的集群
$ . 5-destroy.sh