介绍
Kustomize是一个独立的工具,用来通过kustomization文件定制Kubernetes对象。
它提供以下功能特性来管理应用配置文件:
- 从其他来源生成资源
- 为资源设置贯穿性(Cross-Cutting)字段
- 组织和定制资源集合
从1.14版本开始,kubectl
开始支持使用kustomization文件来管理Kubernetes对象。要查看包含kustomization文件目录中的资源,执行下面命令:
kubectl kustomize <kustomization_directory>
要应用这些资源,使用参数--kustomize
或-k
标志来执行kubectl apply
:
kubectl apply -k <kustomization_directory>
生成资源
ConfigMap和Secret包含其他Kubernetes对象(如Pod)所需要的配置和敏感数据。ConfigMap和Secret中的数据来源往往是集群外部,例如某个.properties
文件或者SSH密钥文件。
Kustomize提供secretGenerator
和configMapGenerator
,可以基于文件或字面值生成Secret
和ConfigMap
。
configMapGenerator
要基于文件来生成ConfigMap,可以在configMapGenerator
的files
列表中添加表项。下面是一个根据.properties
文件的数据条目来生成ConfigMap的示例:
# 生成一个 application.properties 文件
cat <<EOF >application.properties
FOO=Bar
EOF
# 生成kustomization.yaml
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-1
files:
- application.properties
EOF
所生成的ConfigMap可以使用瞎main的命令来检查:
kubectl kustomize ./
所生成的ConfigMap为:
apiVersion: v1
data:
application.properties: |
FOO=Bar
kind: ConfigMap
metadata:
name: example-configmap-1-g4hk9g2ff8
要从env文件生成ConfigMap,需要在configMapGenerator
中的envs
列表中添加一个条目。这也可以用于通过省略=
和值来设置本地环境变量的值。
建议谨慎使用本地环境变量填充功能,用补丁覆盖通常更易于维护。当无法亲送预测变量的值时,在环境中设置值可能很有用。
下面是一个用.env
文件里的数据生成ConfigMap的例子:
# 创建一个.env文件
# BAZ 将使用本地环境变量
cat <<EOF >.env
FOO=Bar
BAZ
EOF
# 创建kustomization.yaml
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-1
envs:
- .env
EOF
可以使用以下命令检查生成的ConfigMap:
BAZ=Qux kubectl kustomize ./
生成的ConfigMap为:
apiVersion: v1
data:
BAZ: Qux
FOO: Bar
kind: ConfigMap
metadata:
name: example-configmap-1-892ghb99c8
说明:
.env文件中的每个变量在生成ConfigMap中称为一个单独的键。这与之前的示例不同,前一个示例将一个名为
.properties
的文件(及其所有条目)潜入到同一个键的值中。
ConfigMap也可基于字面的键值对来生成,要基于键值对来生成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-42cfbf598f
要在Deployment中使用生成的ConfigMap,使用configMapGenerator的名称对其进行引用,Kustomize将自动使用生成的名称替换该名称。
示例:
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
可以基于文件或者键值对生成Secert。要使用文件内容来生成Secret,在secretGenerator
下面的files
里列表中添加表项。
下面是一个根据文件中数据来生成Secret对象的示例:
# 创建一个password.txt文件
cat <<EOF >./password.txt
username=admin
password=secret
EOF
cat <<EOF >./kustomization.yaml
secretGenerator:
- name: example-secret-1
files:
- password.txt
EOF
同样使用kubectl kustomize ./
命令生成Secret,所生成Secret如下:
apiVersion: v1
data:
password.txt: dXNlcm5hbWU9YWRtaW4KcGFzc3dvcmQ9c2VjcmV0Cg==
kind: Secret
metadata:
name: example-secret-1-2kdd8ckcc7
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-8c5228dkb9
type: Opaque
与ConfigMap一样,生成的Secret可以通过引用名称的方式在Deployment中使用:
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
生成的Deployment将通过名称引用生成的Secret:
apiVersion: v1
data:
password.txt: dXNlcm5hbWU9YWRtaW4KcGFzc3dvcmQ9c2VjcmV0Cg==
kind: Secret
metadata:
name: example-secret-1-2kdd8ckcc7
type: Opaque
---
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: /secrets
name: password
volumes:
- name: password
secret:
secretName: example-secret-1-2kdd8ckcc7
generatorOptions
所生成的ConfigMap和Secret都包含内容哈希值后缀。这是为了确保内容发生变化时,所生成的事最新的ConfigMap或Secret。
要禁止自动添加后缀的行为,可以使用generatorOptions
。除此之外,为生成的ConfigMap和Secret指定贯穿性选项也是可以的。
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对象设置贯穿性字段事一种常见的操作,贯穿性字段的一些使用常见如下:
- 为所有资源设置相同的命名空间
- 为所有对象添加相同的前缀或者后缀
- 为对象添加相同的标签集合
- 为对象添加相同的注解集合
示例:
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应用的示例:
# 创建 deployment.yaml 文件
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
# 创建 service.yaml 文件
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
# 创建 kustomization.yaml 来组织以上两个资源
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
- service.yaml
EOF
kubectl kustomize ./
所得到的资源中既包含Deployment也包含Service对象。
apiVersion: v1
kind: Service
metadata:
labels:
run: my-nginx
name: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
---
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: nginx
name: my-nginx
ports:
- containerPort: 80
定制
补丁文件(Patches)可以用来对资源执行不同的定制。 Kustomize 通过 patchesStrategicMerge
和 patchesJson6902
支持不同的打补丁机制。patchesStrategicMerge
的内容是一个文件路径的列表,其中每个文件都应可解析为 策略性合并补丁(Strategic Merge Patch)。 补丁文件中的名称必须与已经加载的资源的名称匹配。 建议构造规模较小的、仅做一件事情的补丁。
例如,构造一个补丁来增加 Deployment 的副本个数;构造另外一个补丁来设置内存限制。
# 创建 deployment.yaml 文件
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
# 生成一个补丁 increase_replicas.yaml
cat <<EOF > increase_replicas.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 3
EOF
# 生成另外一个补丁 set_memroy.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
# 生成 kustomization.yaml
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
文件中指定资源的 组(group)、版本(version)、类别(kind)和名称(name)。
例如,为某 Deployment 对象增加副本个数的操作也可以通过 patchesJson6902
来完成:
# 创建一个 deployment.yaml 文件
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
# 创建一个 JSON 补丁文件
cat <<EOF > patch.yaml
- op: replace
path: /spec/replicas
value: 3
EOF
# 创建 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
字段设置新的镜像来更改容器中使用的镜像。
# 创建 deployment.yaml
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
# 创建 kustomization.yaml
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 可以通过 vars
将 Service 名称注入到容器中。
# 创建一个 deployment.yaml 文件
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
# 创建一个 service.yaml 文件
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
# 创建 kustomization.yaml
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 ./
以查看注入到容器中的Service名称是dev-my-nginx-001
:
apiVersion: v1
kind: Service
metadata:
labels:
run: my-nginx
name: dev-my-nginx-001
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
---
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 中有 基准(bases) 和 覆盖(overlays) 的概念区分。
基准 是包含 kustomization.yaml
文件的一个目录,其中包含一组资源及其相关的定制。 基准可以是本地目录或者来自远程仓库的目录,只要其中存在 kustomization.yaml
文件即可。
覆盖 也是一个目录,其中包含将其他 kustomization 目录当做 bases
来引用的 kustomization.yaml
文件。 基准不了解覆盖的存在,且可被多个覆盖所使用。 覆盖则可以有多个基准,且可针对所有基准中的资源执行组织操作,还可以在其上执行定制。
# 创建一个基准的目录
mkdir base
# 创建 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
# 创建 base/service.yaml
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
# 创建 base/kustomization.yaml
cat <<EOF > base/kustomization.yaml
resources:
- deployment.yaml
- service.yaml
EOF
此基准可在多个覆盖中使用。
可以在不同的覆盖中添加不同的namePrefix
或其他贯穿性字段。
下面是两个使用同一基准的覆盖:
mkdir dev
cat <<EOF > dev/kustomization.yaml
bases:
- ../base
namePrefix: dev-
EOF
mkdir prod
cat <<EOF > prod/kustomization.yaml
bases:
- ../base
namePrefix: prod-
EOF
分别执行kubectl kustomize dev
和kubectl kustomize prod
会发现生成的Service
和Deployment
的name
分别加上了dev
和prod
。
使用Kustomize应用、查看和删除对象
在 kubectl
命令中使用 --kustomize
或 -k
参数来识别被 kustomization.yaml
所管理的资源。 注意 -k
要指向一个 kustomization 目录。例如:
kubectl apply -k <kustomization 目录>/
假定使用下面的kustomization.yaml
:
# 创建 deployment.yaml
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
# 创建 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 ./
kustomize 功能特性列表
字段 | 类型 | 解释 |
---|---|---|
namespace | string | 为所有资源添加命名空间 |
namePrefix | string | 此字段的值将被添加到素有资源名称前面 |
nameSuffix | string | 此字段的值将被添加到所有资源名称后面 |
commonLabels | map[string]string | 要添加到所有资源和选择算符的标签 |
commonAnnotations | map[string]string | 要添加到所有资源的注释 |
resources | []string | 列表中的每个条目都必须能够解析成现有的资源配置文件 |
configMapGenerator | []ConfigMapArgs | 列表中的每个条目都会生成一个 ConfigMap |
secretGenerator | []SecretArgs | 列表中的每个条目都会生成一个Secret |
generatorOptions | GeneratorOptions | 更改所有 ConfigMap 和 Secret 生成器的行为 |
bases | []string | 列表中每个条目都应能解析为一个包含 kustomization.yaml 文件的目录 |
patchesStrategicMerge | []string | 列表中每个条目都能解析为某 Kubernetes 对象的策略性合并补丁 |
patchesJson6902 | []Path | 列表中每个条目都能解析为一个 Kubernetes 对象和一个 JSON 补丁 |
vars | []Var | 每个条目用来从某资源的字段来析取文字 |
images | []Image | 每个条目都用来更改镜像的名称、标记与/或摘要,不必生成补丁 |
configurations | []string | 列表中每个条目都应能解析为一个包含 Kustomize 转换器配置 的文件 |
crds | []string | 列表中每个条目都应能够解析为 Kubernetes 类别的 OpenAPI 定义文件 |