KubeFed: Kubernetes Federation v2 详解

Kubernetes Federation(联邦)一直是很有趣的议题,并被重视的功能,Federation目的是希望实现单一集群统一管理多个Kubernetes集群的机制,这些集群可能是跨地区(Region),也可能是在不同公有云供应商(Cloud Provider)上,亦或者是公司内部自行建立的集群。一但集群进行联邦后,就可以利用Federation API资源来统一管理多个集群的Kubernetes API资源,如定义Deployment如何部署到不同集群上,其集群所需的副本数等。
而Kubernetes Federation 的诞生正是希望利用联邦机制来解决一些问题,并达到一些好处,如以下:
  • 简化管理多个集群的Kubernetes 组件(如Deployment, Service 等)。
  • 在多个集群之间分散工作负载(容器),以提升应用(服务)的可靠性。
  • 跨集群的资源编排,依据编排策略在多个集群进行应用(服务)部署。
  • 在不同集群中,能更快速更容易地迁移应用(服务)。
  • 跨集群的服务发现,服务可以提供给当地存取,以降低延迟。
  • 实践多云(Multi-cloud)或混合云(Hybird Cloud)的部署。
虽然Kubernetes 社区很早之前就已实现Federation(v1) 机制,但随着Kubernetes 成长,Federation v1 发展的越来越缓慢,并在之后版被弃用了??,而SIG Multi-Cluster 团队也随即提出新架构Federation v2 来取代。
至于v1 为何被弃用?而v2 又带来什么变化呢?我将在接下来部分简单说明。

为什么v1 被弃用?

Federation v1在Kubernetes v1.3左右时,就已经着手设计( Design Proposal ),并在后面几个版本中发布了相关的组件与命令行工具(kubefed),用于帮助使用者快速建立联邦集群,并在Kubernetes v1.6时,进入了Beta阶段。
但Federation v1 在进入Beta 后,就没有更进一步的发展,一直到Kubernetes v1.11 左右正式被弃用。至于为什么被弃用呢?这是因为开发团队认为集群联邦的实践比想象中还要困难,有许多问题是v1 架构没被考虑进去的,比如说:
  • 控制平面组件会因为发生问题,而影响整体集群效率。
  • 无法兼容新的Kubernetes API 资源。
  • 无法有效的在多个集群管理权限,如不支持RBAC
  • 联邦层级的设定与策略依赖API 资源的Annotations 内容,这使得弹性不佳。
而这些问题基本上是当初设计架构所延伸而来。我们可以通过了解整体架构来更容易知道问题点。

从上图架构中得知Federation v1 的设计沿用类似Kubernetes 控制平面架构,其主要组件有以下:
  • federation-apiserver :提供Federation API资源,只支持部分Kubernetes API resources。
  • federation-controller-manager :协调不同集群之间的状态,如同步Federated资源与策略,并建立Kubernetes组件至对应集群上。
  • etcd :储存Federation的状态。
Federation v1提供了kubefed工具来简化?安装Federation控制平面元件的过程,并提供新增/删除集群的操作。
从代码大致可以了解Federation v1的API Server在基础上是通过k8s.io/apiserver套件开发,这种是采用API Aggregation方式来扩充Kubernetes API。而Federated API资源则是实作Adapter来管理Kubernetes API资源,但这些Adapter都是写死API版本的,比如说Deployment只支持extensions/v1beta1版本API,所以当建立一个apps/v1的Deployment,并且在Annotations设定联邦策略时,就会无法正常运作。
因此,若想要支持其他资源(如CronJob)或版本,就必须在Federation types新增对应的Adapter,然后通过Code Generator产生API的client-go组件给Controller Manager操作API使用,最后重新建构一版本来更新API Server与Controller Manager以提供对其他资源与版本的支持。另外Federation v1在设计之初未考虑RBAC与CRD(TPR)功能,因此无法提供跨集群的权限控管,以及定制化资源的扩展。从上述状况中,就能感受到Federation v1在扩展性有很多挑战。
也正因为在架构上无法很好解决这些问题,Federation v1 才会发展的越来越缓慢,并在最后被弃用。当然也是因为有这样的发展过程与经验,才能有Federation v2 的诞生。

Federation v2

Kubernetes Cluster Federation又名KubeFed或Federation v2,是Kubernetes SIG Multi-Cluster团队新提出的集群联邦架构( Architecture Doc与Brainstorming Doc ),新架构在Federation v1基础之上,简化扩展Federated API过程,并加强跨集群服务发现与编排的功能。另外KubeFed在设计之初,有两个最重要核心理念是KubeFed希望实现的,分别为Modularization(模块化)与Customizable(定制化),这两个理念大概是希望KubeFed能够跟随着Kubernetes生态发展,并持续保持相容性与扩展性。
KubeFed在组件上最大改变是将API Server移除,并通过CRD机制来完成Federated Resources的扩充。而KubeFed Controller则管理这些CRD,并实现同步Resources、跨集群编排等功能。从架构图中看到,KubeFed提出了一些新概念来加强功能的扩展。

Concepts
目前KubeFed 通过CRD 方式新增了四种API 群组来实现联邦机制的核心功能:
API Group 用途
core.kubefed.k8s.io
集群组态、联邦资源组态、KubeFed Controller 设定档等。
types.kubefed.k8s.io
被联邦的Kubernetes API 资源。
scheduling.kubefed.k8s.io
副本编排策略。
multiclusterdns.kubefed.k8s.io
跨集群服务发现设定。
而在这些核心功能中,我们必须先了解一些KebeFed 提出的基础概念后,才能更清楚知道KubeFed 是如何运作的。

Cluster Configuration

用来定义哪些Kubernetes集群要被联邦。可透过kubefedctl join/unjoin来加入/删除集群,当成功加入时,会建立一个KubeFedCluster组件来储存集群相关信息,如API Endpoint、CA Bundle等。这些信息会被用在KubeFed Controller存取不同Kubernetes集群上,以确保能够建立Kubernetes API资源,示意图如下所示。

在Federation 中,会区分Host 与Member 两种类型集群。
  • Host :用于提供KubeFed API与控制平面的集群。
  • Member :通过KubeFed API注册的集群,并提供相关身份凭证来让KubeFed Controller能够存取集群。Host集群也可以作为Member被加入。

Type Configuration

定义了哪些Kubernetes API资源要被用于联邦管理。比如说想将ConfigMap资源通过联邦机制建立在不同集群上时,就必须先在Federation Host集群中,通过CRD建立新资源FederatedConfigMap,接着再建立名称为configmaps的Type configuration(FederatedTypeConfig)资源,然后描述ConfigMap要被FederatedConfigMap所管理,这样KubeFed Controllers才能知道如何建立Federated资源。以下为简单范例:
apiVersion: core.kubefed.k8s.io/v1beta1
kind: FederatedTypeConfig
metadata:
  name: configmaps
  namespace: kube-federation-system
spec:
  federatedType:
    group: types.kubefed.k8s.io
    kind: FederatedConfigMap
    pluralName: federatedconfigmaps
    scope: Namespaced
    version: v1beta1
  propagation: Enabled
  targetType:
    kind: ConfigMap
    pluralName: configmaps
    scope: Namespaced
    version: v1
若想新增CRD的Federated API的话,可通过kubefedctl enable <res>指令来建立,如下:
$ kubefedctl enable etcdclusters
$ kubectl api-resources | grep etcd
etcdclusters                      etcd         etcd.database.coreos.com         true         EtcdCluster
federatedetcdclusters             fetcd        types.kubefed.k8s.io             true         FederatedEtcdCluster

$ kubectl -n kube-federation-system get federatedtypeconfigs | grep etcd
etcdclusters.etcd.database.coreos.com    3m16s
而一个Federated资源一般都会具备三个主要功能,这些信息能够在spec中由使用者自行定义,如下范例:
apiVersion: types.kubefed.k8s.io/v1beta1
kind: FederatedDeployment
metadata:
  name: test-deployment
  namespace: test-namespace
spec:
  template: # 定义 Deployment 的所有內容,可理解成 Deployment 与 Pod 之间的关联。
    metadata:
      labels:
        app: nginx
    spec:
      ...
  placement:
    clusters:
    - name: cluster2
    - name: cluster1
  overrides: 
  - clusterName: cluster2
    clusterOverrides:
    - path: spec.replicas
      value: 5
    • Placement :定义Federated资源要分散到哪些集群上,若没有该文件,则不会分散到任何集群中。如FederatedDeployment中的spec.placement定义了两个集群时,这些集群将被同步建立相同的Deployment。另外也支用spec.placement.clusterSelector的方式来选择要放置的集群。
    • Override :定义修改指定集群的Federated资源中的spec.template内容。如部署FederatedDeployment到不同公有云上的集群时,就能通过spec.overrides来调整Volume或副本数。
目前Override不支持List(Array)。比如说无法修改spec.template.spec.containers[0].image。

Scheduling

KubeFed提供了一种自动化机制来将工作负载实例分散到不同的集群中,这能够基于总副本数与集群的定义策略来将Deployment或ReplicaSet资源进行编排。编排策略是通过建立ReplicaSchedulingPreference(RSP)文件,再由KubeFed RSP Controller监听与撷取RSP内容来将工作负载实例建立到指定的集群上。
以下为一个RSP 范例。假设有三个集群被联邦,名称分别为ap-northeast、us-east 与us-west。
apiVersion: scheduling.kubefed.k8s.io/v1alpha1
kind: ReplicaSchedulingPreference
metadata:
  name: test-deployment
  namespace: test-ns
spec:
  targetKind: FederatedDeployment
  totalReplicas: 15 
  clusters: 
    "*":
      weight: 2
      maxReplicas: 12
    ap-northeast:
      minReplicas: 1
      maxReplicas: 3
      weight: 1
当该范例建立后,RSP Controller会收到资源,并匹配对应namespace/name的FederatedDeployment与FederatedReplicaSet是否存在,若存在的话,会根据设定的策略计算出每个集群预期的副本数,之后覆写Federated资源中的spec.overrides内容以修改每个集群的副本数,最后再由KubeFed Sync Controller来同步至每个集群的Deployment。以上面为例,结果会是ap-northeast集群会拥有3个Pod,us-east跟us-west则分别会有6个Pod。
  • 若spec.clusters未定义的话,则预设为{“*”:{Weight: 1}}。
  • 若有定义spec.replicas 的overrides 时,副本会以RSP 为优先考量。
  • 分配的计算机制可以参考kubefed/pkg/controller/util/planner/planner.go。

Multi-Cluster DNS

KubeFed提供了一组API资源,以及Controllers来实现跨集群Service/Ingress的DNS records自动产生机制,并结合ExternalDNS来同步更新至DNS服务供应商。以下为简单例子:
apiVersion: multiclusterdns.kubefed.k8s.io/v1alpha1
kind: Domain
metadata:
  name: test
  namespace: kube-federation-system
domain: k8s.example.com
---
apiVersion: multiclusterdns.kubefed.k8s.io/v1alpha1
kind: ServiceDNSRecord
metadata:
  name: nginx
  namespace: development
spec:
  domainRef: test
  recordTTL: 300
首先假设已建立一个名称为nginx的FederatedDeployment,然后放到development namespace中,并且也建立了对应的FederatedService提供LoadBalancer。这时当建立上述Domain与ServiceDNSRecord后,KubeFed的Service DNS Controller会依据ServiceDNSRecord文件内容,去收集不同集群的Service信息,并将这些信息更新至ServiceDNSRecord状态中,接着DNS Endpoint Controller会依据该ServiceDNSRecord的状态内容,建立一个DNSEndpoint文件,并产生DNS records资源,最后再由ExternalDNS来同步更新DNS records至DNS供应商。下图是Service DNS建立的架构。

若是Ingress 的话,会由IngressDNSRecord 文件取代,并由Ingress DNS Controller 收集信息。

Setup Federation v2 on AWS

本节将简单说明如何在AWS 建立跨不同地区的Kubernetes 联邦集群,其架构如下图所示。

  • KubeFed 官方文件也提供了On-premises(minikube 与kind)、GKE 与IBM ICP 的教学,来让使用者快速学习如何构建。

事前准备

开始前,需要先安装下列工具到操作机器上来提供使用:
  • kubectl:用来操作部署完成的Kubernetes集群。版本为v1.14.1。
  • kops:用来部署与管理公有云上的Kubernetes集群。版本为v1.14.0。
    • Mac OS X:
    • $ brew update && brew install kops
    • Linux distro:
    • $ curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64
      $ chmod +x kops-linux-amd64 && sudo mv kops-linux-amd64 /usr/local/bin/kops
  • helm :用来部署Federation v2组件的工具。
  • kubefedctl:用来新增与加入集群成为联邦的工具。可以到连结中下载二进制档,版本为v0.1.0-rc1
  • AWS CLI:用来操作AWS服务的工具。
$ sudo pip install awscli
$ aws --version
aws-cli/1.15.4
上述工具完成后,还要准备一下信息:
  • 申请AWS 帐号,并在IAM 服务新增一个User 设定存取所有服务(AdministratorAccess)。另外这边要记住AccessKey 与SecretKey。
一般来说只需开启S3、Route53、EC2、EBS、ELB 与VPC 权限,但由于偷懒就全开。以下为各AWS 服务在本次安装中的用意:
  • IAM: 提供身份认证与存取管理。
  • EC2: Kubernetes 集群部署的虚拟机环境。
  • ELB: Kubernetes 文件与Service 负载平衡。
  • Route53: 提供Public domain 存取Kubernetes 集群环境与应用。
  • S3: 储存Kops 状态。
  • VPC: 提供Kubernetes 的Host 与CNI 网路环境。
  • 拥有自己的Domain Name,这边可以在AWS Route53 注册,或者是到GoDaddy 购买。

设定脚本参数

教学将使用撰写好的脚本aws-k8s-federation进行部署。首先在操作的节点通过Git取得脚本:
$ git clone https://github.com/kairen/aws-k8s-federation
$ cd aws-k8s-federation
$ cp .env.sample .env
编辑.env档案并修改一下参数:
# Kubernetes version
export KUBERNETES_VERSION="1.14.1"

# Your domain name and envs
export DOMAIN_NAME="k8s.example.com" # 你的 Domain Name( <hoste_dzone_name>.<domain_name>)

建立Route53 Hosted Zone

首先通过aws 工具进行设定使用指定AccessKey 与SecretKey:
$ aws configure
AWS Access Key ID [****************QGEA]:
AWS Secret Access Key [****************zJ+w]:
Default region name [None]:
Default output format [None]:
设定的Keys可以在~/.aws/credentials找到。
接着需要在Route53建立一个Hosted Zone,并在Domain Name供应商上设定NameServers:
$ ./0-create-hosted-domain.sh
# output
...
{
    "HostedZone": {
        "ResourceRecordSetCount": 2,
        "CallerReference": "2018-04-25-16:16",
        "Config": {
            "PrivateZone": false
        },
        "Id": "/hostedzone/Z2JR49ADZ0P3WC",
        "Name": "k8s.example.com."
    },
    "DelegationSet": {
        "NameServers": [
            "ns-1547.awsdns-01.co.uk",
            "ns-1052.awsdns-03.org",
            "ns-886.awsdns-46.net",
            "ns-164.awsdns-20.com"
        ]
    },
    "Location": "https://route53.amazonaws.com/2013-04-01/hostedzone/Z2JR49ADZ0P3WC",
    "ChangeInfo": {
        "Status": "PENDING",
        "SubmittedAt": "2018-04-25T08:16:57.462Z",
        "Id": "/change/C3802PE0C1JVW2"
    }
}
之后将上述NameServers新增至自己的Domain name的record中,如Godaddy:

部署集群

当上述流程都完成后,即可依照脚本顺序来完成Kubernetes 集群与Federation 集群的建立,过程中也会包含操作Federation v2 的功能。最终会以Federated 组件建立一个NGINX 应用,并部署到不同集群中,然后通过MultiClusterDNS + ExternalDNS 来自动建立DNS records 到AWS 上。

Summary
虽然KubeFed 还处于Alpha 阶段,但整体架构基于Federation v1 进行了很多改善,而从GitHub 近几个月的贡献来看,可以发现Red Hat 在此项目投入许多的贡献,这对于KubeFed 来说是很好的发展。而现在KubeFed 官方也有发布来一些文件,用来帮助使用者快速在Minikube、kind(Kubernetes IN Docker)、GCP 上部署,这对于初次接触的人是一项福利。
另外有趣的是从OpenShift v4.0 Roadmap中,也能看到KubeFed被放入其中,在Operator Hub跟federation-v2-operator也能看到Red Hat在这方面的布局。我想之后Kubernetes集群联邦又会再次成为热烈讨论的议题,或许Red Hat也是希望通过KubeFed实现OpenShift的多云(Multi-cloud)与混合云(Hybird Cloud)部署吧(个人觉得拉)。
不过这不完全表示KubeFed 在今后势必会发展得很好,因为随着Kubernetes 发展,想必还会有更多的问题需要去发现、提出与解决的,比如说有状态服务(Stateful Service)、Federation Host集群挂了怎么办等问题,这些问题若之后有相关社群的信息,我也会更新上来。

Related Posts

  • https://k2r2bai.com/2018/03/21/kubernetes/federation-v1/
  • https://k2r2bai.com/2018/04/21/kubernetes/aws-federation-v1/
  • https://speakerdeck.com/kairen/setup-kubernetes-federation-v2-on-aws
  • https://speakerdeck.com/kairen/setup-eks-multi-cluster-using-federation-v2

References

  • https://github.com/kubernetes-sigs/kubefed
  • https://kubernetes.io/blog/2018/12/12/kubernetes-federation-evolution/
  • https://containerjournal.com/2019/04/09/kubernetes-and-the-challenge-of-federation/
  • https://blog.openshift.com/combining-federation-v2-and-istio-multicluster/
  • https://medium.com/condenastengineering/k8s-federation-v2-a-guide-on-how-to-get-started-ec9cc26b1fa7
  • https://podctl.com/multi-cluster-and-federation-v2/
  • https://www.youtube.com/watch?v=q27rbaX5Jis&feature=youtu.be&t=7m20s
K8S中文社区微信公众号

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址