使用 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 version
。
Kustomize 概述
Kustomize 是一个用于定制 Kubernetes 配置的工具。它具有以下管理应用配置文件的功能:
- 从其他源生成资源
- 为资源设置跨领域字段
- 组合和定制资源集合
生成资源
ConfigMaps 和 Secrets 包含配置或敏感数据,供其他 Kubernetes 对象(如 Pod)使用。ConfigMaps 或 Secrets 的真实来源通常在集群外部,例如 .properties
文件或 SSH 密钥文件。Kustomize 具有 secretGenerator
和 configMapGenerator
,可以从文件或字面值生成 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
说明
.env
文件中的每个变量都成为你生成的 ConfigMap 中的一个独立键。这与上一个示例不同,上一个示例将名为 application.properties
的文件(及其所有条目)作为单个键的值嵌入。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 的 Deployment 示例:
# Create an 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 一样,通过引用 secretGenerator 的名称,可以在 Deployments 中使用生成的 Secrets
# 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"
labels:
- pairs:
app: bingo
includeSelectors: true
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 通过使用 patches
字段,支持 StrategicMerge
和 Json6902
等不同的补丁机制。patches
可以是一个文件或内联字符串,目标可以是一个或多个资源。
patches
字段包含按指定顺序应用的补丁列表。补丁目标通过 group
、version
、kind
、name
、namespace
、labelSelector
和 annotationSelector
来选择资源。
建议使用只做一件事情的小补丁。例如,创建一个用于增加 Deployment 副本数的补丁,另一个用于设置内存限制。目标资源通过补丁文件中的 group
、version
、kind
和 name
字段进行匹配。
# 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
patches:
- path: increase_replicas.yaml
- path: 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
并非所有资源或字段都支持 strategicMerge
补丁。为了支持修改任意资源中的任意字段,Kustomize 提供了通过 Json6902
应用 JSON 补丁的能力。要为 Json6902
补丁找到正确的资源,必须在 kustomization.yaml
中指定 target
字段。
例如,增加 Deployment 对象的副本数也可以通过 Json6902
补丁完成。目标资源通过 target
字段中的 group
、version
、kind
和 name
进行匹配。
# 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
patches:
- 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 需要从环境变量或作为命令行参数读取对应的 Service 名称。由于在 kustomization.yaml
文件中添加 namePrefix
或 nameSuffix
后,Service 名称可能会更改。因此,不建议在命令行参数中硬编码 Service 名称。对于此用例,Kustomize 可以通过 replacements
将 Service 名称注入到容器中。
# 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_PLACEHOLDER"]
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
replacements:
- source:
kind: Service
name: my-nginx
fieldPath: metadata.name
targets:
- select:
kind: Deployment
name: my-nginx
fieldPaths:
- spec.template.spec.containers.0.command.2
EOF
运行 kubectl kustomize ./
查看注入到容器中的 Service 名称是 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
Base 和 Overlay
Kustomize 有 base 和 overlay 的概念。一个 base 是一个包含 kustomization.yaml
的目录,其中包含一组资源和相关的自定义设置。只要其中存在 kustomization.yaml
文件,base 既可以是本地目录,也可以是远程仓库中的目录。一个 overlay 是一个包含 kustomization.yaml
的目录,它将其 bases
字段指向其他 kustomization 目录。一个 base 不知道任何 overlay,并且可以在多个 overlay 中使用。
overlay 目录中的 kustomization.yaml
文件可以指向多个 bases
,将这些 base 中定义的所有资源组合成一个统一的配置。此外,它还可以在这些资源的基础上应用自定义设置,以满足特定要求。
这是一个 base 的示例:
# 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
这个 base 可以在多个 overlay 中使用。你可以在不同的 overlay 中添加不同的 namePrefix
或其他跨领域字段。这是使用同一个 base 的两个 overlay 示例。
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-
labels:
- pairs:
app: my-nginx
includeSelectors: true
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 功能列表
字段 | 类型 | 说明 |
---|---|---|
bases | []string | 此列表中的每个条目都应指向一个包含 kustomization.yaml 文件的目录 |
commonAnnotations | map[string]string | 添加到所有资源的注解 |
commonLabels | map[string]string | 添加到所有资源和选择器的标签 |
configMapGenerator | []ConfigMapArgs | 此列表中的每个条目都会生成一个 ConfigMap |
configurations | []string | 此列表中的每个条目都应指向一个包含 Kustomize 转换器配置的文件 |
crds | []string | 此列表中的每个条目都应指向 Kubernetes 类型的 OpenAPI 定义文件 |
generatorOptions | GeneratorOptions | 修改所有 ConfigMap 和 Secret 生成器的行为 |
images | []Image | 每个条目用于修改一个镜像的名称、标签和/或摘要,无需创建补丁 |
labels | map[string]string | 添加标签,无需自动注入相应的选择器 |
namePrefix | string | 此字段的值将前置到所有资源的名称之前 |
nameSuffix | string | 此字段的值将附加到所有资源的名称之后 |
patchesJson6902 | []Patch | 此列表中的每个条目都应指向一个 Kubernetes 对象和一个 Json 补丁 |
patchesStrategicMerge | []string | 此列表中的每个条目都应指向一个 Kubernetes 对象的战略合并补丁 |
replacements | []Replacements | 将资源字段中的值复制到任意数量的指定目标。 |
resources | []string | 此列表中的每个条目都必须指向一个现有资源配置文件 |
secretGenerator | []SecretArgs | 此列表中的每个条目都会生成一个 Secret |
vars | []Var | 每个条目用于从一个资源的字段中捕获文本 |