雲原生之旅

2022-10-31 12:02:31

前言

相信經過前一篇文章的學習,大家已經對Helm有所瞭解,本篇文章介紹另一款工具 Kustomize,為什麼Helm如此流行,還會出現 Kustomize?而且 Kustomize 自 kubectl 1.14以來早已內建到其中,說明官方對其很認可。

我認為還是Helm 引數化模板方式來自定義設定需要學習複雜的DSL語法,難上手,易出錯,而 kustomize 是使用 Kubernetes 原生概念幫助使用者創作並複用宣告式設定。

 

認識 Kustomize

https://kustomize.io/
 
根據官網的描述:kustomize 是 kubernetes 原生的設定管理,以無模板方式來客製化應用的設定。kustomize 使用 kubernetes 原生概念幫助建立並複用資源設定(YAML),允許使用者以一個應用描述檔案為基礎(Base YAML),然後通過 Overlay 的方式生成最終部署應用所需的描述檔案。
 

安裝

參考官方檔案
我本地MacOs 直接執行 brew install kustomize
kubectl 1.14 以後可以不用下載單獨的kustomize,直接使用kubectl命令。
 

範例解析

檔案結構:
demo-manifests
├── base
│   ├── deployment.yaml
│   ├── kustomization.yaml
│   ├── service-account.yaml
│   └── service.yaml
└── services
    ├── demo-app
    │   ├── _common
    │   │   ├── deployment-patch.yaml
    │   │   ├── kustomization.yaml
    │   │   └── namespace.yaml
    │   ├── dev
    │   │   ├── config.json
    │   │   ├── deployment-patch.yaml
    │   │   └── kustomization.yaml
    │   ├── staging
    │   │   ├── config.json
    │   │   ├── deployment-patch.yaml
    │   │   └── kustomization.yaml
    │   └── prod
    │   │   ├── config.json
    │   │   ├── deployment-patch.yaml
    │   │   └── kustomization.yaml
    └── demo-app2
        └── xxx

先看base 目錄,有幾個常見的deployment/service/service-account YAML 資原始檔

還有個 kustomization.yaml 組態檔

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
- service-account.yaml

commonLabels:
  managed-by: Kustomize

這裡麵包含了剛才的幾個resource檔案以及要應用於它們的一些自定義,如新增一個通用的標籤Common Labels

這時候也可以通過 kustomize build 命令來生成完整的YAML進行檢視

kustomize build demo-manifests/base > base.yaml
base.yaml

build 出來的 YAML 每個資源物件上都會存在通用的標籤 managed-by: Kustomize

 

接下來看 Service目錄,此目錄存放所有的服務專案,比如demo-app , 裡面的YAML就是來覆蓋base 也就是官方說的 Overlays

只需要把不同的資源描述通過Patch方式覆蓋掉base中的就行了。這邊我又將三個環境 dev/staging/prod 公共的部分抽取出來放入 common資料夾。

_common/kustomization.yaml檔案如下

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../base
- namespace.yaml
patchesStrategicMerge:
- deployment-patch.yaml

我這個demo-app 需要configMap,另外心跳介面也不一樣, 所以 deployment-patch.yaml 需要寫出這些不一樣的,然後去覆蓋base中的。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: NAME_PLACEHOLDER
spec:
  template:
    spec:
      serviceAccountName: NAME_PLACEHOLDER
      containers:
      - name: app
        image: wadexu007/demo:IMG_TAG_PLACEHOLDER
        livenessProbe:
          failureThreshold: 5
          httpGet:
            path: /pizzas
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 40
          timeoutSeconds: 1
        readinessProbe:
          failureThreshold: 5
          httpGet:
            path: /pizzas
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 20
          timeoutSeconds: 1
        volumeMounts:
        - name: config-volume
          mountPath: /app/conf/config.json
          subPath: config.json
      volumes:
      - name: config-volume
        configMap:
          name: demo-app-config
deployment-patch.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: demo
namespace.yaml

 ### 文章首發於部落格園 https://www.cnblogs.com/wade-xu/p/16839829.html

最後我們看 dev/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../_common
namespace: demo
commonLabels: app: demo-app
replicas: - count: 1 name: demo-app configMapGenerator: - files: - config.json name: demo-app-config patches: - patch: |- - op: replace path: /metadata/name value: demo-app target: name: NAME_PLACEHOLDER
patchesStrategicMerge: - deployment-patch.yaml
images: - name: wadexu007/demo newTag: 1.0.0

dev env 裡面將replicas設定成1, 用config.json 生成 configMap

{
    "SOME_CONFIG": "/demo/path"
}
config.json

deployment-patch.yaml 裡面也將container resource request/limit 設定設定小一點, 採用 patchesStrategicMerge 與 common 和 base裡面的deployment資源合併。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: NAME_PLACEHOLDER
spec:
  template:
    spec:
      containers:
      - name: app
        resources:
          limits:
            cpu: 1
            memory: 1Gi
          requests:
            cpu: 200m
            memory: 256Mi
deployment-patch.yaml

另外還採用了 patch 的方式,改了每個資源的name --> demo-app

以及images 替換了原來的 image name and tag.

kustomize 命令如下

 kustomize build demo-manifests/services/demo-app/dev > demo-app.yaml

如果用 kubectl 命令的話,範例如下

kubectl kustomize services/demo-app/dev/ > demo-app.yaml

最終結果

apiVersion: v1
kind: Namespace
metadata:
  labels:
    app: demo-app
  name: demo
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app: demo-app
    managed-by: Kustomize
  name: demo-app
  namespace: demo
---
apiVersion: v1
data:
  config.json: |-
    {
        "SOME_CONFIG": "/demo/path"
    }
kind: ConfigMap
metadata:
  labels:
    app: demo-app
  name: demo-app-config-t7c64mbtt2
  namespace: demo
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: demo-app
    managed-by: Kustomize
  name: demo-app
  namespace: demo
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: http
  selector:
    app: demo-app
    managed-by: Kustomize
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: demo-app
    managed-by: Kustomize
  name: demo-app
  namespace: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo-app
      managed-by: Kustomize
  template:
    metadata:
      labels:
        app: demo-app
        managed-by: Kustomize
    spec:
      containers:
      - image: wadexu007/demo:1.0.0
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 5
          httpGet:
            path: /pizzas
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 40
          timeoutSeconds: 1
        name: app
        ports:
        - containerPort: 8080
          name: http
        readinessProbe:
          failureThreshold: 5
          httpGet:
            path: /pizzas
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 20
          timeoutSeconds: 1
        resources:
          limits:
            cpu: 1
            memory: 1Gi
          requests:
            cpu: 200m
            memory: 256Mi
        securityContext:
          allowPrivilegeEscalation: false
        volumeMounts:
        - mountPath: /app/conf/config.json
          name: config-volume
          subPath: config.json
      serviceAccountName: demo-app
      volumes:
      - configMap:
          name: demo-app-config-t7c64mbtt2
        name: config-volume
demo-app.yaml

 ### https://www.cnblogs.com/wade-xu/p/16839829.html

staging/prod 資料夾也是類似dev的檔案,環境不一樣,config.json 以及資源設定,image tag 不一樣,顯示申明就行了。

完整程式碼請參考我的 Github

 

涵蓋 Kustomize 知識點

  • commonLabels
  • patchesStrategicMerge
  • patches
  • configMapGenerator
  • replicas
  • images

 

總結

經過本篇文章的學習,以及上一篇 [雲原生之旅 - 5)Kubernetes時代的包管理工具 Helm ]關於Helm的學習,您已經能體會到兩款工具的不同之處。

Helm 通過將應用抽象成 Chart 來管理, 專注於應用的操作、生命週期管理(如 install、upgrade、rollback)等, 而 kustomize 關注於 k8s API 物件的管理。
Helm 適合對外交付使用,使用的Chart 相對固定、穩定,相當於靜態管理,而 kustomize 管理的是正在變更的應用,建立新的 overlay 將應用部署在新的環境,相當於動態管理,適合於 DevOps 流程。
Helm 通過 Chart 方式打包並管理應用版本,kustomize 通過 overlay 方式管理應用不同的變體,通過 Git 來版本管理。
總的來說,Helm 有自己一套體系來管理應用,而 kustomize 更輕量級,也更靈活。另外,Kustomize也有 Terraform provider 通過TF來安裝。

感謝閱讀,如果您覺得本文的內容對您的學習有所幫助,您可以打賞和推薦,您的鼓勵是我創作的動力。