K8s:通過 Kustomize 實(shí)現(xiàn)YAML資源文件組合與繼承

在使用 helm 的時(shí)候,有些 chart 包里面,小伙伴可能會(huì)發(fā)現(xiàn),好多資源對(duì)象是定義在一個(gè)文件里的,而且定義的順序是按照創(chuàng)建順序的,剛開始我一直以為是寫好之后又整合到一起的,但是后來遇到了 Kustomize,才發(fā)現(xiàn)可能并不是那樣。


Kustomize 通過 kustomization 文件 不但可以定制 Kubernetes 對(duì)象。還可以組合 多個(gè)資源對(duì)象為一個(gè) yaml 文件 ,實(shí)現(xiàn)資源對(duì)象 yaml 文件的簡單管理。




組合和繼承資源

一種常見的做法是在項(xiàng)目中構(gòu)造資源集合并將其放到同一個(gè)文件或目錄中管理。 Kustomize 提供基于不同配置文件來合并資源并向其應(yīng)用一些補(bǔ)丁或者其他定制的能力。


資源文件的組合

Kustomize 支持組合不同的資源。kustomization.yaml 文件的 resources 字段定義配置中要包含的資源列表。 你可以將 resources 列表中的路徑設(shè)置為資源配置文件的路徑。 下面是由 Deployment 和 Service 構(gòu)成的 NGINX 應(yīng)用的示例:


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

如果希望直接應(yīng)用他們,可以實(shí)現(xiàn)下面的命令


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

資源文件的繼承

補(bǔ)丁文件(Patches)可以用來對(duì)資源執(zhí)行不同的定制。用通俗的話講,即可以定義一些其他的文件(補(bǔ)丁文件),在繼承原來資源文件的基礎(chǔ)上,重寫原來的單一的資源文件中某些字段。類似于面向?qū)ο罄锩娴睦^承關(guān)系。


Kustomize 通過 patchesStrategicMerge 和 patchesJson6902 支持不同的打補(bǔ)丁機(jī)制(重寫)。


模板化重寫

patchesStrategicMerge 的內(nèi)容是一個(gè)文件路徑的列表,其中每個(gè)文件都應(yīng)可解析為 策略性合并補(bǔ)丁(Strategic Merge Patch)。 補(bǔ)丁文件中的名稱必須與已經(jīng)加載的資源的名稱匹配。 建議構(gòu)造規(guī)模較小的、僅做一件事情的補(bǔ)丁。


例如,構(gòu)造一個(gè)補(bǔ)丁來增加 Deployment 的副本個(gè)數(shù);構(gòu)造另外一個(gè)補(bǔ)丁來設(shè)置內(nèi)存限制。


原始文件


┌──[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 的副本個(gè)數(shù)


┌──[root@vms81.liruilongs.github.io]-[~/kustomize/patches]

└─$cat increase_replicas.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: my-nginx

spec:

  replicas: 3

重寫 pod 模板的內(nèi)存限制


┌──[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 文件可以看做是描述繼承關(guān)系的文件


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

局部值重寫

并非所有資源或者字段都支持策略性合并補(bǔ)丁。為了支持對(duì)任何資源的任何字段進(jìn)行修改, Kustomize 提供通過 patchesJson6902 來應(yīng)用 JSON 補(bǔ)丁的能力。 為了給 JSON 補(bǔ)丁找到正確的資源,需要在 kustomization.yaml 文件中指定資源的組(group)、 版本(version)、類別(kind)和名稱(name)。 例如,為某 Deployment 對(duì)象增加副本個(gè)數(shù)的操作也可以通過 patchesJson6902 來完成:


# 創(chuàng)建一個(gè) JSON 補(bǔ)丁文件

cat  patch.yaml

- op: replace

  path: /spec/replicas

  value: 3

# 創(chuàng)建一個(gè) kustomization.yaml

cat ./kustomization.yaml

resources:

- deployment.yaml


patchesJson6902:

- target:

    group: apps

    version: v1

    kind: Deployment

    name: my-nginx

  path: patch.yaml

對(duì)象字段重寫

除了補(bǔ)丁之外,Kustomize 還提供定制容器鏡像或者將其他對(duì)象的字段值注入到容器中的能力,并且不需要?jiǎng)?chuàng)建補(bǔ)丁。 例如,你可以通過在 kustomization.yaml 文件的 images 字段設(shè)置新的鏡像來更改容器中使用的鏡像。


cat ./kustomization.yaml

resources:

- deployment.yaml

images:

- name: nginx

  newName: my.image.registry/nginx

  newTag: 1.4.0

組合中變量的使用

有些時(shí)候,Pod 中運(yùn)行的應(yīng)用可能需要使用來自其他對(duì)象的配置值。 例如,某 Deployment 對(duì)象的 Pod 需要從環(huán)境變量或命令行參數(shù)中讀取讀取 Service 的名稱。 由于在 kustomization.yaml 文件中添加 namePrefix 或 nameSuffix 時(shí) Service 名稱可能發(fā)生變化,建議不要在命令參數(shù)中硬編碼 Service 名稱。 對(duì)于這種使用場景,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 中有 基準(zhǔn)(bases) 和 覆蓋(overlays) 的概念區(qū)分。 這里可以理解為目錄級(jí)別 yaml 資源文件的繼承?;鶞?zhǔn) 為父類目錄,覆蓋 為子類重寫目錄。


基準(zhǔn) 是包含 kustomization.yaml 文件的一個(gè)目錄,其中包含一組資源及其相關(guān)的定制。 基準(zhǔn)可以是本地目錄或者來自遠(yuǎn)程倉庫的目錄,只要其中存在 kustomization.yaml 文件即可。


覆蓋 也是一個(gè)目錄,其中包含將其他 kustomization 目錄當(dāng)做 bases 來引用的 kustomization.yaml 文件。 基準(zhǔn)不了解覆蓋的存在,且可被多個(gè)覆蓋所使用。 覆蓋則可以有多個(gè)基準(zhǔn),且可針對(duì)所有基準(zhǔn)中的資源執(zhí)行組織操作,還可以在其上執(zhí)行定制。


創(chuàng)建一個(gè) bases 目錄。里面存放基準(zhǔn) 的 yaml 文件


kustomization.yaml 文件定義


┌──[root@vms81.liruilongs.github.io]-[~/kustomize/rebase]

└─$cat kustomization.yaml

resources:

- deployment.yaml

- service.yaml

合并后的基準(zhǔn)文件


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

此基準(zhǔn)可在多個(gè)覆蓋中使用。你可以在不同的覆蓋中添加不同的 namePrefix 或其他通用字段。 下面是兩個(gè)使用同一基準(zhǔn)的覆蓋(具體的 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 來應(yīng)用、查看和刪除對(duì)象

應(yīng)用對(duì)象


┌──[root@vms81.liruilongs.github.io]-[~/kustomize/merge]

└─$kubectl apply -k ./

service/web-svc created

deployment.apps/web created

查看對(duì)象


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

刪除對(duì)象


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




作者:山河已無恙


歡迎關(guān)注微信公眾號(hào) :山河已無恙