使用 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
你可以從檔案或字面量鍵值對生成 Secret。要從檔案生成 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
與 ConfigMap 類似,生成的 Secret 可以透過引用 secretGenerator 的名稱在 Deployment 中使用。
# 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
生成的 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 資源設定交叉欄位是很常見的。設定交叉欄位的一些用例:
- 為所有資源設定相同的名稱空間
- 新增相同的名稱字首或字尾
- 新增相同的標籤集
- 新增相同的註解集
這是一個例子:
# 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 需要從 Env 或作為命令引數讀取相應的 Service 名稱。由於 Service 名稱可能會隨著 kustomization.yaml
檔案中新增的 namePrefix
或 nameSuffix
而改變,因此不建議在命令引數中硬編碼 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
基礎和疊加
Kustomize 具有基礎和疊加的概念。基礎是一個包含 kustomization.yaml
檔案的目錄,其中包含一組資源和相關的定製。基礎可以是本地目錄,也可以是遠端倉庫中的目錄,只要其中存在 kustomization.yaml
。疊加是一個包含 kustomization.yaml
檔案的目錄,它將其他 kustomization 目錄作為其 bases
引用。基礎不知道疊加的存在,並且可以在多個疊加中使用。
疊加目錄中的 kustomization.yaml
可以引用多個 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-
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 | 每個條目用於從資源的欄位中捕獲文字 |