Kubernetes Helm Chart 与 Operator 的对比

Kubernetes 的 Helm Chart 和 Operator 有一些共同点——首先,这两个术语都是"non-self-explanatory jargon"的典型代表。即使对于有编程经验的人来说,在 Kubernetes 语境下的"operator"一词可能也让人费解,因为它与编码中的"运算符"毫无关系。

至于 Helm Chart,你确实需要懂点希腊语——或者至少要知道 Kubernetes 源自一个意为"舵手"的希腊词——并且还得懂得欣赏这种俏皮、自我指涉的行话,才能明白为什么 Helm Chart 叫这个名字。(如果还不清楚的话,答案是:Helm Chart 帮助"引导"Kubernetes,就像舵轮引导船只一样。)

但是,除了它们都是让初学者感到困惑的术语之外,Operator 和 Helm Chart 的共同点并不多。确实,它们都服务于相同的基本目标:帮助在 Kubernetes 中安装和配置应用程序。但它们的实现方式不同。根据你所需要的控制程度以及应用生命周期管理的重要性等因素,Operator 可能比 Helm Chart 更合适,反之亦然。

认识到这一点后,请继续阅读,详细了解 Kubernetes Operator 和 Helm Chart 的对比,以及关于在何种情况下使用哪种解决方案的提示。

图片

什么是 Kubernetes Operator?

在 Kubernetes 中,Operator 是一种控制器,它可以使用 Kubernetes 自定义资源来安装和管理应用程序。为了更详细地解释这一点,让我们来解析这个定义中的两个关键词:控制器和自定义资源。

控制器

Kubernetes 中的控制器是一种例程,它监视 Kubernetes 配置的状态以及 Kubernetes 集群资源的实际状态。当它检测到某个资源的期望状态和实际状态之间存在偏差时(这可能是因为管理员修改了配置,或者由于 Kubernetes 集群内部发生了某种故障),控制器会尝试使期望状态和实际状态重新保持一致。

因此,如果你部署了一个描述你希望应用程序如何行为的配置,控制器将检测到该配置并应用它(假设考虑到你整个 Kubernetes 集群的状态,该配置是可以应用的)。

自定义资源

Kubernetes 中的自定义资源是 Kubernetes API 的一种扩展,它使得可以向 Kubernetes 集群添加默认情况下不可用的功能。你可以通过创建自定义资源定义(CRD)来实现这一点。

如果你想使用 Kubernetes Operator 安装或管理应用程序,你可以创建一个 CRD,实现该应用程序需要支持的任何功能。如果你随后将该 CRD 与一个控制器共同作为 Operator 的一部分,Kubernetes 控制器例程将检测并部署它。

Kubernetes Operator 示例

对于那些寻找基本 Kubernetes Operator 示例的人,hello-operator2 代码(由 Deepak Sharma 提供)是一个很好的样例。我们不会在此复制全部代码,但展示一些关键部分。

首先,Operator 定义了一些基本的上下文参数:

// 示例代码部分,展示定义
Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    // 1. 通过名称加载 HelloApp
    var helloApp demov1alpha1.HelloApp
    if err := r.Get(ctx, req.NamespacedName, &helloApp); err != nil {
        log.Info("Error loading HelloApp, ignoring because object must be deleted")
        return ctrl.Result{}, ignoreIsNotFound(err)
    }

然后,它实现了一个检查部署状态的函数:

    // 2. 检查 Deployment 是否存在,如果不存在则创建
    var deployment appsv1.Deployment
    if err := r.Get(ctx, req.NamespacedName, &deployment); err != nil && errors.IsNotFound(err) {
        // 为 HelloApp 创建新的 Deployment
        deployment := r.createHelloAppDeployment(helloApp)
        log.Info("Creating new deployment", "name", deployment.Name)
        if err := r.Create(ctx, deployment); err != nil {
            log.Info("Error creating deployment, will requeue", "error", err)
            return ctrl.Result{}, err
        }
        return ctrl.Result{Requeue: true}, nil
    }

接着,它创建了一个新的 Deployment:

func (r *HelloAppReconciler) createHelloAppDeployment(helloApp demov1alpha1.HelloApp) *appsv1.Deployment {
    // ... 设置部署规格的代码 ...
    return &appsv1.Deployment{
        ObjectMeta: metav1.ObjectMeta{
            Name:      helloApp.Name,
            Namespace: helloApp.Namespace,
        },
        Spec: *depSpec,
    }
}

如果你需要更多 Kubernetes Operator 示例,请查看 OperatorHub.io,它托管了数百个用于流行应用程序的免费 Kubernetes Operator。

什么是 Helm Chart?

既然我们已经了解了 Kubernetes Operator,现在让我们来谈谈 Helm 以及 Helm Chart 能实现什么。

Helm Chart 是一个,它包含使用一种名为 Chart 的打包格式在 Kubernetes 上部署应用程序所需的资源。你可以使用 Helm(猜对了!就是它)来安装 Helm Chart,Helm 是一个用于 Kubernetes 的应用程序包管理器和配置管理工具。

Helm Chart 和 Helm 包管理器类似于 Ubuntu 上的 Debian 包和 apt-get,或者 Red Hat 上的 RPM 包和 DNF,只有一个关键区别:与操作系统应用程序包不同,Helm Chart 通常不包含应用程序二进制文件。相反,它们包含指向部署应用程序所需安装的容器镜像的文件。

Helm Chart 示例

你可以在 Helm 项目的 GitHub 仓库 中找到基本 "hello world" 应用程序的示例 Helm Chart。该仓库包含两个关键文件。

图片

首先,是 Chart.yaml,它包含 Helm Chart 的配置数据:

apiVersion: v2
name: hello-world
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: "1.16.0"

然后,是 values.yaml,它定义了应用程序本身:

image:
  repository: nginx
  pullPolicy: IfNotPresent
  tag: ""

nameOverride: ""
fullnameOverride: ""

serviceAccount:
  create: true
  automount: true

要使用这样的 Helm Chart,你首先需要在系统上安装 helm CLI 工具。然后,使用如下命令添加包含你想要安装的 Helm Chart 的仓库:

helm repo add repo-name https://some-domain.com/path/to/repo

接着更新你的仓库列表:

helm repo update

最后,安装应用程序:

helm install my-release repo-name/hello-world

你也可以使用 Helm 来更新和删除应用程序,但我们将把 Helm 的全面使用指南留到另一篇文章中介绍。

Kubernetes Operator 与 Helm:11 个关键区别

如果你读到这里,你已经知道 Kubernetes Operator 和 Helm Chart 都是达到同一目的的手段:安装和管理应用程序。两者也都可以用于部署辅助 Kubernetes 故障排除和 Kubernetes 监控的工具。

但是 Kubernetes Operator 和 Helm Chart 实现这些目标的方式有些不同。以下是 Operator 和 Helm Chart 之间的关键区别 breakdown。

#1. 范围和功能

通常,Helm Chart 的范围更窄。Helm Chart 的主要目的是安装标准应用程序,即那些可以基于现有容器镜像运行的应用程序。例如,如果你需要运行一个依赖于特殊 Kubernetes API 扩展的自定义应用程序,Helm 不是一个好的解决方案,但你可以使用 Operator 来实现这个目的。

类似地,Helm 在配置方面的灵活性较差。你可以在安装 Chart 时向 Helm 传递参数来配置应用程序,但这仅限于该 Chart 在设计时支持这些参数。

相比之下,对于 Kubernetes Operator,在定制你的应用程序方面,极限在于天空——或者更具体地说,在于你编写的代码。

#2. 复杂性和灵活性

与 Helm 相比,Operator 灵活性增加的代价是 Operator 也更复杂。创建一个 Operator 需要能够编写 CRD,而你只需要基于一些相对简单的 YAML 代码就可以创建一个 Helm Chart。

另外,从安装的角度来看,Helm 更简单,因为你只需一条命令就可以安装它。安装 Operator 通常需要运行长长的 kubectl 命令。

#3. 定制化

如前所述,Operator 提供了更大的定制空间,因为你可以实现 CRD 支持的任何功能。Helm Chart 配置的某些方面是可以定制的,但这仅限于创建 Helm Chart 的开发人员在构建 Chart 时实现了配置选项。

这里的区别有点像从源代码构建标准应用程序和使用包管理器安装应用程序之间的区别。当你从源代码构建时,你可以修改源代码以随心所欲地定制应用程序。但如果你使用包管理器安装,你只能修改你的包管理系统和环境所支持的配置选项。

#4. 云成本考虑

由于 Chart 通常不像 Operator 那样可定制,它们更倾向于在你的环境中造成臃肿。一个 Helm Chart 可能会安装和运行你并不严格需要的应用程序功能,并且除非你重写整个 Chart,否则可能无法关闭这些功能。相比之下,使用 Operator,你可以对究竟运行什么进行细粒度控制

因此,Helm 可能会增加云成本,因为使用 Chart 安装的应用程序更有可能消耗更多的资源。总的来说,这个问题对你云支出的整体影响会比内存泄漏或浪费 CPU 的故障代码等问题要小,但如果你想要优化成本,这仍然是值得考虑的事情。

#5. 学习曲线

几乎可以肯定,几乎每个人都会发现学习使用 Helm 比学习 Operator 更容易。Chart 的工作方式与任何类型的软件包都非常相似,所以如果你有在其他环境下使用软件包的经验,你应该能很快掌握 Helm。

相比之下,Operator 基于 Kubernetes 特有的概念。在你理解 Kubernetes 的关键概念(如控制器和 CRD)之前,你不应该期望能理解 Operator 的工作原理——更不用说创建或修改一个了。

#6. 自动化

Operator 和 Chart 都有助于自动化应用程序安装和管理任务,否则这些任务必须手动执行。然而,Helm 提供的自动化功能不多,因为(如上所述)它的范围仅限于管理标准应用程序。

你可以使用 Helm 基于容器镜像自动化安装或更新应用程序,但你不能自动化超出 Helm 原生功能范围的自定义应用程序配置更改。然而,使用 Operator,你可以自动化 Kubernetes API 和控制器支持的任何操作。

#7. 生命周期管理

Operator 和 Chart 都支持应用程序生命周期管理,因为你可以使用它们来安装、更新和删除应用程序。然而,对于 Helm 来说,生命周期管理有点更生硬,不够精细

使用 Helm 管理应用程序生命周期,你仅限于使用内置命令,如 installupgrade 和 uninstall。你可以用一个新版本整体替换掉一个应用程序版本,或者完全删除一个应用程序。但是你不能像通过修改应用程序的 Operator 那样,对现有应用程序进行微小的修改,而无需升级整个应用程序。

#8. 维护

类似地,在应用程序维护方面,Operator 提供了更大的灵活性和控制力。如果你只想升级或删除一个应用程序,你可以用 Helm 做到。但如果你想执行其他应用程序维护任务,比如修改应用程序的存储配置,Helm 将无能为力,除非你创建一个新的 Helm Chart 并用它来重新安装你的应用程序。然而,使用 Operator,你可以进行更细粒度的维护更改。

#9. 用例

总而言之,Operator 支持的用例范围比 Helm 更广。后者仅擅长应用程序安装、升级和移除。Operator 也能做这些事,但它们还支持像应用程序备份这样的用例。

#10. 对 GitOps 的适用性

Illustration explaining GitOPs in a nutshell, where the configurations of your app data can be automatically pushed to production

解释 GitOps 的插图

GitOps 意味着使用存储在 Git 仓库中的代码来管理应用程序部署和基础设施的变更。如果你将应用程序和基础设施的配置数据存储在 Git 中,你可以从那里自动将配置推送到生产环境。你还可以根据代码在 Git 中的版本历史来跟踪资源的变更。

由于你可以将 Operator 和 Chart 的代码都存储在 Git 中,两种解决方案都兼容 GitOps 方法论。也就是说,你可能会认为 GitOps 与 Operator 一起使用能提供更多好处,因为对 Operator 所能做的变更范围更广。在这个意义上,能够以细粒度的方式跟踪变更具有更大的价值。使用 GitOps,对 Operator 中单行代码的变更将很容易跟踪——例如,如果你更改了 Operator 后某些东西坏了,你想找出是哪个变更引发了问题,这可能很有用。

#11. 社区和生态系统

Operator 和 Helm 都拥有强大的社区和生态系统。在 OperatorHub.io 和 Artifact Hub 等网站上很容易找到公开可用的 Operator 和 Helm Chart。也有大量关于这两种解决方案的文档可以免费获取。

也就是说,在社区参与度方面,Operator 和 Helm 之间的一个重要区别是,Helm 是一个拥有自己一套官方资源的开源项目,而没有专门针对 Operator 的项目(尽管 Kubernetes 项目维护着关于它们的文档)。从这个意义上说,Helm 有一个特定的"官方"社区,而 Operator 则没有。

Kubernetes Operator 与 Helm:如何选择?

对于"我应该选择 Operator 还是 Helm?"这个问题,有两种处理方法。这取决于你是向其他用户分发应用程序,还是只是想安装一个。

应用程序分发

考虑因素

选择

无状态应用

Helm Chart

应用需要定制化

Operator

用户 Kubernetes 经验有限

Helm Chart

需要支持复杂的维护

Operator

应用程序安装

考虑因素

选择

简单的部署需求

Helm Chart

需要深度定制

Operator

优先考虑易用性

Helm Chart

优先考虑灵活性和控制力

Operator

关注云成本

Operator

总结:Operator 与 Helm Chart

归根结底,Kubernetes Operator 和 Helm Chart 之间的选择取决于你的具体需求。如果你正在分发或安装一个相对简单、标准的应用程序,并且不需要大量定制或复杂的生命周期管理,Helm Chart 很可能是更好的选择。如果你需要 Helm 范围之外的灵活性、控制力和自动化,那么 Kubernetes Operator 是更强大的解决方案。

请记住,你并不总是需要在这两者之间做出选择。在某些情况下,你可能会使用 Helm Chart 来安装应用程序,然后使用 Operator 来管理它——或者,更常见的是,使用 Helm 来安装 Operator 本身,然后让 Operator 来管理你的应用程序部署。

更多推荐