傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。——–王小波
写在前面
分享一些通过Kustomize 实现YAML资源文件组合与继承的笔记
官方文档里叫做组织和定制,这里这么叫方便理解
博文内容基本为官网文档内容
理解不足小伙伴帮忙指正
傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。——–王小波
在使用 helm 的时候,有些 chart 包里面,小伙伴可能会发现,好多资源对象是定义在一个文件里的,而且定义的顺序是按照创建顺序的,刚开始我一直以为是写好之后又整合到一起的,但是后来遇到了 Kustomize,才发现可能并不是那样。
Kustomize 通过 kustomization 文件 不但可以定制 Kubernetes 对象。还可以组合 多个资源对象为一个 yaml 文件 ,实现资源对象 yaml 文件的简单管理。
组合和继承资源 一种常见的做法是在项目中构造资源集合并将其放到同一个文件或目录中管理。 Kustomize 提供基于不同配置文件来合并资源并向其应用一些补丁或者其他定制的能力。
资源文件的组合 Kustomize 支持组合不同的资源。kustomization.yaml 文件的 resources 字段定义配置中要包含的资源列表。 你可以将 resources 列表中的路径设置为资源配置文件的路径。 下面是由 Deployment 和 Service 构成的 NGINX 应用的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$cat deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: web-deploy name: web spec: replicas: 3 selector: matchLabels: app: web strategy: {} template: metadata: creationTimestamp: null labels: app: web spec: containers: - image: nginx name: nginx-web ports: - containerPort: 80 name: nginx-web resources: {} status: {}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$cat service.yaml apiVersion: v1 kind: Service metadata: name: web-svc labels: app: nginx-svc spec: ports: - port: 30088 targetPort: 80 name: nginx-web selector: app: web
定义如下的 kustomization yaml 文件,即可以做到 deploy 和 svc 的 yaml 文件整合
1 2 3 4 5 6 7 8 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$cat kustomization.yaml resources: - deploy.yaml - service.yaml ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$ls deploy.yaml kustomization.yaml service.yaml
kubectl kustomize ./ 检查生成的资源文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$kubectl kustomize ./ apiVersion: v1 kind: Service metadata: labels: app: nginx-svc name: web-svc spec: ports: - name: nginx-web port: 30088 targetPort: 80 selector: app: web --- apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: web-deploy name: web spec: replicas: 3 selector: matchLabels: app: web strategy: {} template: metadata: creationTimestamp: null labels: app: web spec: containers: - image: nginx name: nginx-web ports: - containerPort: 80 name: nginx-web resources: {} status: {}
如果希望直接应用他们,可以实现下面的命令
1 2 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$kubectl apply -k ./
1 2 3 4 5 6 7 8 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$kubectl get svc web-svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE web-svc ClusterIP 10.106.69.74 <none> 30088/TCP 25h ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$kubectl get deployments.apps web NAME READY UP-TO-DATE AVAILABLE AGE web 3/3 3 3 25h
资源文件的继承 补丁文件(Patches)可以用来对资源执行不同的定制。用通俗的话讲,即可以定义一些其他的文件(补丁文件),在继承原来资源文件的基础上,重写原来的单一的资源文件中某些字段。类似于面向对象里面的继承关系。
Kustomize 通过 patchesStrategicMerge 和 patchesJson6902 支持不同的打补丁机制(重写)。
模板化重写 patchesStrategicMerge 的内容是一个文件路径的列表,其中每个文件都应可解析为 策略性合并补丁(Strategic Merge Patch)。 补丁文件中的名称必须与已经加载的资源的名称匹配。 建议构造规模较小的、仅做一件事情的补丁。
例如,构造一个补丁来增加 Deployment 的副本个数;构造另外一个补丁来设置内存限制。
原始文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/patches] └─$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
重写 Deployment 的副本个数
1 2 3 4 5 6 7 8 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/patches] └─$cat increase_replicas.yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx spec: replicas: 3
重写 pod 模板的内存限制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/patches] └─$cat set_memory.yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx spec: template: spec: containers: - name: my-nginx resources: limits: memory: 512Mi ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/patches] └─$
kustomization 文件可以看做是描述继承关系的文件
1 2 3 4 5 6 7 8 9 10 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/patches] └─$ls deployment.yaml increase_replicas.yaml kustomization.yaml set_memory.yaml ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/patches] └─$cat kustomization.yaml resources: - deployment.yaml patchesStrategicMerge: - increase_replicas.yaml - set_memory.yaml
生成的新的资源文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/patches] └─$kubectl kustomize ./ 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 来完成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 cat patch.yaml - op: replace path: /spec/replicas value: 3 cat ./kustomization.yaml resources: - deployment.yaml patchesJson6902: - target: group: apps version: v1 kind: Deployment name: my-nginx path: patch.yaml
对象字段重写 除了补丁之外,Kustomize 还提供定制容器镜像或者将其他对象的字段值注入到容器中的能力,并且不需要创建补丁。 例如,你可以通过在 kustomization.yaml 文件的 images 字段设置新的镜像来更改容器中使用的镜像。
1 2 3 4 5 6 7 cat ./kustomization.yaml resources: - deployment.yaml images: - name: nginx newName: my.image.registry/nginx newTag: 1.4 .0
组合中变量的使用 有些时候,Pod 中运行的应用可能需要使用来自其他对象的配置值。 例如,某 Deployment 对象的 Pod 需要从环境变量或命令行参数中读取读取 Service 的名称。 由于在 kustomization.yaml 文件中添加 namePrefix 或 nameSuffix 时 Service 名称可能发生变化,建议不要在命令参数中硬编码 Service 名称。 对于这种使用场景,Kustomize 可以通过 vars 将 Service 名称注入到容器中。
deployment 中使用了变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/vars] └─$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)" ] ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/vars] └─$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
kustomization.yaml 需要定义变量的来源。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/vars] └─$ls deployment.yaml kustomization.yaml service.yaml ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/vars] └─$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
查看组合后的变量情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/vars] └─$kubectl kustomize ./ 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 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/vars] └─$
Bases 与 Overlays Kustomize 中有 基准(bases) 和 覆盖(overlays) 的概念区分。 这里可以理解为目录级别 yaml 资源文件的继承。基准 为父类目录,覆盖 为子类重写目录。
基准 是包含 kustomization.yaml 文件的一个目录,其中包含一组资源及其相关的定制。 基准可以是本地目录或者来自远程仓库的目录,只要其中存在 kustomization.yaml 文件即可。
覆盖 也是一个目录,其中包含将其他 kustomization 目录当做 bases 来引用的 kustomization.yaml 文件。 基准不了解覆盖的存在,且可被多个覆盖所使用。 覆盖则可以有多个基准,且可针对所有基准中的资源执行组织操作,还可以在其上执行定制。
创建一个 bases 目录。里面存放基准 的 yaml 文件
kustomization.yaml 文件定义
1 2 3 4 5 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/rebase] └─$cat kustomization.yaml resources: - deployment.yaml - service.yaml
合并后的基准文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/rebase] └─$kubectl kustomize ./ 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
此基准可在多个覆盖中使用。你可以在不同的覆盖中添加不同的 namePrefix 或其他通用字段。 下面是两个使用同一基准的覆盖(具体的 Yaml 资源目录继承):
1 2 3 4 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/] └─$mkdir dev ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/] └─$mkdir prod
编写继承的 yaml 资源文件目录的 kustomization.yaml 文件
1 2 3 4 5 6 7 8 9 10 11 12 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize] └─$cat ./prod/kustomization.yaml bases: - ../rebase namePrefix: prod- namespace: liruilong-prod ┌──[root@vms81.liruilongs.github.io]-[~/kustomize] └─$cat ./dev/kustomization.yaml bases: - ../rebase namePrefix: dev- namespace: liruilong-dev
查看覆盖(继承)后新的资源文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize] └─$kubectl kustomize ./prod/ apiVersion: v1 kind: Service metadata: labels: run: my-nginx name: prod-my-nginx namespace: liruilong-prod spec: ports: - port: 80 protocol: TCP selector: run: my-nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: prod-my-nginx namespace: liruilong-prod spec: replicas: 2 selector: matchLabels: run: my-nginx template: metadata: labels: run: my-nginx spec: containers: - image: nginx name: my-nginx ┌──[root@vms81.liruilongs.github.io]-[~/kustomize] └─$kubectl kustomize ./dev/ apiVersion: v1 kind: Service metadata: labels: run: my-nginx name: dev-my-nginx namespace: liruilong-dev spec: ports: - port: 80 protocol: TCP selector: run: my-nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: dev-my-nginx namespace: liruilong-dev spec: replicas: 2 selector: matchLabels: run: my-nginx template: metadata: labels: run: my-nginx spec: containers: - image: nginx name: my-nginx ┌──[root@vms81.liruilongs.github.io]-[~/kustomize] └─$
如何使用 Kustomize 来应用、查看和删除对象 应用对象
1 2 3 4 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$kubectl apply -k ./ service/web-svc created deployment.apps/web created
查看对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$kubectl get -k ./ NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/web-svc ClusterIP 10.100.206.11 <none> 30088/TCP 7s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/web 1/3 3 1 7s ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$kubectl describe -k ./ Name: web-svc Namespace: awx Labels: app=nginx-svc Annotations: <none> Selector: app=web Type: ClusterIP 。。。。。。 Name: web Namespace: awx CreationTimestamp: Sat, 24 Dec 2022 01:14:23 +0800 Labels: app=web-deploy Annotations: deployment.kubernetes.io/revision: 1 Selector: app=web Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 。。。。。 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$kubectl diff -k ./
删除对象
1 2 3 4 5 6 ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$kubectl delete -k ./ service "web-svc" deleted deployment.apps "web" deleted ┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge] └─$
博文参考
https://kubectl.docs.kubernetes.io/zh/installation/
https://github.com/kubernetes-sigs/kustomize
https://kubernetes.io/zh-cn/docs/tasks/manage-kubernetes-objects/kustomization/
qiabib