山河已无恙
作者山河已无恙·2023-01-13 09:33
开发工程师·浩鲸科技

K8s:通过 Kustomize 实现YAML资源文件组合与继承

字数 12179阅读 1731评论 0赞 1

在使用 helm 的时候,有些 chart 包里面,小伙伴可能会发现,好多资源对象是定义在一个文件里的,而且定义的顺序是按照创建顺序的,刚开始我一直以为是写好之后又整合到一起的,但是后来遇到了 Kustomize,才发现可能并不是那样。

Kustomize 通过 kustomization 文件 不但可以定制 Kubernetes 对象。还可以组合 多个资源对象为一个 yaml 文件 ,实现资源对象 yaml 文件的简单管理。

组合和继承资源

一种常见的做法是在项目中构造资源集合并将其放到同一个文件或目录中管理。 Kustomize 提供基于不同配置文件来合并资源并向其应用一些补丁或者其他定制的能力。

资源文件的组合

Kustomize 支持组合不同的资源。kustomization.yaml 文件的 resources 字段定义配置中要包含的资源列表。 你可以将 resources 列表中的路径设置为资源配置文件的路径。 下面是由 Deployment 和 Service 构成的 NGINX 应用的示例:

┌──[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: {}

┌──[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 文件整合

┌──[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 ./ 检查生成的资源文件

┌──[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: {}

如果希望直接应用他们,可以实现下面的命令

┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge]  
└─$kubectl apply  -k ./

┌──[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           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 的副本个数;构造另外一个补丁来设置内存限制。

原始文件

┌──[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 的副本个数

┌──[root@vms81.liruilongs.github.io]-[~/kustomize/patches]  
└─$cat increase_replicas.yaml  
apiVersion: apps/v1  
kind: Deployment  
metadata:  
  name: my-nginx  
spec:  
  replicas: 3

重写 pod 模板的内存限制

┌──[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 文件可以看做是描述继承关系的文件

┌──[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

生成的新的资源文件

┌──[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 来完成:

# 创建一个 JSON 补丁文件  
cat  patch.yaml  
- op: replace  
  path: /spec/replicas  
  value: 3  
# 创建一个 kustomization.yaml  
cat ./kustomization.yaml  
resources:  
- deployment.yaml  

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

对象字段重写

除了补丁之外,Kustomize 还提供定制容器镜像或者将其他对象的字段值注入到容器中的能力,并且不需要创建补丁。 例如,你可以通过在 kustomization.yaml 文件的 images 字段设置新的镜像来更改容器中使用的镜像。

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 中使用了变量

┌──[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 需要定义变量的来源。

┌──[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

查看组合后的变量情况

┌──[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 文件定义

┌──[root@vms81.liruilongs.github.io]-[~/kustomize/rebase]  
└─$cat kustomization.yaml  
resources:  
- deployment.yaml  
- service.yaml

合并后的基准文件

┌──[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 资源目录继承):

┌──[root@vms81.liruilongs.github.io]-[~/kustomize/]  
└─$mkdir dev  
┌──[root@vms81.liruilongs.github.io]-[~/kustomize/]  
└─$mkdir prod

编写继承的 yaml 资源文件目录的 kustomization.yaml 文件

┌──[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

查看覆盖(继承)后新的资源文件

┌──[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 来应用、查看和删除对象

应用对象

┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge]  
└─$kubectl apply -k ./  
service/web-svc created  
deployment.apps/web created

查看对象

┌──[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           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:         
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 ./

删除对象

┌──[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]  
└─$

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

1

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广