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

介绍 kustomize;无需模板的 Kubernetes 配置定制

如果你运行着 Kubernetes 环境,很可能你已经自定义过 Kubernetes 配置——你复制了一些 API 对象 YAML 文件并根据自己的需求进行了编辑。

但这种方法存在缺点——很难回到源代码并整合对其进行的任何改进。今天,Google 宣布推出 kustomize,这是一个命令行工具,作为 SIG-CLI 的一个子项目贡献。该工具提供了一种新的、纯粹的声明式配置定制方法,它遵循并利用了熟悉且精心设计的 Kubernetes API。

这是一个常见的场景。在互联网上,你可能会找到某个内容管理系统 (CMS) 的 Kubernetes 配置。这是一组包含 Kubernetes API 对象 YAML 规范的文件。然后,在你自己公司的某个角落,你会找到一个用于支持该 CMS 的数据库配置——这个数据库是你偏爱的,因为你很熟悉它。

你想以某种方式将它们一起使用。此外,你想定制这些文件,以便你的资源实例在集群中显示一个标签,将其与在同一集群中做同样事情的同事的资源区分开来。你还想为 CPU、内存和副本数量设置适当的值。

另外,你可能还需要整个配置的多个变体:一个用于测试和实验的较小变体(在使用计算资源方面),以及一个用于在生产环境中服务外部用户的较大变体。同样,其他团队也会需要他们自己的变体。

这引发了各种各样的问题。你会将配置复制到多个位置并独立编辑吗?如果你有数十个开发团队需要堆栈的细微不同变体怎么办?你如何维护和升级它们共享的公共配置部分?使用 kustomize 的工作流程为这些问题提供了答案。

定制就是复用

Kubernetes 配置不是代码(它们是 API 对象的 YAML 规范,更严格地说应被视为数据),但配置的生命周期与代码的生命周期有许多相似之处。

你应该将配置保存在版本控制中。配置所有者不一定与配置使用者是同一组人。配置可以作为更大整体的一部分使用。用户会希望出于不同目的来复用配置。

一种配置复用方法,就像代码复用一样,就是简单地复制所有内容并定制副本。与代码类似,切断与源代码的连接使得很难受益于源代码的持续改进。对于拥有自己配置变体的多个团队或环境而言,采用这种方法会使简单的升级变得棘手。

另一种复用方法是将源代码表达为一个参数化模板。工具会处理该模板——执行任何嵌入的脚本并将参数替换为所需的值——以生成配置。复用来自于对同一模板使用不同的值集。这里的挑战在于,模板和值文件不是 Kubernetes API 资源的规范。它们必然是一种新事物、一种新语言,它包装了 Kubernetes API。是的,它们功能强大,但也带来了学习和工具成本。不同的团队想要不同的更改——因此几乎你可以包含在 YAML 文件中的每个规范都变成了一个需要值的参数。结果是,值集变得庞大,因为所有参数(没有可信默认值的参数)都必须指定要替换的值。这违背了复用的一个目标——在没有完整资源声明的情况下,使变体之间的差异在大小上很小且易于理解。

配置定制的新选项

与此相比,kustomize 的工具行为由在名为 kustomization.yaml 的文件中表达的声明式规范决定。

kustomize 程序读取该文件及其引用的 Kubernetes API 资源文件,然后将完整的资源输出到标准输出。此文本输出可以由其他工具进一步处理,或直接通过管道传输到 kubectl 以应用于集群。

例如,如果当前工作目录中有一个名为 kustomization.yaml 的文件,其内容如下所示:

   commonLabels:
     app: hello
   resources:
   - deployment.yaml
   - configMap.yaml
   - service.yaml

并在当前工作目录中存在,同时还存在其中提到的三个资源文件,那么运行

kustomize build

会输出一个 YAML 流,其中包含指定的三个资源,并为每个资源添加一个公共标签 app: hello

类似地,你可以使用 commonAnnotations 字段为所有资源添加注解,并使用 namePrefix 字段为所有资源名称添加公共前缀。这种简单但常见的定制只是个开始。

一个更常见的用例是,你需要一组公共资源的多个变体,例如开发预生产生产变体。

为此,kustomize 支持叠加层 (overlay)基础层 (base) 的概念。两者都由一个 kustomization 文件表示。基础层声明了变体共享的公共内容(资源和对这些资源的共同定制),而叠加层声明了差异。

以下是一个文件系统布局示例,用于管理特定集群应用的预生产生产变体:

   someapp/
   ├── base/
   │   ├── kustomization.yaml
   │   ├── deployment.yaml
   │   ├── configMap.yaml
   │   └── service.yaml
   └── overlays/
      ├── production/
      │   └── kustomization.yaml
      │   ├── replica_count.yaml
      └── staging/
          ├── kustomization.yaml
          └── cpu_count.yaml

文件 someapp/base/kustomization.yaml 指定了公共资源以及对这些资源的共同定制(例如,它们都获得某个标签、名称前缀和注解)。

文件 someapp/overlays/production/kustomization.yaml 的内容可能是:

   commonLabels:
    env: production
   bases:
   - ../../base
   patches:
   - replica_count.yaml

这个 kustomization 指定了一个补丁 (patch) 文件 replica_count.yaml,其内容可能是:

   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: the-deployment
   spec:
     replicas: 100

补丁是部分资源声明,在这里是针对 someapp/base/deployment.yaml 中的 Deployment 进行的补丁,仅修改副本数 (replicas) 以处理生产流量。

补丁作为部分 Deployment 规范,具有清晰的上下文和目的,即使与剩余配置隔离读取也可以验证。它不仅仅是一个没有上下文的 {参数名, 值} 对。

要创建生产变体的资源,运行

kustomize build someapp/overlays/production

结果作为一组完整的资源打印到标准输出,可直接应用于集群。类似的命令可以定义预生产环境。

总结

使用 kustomize,你只使用 Kubernetes API 资源文件就可以管理任意数量的独特定制的 Kubernetes 配置。kustomize 使用的每个 artifact 都是纯 YAML,并且可以像这样进行验证和处理。kustomize 鼓励一种 fork/modify/rebase 的工作流

要开始使用,请尝试 hello world 示例。如需讨论和反馈,请加入邮件列表提交问题。欢迎提交 Pull Request。