本文发布已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已不正确。

Kubernetes 1.5 中的集群联邦

编者按: 这篇文章是关于 Kubernetes 1.5 新特性的系列深度文章的一部分

在最新的 Kubernetes 1.5 版本中,你会注意到对集群联邦的支持正在成熟。该功能在 Kubernetes 1.3 中引入,1.5 版本包含许多新功能,包括更简单的设置体验和更接近支持所有 Kubernetes API 对象。

引入了一个名为“kubefed”的新命令行工具,使集群联邦的入门更加简单。此外,还为 Federated DaemonSets、Deployments 和 ConfigMaps 添加了 alpha 级支持。总而言之

  • DaemonSets 是 Kubernetes 部署规则,它保证给定的 Pod 始终存在于每个节点上,因为新节点被添加到集群中(更多信息)。
  • Deployments 描述了副本集的期望状态(更多信息)。
  • ConfigMaps 是应用于副本集的变量(这大大提高了镜像的可重用性,因为它们的参数可以被外部化 - 更多信息)。Federated DaemonSetsFederated DeploymentsFederated ConfigMaps 将基本概念的质量提升到了新的水平。例如,Federated DaemonSets 保证 Pod 被部署在每个新添加的集群的每个节点上。

但“联邦”实际上是什么?让我们通过它需要满足的需求来解释它。想象一个在全球范围内运营的服务。自然地,所有用户都期望获得相同的服务质量,无论他们位于亚洲、欧洲还是美国。这意味着服务必须在每个位置对请求做出同样快速的响应。这听起来很简单,但幕后涉及很多逻辑。这就是 Kubernetes 集群联邦的目标。

它是如何工作的?其中一个 Kubernetes 集群必须通过运行 联邦控制平面 成为主集群。实际上,这是一个监视其他集群的健康状况并为管理提供单一入口点的控制器。入口点的行为类似于典型的 Kubernetes 集群。它允许创建副本集部署服务,但联邦控制平面将资源传递给底层集群。这意味着如果我们请求联邦控制平面创建一个具有 1,000 个副本的副本集,它将跨所有底层集群传播请求。如果我们有 5 个集群,那么默认情况下每个集群将获得 200 个副本。

这本身就是一个强大的机制。但还有更多。还可以创建一个 Federated Ingress。实际上,这是一个全局应用层负载均衡器。由于理解了应用层,它允许负载均衡更加“智能” - 例如,通过考虑客户端和服务器的地理位置,并在它们之间以最佳方式路由流量。

总而言之,借助 Kubernetes 集群联邦,我们可以促进所有集群的管理(单点访问),还可以优化全球范围内的内容交付。在以下部分中,我们将展示它是如何工作的。

创建联邦平面

在本练习中,我们将联合几个集群。为了方便起见,所有命令都分组为 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 (1-create.sh) 创建几个 Google Container Engine (GKE) 集群。在本例中,一个在美国,一个在欧洲,一个在亚洲。

$ 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 (2-getcredentials.sh) 获取 kubectl 配置。这些配置将用于指示 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 环境变量指示,将用于运行联邦平面。为此,我们将使用 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

联邦上下文将成为我们的管理入口点。现在是加入集群的时候了 (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 来运行联邦控制平面,也用作工作集群。这种循环依赖有助于更有效地利用资源,并且可以通过使用 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

我们一切就绪。

使用联邦运行应用程序

在我们的 存储库中,你将找到有关如何构建带有 Web 服务的 Docker 镜像的说明,该 Web 服务显示容器的主机名和 Google Cloud Platform (GCP) 区域。

示例输出可能如下所示

{"hostname":"k8shserver-6we2u","zone":"europe-west1-b"}

现在我们将部署副本集 (k8shserver.yaml)

$ kubectl --context=federation create -f rs/k8shserver

和一个联邦服务 (k8shserver.yaml)

$ kubectl --context=federation create -f service/k8shserver

如你所见,这两个命令都引用了“federation”上下文,即联邦控制平面。几分钟后,你会意识到底层集群正在运行副本集和服务。

创建入口

服务准备就绪后,我们可以创建 Ingress - 全局负载均衡器。命令如下所示

kubectl --context=federation create -f ingress/k8shserver.yaml

文件的内容指向我们在上一步中创建的服务

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"}

有关我们所描述的所有内容如何运作的更多细节,请参考此issue

演示

总结

集群联邦(Cluster Federation)正在积极开发中,尚未完全正式发布(General Available)。一些API处于beta阶段,另一些则处于alpha阶段。一些功能缺失,例如不支持跨云负载均衡(联邦入口目前仅在Google Cloud Platform上工作,因为它依赖于GCP HTTP(S) 负载均衡)。

尽管如此,随着功能的成熟,它将为所有旨在全球市场的公司提供便利,这些公司目前无法负担像Netflix或亚马逊那样复杂的管理技术。这就是为什么我们密切关注这项技术,希望它能尽快兑现承诺。

PS. 完成后,记得销毁你的集群

$ . 5-destroy.sh