首页 >后端开发 >Golang >Kubernetes 云控制器管理器

Kubernetes 云控制器管理器

Patricia Arquette
Patricia Arquette原创
2024-12-24 09:25:21701浏览

请注意,这篇文章最初是我在medium.com 上发布的,此后我决定转到dev.to!

The Kubernetes Cloud Controller Manager

本文假设您对操作/运行 Kubernetes 以及一些 Go 编程语言概念有一定的经验。

在过去的一年半中,我们在 Etraveli Group 与 OpenStack 和 Kubernetes 进行了大量合作。我们是我们自己的云提供商,最终用户是开发人员和开发组织中的周边团队。

在 OpenStack 之上运行 Kubernetes 的关键组件之一是云控制器管理器。它是将两个平台粘合在一起的部件之一。对于那些在公共云(或私有云)中使用托管 Kubernetes 服务的人来说,已经为您解决了这个问题。 Kubernetes 控制平面对你来说或多或少是遥不可及的。

那么为什么要写一些关于云控制器管理器的内容呢?主要驱动因素是我的一位同事提出的最简单的问题:

“(OpenStack)云控制器管理器到底做什么?”

我试图回答这个问题,但我基本上不知道我在说什么,我知道它负责在创建 LoadBalancer 类型的 Service 对象时在底层云中创建负载均衡器。

我立即决定深入研究一下这个问题,最终我进行了相当深入的研究,试图理解这个难题的每一点,在这篇文章中我将总结我的发现。

在这篇文章中我将参考:

  • 云控制器管理器作为“CCM

  • Kubernetes 主源代码存储库为“k/k

  • Kubernetes 为“k8s

当我开始写这篇文章时,我创建了一个小项目和存储库,在其中我按照规定构建了自己的云控制器管理器,并将两个小型 Kubernetes (v1.18.2) 集群相互进行比较,其中一个运行CCM 和没有的。这是一个概念验证,旨在向您展示运行自己的 CCM 到底需要什么。从构成 CCM 的代码到 k8s 清单的所有内容都表明您需要部署它。

在我们开始之前,很高兴知道这篇文章链接到 k8s 源代码存储库的各个部分,我使用了 v1.18.0 标签。

所有插图都是我自己的。

享受吧!

请留下一两条评论(!),我们非常感谢任何反馈!

云控制器管理器

从高层次的角度来看,云控制器管理器可以被描述为三个不同的事物:

  • 二进制

  • 多个控制循环

  • k8s 和云之间的一部分粘合剂

代码方面,CCM 是 k/k 存储库的一部分,请查看此处。正如官方 k8s 文档中提到的,k/k 中的 CCM 代码可以用作您自己实现的框架。区别在于您提供和导入的用于与云交互的代码(包)。

CCM 通常会通过 k8s 清单和内置于从众所周知的容器注册表中提取的(Docker)容器中的二进制文件进行部署。

值得注意的是,CCM 将被分配端口 10258,如果需要,您需要公开它。开箱即用的 CCM 将公开 /healthz 端点来检查服务的运行状况。

在 GitHub 中查看 k8s 组织时,您会发现许多不同的 CCM 实现,它们也称为外部 CCM,因为它们位于 k/k 存储库之外,并且由一组精心设计的 Golang 接口组成,如下所示以及任何人创建自己的 CCM 的最低限度。

稍后我们将详细了解这一切。

CCM 的核心由四个运行控制循环的(云)控制器组成,您可以选择与其他控制器一起运行自己的控制器。

The Kubernetes Cloud Controller Manager

我们将在接下来的部分中更深入地了解 CCM 中运行的每个云控制器。

节点控制器

节点控制器确保您的云节点(例如虚拟机)使用云提供商提供的其他相关信息进行标记、污染和更新。控制器将定期在无序列表中执行以下操作:

The Kubernetes Cloud Controller Manager

  • 使用以下污点初始化添加到云提供商的新节点:node.cloudprovider.kubernetes.io/uninitialized 设置为 true 并将污点效果设置为 NoSchedule。当节点初始化时,节点控制器将删除此污点,从而允许在节点上调度工作负载。对于例如至关重要的 Pod运行集群当然会在已经受污染的节点上安排需要的容忍度。

  • 通过将云提供商中的 IP 地址与 k8s API 中 Node 对象中存储的 IP 地址进行比较来更新节点 IP 地址。

  • 使用云提供的信息添加或更新节点标签,其中包括:实例类型区域故障域区域区域。区域特定信息不是强制性的,我们稍后会看到。

关于节点标签以及如何获取上面提到的实例信息并将其添加到 Node 对象中。举个例子,OpenStack 外部 CCM 通过从磁盘(配置磁盘)读取元数据或使用每个节点内可访问的元数据服务端点来执行此操作。

服务控制器

服务控制器将处理与在云中创建的基于服务对象的负载均衡器的生命周期相关的所有内容。服务提供了一种从 k8s 集群的角度内部和/或外部公开应用程序的方法。

这个特定的控制器将只处理 LoadBalancer 类型的 Service 对象。这意味着,从云提供商的角度来看,它将确保在您的云中创建、删除和更新某种类型的负载均衡器。

The Kubernetes Cloud Controller Manager

根据您的 CCM 如何实现服务控制器逻辑,您可以创建一个云负载均衡器,在云内部对网络流量进行负载平衡。这通常通过在服务对象的元数据部分定义一组注释来完成。

请注意,默认行为,正如我在例如中所指出的那样OpenStack 是在应用简单的 Service 对象(类型为 LoadBalancer)清单时将创建以下对象:

  • 云负载均衡器,其中包含流量将负载均衡到的节点的填充列表。负载均衡器将使用生成的随机 NodePort

  • 指向每个节点
  • NodePort 类型的 Service 对象

如上所示,实际上有很多东西构成了 k8s 和云提供商中的 Service 对象。对于用户来说,这意味着 EXTERNAL-IP 列将填充云负载均衡器的云提供商 IP。使用 kubectl 列出服务对象时可见:

$> kubectl get service my-app-svc
NAME       TYPE         CLUSTER-IP    EXTERNAL-IP     PORT(S)
my-app-svc LoadBalancer 172.20.10.100 123.123.123.123 80:31147/TCP

路线控制器

在四个控制器中,有一个有点特殊,那就是(云)路由控制器,除非您提供 --allocate-node-cidrs 或 --configure-cloud-routes 标志,否则它不会启动CCM。另外,如果您还没有实现任何路由处理逻辑,那么该控制器将不会启动,稍后会详细介绍。

The Kubernetes Cloud Controller Manager

此控制器将定期尝试执行以下操作:

  • 列出与 k8s 集群关联的所有路由,这是通过查询云提供商 API 来完成的。

  • 通过查询 k8s API 列出所有节点。

  • 循环遍历节点规范的每个节点和 podCIDRs 字段。 Pod CIDR 和节点名称将用于通过云提供商 API 创建路由。

此外,在控制循环期间,控制器将删除未使用的路由。当所有路由都创建完成后,节点将被视为就绪,这意味着 NetworkUnavailable 的节点条件字段将设置为 false 。如果节点没有任何与其关联的路由,则 NetworkUnavailable 字段将设置为 true 。这些条件由 NodeLifeCycle 控制器转化为污点,不要与 CCM 负责的条件混淆。

生命周期控制器

如果从云中删除节点,(云节点)生命周期控制器将确保以 Kubernetes API 节点对象表示的节点也被删除。

The Kubernetes Cloud Controller Manager

此外,如果节点处于云提供商指定的关闭状态,则该节点会相应地受到 node.cloudprovider.kubernetes.io/shutdown 和 NoSchedule 的污染效果的污染。

这就是您将从 CCM 获得的所有功能,大多数时候您的云可能有自己的控制器(以来自单独存储库的单独二进制文件提供)来处理 Ingress 类型的 k8s 对象,或者帮助您与底层网络基础设施原生集成。

CCM 不会是一站式解决方案,它只是一个更大拼图的一部分。

如果您一直在关注,并且可能查看了 CCM 处理的不同控制器的源代码,您可能会注意到没有任何云提供商特定的代码。只是对各种对象上有些神秘的方法进行了一堆调用。

云提供商特定的代码及其连接将是这个 CCM 难题中缺失的一块。

The Kubernetes Cloud Controller Manager

看看后视镜

在讨论云提供商包 (k8s.io/cloud-provider)(CCM 难题中缺失的一块)之前,我们将回顾一下 CCM 和云提供商背后的一些历史。这些年来它们是如何演变的以及一切是如何形成的。

出于显而易见的原因,从一开始,云集成就一直是 k8s 的一部分的基础。让我们看一下在 2015 年 7 月发布的 v1.0 的 k8s 存储库 (k/k) 中拥有特定提供商代码的云提供商:

  • AWS
  • GCE
  • Mesos
  • OpenStack
  • 奥维尔特
  • 机架空间
  • 流浪者

您可能认识以上所有“云提供商”,其中一些是虚拟化技术,并不完全符合我们通常所认为的云提供商。至少可以说。

早在 2015 年 7 月,所有云提供商特定代码均由 kubelet 导入和使用,kubelet 是构成 k8s 集群节点的关键节点组件之一。

k8s 社区已经认识到云提供商特定代码的原始实现存在许多问题,并且到目前为止正在努力解决。

以下是这些年来出现的一些问题:

  • kubelet 不应运行云提供商特定的控制循环。现已移至 CCM。

  • 云提供商不应成为 k/k(树内)的一部分,原因是云提供商代码将绑定到 k8s 发布周期,并且可以将代码提交到 k/k一项乏味的任务。

  • 通过提供单独的包以及将云与 k8s 集成的可插拔方式来支持外部(树外)云提供商。这成为 k8s.io/cloud-provider 包。

  • CCM 使用的所有云控制器代码都应移动到 k8s.io/cloud-provider 包中,树中仍有剩余代码将被移动。

出于向后兼容性的原因,树内的代码将存在一段时间,但现在它是自己的包(k8s.io/legacy-cloud-providers)。

我试图通过挖掘 k8s 组织中的各个存储库来了解 CCM 和 k8s.io/cloud-provider 是如何形成的,就像数字考古一样。以下是一些亮点:

  • 2016 年 9 月,创建了增强 #88 (KEP) 问题以支持树外云提供商(可插入)。

  • 开始将 (kube) 控制器管理器分成两部分,2016 年 10 月。请注意,此 PR 提到了volumeController,这是 CSI 之前的时间。此后该控制器已从 CCM 中删除。

  • 云控制器管理器讨论 2017 年 7 月。在 v1.11 中进入测试版。

  • 这里很好地解释了 kubelet 和云提供商曾经的紧密耦合程度。关于如何解耦 kubelet 和云提供商,有以下三种方法。

云提供商包

云提供商包在 CCM 中作为 k8s.io/cloud-provider 导入,并定义了许多 (Golang) 接口。主要的一个是 Interface 接口,这使得这个包可以为云提供商插入。

The Kubernetes Cloud Controller Manager

接口定义了一组方法,其中一些方法返回其他接口。这些返回的接口也在云提供商包的cloud.go文件中定义。

$> kubectl get service my-app-svc
NAME       TYPE         CLUSTER-IP    EXTERNAL-IP     PORT(S)
my-app-svc LoadBalancer 172.20.10.100 123.123.123.123 80:31147/TCP

正如您在上面看到的,方法签名在返回的接口旁边指定了一个 bool 返回值,这意味着您可以启用/禁用 CCM 无法或不应该实现的功能。这是在实现接口定义的功能的控制器初始化期间检查的内容。

以下是哪个控制器使用哪些 k8s.io/cloud-provider 接口方法的快速概述:

  • 实例接口方法将从节点和生命周期控制器调用。

  • Zones 接口方法将从 Node 和 Lifecycle 控制器调用。

  • Route 接口方法将从 Route 控制器调用。

  • LoadBalancer 接口方法将从服务控制器调用。

  • 集群接口仅供 GCP 外部云提供商使用。

请注意,k/k 存储库中的许多位置都调用了上述接口中的各种方法,例如在 kubelet 和 API 服务器中。

除了 k8s.io/cloud-provider 包上面的接口之外,还包括使用 CCM 注册和初始化云提供商所需的一切。

让我们看一下LoadBalancer接口,你会看到一堆需要实现的方法:

LoadBalancer() (LoadBalancer, bool)
Instances() (Instances, bool)
Zones() (Zones, bool)
Clusters() (Clusters, bool)
Routes() (Routes, bool)

这些方法将由在 CCM 中运行的服务控制器调用,我将这些方法作为示例进行展示,因为您将看到这些方法在服务控制器的源代码中被调用。

实际上在整个 CCM 中传递的是您的实例化对象,它将充当云提供商(满足所有云提供商接口)。

这就是 CCM 维护的云控制器如何在您的云中创建、更新和删除资源。

The Kubernetes Cloud Controller Manager

k8s.io/cloud-provider 包不会定义任何连接方式,例如向您的云进行身份验证。您必须将这种逻辑构建到 CCM 中。

当您满足了 k8s.io/cloud-provider 包中定义的所有接口并将所有内容连接在一起时,您就成功成为了云提供商。剩下的唯一事情就是构建 CCM 二进制文件并将其打包到容器中并将其部署到 k8s!

展望未来,在查看 k/k 存储库的云提供商部分时,实际上会发生很多事情,在撰写本文时,正在采取一项持续的举措来重组并使 k8s.io/cloud-provider 或多或少独立的。意思是例如云控制器将成为 k8s.io/cloud-provider 包的一部分,这意味着最终您作为云提供商将导入一个包,以便能够构建和实现您自己的 CCM 和外部云提供商。

从 Kubernetes 的角度来看

为了能够运行新组装且 Docker 打包的 CCM,在启动 k8s 控制平面时需要配置一些内容:

  • kubelet 应以 --cloud-provider=external 标志启动,这向 kubelet 发出信号,表明有另一个控制器正在初始化节点。

正如本文开头提到的,我在这个存储库中展示并解释了运行您自己的外部云提供商 CCM 的技术方面。

如果您现在在 AWS 上在 EC2 实例上运行自己的 k8s 集群,并且希望与 AWS 进行更原生的集成,那么您可能会部署云提供商 AWS CCM。您也可以(尽管不推荐)仅在 kubelet 上指定 --cloud-provider=aws。这就是您向 k8s 发出信号表示您想要使用树内云提供商的方式,其中只有少数已实现。任何“较新”的私有/公共云都会有一个外部云提供商 CCM。

树内云提供商的代码是通过 k8s.io/legacy-cloud-providers 导入的,请注意,当您使用 k/k 中的 CCM 框架代码时,您将从一开始就导入此包.

资源

要了解 k8s 背景下与云提供商相关的一切动态,请参阅以下资源:

  • SIG 云提供商

  • k8s Slack 空间中的 sig-cloud-provider 频道

  • 所有带有 sig/cloud-provider 标签的 k8s 增强问题

这是外部云提供商的列表,非常适合用作参考,或者如果您只是对其他人的做法感到好奇:

  • OpenStack

  • 数字海洋

  • AWS

  • GCP

  • 阿里云

  • 华为云

  • 百度云

  • vSphere

  • 天蓝色

以上是Kubernetes 云控制器管理器的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn