DIY:使用 Kubernetes 创建您自己的云(第 3 部分)

本文将深入探讨在 Kubernetes 内部运行 Kubernetes 的有趣阶段。重点介绍 Kamaji 和 Cluster API 等技术,以及它们与 KubeVirt 的集成。

之前的讨论涵盖了在裸机上准备 Kubernetes 以及如何将 Kubernetes 转变为虚拟机管理系统。本文将通过解释如何使用上述所有内容,构建一个功能齐全的托管 Kubernetes,并只需点击一下即可运行虚拟 Kubernetes 集群,来结束本系列文章。

首先,让我们深入了解 Cluster API。

Cluster API

Cluster API 是 Kubernetes 的一个扩展,允许将 Kubernetes 集群作为自定义资源在另一个 Kubernetes 集群中进行管理。

Cluster API 的主要目标是为描述 Kubernetes 集群的基本实体及其生命周期管理提供一个统一的接口。这使得创建、更新和删除集群的过程自动化,简化了扩展和基础设施管理。

在 Cluster API 的上下文中,有两个术语:管理集群租户集群

  • 管理集群是一个 Kubernetes 集群,用于部署和管理其他集群。这个集群包含所有必要的 Cluster API 组件,并负责描述、创建和更新租户集群。它通常仅用于此目的。
  • 租户集群是用户集群或使用 Cluster API 部署的集群。它们是通过在管理集群中描述相关资源来创建的。然后,最终用户使用它们来部署应用程序和服务。

重要的是要理解,物理上,租户集群不一定必须与管理集群在同一基础设施上运行;它们通常在其他地方运行。

A diagram showing interaction of management Kubernetes cluster and tenant Kubernetes clusters using Cluster API

展示使用 Cluster API 的管理 Kubernetes 集群和租户 Kubernetes 集群之间交互的图表

为了运行,Cluster API 利用了提供程序的概念,这些提供程序是负责所创建集群的特定组件的独立控制器。在 Cluster API 中,有几种类型的提供程序。主要的有:

  • 基础设施提供程序,负责提供计算基础设施,例如虚拟机或物理服务器。
  • 控制平面提供程序,提供 Kubernetes 控制平面,即 kube-apiserver、kube-scheduler 和 kube-controller-manager 组件。
  • 引导程序提供程序,用于为正在创建的虚拟机和服务器生成 cloud-init 配置。

要开始使用,您需要安装 Cluster API 本身以及每种类型的一个提供程序。您可以在项目的文档中找到支持的提供程序的完整列表。

对于安装,您可以使用 clusterctl 实用程序,或使用Cluster API Operator作为更具声明性的方法。

选择提供程序

基础设施提供程序

要使用 KubeVirt 运行 Kubernetes 集群,必须安装KubeVirt 基础设施提供程序。它支持在 Cluster API 运行的同一管理集群中为工作节点部署虚拟机。

控制平面提供程序

Kamaji 项目提供了一个现成的解决方案,用于在管理集群中以容器形式运行租户集群的 Kubernetes 控制平面。这种方法有几个显着的优点:

  • 成本效益:在容器中运行控制平面避免了为每个集群使用单独的控制平面节点,从而显著降低了基础设施成本。
  • 稳定性:通过消除复杂的多层部署方案来简化架构。不再是依次启动虚拟机,然后在其中安装 etcd 和 Kubernetes 组件,而是有一个简单的控制平面,它作为 Kubernetes 内的常规应用程序进行部署和运行,并由 Operator 管理。
  • 安全性:集群的控制平面对最终用户是隐藏的,减少了其组件被破坏的可能性,并且消除了用户对集群证书存储的访问。这种组织对用户不可见的控制平面的方法通常被云提供商使用。

引导程序提供程序

Kubeadm 作为引导程序提供程序 - 作为在 Cluster API 中准备集群的标准方法。此提供程序作为 Cluster API 本身的一部分开发。它只需要一个安装了 kubelet 和 kubeadm 的预备系统镜像,并允许生成 cloud-init 和 ignition 格式的配置。

值得注意的是,Talos Linux 也支持通过 Cluster API 进行配置,并且为此提供程序。尽管之前的文章讨论了使用 Talos Linux 在裸机节点上设置管理集群,但要配置租户集群,Kamaji+Kubeadm 方法具有更多优势。它有助于在容器中部署 Kubernetes 控制平面,从而无需为控制平面实例单独使用虚拟机。这简化了管理并降低了成本。

工作原理

Cluster API 中的主要对象是 Cluster 资源,它是所有其他资源的父级。通常,此资源引用另外两个资源:一个描述控制平面的资源和一个描述基础设施的资源,每个资源都由一个单独的提供程序管理。

与 Cluster 不同,这两个资源没有标准化,它们的类型取决于您使用的特定提供程序。

A diagram showing the relationship of a Cluster resource and the resources it links to in Cluster API

展示 Cluster 资源及其在 Cluster API 中链接到的资源的关系的图表

在 Cluster API 中,还有一个名为 MachineDeployment 的资源,它描述了一组节点,无论是物理服务器还是虚拟机。此资源的功能类似于标准的 Kubernetes 资源,例如 Deployment、ReplicaSet 和 Pod,为声明性描述一组节点和自动扩展提供了一种机制。

换句话说,MachineDeployment 资源允许您以声明方式描述集群的节点,根据指定的参数和请求的副本数自动创建、删除和更新它们。

A diagram showing the relationship of a Cluster resource and its children in Cluster API

展示 MachineDeployment 资源及其在 Cluster API 中子关系的图表

为了创建机器,MachineDeployment 引用一个用于生成机器本身的模板和一个用于生成其 cloud-init 配置的模板

A diagram showing the relationship of a Cluster resource and the resources it links to in Cluster API

展示 MachineDeployment 资源及其在 Cluster API 中链接到的资源的关系的图表

要使用 Cluster API 部署新的 Kubernetes 集群,您需要准备以下资源集:

  • 一个通用的 Cluster 资源
  • 一个 KamajiControlPlane 资源,负责由 Kamaji 运行的控制平面
  • 一个 KubevirtCluster 资源,描述 KubeVirt 中的集群配置
  • 一个 KubevirtMachineTemplate 资源,负责虚拟机模板
  • 一个 KubeadmConfigTemplate 资源,负责生成令牌和 cloud-init
  • 至少一个 MachineDeployment 来创建一些工作节点

完善集群

在大多数情况下,这已经足够了,但根据使用的提供程序,您可能还需要其他资源。您可以在Kamaji 项目文档中找到为每种类型的提供程序创建的资源示例。

在这个阶段,您已经拥有一个准备就绪的租户 Kubernetes 集群,但到目前为止,它只包含 API 工作节点和几个核心插件,这些插件标准地包含在任何 Kubernetes 集群的安装中:kube-proxyCoreDNS。为了完全集成,您还需要安装更多组件

要安装其他组件,您可以使用一个单独的用于 Helm 的 Cluster API 附加提供程序,或在之前的文章中讨论的相同的 FluxCD

在 FluxCD 中创建资源时,可以通过引用 Cluster API 生成的 kubeconfig 来指定目标集群。然后,安装将直接在其内部执行。因此,FluxCD 成为管理管理集群和用户租户集群中资源的通用工具。

A diagram showing the interaction scheme of fluxcd, which can install components in both management and tenant Kubernetes clusters

展示 fluxcd 交互方案的图表,它可以在管理和租户 Kubernetes 集群中安装组件

这里讨论哪些组件?一般来说,该集合包括以下内容:

CNI 插件

为了确保租户 Kubernetes 集群中的 Pod 之间进行通信,有必要部署 CNI 插件。此插件创建一个虚拟网络,允许 Pod 相互交互,并且传统上以 Daemonset 的形式部署在集群的工作节点上。您可以选择并安装任何您认为合适的 CNI 插件。

A diagram showing a CNI plugin installed inside the tenant Kubernetes cluster on a scheme of nested Kubernetes clusters

展示在嵌套 Kubernetes 集群方案中安装在租户 Kubernetes 集群内的 CNI 插件的图表

云控制器管理器

云控制器管理器 (CCM) 的主要任务是将 Kubernetes 与云基础设施提供商的环境集成(在您的情况下,它是配置租户 Kubernetes 的所有工作节点的管理 Kubernetes 集群)。以下是它执行的一些任务:

  1. 当创建类型为 LoadBalancer 的服务时,CCM 会启动创建云负载均衡器的过程,该负载均衡器会将流量定向到您的 Kubernetes 集群。
  2. 如果从云基础设施中删除节点,CCM 会确保也将其从您的集群中删除,从而维护集群的当前状态。
  3. 使用 CCM 时,会将节点添加到集群中,并带有特殊的污点 node.cloudprovider.kubernetes.io/uninitialized,如果需要,这允许处理额外的业务逻辑。成功初始化后,此污点会从节点中删除。

根据云提供商的不同,CCM 可以在租户集群的内部和外部运行。

KubeVirt 云提供程序旨在安装在外部父管理集群中。因此,在租户集群中创建类型为 LoadBalancer 的服务会启动在父集群中创建 LoadBalancer 服务,这些服务会将流量定向到租户集群。

A diagram showing a Cloud Controller Manager installed outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters and the mapping of services it manages from the parent to the child Kubernetes cluster

展示在嵌套 Kubernetes 集群方案中安装在租户 Kubernetes 集群外部的云控制器管理器,以及它管理的从父 Kubernetes 集群到子 Kubernetes 集群的服务映射的图表

CSI 驱动程序

容器存储接口 (CSI) 分为两个主要部分,用于在 Kubernetes 中与存储交互:

  • csi-controller:此组件负责与云提供商的 API 交互,以创建、删除、附加、分离和调整卷大小。
  • csi-node:此组件在每个节点上运行,并根据 kubelet 的请求,促进将卷挂载到 Pod。

在使用KubeVirt CSI 驱动程序的上下文中,会出现一个独特的机会。由于 KubeVirt 中的虚拟机在管理 Kubernetes 集群内运行,其中提供了一个功能齐全的 Kubernetes API,这为在用户的租户集群外部运行 csi-controller 开辟了道路。这种方法在 KubeVirt 社区中很受欢迎,并提供了几个关键优势:

  • 安全性:此方法向最终用户隐藏了内部云 API,仅通过 Kubernetes 接口提供对资源的访问。因此,它降低了从用户集群直接访问管理集群的风险。
  • 简洁性和便利性:用户无需在其集群中管理额外的控制器,从而简化了架构并减轻了管理负担。

但是,CSI 节点必须在租户集群内运行,因为它直接与每个节点上的 kubelet 交互。此组件负责将卷挂载和卸载到 Pod 中,因此需要与直接在集群节点上发生的进程紧密集成。

KubeVirt CSI 驱动程序充当订购卷的代理。当在租户集群内部创建 PVC 时,将在管理集群中创建一个 PVC,然后将创建的 PV 连接到虚拟机。

A diagram showing a CSI plugin components installed on both inside and outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters and the mapping of persistent volumes it manages from the parent to the child Kubernetes cluster

该图显示了 CSI 插件组件安装在嵌套 Kubernetes 集群方案中租户 Kubernetes 集群的内部和外部,以及它管理的从父 Kubernetes 集群到子 Kubernetes 集群的持久卷的映射。

集群自动扩缩器

集群自动扩缩器是一个多功能的组件,可以与各种云 API 一起使用,并且它与 Cluster-API 的集成只是其中一项可用功能。为了进行正确的配置,它需要访问两个集群:租户集群(用于跟踪 Pod 并确定是否需要添加新节点)和管理 Kubernetes 集群(管理 Kubernetes 集群),它在其中与 MachineDeployment 资源交互并调整副本的数量。

尽管集群自动扩缩器通常在租户 Kubernetes 集群内部运行,但在这种情况下,建议将其安装在外部,原因与之前所述相同。这种方法更易于维护且更安全,因为它阻止了租户集群的用户访问管理集群的管理 API。

A diagram showing a Cloud Controller Manager installed outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters

该图显示了集群自动扩缩器安装在嵌套 Kubernetes 集群方案中租户 Kubernetes 集群外部的情况。

Konnectivity

我想提及另一个额外的组件 - Konnectivity。您可能稍后需要它来使 Webhook 和 API 聚合层在您的租户 Kubernetes 集群中正常工作。我的上一篇文章中详细介绍了此主题。

与上面介绍的组件不同,Kamaji 允许您轻松启用 Konnectivity 并将其作为租户集群的核心组件之一进行管理,与 kube-proxy 和 CoreDNS 一起。

结论

现在,您拥有一个功能齐全的 Kubernetes 集群,具有动态扩展、自动配置卷和负载均衡器的功能。

接下来,您可能会考虑从租户集群收集指标和日志,但这超出了本文的范围。

当然,部署 Kubernetes 集群所需的所有组件都可以打包到一个 Helm chart 中,并作为统一的应用程序进行部署。这正是我们在我们的开放 PaaS 平台 Cozystack 上,通过单击按钮来组织托管 Kubernetes 集群部署的方式,您可以在其中免费试用本文中描述的所有技术。