本文已超过一年。旧文章可能包含过时内容。请检查页面信息自发布以来是否已不再正确。
使用 Terraform 和 Kubernetes
作为 Kubestack(一个针对 Kubernetes 的开源 Terraform GitOps 框架)的维护者,我毫无疑问地花大量时间在使用 Terraform 和 Kubernetes。Kubestack 使用 Terraform 供应 AKS、EKS 和 GKE 等托管 Kubernetes 服务,但也将基于 Kustomize 的集群服务集成到 GitOps 工作流中。可以将集群服务视为在部署应用工作负载之前,Kubernetes 集群上所需的一切。
Hashicorp 最近宣布改进 Terraform 和 Kubernetes 之间的集成。我借此机会概述了目前如何将 Terraform 与 Kubernetes 结合使用以及需要注意的事项。
然而,在本文中,我将仅关注使用 Terraform 供应 Kubernetes API 资源,而不是 Kubernetes 集群。
Terraform 是一个流行的基础设施即代码解决方案,因此我在这里只做非常简要的介绍。简而言之,Terraform 允许将资源的期望状态声明为代码,然后确定并执行一个计划,将基础设施从当前状态变为期望状态。
为了能够支持不同的资源,Terraform 需要能够集成相应 API 的 provider。因此,要创建 Kubernetes 资源,我们需要一个 Kubernetes provider。以下是我们的选择:
Terraform kubernetes
provider (官方)
首先是官方的 Kubernetes provider。这个 provider 无疑是三者中最成熟的。然而,它有一个很大的限制,这可能是使用 Terraform 维护 Kubernetes 资源不流行的主要原因。
Terraform 要求为每个资源提供一个 schema,这意味着维护者必须将每个 Kubernetes 资源的 schema 转换为 Terraform schema。这需要大量工作,也是为什么长期以来支持的资源非常有限的原因。虽然随着时间的推移有所改进,但仍然不是所有资源都受支持。特别是自定义资源无法以这种方式支持。
这种 schema 转换还会导致一些需要注意的边缘情况。例如,Terraform schema 中的 metadata
是一个 maps 列表。这意味着你在 Terraform 中引用 Kubernetes 资源的 metadata.name
时必须这样写:kubernetes_secret.example.metadata.0.name
。
然而,积极的一面是,拥有 Terraform schema 意味着 Kubernetes 可以与其他 Terraform 资源完全集成。例如,使用 Terraform 创建一个类型为 LoadBalancer
的 Kubernetes Service,然后在 Route53 记录中使用返回的 ELB 主机名来配置 DNS。示例见此。
使用 Terraform 维护 Kubernetes 资源的最大好处是集成到 Terraform 的 plan/apply 生命周期中。因此,你可以在应用计划中的更改之前进行审阅。此外,使用 kubectl
从集群中清除资源并非易事,通常需要手动干预。Terraform 可以可靠地完成这项工作。
Terraform kubernetes-alpha
provider
其次是新的 Kubernetes Alpha provider。为了解决当前 Kubernetes provider 的局限性,Hashicorp 团队最近发布了一个新 provider 的 Alpha 版本。
这个 provider 使用动态资源类型和 server-side-apply 来支持所有 Kubernetes 资源。我个人认为这个 provider 有潜力成为游戏规则的改变者——尽管在 HCL 中管理 Kubernetes 资源可能仍然不是所有人的选择。也许下面的 Kustomize provider 能在这方面提供帮助。
唯一的缺点是,明确不鼓励将其用于测试以外的任何用途。但测试的人越多,它应该就越快准备好投入正式使用。所以我鼓励大家尝试一下。
Terraform kustomize
provider
最后,我们有 kustomize
provider。Kustomize 提供了一种使用继承而非模板来定制 Kubernetes 资源的方式。它被设计为将结果输出到标准输出,然后你可以使用 kubectl
应用更改。这种方法意味着 kubectl
的边缘情况,例如无法清除或更改不可变属性,仍然使得完全自动化变得困难。
Kustomize 是一种处理定制的流行方式。但我一直在寻找一种更可靠的方式来自动化应用更改。由于这正是 Terraform 的强项,Kustomize provider 应运而生。
这里不做过多详细介绍,但从 Terraform 的角度来看,这个 provider 将每个 Kubernetes 资源视为一个 JSON 字符串。这样它就可以处理 Kustomize 构建产生的任何 Kubernetes 资源。但这带来一个很大的缺点,即 Kubernetes 资源无法轻易与其他 Terraform 资源集成。记住上面的负载均衡器示例。
在底层,与新的 Kubernetes Alpha provider 类似,Kustomize provider 也使用了动态 Kubernetes 客户端和 server-side-apply。未来,我计划弃用 Kustomize provider 中与新 Kubernetes provider 重叠的部分,只保留 Kustomize 集成。
结论
对于已经投入使用 Terraform 的团队,或者正在寻找在自动化中替代 kubectl
的团队来说,Terraform 的 plan/apply 生命周期一直是自动化更改 Kubernetes 资源的一个有前途的选择。然而,官方 Kubernetes provider 的局限性导致其未能得到广泛采用。
新的 Alpha provider 消除了这些限制,并有可能使 Terraform 成为自动化更改 Kubernetes 资源的主要选项。
对于已经采用 Kustomize 的团队,可能会发现使用 Kustomize provider 集成 Kustomize 和 Terraform 比使用 kubectl
更具优势,因为它避免了一些常见的边缘情况。即使在这种设置下,Terraform 只能轻松用于计划和应用更改,而不能修改 Kubernetes 资源本身。未来,这个问题可能通过将 Kustomize provider 与新的 Kubernetes provider 结合来解决。
如果你对这三种选项有任何疑问,欢迎随时在 Kubernetes Slack 的 #kubestack 或 #kustomize 频道联系我。如果你试用了其中任何一个 provider 并遇到了问题,请提交 GitHub issue 以帮助维护者修复。