diff --git a/content/zh/docs/tasks/manage-kubernetes-objects/kustomization.md b/content/zh/docs/tasks/manage-kubernetes-objects/kustomization.md new file mode 100644 index 0000000000..02ce76b4ab --- /dev/null +++ b/content/zh/docs/tasks/manage-kubernetes-objects/kustomization.md @@ -0,0 +1,1068 @@ +--- +title: 使用 Kustomize 对 Kubernetes 对象进行声明式管理 +content_type: task +weight: 20 +--- + + + + +[Kustomize](https://github.com/kubernetes-sigs/kustomize) 是一个独立的工具,用来通过 +[kustomization 文件](https://github.com/kubernetes-sigs/kustomize/blob/master/docs/glossary.md#kustomization) +定制 Kubernetes 对象。 + + +从 1.14 版本开始,`kubectl` 也开始支持使用 kustomization 文件来管理 Kubernetes 对象。 +要查看包含 kustomization 文件的目录中的资源,执行下面的命令: + +```shell +kubectl kustomize +``` + + +要应用这些资源,使用参数 `--kustomize` 或 `-k` 标志来执行 `kubectl apply`: + +```shell +kubectl apply -k +``` + +## {{% heading "prerequisites" %}} + + +安装 [`kubectl`](/zh/docs/tasks/tools/install-kubectl/). + +{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} + + + + +## Kustomize 概述 {#overview-of-kustomize} + +Kustomize 是一个用来定制 Kubernetes 配置的工具。它提供以下功能特性来管理 +应用配置文件: + +* 从其他来源生成资源 +* 为资源设置贯穿性(Cross-Cutting)字段 +* 组织和定制资源集合 + + +### 生成资源 {#generating-resources} + +ConfigMap 和 Secret 包含其他 Kubernetes 对象(如 Pod)所需要的配置或敏感数据。 +ConfigMap 或 Secret 中数据的来源往往是集群外部,例如某个 `.properties` +文件或者 SSH 密钥文件。 +Kustomize 提供 `secretGenerator` 和 `configMapGenerator`,可以基于文件或字面 +值来生成 Secret 和 ConfigMap。 + + +#### configMapGenerator + +要基于文件来生成 ConfigMap,可以在 `configMapGenerator` 的 `files` +列表中添加表项。 +下面是一个根据 `.properties` 文件中的数据条目来生成 ConfigMap 的示例: + +```shell +# 生成一个 application.properties 文件 +cat <application.properties +FOO=Bar +EOF + +cat <./kustomization.yaml +configMapGenerator: +- name: example-configmap-1 + files: + - application.properties +EOF +``` + + +所生成的 ConfigMap 可以使用下面的命令来检查: + +```shell +kubectl kustomize ./ +``` + + +所生成的 ConfigMap 为: + +```yaml +apiVersion: v1 +data: + application.properties: | + FOO=Bar +kind: ConfigMap +metadata: + name: example-configmap-1-8mbdf7882g +``` + + +ConfigMap 也可基于字面的键值偶对来生成。要基于键值偶对来生成 ConfigMap, +在 `configMapGenerator` 的 `literals` 列表中添加表项。下面是一个例子,展示 +如何使用键值偶对中的数据条目来生成 ConfigMap 对象: + +```shell +cat <./kustomization.yaml +configMapGenerator: +- name: example-configmap-2 + literals: + - FOO=Bar +EOF +``` + + +可以用下面的命令检查所生成的 ConfigMap: + +```shell +kubectl kustomize ./ +``` + + +所生成的 ConfigMap 为: + +```yaml +apiVersion: v1 +data: + FOO: Bar +kind: ConfigMap +metadata: + name: example-configmap-2-g2hdhfc6tk +``` + +#### secretGenerator + + +你可以基于文件或者键值偶对来生成 Secret。要使用文件内容来生成 Secret, +在 `secretGenerator` 下面的 `files` 列表中添加表项。 +下面是一个根据文件中数据来生成 Secret 对象的示例: + +```shell +# 创建一个 password.txt 文件 +cat <./password.txt +username=admin +password=secret +EOF + +cat <./kustomization.yaml +secretGenerator: +- name: example-secret-1 + files: + - password.txt +EOF +``` + + +所生成的 Secret 如下: + +```yaml +apiVersion: v1 +data: + password.txt: dXNlcm5hbWU9YWRtaW4KcGFzc3dvcmQ9c2VjcmV0Cg== +kind: Secret +metadata: + name: example-secret-1-t2kt65hgtb +type: Opaque +``` + + +要基于键值偶对字面值生成 Secret,先要在 `secretGenerator` 的 `literals` +列表中添加表项。下面是基于键值偶对中数据条目来生成 Secret 的示例: + +```shell +cat <./kustomization.yaml +secretGenerator: +- name: example-secret-2 + literals: + - username=admin + - password=secret +EOF +``` + + +所生成的 Secret 如下: + +```yaml +apiVersion: v1 +data: + password: c2VjcmV0 + username: YWRtaW4= +kind: Secret +metadata: + name: example-secret-2-t52t6g96d8 +type: Opaque +``` + +#### generatorOptions + + +所生成的 ConfigMap 和 Secret 都会包含内容哈希值后缀。 +这是为了确保内容发生变化时,所生成的是新的 ConfigMap 或 Secret。 +要禁止自动添加后缀的行为,用户可以使用 `generatorOptions`。 +除此以外,为生成的 ConfigMap 和 Secret 指定贯穿性选项也是可能的。 + +```shell +cat <./kustomization.yaml +configMapGenerator: +- name: example-configmap-3 + literals: + - FOO=Bar +generatorOptions: + disableNameSuffixHash: true + labels: + type: generated + annotations: + note: generated +EOF +``` + + +运行 `kubectl kustomize ./` 来查看所生成的 ConfigMap: + +```yaml +apiVersion: v1 +data: + FOO: Bar +kind: ConfigMap +metadata: + annotations: + note: generated + labels: + type: generated + name: example-configmap-3 +``` + + +### 设置贯穿性字段 {#setting-cross-cutting-fields} + +在项目中未所有 Kubernetes 对象设置贯穿性字段是一种常见操作。 +贯穿性字段的一些使用场景如下: + +* 为所有资源设置相同的名字空间 +* 为所有对象添加相同的前缀或后缀 +* 为对象添加相同的标签集合 +* 为对象添加相同的注解集合 + +下面是一个例子: + +```shell +# 创建一个 deployment.yaml +cat <./deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment + labels: + app: nginx +spec: + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx +EOF + +cat <./kustomization.yaml +namespace: my-namespace +namePrefix: dev- +nameSuffix: "-001" +commonLabels: + app: bingo +commonAnnotations: + oncallPager: 800-555-1212 +resources: +- deployment.yaml +EOF +``` + + +执行 `kubectl kustomize ./` 查看这些字段都被设置到 Deployment 资源上: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + oncallPager: 800-555-1212 + labels: + app: bingo + name: dev-nginx-deployment-001 + namespace: my-namespace +spec: + selector: + matchLabels: + app: bingo + template: + metadata: + annotations: + oncallPager: 800-555-1212 + labels: + app: bingo + spec: + containers: + - image: nginx + name: nginx +``` + + +### 组织和定制资源 {#composing-and-customizing-resources} + +一种常见的做法是在项目中构造资源集合并将其放到同一个文件或目录中管理。 +Kustomize 提供基于不同文件来组织资源并向其应用补丁或者其他定制的能力。 + + +#### 组织 {#composing} + +Kustomize 支持组合不同的资源。`kustomization.yaml` 文件的 `resources` 字段 +定义配置中要包含的资源列表。你可以将 `resources` 列表中的路径设置为资源配置文件 +的路径。下面是由 Deployment 和 Service 构成的 NGINX 应用的示例: + + +```shell +# 创建 deployment.yaml 文件 +cat < deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + ports: + - containerPort: 80 +EOF + +# 创建 service.yaml 文件 +cat < service.yaml +apiVersion: v1 +kind: Service +metadata: + name: my-nginx + labels: + run: my-nginx +spec: + ports: + - port: 80 + protocol: TCP + selector: + run: my-nginx +EOF + +# 创建 kustomization.yaml 来组织以上两个资源 +cat <./kustomization.yaml +resources: +- deployment.yaml +- service.yaml +EOF +``` + + +`kubectl kustomize ./` 所得到的资源中既包含 Deployment 也包含 Service 对象。 + + +#### 定制 {#customizing} + +补丁文件(Patches)可以用来对资源执行不同的定制。 +Kustomize 通过 `patchesStrategicMerge` 和 `patchesJson6902` 支持不同的打补丁 +机制。`patchesStrategicMerge` 的内容是一个文件路径的列表,其中每个文件都应可解析为 +[策略性合并补丁(Strategic Merge Patch)](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/strategic-merge-patch.md)。 +补丁文件中的名称必须与已经加载的资源的名称匹配。 +建议构造规模较小的、仅做一件事情的补丁。 +例如,构造一个补丁来增加 Deployment +的副本个数;构造另外一个补丁来设置内存限制。 + +```shell +# 创建 deployment.yaml 文件 +cat < deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + ports: + - containerPort: 80 +EOF + +# 生成一个补丁 increase_replicas.yaml +cat < increase_replicas.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + replicas: 3 +EOF + +# 生成另一个补丁 set_memory.yaml +cat < set_memory.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + template: + spec: + containers: + - name: my-nginx + resources: + limits: + memory: 512Mi +EOF + +cat <./kustomization.yaml +resources: +- deployment.yaml +patchesStrategicMerge: +- increase_replicas.yaml +- set_memory.yaml +EOF +``` + + +执行 `kubectl kustomize ./` 来查看 Deployment: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + replicas: 3 + selector: + matchLabels: + run: my-nginx + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - image: nginx + limits: + memory: 512Mi + name: my-nginx + ports: + - containerPort: 80 +``` + + +并非所有资源或者字段都支持策略性合并补丁。为了支持对任何资源的任何字段进行修改, +Kustomize 提供通过 `patchesJson6902` 来应用 [JSON 补丁](https://tools.ietf.org/html/rfc6902) +的能力。为了给 JSON 补丁找到正确的资源,需要在 `kustomization.yaml` 文件中指定资源的 +组(group)、版本(version)、类别(kind)和名称(name)。 +例如,为某 Deployment 对象增加副本个数的操作也可以通过 `patchesJson6902` +来完成: + +```shell +# 创建一个 deployment.yaml 文件 +cat < deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + ports: + - containerPort: 80 +EOF + +# 创建一个 JSON 补丁文件 +cat < patch.yaml +- op: replace + path: /spec/replicas + value: 3 +EOF + +# 创建一个 kustomization.yaml +cat <./kustomization.yaml +resources: +- deployment.yaml + +patchesJson6902: +- target: + group: apps + version: v1 + kind: Deployment + name: my-nginx + path: patch.yaml +EOF +``` + + +执行 `kubectl kustomize ./` 以查看 `replicas` 字段被更新: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + replicas: 3 + selector: + matchLabels: + run: my-nginx + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - image: nginx + name: my-nginx + ports: + - containerPort: 80 +``` + + +除了补丁之外,Kustomize 还提供定制容器镜像或者将其他对象的字段值注入到容器 +中的能力,并且不需要创建补丁。 +例如,你可以通过在 `kustomization.yaml` 文件的 `images` 字段设置新的镜像来 +更改容器中使用的镜像。 + +```shell +cat < deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + ports: + - containerPort: 80 +EOF + +cat <./kustomization.yaml +resources: +- deployment.yaml +images: +- name: nginx + newName: my.image.registry/nginx + newTag: 1.4.0 +EOF +``` + + +执行 `kubectl kustomize ./` 以查看所使用的镜像已被更新: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + replicas: 2 + selector: + matchLabels: + run: my-nginx + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - image: my.image.registry/nginx:1.4.0 + name: my-nginx + ports: + - containerPort: 80 +``` + + +有些时候,Pod 中运行的应用可能需要使用来自其他对象的配置值。 +例如,某 Deployment 对象的 Pod 需要从环境变量或命令行参数中读取读取 +Service 的名称。 +由于在 `kustomization.yaml` 文件中添加 `namePrefix` 或 `nameSuffix` 时 +Service 名称可能发生变化,建议不要在命令参数中硬编码 Service 名称。 +对于这种使用场景,Kustomize 可以通过 `vars` 将 Service 名称注入到容器中。 + +```shell +# 创建一个 deployment.yaml 文件 +cat < deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + command: ["start", "--host", "\$(MY_SERVICE_NAME)"] +EOF + +# 创建一个 service.yaml 文件 +cat < service.yaml +apiVersion: v1 +kind: Service +metadata: + name: my-nginx + labels: + run: my-nginx +spec: + ports: + - port: 80 + protocol: TCP + selector: + run: my-nginx +EOF + +cat <./kustomization.yaml +namePrefix: dev- +nameSuffix: "-001" + +resources: +- deployment.yaml +- service.yaml + +vars: +- name: MY_SERVICE_NAME + objref: + kind: Service + name: my-nginx + apiVersion: v1 +EOF +``` + + +执行 `kubectl kustomize ./` 以查看注入到容器中的 Service 名称是 `dev-my-nginx-001`: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dev-my-nginx-001 +spec: + replicas: 2 + selector: + matchLabels: + run: my-nginx + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - command: + - start + - --host + - dev-my-nginx-001 + image: nginx + name: my-nginx +``` + + +## 基准(Bases)与覆盖(Overlays) + +Kustomize 中有 **基准(bases)** 和 **覆盖(overlays)** 的概念区分。 +**基准** 是包含 `kustomization.yaml` 文件的一个目录,其中包含一组资源及其相关的定制。 +基准可以是本地目录或者来自远程仓库的目录,只要其中存在 `kustomization.yaml` 文件即可。 +**覆盖** 也是一个目录,其中包含将其他 kustomization 目录当做 `bases` 来引用的 +`kustomization.yaml` 文件。 +**基准**不了解覆盖的存在,且可被多个覆盖所使用。 +覆盖则可以有多个基准,且可针对所有基准中的资源执行组织操作,还可以在其上执行定制。 + +```shell +# 创建一个包含基准的目录 +mkdir base +# 创建 base/deployment.yaml +cat < base/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx +EOF + +# 创建 base/service.yaml 文件 +cat < base/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: my-nginx + labels: + run: my-nginx +spec: + ports: + - port: 80 + protocol: TCP + selector: + run: my-nginx +EOF + +# 创建 base/kustomization.yaml +cat < base/kustomization.yaml +resources: +- deployment.yaml +- service.yaml +EOF +``` + + +此基准可在多个覆盖中使用。你可以在不同的覆盖中添加不同送的 `namePrefix` 或 +其他贯穿性字段。下面是两个使用同一基准的覆盖: + +```shell +mkdir dev +cat < dev/kustomization.yaml +bases: +- ../base +namePrefix: dev- +EOF + +mkdir prod +cat < prod/kustomization.yaml +bases: +- ../base +namePrefix: prod- +EOF +``` + + +## 如何使用 Kustomize 来应用、查看和删除对象 + +在 `kubectl` 命令中使用 `--kustomize` 或 `-k` 参数来识别被 `kustomization.yaml` 所管理的资源。 +注意 `-k` 要指向一个 kustomization 目录。例如: + +```shell +kubectl apply -k / +``` + + +假定使用下面的 `kustomization.yaml`, + +```shell +# 创建 deployment.yaml 文件 +cat < deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + ports: + - containerPort: 80 +EOF + +# 创建 kustomization.yaml +cat <./kustomization.yaml +namePrefix: dev- +commonLabels: + app: my-nginx +resources: +- deployment.yaml +EOF +``` + + +执行下面的命令来应用 Deployment 对象 `dev-my-nginx`: + +```shell +kubectl apply -k ./ +``` +``` +deployment.apps/dev-my-nginx created +``` + + +运行下面的命令之一来查看 Deployment 对象 `dev-my-nginx`: + +```shell +kubectl get -k ./ +``` + +```shell +kubectl describe -k ./ +``` + + +执行下面的命令来比较 Deployment 对象 `dev-my-nginx` 与清单被应用之后 +集群将处于的状态: + +```shell +kubectl diff -k ./ +``` + + +执行下面的命令删除 Deployment 对象 `dev-my-nginx`: + +```shell +kubectl delete -k ./ +``` +``` +deployment.apps "dev-my-nginx" deleted +``` + + +## Kustomize 功能特性列表 + + + +| 字段 | 类型 | 解释 | +|-----------------------|--------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| +| namespace | string | 为所有资源添加名字看 | +| namePrefix | string | 此字段的值将被添加到所有资源名称前面 | +| nameSuffix | string | 此字段的值将被添加到所有资源名称后面 | +| commonLabels | map[string]string | 要添加到所有资源和选择算符的标签 | +| commonAnnotations | map[string]string | 要添加到所有资源的注解 | +| resources | []string | 列表中的每个条目都必须能够解析为现有的资源配置文件 | +| configmapGenerator | [][ConfigMapArgs](https://github.com/kubernetes-sigs/kustomize/blob/release-kustomize-v4.0/api/types/kustomization.go#L99) | 列表中的每个条目都会生成一个 ConfigMap | +| secretGenerator | [][SecretArgs](https://github.com/kubernetes-sigs/kustomize/blob/release-kustomize-v4.0/api/types/kustomization.go#L106) | 列表中的每个条目都会生成一个 Secret | +| generatorOptions | [GeneratorOptions](https://github.com/kubernetes-sigs/kustomize/blob/release-kustomize-v4.0/api/types/kustomization.go#L109) | 更改所有 ConfigMap 和 Secret 生成器的行为 | +| bases | []string | 列表中每个条目都应能解析为一个包含 kustomization.yaml 文件的目录 | +| patchesStrategicMerge | []string | 列表中每个条目都赢能解析为某 Kubernetes 对象的策略性合并补丁 | +| patchesJson6902 | [][Json6902](https://github.com/kubernetes-sigs/kustomize/blob/release-kustomize-v4.0/api/types/patchjson6902.go#L8) | 列表中每个条目都赢能解析为一个 Kubernetes 对象和一个 JSON 补丁 | +| vars | [][Var](https://github.com/kubernetes-sigs/kustomize/blob/master/api/types/var.go#L31) | 每个条目用来从某资源的字段来析取文字 | +| images | [][Image](https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/image.go#L23) | 每个条目都用来更改镜像的名称、标记与/或摘要,不必生成补丁 | +| configurations | []string | 列表中每个条目都应能解析为一个包含 [Kustomize 转换器配置](https://github.com/kubernetes-sigs/kustomize/tree/master/examples/transformerconfigs) 的文件 | +| crds | []string | 列表中每个条目都赢能够解析为 Kubernetes 类别的 OpenAPI 定义文件 | + +## {{% heading "whatsnext" %}} + + +* [Kustomize](https://github.com/kubernetes-sigs/kustomize) +* [Kubectl Book](https://kubectl.docs.kubernetes.io) +* [Kubectl 命令参考](/docs/reference/generated/kubectl/kubectl-commands/) +* [Kubernetes API 参考](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/) +