使用 Kustomize 声明式管理 Kubernetes 对象

Kustomize 是一款独立工具,用于通过 kustomization 文件 自定义 Kubernetes 对象。

从 1.14 版本开始,Kubectl 也支持使用 kustomization 文件管理 Kubernetes 对象。要查看包含 kustomization 文件的目录中找到的资源,请运行以下命令

kubectl kustomize <kustomization_directory>

要应用这些资源,请使用 --kustomize-k 标志运行 kubectl apply

kubectl apply -k <kustomization_directory>

在开始之前

安装 kubectl

您需要拥有一个 Kubernetes 集群,并且必须将 kubectl 命令行工具配置为与您的集群通信。建议在至少有两个节点(不充当控制平面主机)的集群上运行本教程。如果您还没有集群,可以使用 minikube 创建一个,或者可以使用以下 Kubernetes 游乐场之一

要检查版本,请输入 kubectl 版本

Kustomize 概述

Kustomize 是一种用于自定义 Kubernetes 配置的工具。它具有以下功能来管理应用程序配置文件

  • 从其他来源生成资源
  • 为资源设置跨领域字段
  • 组合和自定义资源集合

生成资源

ConfigMaps 和 Secrets 保存由其他 Kubernetes 对象(例如 Pod)使用的配置或敏感数据。ConfigMaps 或 Secrets 的真实来源通常位于集群之外,例如 .properties 文件或 SSH 密钥文件。Kustomize 具有 secretGeneratorconfigMapGenerator,它们从文件或字面量生成 Secret 和 ConfigMap。

configMapGenerator

要从文件生成 ConfigMap,请在 configMapGenerator 中的 files 列表中添加一个条目。以下是如何从 .properties 文件生成具有数据项的 ConfigMap 的示例

# Create a application.properties file
cat <<EOF >application.properties
FOO=Bar
EOF

cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-1
  files:
  - application.properties
EOF

可以使用以下命令检查生成的 ConfigMap

kubectl kustomize ./

生成的 ConfigMap 为

apiVersion: v1
data:
  application.properties: |
    FOO=Bar    
kind: ConfigMap
metadata:
  name: example-configmap-1-8mbdf7882g

要从 env 文件生成 ConfigMap,请在 configMapGenerator 中的 envs 列表中添加一个条目。以下是如何从 .env 文件生成具有数据项的 ConfigMap 的示例

# Create a .env file
cat <<EOF >.env
FOO=Bar
EOF

cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-1
  envs:
  - .env
EOF

可以使用以下命令检查生成的 ConfigMap

kubectl kustomize ./

生成的 ConfigMap 为

apiVersion: v1
data:
  FOO: Bar
kind: ConfigMap
metadata:
  name: example-configmap-1-42cfbf598f

还可以从字面量键值对生成 ConfigMaps。要从字面量键值对生成 ConfigMap,请在 configMapGenerator 中的 literals 列表中添加一个条目。以下是如何从键值对生成具有数据项的 ConfigMap 的示例

cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-2
  literals:
  - FOO=Bar
EOF

可以使用以下命令检查生成的 ConfigMap

kubectl kustomize ./

生成的 ConfigMap 为

apiVersion: v1
data:
  FOO: Bar
kind: ConfigMap
metadata:
  name: example-configmap-2-g2hdhfc6tk

要在 Deployment 中使用生成的 ConfigMap,请按 configMapGenerator 的名称引用它。Kustomize 会自动将此名称替换为生成的名称。

这是一个使用生成的 ConfigMap 的部署示例

# Create a application.properties file
cat <<EOF >application.properties
FOO=Bar
EOF

cat <<EOF >deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: my-app
        volumeMounts:
        - name: config
          mountPath: /config
      volumes:
      - name: config
        configMap:
          name: example-configmap-1
EOF

cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
configMapGenerator:
- name: example-configmap-1
  files:
  - application.properties
EOF

生成 ConfigMap 和 Deployment

kubectl kustomize ./

生成的 Deployment 将按名称引用生成的 ConfigMap

apiVersion: v1
data:
  application.properties: |
    FOO=Bar    
kind: ConfigMap
metadata:
  name: example-configmap-1-g4hk9g2ff8
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: my-app
  name: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - image: my-app
        name: app
        volumeMounts:
        - mountPath: /config
          name: config
      volumes:
      - configMap:
          name: example-configmap-1-g4hk9g2ff8
        name: config

secretGenerator

您可以从文件或字面量键值对生成 Secrets。要从文件生成 Secret,请在 secretGenerator 中的 files 列表中添加一个条目。以下是如何从文件生成具有数据项的 Secret 的示例

# Create a password.txt file
cat <<EOF >./password.txt
username=admin
password=secret
EOF

cat <<EOF >./kustomization.yaml
secretGenerator:
- name: example-secret-1
  files:
  - password.txt
EOF

生成的 Secret 如下所示

apiVersion: v1
data:
  password.txt: dXNlcm5hbWU9YWRtaW4KcGFzc3dvcmQ9c2VjcmV0Cg==
kind: Secret
metadata:
  name: example-secret-1-t2kt65hgtb
type: Opaque

要从字面量键值对生成 Secret,请在 secretGenerator 中的 literals 列表中添加一个条目。以下是如何从键值对生成具有数据项的 Secret 的示例

cat <<EOF >./kustomization.yaml
secretGenerator:
- name: example-secret-2
  literals:
  - username=admin
  - password=secret
EOF

生成的 Secret 如下所示

apiVersion: v1
data:
  password: c2VjcmV0
  username: YWRtaW4=
kind: Secret
metadata:
  name: example-secret-2-t52t6g96d8
type: Opaque

与 ConfigMaps 一样,生成的 Secrets 可以通过引用 secretGenerator 的名称在 Deployments 中使用

# Create a password.txt file
cat <<EOF >./password.txt
username=admin
password=secret
EOF

cat <<EOF >deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: my-app
        volumeMounts:
        - name: password
          mountPath: /secrets
      volumes:
      - name: password
        secret:
          secretName: example-secret-1
EOF

cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
secretGenerator:
- name: example-secret-1
  files:
  - password.txt
EOF

generatorOptions

生成的 ConfigMaps 和 Secrets 附带内容散列后缀。这可确保在内容更改时生成新的 ConfigMap 或 Secret。要禁用追加后缀的行为,可以使用 generatorOptions。此外,还可以为生成的 ConfigMaps 和 Secrets 指定跨领域选项。

cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-3
  literals:
  - FOO=Bar
generatorOptions:
  disableNameSuffixHash: true
  labels:
    type: generated
  annotations:
    note: generated
EOF

运行 kubectl kustomize ./ 以查看生成的 ConfigMap

apiVersion: v1
data:
  FOO: Bar
kind: ConfigMap
metadata:
  annotations:
    note: generated
  labels:
    type: generated
  name: example-configmap-3

设置跨领域字段

通常需要为项目中的所有 Kubernetes 资源设置跨领域字段。设置跨领域字段的一些用例

  • 为所有资源设置相同的命名空间
  • 添加相同的名称前缀或后缀
  • 添加相同的标签集
  • 添加相同的注释集

以下是一个示例

# Create a deployment.yaml
cat <<EOF >./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 <<EOF >./kustomization.yaml
namespace: my-namespace
namePrefix: dev-
nameSuffix: "-001"
commonLabels:
  app: bingo
commonAnnotations:
  oncallPager: 800-555-1212
resources:
- deployment.yaml
EOF

运行 kubectl kustomize ./ 以查看所有这些字段都已设置在 Deployment 资源中

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

组合和自定义资源

通常需要组合项目中的一组资源并在同一个文件或目录中管理它们。Kustomize 提供从不同文件组合资源并将补丁或其他自定义应用于它们的功能。

组合

Kustomize 支持组合不同的资源。kustomization.yaml 文件中的 resources 字段定义要包含在配置中的资源列表。在 resources 列表中设置资源配置文件的路径。以下是一个包含 Deployment 和 Service 的 NGINX 应用程序示例

# Create a deployment.yaml file
cat <<EOF > 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

# Create a service.yaml file
cat <<EOF > 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

# Create a kustomization.yaml composing them
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
- service.yaml
EOF

kubectl kustomize ./ 中的资源包含 Deployment 和 Service 对象。

自定义

补丁可用于对资源应用不同的自定义。Kustomize 通过 patchesStrategicMergepatchesJson6902 支持不同的补丁机制。patchesStrategicMerge 是一个文件路径列表。每个文件都应解析为 策略合并补丁。补丁中的名称必须与已加载的资源名称匹配。建议使用执行一项操作的小补丁。例如,为增加部署副本数创建一个补丁,为设置内存限制创建一个补丁。

# Create a deployment.yaml file
cat <<EOF > 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

# Create a patch increase_replicas.yaml
cat <<EOF > increase_replicas.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 3
EOF

# Create another patch set_memory.yaml
cat <<EOF > 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 <<EOF >./kustomization.yaml
resources:
- deployment.yaml
patchesStrategicMerge:
- increase_replicas.yaml
- set_memory.yaml
EOF

运行 kubectl kustomize ./ 以查看 Deployment

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
        resources:
          limits:
            memory: 512Mi

并非所有资源或字段都支持策略合并补丁。为了支持修改任意资源中的任意字段,Kustomize 提供通过 patchesJson6902 应用 JSON 补丁 的功能。要查找 JSON 补丁的正确资源,需要在 kustomization.yaml 中指定该资源的组、版本、类型和名称。例如,可以通过 patchesJson6902 增加 Deployment 对象的副本数。

# Create a deployment.yaml file
cat <<EOF > 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

# Create a json patch
cat <<EOF > patch.yaml
- op: replace
  path: /spec/replicas
  value: 3
EOF

# Create a kustomization.yaml
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml

patchesJson6902:
- target:
    group: apps
    version: v1
    kind: Deployment
    name: my-nginx
  path: patch.yaml
EOF

运行 kubectl kustomize ./ 以查看 replicas 字段已更新

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 字段中指定新镜像来更改容器中使用的镜像。

cat <<EOF > 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 <<EOF >./kustomization.yaml
resources:
- deployment.yaml
images:
- name: nginx
  newName: my.image.registry/nginx
  newTag: 1.4.0
EOF

运行 kubectl kustomize ./ 以查看使用的镜像已更新

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 需要从 Env 或作为命令参数读取相应的服务名称。由于服务名称可能会随着 kustomization.yaml 文件中添加的 namePrefixnameSuffix 而更改,因此不建议在命令参数中硬编码服务名称。对于此用途,Kustomize 可以通过 vars 将服务名称注入容器。

# Create a deployment.yaml file (quoting the here doc delimiter)
cat <<'EOF' > 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

# Create a service.yaml file
cat <<EOF > 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 <<EOF >./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 ./ 以查看注入容器的服务名称为 dev-my-nginx-001

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

基础和覆盖

Kustomize 具有 **基础** 和 **覆盖** 的概念。**基础** 是包含 kustomization.yaml 的目录,其中包含一组资源和关联的自定义。基础可以是本地目录,也可以是从远程存储库的目录,只要里面存在 kustomization.yaml 即可。**覆盖** 是包含 kustomization.yaml 的目录,该目录将其他 kustomization 目录作为其 bases 引用。**基础** 不了解覆盖,并且可以在多个覆盖中使用。覆盖可能有多个基础,它组合来自所有基础的资源,并且也可能在它们的基础上进行自定义。

以下是一个基础示例

# Create a directory to hold the base
mkdir base
# Create a base/deployment.yaml
cat <<EOF > 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

# Create a base/service.yaml file
cat <<EOF > 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
# Create a base/kustomization.yaml
cat <<EOF > base/kustomization.yaml
resources:
- deployment.yaml
- service.yaml
EOF

此基础可以在多个覆盖中使用。您可以在不同的覆盖中添加不同的 namePrefix 或其他跨领域字段。以下是如何使用相同基础的两个覆盖。

mkdir dev
cat <<EOF > dev/kustomization.yaml
resources:
- ../base
namePrefix: dev-
EOF

mkdir prod
cat <<EOF > prod/kustomization.yaml
resources:
- ../base
namePrefix: prod-
EOF

如何使用 Kustomize 应用/查看/删除对象

kubectl 命令中使用 --kustomize-k 来识别由 kustomization.yaml 管理的资源。请注意,-k 应指向 kustomization 目录,例如

kubectl apply -k <kustomization directory>/

给定以下 kustomization.yaml

# Create a deployment.yaml file
cat <<EOF > 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

# Create a kustomization.yaml
cat <<EOF >./kustomization.yaml
namePrefix: dev-
commonLabels:
  app: my-nginx
resources:
- deployment.yaml
EOF

运行以下命令以应用 Deployment 对象 dev-my-nginx

> kubectl apply -k ./
deployment.apps/dev-my-nginx created

运行以下命令之一以查看 Deployment 对象 dev-my-nginx

kubectl get -k ./
kubectl describe -k ./

运行以下命令以将 Deployment 对象 dev-my-nginx 与应用清单后集群将处于的状态进行比较

kubectl diff -k ./

运行以下命令以删除 Deployment 对象 dev-my-nginx

> kubectl delete -k ./
deployment.apps "dev-my-nginx" deleted

Kustomize 功能列表

字段类型解释
namespacestring将命名空间添加到所有资源
namePrefixstring此字段的值将附加到所有资源的名称之前
nameSuffixstring此字段的值将附加到所有资源的名称之后
commonLabelsmap[string]string要添加到所有资源和选择器的标签
commonAnnotationsmap[string]string要添加到所有资源的注释
resources[]string此列表中的每个条目都必须解析为现有的资源配置文件
configMapGenerator[]ConfigMapArgs此列表中的每个条目都会生成一个 ConfigMap
secretGenerator[]SecretArgs此列表中的每个条目都会生成一个 Secret
generatorOptionsGeneratorOptions修改所有 ConfigMap 和 Secret 生成器的行为
bases[]string此列表中的每个条目都应解析为包含 kustomization.yaml 文件的目录
patchesStrategicMerge[]string此列表中的每个条目都应解析为 Kubernetes 对象的策略性合并补丁
patchesJson6902[]Patch此列表中的每个条目都应解析为 Kubernetes 对象和 Json Patch
vars[]Var每个条目用于捕获一个资源字段中的文本
images[]Image每个条目用于修改一个镜像的名称、标签和/或摘要,而不会创建补丁
configurations[]string此列表中的每个条目都应解析为包含 Kustomize 变换器配置 的文件
crds[]string此列表中的每个条目都应解析为 Kubernetes 类型 的 OpenAPI 定义文件

下一步

上次修改时间:2023 年 4 月 18 日下午 3:26 PST: docs/en: Update kustomize examples to use non-deprecated resources key (b2b28c49f5)