本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

使用 Terraform 和 Kubernetes

作为开源 Kubernetes Terraform GitOps 框架 Kubestack 的维护者,我理所当然地花了很多时间使用 Terraform 和 Kubernetes。Kubestack 使用 Terraform 供应 AKS、EKS 和 GKE 等托管 Kubernetes 服务,还将 Kustomize base 中的集群服务集成到 GitOps 工作流中。集群服务是指在部署应用程序工作负载之前,Kubernetes 集群上所需的一切。

Hashicorp 最近宣布了 Terraform 和 Kubernetes 之间更好的集成。我借此机会概述了当前如何将 Terraform 与 Kubernetes 结合使用以及需要注意的事项。

然而,在这篇文章中,我将只关注使用 Terraform 供应 Kubernetes API 资源,而不是 Kubernetes 集群。

Terraform 是一种流行的基础设施即代码解决方案,因此我在这里只做简要介绍。简而言之,Terraform 允许将资源的所需状态声明为代码,并将确定并执行一个计划,将基础设施从当前状态转换为所需状态。

为了支持不同的资源,Terraform 需要集成相应 API 的提供程序。因此,要创建 Kubernetes 资源,我们需要一个 Kubernetes 提供程序。以下是我们的选择:

Terraform `kubernetes` 提供程序(官方)

首先是官方 Kubernetes 提供程序。这个提供程序无疑是三者中最成熟的。然而,它有一个很大的注意事项,这可能是使用 Terraform 维护 Kubernetes 资源并非流行选择的主要原因。

Terraform 要求每个资源都有一个模式,这意味着维护者必须将每个 Kubernetes 资源的模式转换为 Terraform 模式。这需要大量精力,也是为什么长期以来支持的资源非常有限的原因。虽然这种情况随着时间的推移有所改善,但仍然不是所有资源都支持。特别是自定义资源无法以这种方式支持。

这种模式转换还会导致一些需要注意的边缘情况。例如,Terraform 模式中的 `metadata` 是一个映射列表。这意味着您必须在 Terraform 中像这样引用 Kubernetes 资源的 `metadata.name`:`kubernetes_secret.example.metadata.0.name`。

然而,从积极的方面来看,拥有 Terraform 模式意味着 Kubernetes 和其他 Terraform 资源之间可以完全集成。例如,例如,使用 Terraform 创建一个类型为 `LoadBalancer` 的 Kubernetes 服务,然后使用返回的 ELB 主机名在 Route53 记录中配置 DNS。

使用 Terraform 维护 Kubernetes 资源的最大好处是集成到 Terraform 的计划/应用生命周期中。因此,您可以在应用更改之前查看计划的更改。此外,在没有人工干预的情况下,使用 `kubectl` 从集群中清除资源并不容易。Terraform 可以可靠地完成此操作。

Terraform `kubernetes-alpha` 提供程序

其次是新的 alpha Kubernetes 提供程序。为了解决当前 Kubernetes 提供程序的局限性,Hashicorp 团队最近发布了一个新提供程序的 alpha 版本。

此提供程序使用动态资源类型和服务器端应用来支持所有 Kubernetes 资源。我个人认为这个提供程序有潜力成为游戏规则改变者——即使在 HCL 中管理 Kubernetes 资源可能仍然不适合所有人。也许下面的 Kustomize 提供程序会有所帮助。

唯一的缺点是,明确不鼓励将其用于除测试之外的任何用途。但是,测试的人越多,它就越快准备好投入使用。所以我鼓励大家尝试一下。

Terraform `kustomize` 提供程序

最后,我们有`kustomize` 提供程序。Kustomize 提供了一种使用继承而不是模板来定制 Kubernetes 资源的方法。它旨在将结果输出到 `stdout`,然后您可以使用 `kubectl` 应用更改。这种方法意味着 `kubectl` 的边缘情况,例如无法清除或更改不可变属性,仍然使完全自动化变得困难。

Kustomize 是一种流行的定制处理方式。但我正在寻找一种更可靠的方法来自动化应用更改。由于这正是 Terraform 的强项,因此 Kustomize 提供程序应运而生。

这里不赘述太多细节,但从 Terraform 的角度来看,此提供程序将每个 Kubernetes 资源视为 JSON 字符串。这样,它可以处理 Kustomize 构建产生的任何 Kubernetes 资源。但它有一个很大的缺点,即 Kubernetes 资源无法轻易与其他 Terraform 资源集成。请记住上面提到的负载均衡器示例。

在底层,类似于新的 Kubernetes alpha 提供程序,Kustomize 提供程序也使用动态 Kubernetes 客户端和服务器端应用。未来,我计划弃用 Kustomize 提供程序中与新 Kubernetes 提供程序重叠的部分,并仅保留 Kustomize 集成。

结论

对于已经投入 Terraform 的团队,或者正在寻找替代 `kubectl` 进行自动化的团队来说,Terraform 的计划/应用生命周期一直是一个很有前途的选择,可以自动化对 Kubernetes 资源的更改。然而,官方 Kubernetes 提供程序的局限性导致其未能得到广泛采用。

新的 alpha 提供程序消除了这些限制,并有潜力使 Terraform 成为自动化 Kubernetes 资源更改的首选。

对于已经采用 Kustomize 的团队来说,使用 Kustomize 提供程序将 Kustomize 和 Terraform 集成可能比使用 `kubectl` 更有益,因为它避免了常见的边缘情况。即使在这种设置中,Terraform 也只能轻松用于计划和应用更改,而不能用于调整 Kubernetes 资源。未来,这个问题可能通过结合 Kustomize 提供程序和新的 Kubernetes 提供程序来解决。

如果您对这三种选择有任何疑问,请随时通过 Kubernetes Slack 在 #kubestack#kustomize 频道与我联系。如果您尝试使用任何提供程序并遇到问题,请提交 GitHub 问题以帮助维护者解决。