园丁项目更新

作者: 拉斐尔·弗朗兹克 (树液), 瓦苏 Chandrasekhara (树液)

去年,我们介绍了 园丁 在里面 Kubernetes Community Meeting并在 Kubernetes Blog。在SAP,我们一直 经营Gardener超过两年,并成功管理 thousands of 一致的 在所有主要的超级缩放器上以及在众多版本中的各种版本的集群 通常通过以下方式加入企业的基础架构和私有云 acquisitions.

人们经常被问到为什么少数几个动态可伸缩集群不会 足够了。我们也以类似的心态开始了Kubernetes之旅。但 我们意识到将Kubernetes的架构和原理应用于 生产场景中,我们的内部和外部客户非常需要 在大多数情况下,关注点和所有权的合理分离 导致使用多个群集。因此,可扩展和可管理 Kubernetes即服务解决方案通常也是采用的基础。 特别是当大型组织在不同的产品上运行多个产品时 供应商和不同地区,集群的数量将迅速上升到 数百甚至数千。

今天,我们想提供过去一年中实施的最新信息 关于可扩展性和可定制性,以及我们计划为我们做些什么 next milestone.

简短回顾:什么是园丁?

园丁的主要原则是将Kubernetes原语用于其所有 操作,通常称为初始或kubeception。来自的反馈 社区最初是我们的 建筑 diagram 看起来 “压倒性的”,但是在稍微深入研究材料之后,我们 要做的就是“ Kubernetes方式”。人们可以重用与API有关的所有知识, control loops, etc.
基本思想是所谓的 种子 群集用于托管 最终用户集群的控制平面(统称 )。
园丁提供了香草Kubernetes集群作为服务,独立于 基础架构提供者以同质方式利用上游 provided k8s.gcr.io/* images as open distribution. The project is built 完全基于Kubernetes扩展概念,因此添加了自定义API 服务器,控制器管理器和调度程序以创建和管理生命周期 Kubernetes集群。它使用自定义资源扩展了Kubernetes API, most prominently the 园丁 cluster specification (Shoot resource), that can 用于以声明方式“排序” Kubernetes集群(对于第一天,但 还要协调第二天的所有管理活动)。

通过利用Kubernetes作为基础架构,我们能够设计出一个 combined 水平和垂直Pod自动缩放器 (HVPA) 当配置 自定义试探法,按比例放大/缩小或缩小/放大所有控制平面组件 自动。这可以实现快速扩展,甚至超出了 通常一些固定数量的主节点。这一建筑特色是 与许多其他Kubernetes集群配置相比的主要区别 工具。但是在我们的生产中,园丁不仅有效地减少了 通过装箱控制平面来节省总拥有成本。这也简化了 实施“第2天的操作”(例如集群更新或健壮性 质量)。再次,基本上是依靠所有成熟的Kubernetes功能 and capabilities.

现在,针对Gardener的新引入的扩展概念使提供商能够 只维持其特定的扩展,而无需在内部进行开发 核心源代码树。

可扩展性

由于过去几年的增长,Kubernetes代码库包含了 大量的特定于提供商的代码现在正从 它的核心源代码树。园丁计划也发生了同样的事情:随着时间的流逝, 有关云提供商,操作系统,网络插件等的许多细节。 已经积累了。通常,这导致 在可维护性,可测试性或新版本方面进行努力。我们的 community member 贡献了 园丁 support 对于他们的基础架构树, 并遭受了上述缺点。

因此,类似于Kubernetes社区决定移动他们的 云控制器管理器在树外或CSI的卷插件等, Gardener community 提议的 并实施了类似的扩展概念。园丁的核心源代码树是 现在没有任何提供商详细信息,允许供应商仅专注于他们的 基础架构方面的细节,并使核心贡献者变得更加敏捷 again.

通常,设置集群需要一系列相互依赖的步骤, 首先是生成证书并准备 基础设施,继续提供控制平面和 工作节点,最后以系统组件的部署结束。我们想 在这里强调所有这些步骤都是必要的(cf. Kubernetes的硬汉 Way) 和所有 Kubernetes集群创建工具执行相同的步骤 学位)。

园丁的可扩展性概念的总体思想是 这个 flow 更通用,并为每个步骤分配自定义资源 理想的扩展点。

具有扩展点的集群对帐流程

图1带有扩展点的群集对帐流程。

借助Gardener的流程框架,我们隐式地拥有了可重现的状态机 适用于群集的所有基础架构和所有可能的状态。

园丁的可扩展性方法定义了理想的自定义资源 以下类别的扩展点:

  • DNS提供商(例如Route53,CloudDNS等),
  • Blob存储提供者(例如S3,GCS,ABS等),
  • 基础架构提供商(例如AWS,GCP,Azure等),
  • 操作系统(例如,CoreOS Container Linux,Ubuntu,FlatCar Linux等),
  • 网络插件(例如Calico,Flannel,Cilium等),
  • 非必要的扩展名(例如,让我们加密证书服务)。

延伸点

除了利用自定义资源定义之外,我们还有效地使用了变异 /验证种子集群中的webhooks。扩展控制器本身运行 in these clusters and react on CRDs and workload resources (like Deployment, StatefulSet等)。类似于 簇 API的方法,这些CRD也可能包含 提供商特定的信息。

步骤2-10. 10. [cf.图1]涉及基础架构特定的元数据 指特定于基础架构的实现,例如用于那里的DNS记录 might be aws-route53, google-clouddns, or for isolated networks even openstack-designate, 还有很多。我们将检查步骤4和6 在以下各段中,作为一般概念的示例(基于 AWS的实施)。如果您有兴趣,可以阅读全文 我们的文件API合同 可扩展性 documents.

Example: Infrastructure CRD

AWS上的Kubernetes集群需要进行一定的基础架构准备工作 他们可以使用。例如,这包括创建VPC,子网, etc. The purpose of the Infrastructure CRD is to trigger 这个 preparation:

apiVersion: extensions.gardener.cloud/v1alpha1
kind: Infrastructure
metadata:
  name: infrastructure
  namespace: shoot--foobar--aws
spec:
  type: aws
  region: eu-west-1
  secretRef:
    name: cloudprovider
    namespace: shoot--foobar—aws
  sshPublicKey: c3NoLXJzYSBBQUFBQ...
  providerConfig:
    apiVersion: aws.provider.extensions.gardener.cloud/v1alpha1
    kind: InfrastructureConfig
    networks:
      vpc:
        cidr: 10.250.0.0/16
      zones:
      - name: eu-west-1a
        internal: 10.250.112.0/22
        public: 10.250.96.0/22
        workers: 10.250.0.0/19

Based on the Shoot resource, 园丁 creates 这个 Infrastructure resource as part of its reconciliation 流. The AWS-specific providerConfig is part of the end-user's configuration 在里面 Shoot resource and not evaluated by 园丁,但只是传递给种子集群中的扩展控制器。

在当前实施中,AWS扩展创建了一个新的VPC和三个 subnets 在里面 eu-west-1a zones. Also, it creates a NAT and an internet 网关,弹性IP,路由表,安全组,IAM角色,实例 配置文件和一个EC2密钥对。

完成任务后,它将报告状态和一些 提供者特定的输出:

apiVersion: extensions.gardener.cloud/v1alpha1
kind: Infrastructure
metadata:
  name: infrastructure
  namespace: shoot--foobar--aws
spec: ...
status:
  lastOperation:
    type: Reconcile
    state: Succeeded
  providerStatus:
    apiVersion: aws.provider.extensions.gardener.cloud/v1alpha1
    kind: InfrastructureStatus
    ec2:
      keyName: shoot--foobar--aws-ssh-publickey
    iam:
      instanceProfiles:
      - name: shoot--foobar--aws-nodes
        purpose: nodes
      roles:
      - arn: "arn:aws:iam::<accountID>:role/shoot..."
        purpose: nodes
    vpc:
      id: vpc-0815
      securityGroups:
      - id: sg-0246
        purpose: nodes
      subnets:
      - id: subnet-1234
        purpose: nodes
        zone: eu-west-1b
      - id: subnet-5678
        purpose: public
        zone: eu-west-1b

The information inside the providerStatus can be used in subsequent steps, 例如配置云控制器管理器或检测 机器控制器经理。

示例:群集控制平面的部署

园丁的主要特征之一是群集的同质性 跨不同的基础架构进行管理。因此,它仍然负责 将独立于提供程序的控制平面组件部署到种子中 集群(例如etcd,kube-apiserver)。部署特定于提供程序的控件 触发了诸如云控制器管理器或CSI控制器之类的平面组件 by a dedicated ControlPlane CRD. In 这个 paragraph, however, we want to focus 关于标准组件的定制。

让我们专注于kube-apiserver和kube-controller-manager Deployments。我们针对Gardener的AWS扩展尚未使用CSI,而是依靠 在树内EBS卷插件上。因此,它需要启用 PersistentVolumeLabel 接纳插件并提供云提供商 配置到kube-apiserver。同样,kube-controller-manager将是 指示使用其树内音量插件。

The kube-apiserver Deployment incorporates the kube-apiserver container and 由Gardener部署,如下所示:

containers:
- command:
  - /hyperkube
  - apiserver
  - --enable-admission-plugins=Priority,...,NamespaceLifecycle
  - --allow-privileged=true
  - --anonymous-auth=false
  ...

Using a MutatingWebhookConfiguration the AWS extension injects the mentioned 标记并修改规范,如下所示:

containers:
- command:
  - /hyperkube
  - apiserver
  - --enable-admission-plugins=Priority,...,NamespaceLifecycle,PersistentVolumeLabel
  - --allow-privileged=true
  - --anonymous-auth=false
  ...
  - --cloud-provider=aws
  - --cloud-config=/etc/kubernetes/cloudprovider/cloudprovider.conf
  - --endpoint-reconciler-type=none
  ...
  volumeMounts:
  - mountPath: /etc/kubernetes/cloudprovider
    name: cloud-provider-config
volumes:
- configMap:
    defaultMode: 420
    name: cloud-provider-config
  name: cloud-provider-config

The kube-controller-manager Deployment is handled in a similar way.

种子簇中的Webhook可用于变异与芽相关的任何东西 由Gardener或任何其他扩展部署的群集控制平面。有一个 案例扩展中,拍摄集群中资源的类似webhook概念 控制器需要定制Gardener部署的系统组件。

扩展控制器的注册

园丁 API使用两个特殊资源来注册和安装扩展。 The registration itself is declared via the ControllerRegistration resource. 最简单的选择是定义Helm图表以及一些要渲染的值 该图表,但是,通过自定义代码支持任何其他部署机制 as well.

园丁确定在特定环境中是否需要扩展控制器 seed cluster, and creates a ControllerInstallation that is used to trigger the deployment.

迄今为止,每个注册的扩展控制器都已部署到每个种子集群 通常没有必要。未来,园丁将变得更加 选择仅在特定种子上部署所需的扩展 clusters.

我们的动态注册方法允许您在 正在运行的系统-无需重建或重新启动任何组件。

具有扩展控制器的园丁体系结构

图2具有扩展控制器的Gardener架构。

现状

We have recently introduced the new core.gardener.cloud API group that incorporates fully forwards and backwards compatible Shoot resources, and that 允许提供者使用Gardener而无需修改其核心源中的任何内容 tree.

我们已经调整了所有控制器以使用此新的API组,并具有 不推荐使用旧的API。最终,几个月后,我们将其删除,因此 建议最终用户尽快开始迁移到新的API。

除此之外,我们还启用了所有相关扩展程序,以帮助 拍摄健康状况并执行相应的合同。基本思想是 that the CRDs may have .status.conditions that are picked up by 园丁 and merged with its standard health checks into the Shoot status field.

另外,我们想实现一些易于使用的库函数,以促进 CRD的默认和验证Webhook,以验证 providerConfig 由最终用户控制的字段。

最后,我们将拆分 gardener/gardener-extensions 将信息库存储到单独的信息库中,并仅将其用于通用库 可用于编写扩展控制器的函数。

下一步

Kubernetes已将许多基础设施管理挑战外部化。 初始设计通过将生命周期操作委托给客户来解决大多数问题 单独的管理平面(种子集群)。但是,如果花园群或一个 种子簇掉了吗?我们如何扩展到成千上万的托管 需要并行协调的集群?我们正在进一步投资 加强了Gardener的可伸缩性和灾难恢复功能。让我们简单地 突出显示其中三个功能:

小花园

从园丁项目的开始,我们就开始实施 算子 pattern:我们 有一个根据我们自己的自定义资源执行操作的自定义控制器管理器。现在, 当您开始考虑 园丁 architecture,你 将认识到与Kubernetes的一些有趣的相似之处 体系结构:可以将芽簇与吊舱进行比较,并且可以将种子簇与 被视为工作节点。以此观察为指导,我们介绍了 园丁计划者。其主要任务是找到合适的种子簇以 为新排序的集群托管控制平面,类似于 kube-scheduler为新创建的Pod找到合适的节点。通过提供 一个区域(或提供者)的多个种子集群并分配工作量, 我们还减少了潜在的爬升半径。

Kubernetes和Gardener架构之间的相似之处

图3 Kubernetes与Gardener架构之间的相似性

但是,Kubernetes与 Gardener架构:Kubernetes在每个节点上运行一个主要的“代理”, kubelet,主要负责管理其上的容器和容器 特定节点。园丁使用其控制器-经理负责 所有种子簇上的所有芽簇,并且它正在执行对帐 从花园集群集中循环。

尽管这在当今成千上万个集群中都可以很好地实现,但我们的目标是 遵循Kubernetes原则实现真正的可扩展性 一个控制器-经理):我们现在正在努力分配逻辑 (或Gardener运算符)放入种子集群,并将引入 相应的组件,充分命名为 小花园。这将是 园丁在每个种子簇上的主要“代理”,仅负责 用于位于其特定种子簇中的芽簇。

园丁-控制器-经理仍将保留其控制循环以供其他 Gardener API的资源,但是它将不再与种子/拍摄对话 clusters.

反转控制流甚至可以将种子/拍摄群集放置在后面 无需直接访问(通过VPN隧道)的防火墙 anymore.

小花园的详细架构

图4使用Gardenlet的详细架构。

种子簇之间的控制平面迁移

当种子群集出现故障时,用户的静态工作负载将继续运行。 但是,将无法管理集群,因为拍摄 在失败的种子中运行的群集的API服务器不再可访问。

我们已经实施了由种子击中的失败控制飞机的重定位 灾难到另一个种子,现在正在致力于完全自动化这种独特的 能力。实际上,这种方法不仅可行,而且我们已经执行了 我们的生产中多次执行故障转移程序。

自动故障转移功能将使我们能够实施更多 全面的灾难恢复和可伸缩性质量,例如自动化 为所有人配置和重新平衡种子集群或自动迁移 不可预见的情况。再次考虑一下与Kubernetes的相似之处 关于吊舱搬迁和节点排水。

园丁戒指

园丁戒指是我们用于配置和管理Kubernetes的新颖方法 群集,而无需依赖初始群集的外部配置工具。 通过以递归方式使用Kubernetes,我们可以大大减少 通过在创建新工具时避免必要的工具集来管理复杂性 具有自稳定循环系统的质量。

Ring方法在概念上不同于自托管和静态Pod 基于基础的部署。这个想法是制造三(或更多)个射击圈 每个主机都承载其后继控制平面的集群。

一个群集的中断不会影响该群集的稳定性和可用性。 振铃,并且当控制平面被外部化时,发生故障的群集可能是 通过Gardener的自我修复功能自动恢复。只要 there is a quorum of at least n/2+1 available clusters the Ring will always 稳定自己。在不同的云提供商上(或在 至少在不同地区/数据中心)减少了仲裁的可能性 losses.

Kubernetes集群的自稳定环

图5 Kubernetes集群的自稳定环

园丁的分布式实例如何共享相同数据的方式是通过 部署与同一个etcd集群通信的单独的kube-apiserver实例。 这些kube-apiserver正在形成一个无节点的Kubernetes集群,该集群可以 用作Gardener及其相关应用程序的“数据容器”。

我们正在运行受环内部保护的测试环境,它已保存 我们通过人工干预。随着自动控制平面的迁移 在这里,我们可以轻松地引导环并解决“初始簇 问题”,并提高整体健壮性。

入门!

如果您有兴趣编写扩展程序,则可能需要查看 following resources:

当然,对我们项目的任何其他贡献也将受到欢迎!我们是 一直在寻找新的社区成员。

如果您想尝试园丁,请查看我们的 快速安装 guide。此安装程序将设置一个完整的 园丁环境准备就绪,可以在短短的时间内用于测试和评估 few minutes.

捐款欢迎!

园丁项目是作为开源开发的,并托管在GitHub上: //github.com/gardener

如果您看到Gardener项目的潜力,请通过GitHub加入我们。

我们每周有一次 公共社区 meeting 预定于欧洲中部时间每周五10-11点公开 #园丁 Slack Kubernetes中的频道 工作区。另外,我们正在计划 第一季度的园丁黑客马拉松 2020 并期待与您会面!