【Kubernetes】kustomizeで環境毎のマニフェストを作成

f:id:tm200:20210507170855p:plain

kubernetesで環境毎の設定管理にkustomizeを使用したのでメモ。
ingressのannotationsにスラッシュが含まれていた為、patchesJson6902のプロパティ指定はどうやるのだろうと思ったのですが、エスケープに「~1」を用いる事で解決しました。


⬇️ これからkubernetesやDockerの経験を積みたい方にお勧めです!
Dockerfileや各種マニフェストの基本的な使い方が書かれています。

Docker/Kubernetes 実践コンテナ開発入門

Docker/Kubernetes 実践コンテナ開発入門

  • 作者:山田 明憲
  • 発売日: 2018/08/25
  • メディア: 単行本(ソフトカバー)


kustomize

github.com

環境

macOS Catalina 10.15.7

# インストール
$ brew install kustomize

ディレクトリはこんな感じ。

$ tree
.
...
├── k8s
│    ├── base
|    |    ├── config
│    |    |    └── nginx.conf # configMapに登録する設定ファイル
│    |    ├── deployment.yaml
│    |    ├── ingress.yaml
│    |    ├── kustomization.yaml
│    |    ├── pod_disruption_budget.yaml
|    |    └── service.yaml
│    └── overlays
|        ├── staging
|        |   ├── kustomization.yaml
|        |   ├── patch_deployment.yaml
|        |   └── patch_ingress.yaml
|        └── prod
|             └── ...
...

base

ベースとなる各種yamlを配置。

kustomization.yaml

configMapGeneratorでconfigMapを生成する方法を記載。
jsonyamlなどもこの方法で指定できる、、、はず。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

commonLabels:
  app: test-app

resources:
- deployment.yaml
- ingress.yaml
- service.yaml
- pod_disruption_budget.yaml

# configMapの設定、jsonなどの設定ファイルから取り込む場合
configMapGenerator:
- name: nginx-config
   namespace: test-namespace # ネームスペース を個別に指定する場合
   files:
     - config/nginx.conf

# configMapの共通設定
generatorOptions:
  disableNameSuffixHash: true # 生成されるconfigMapのサフィックスからハッシュ値を取り除く場合
  labels:
    app: test-app

deployment.yaml

普通の3層クライアントサーバーシステムっぽい設定。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-app
spec:
  selector:
    matchLabels:
      app: test-app
  replicas: 2
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  minReadySeconds: 10
  template:
    metadata:
      labels:
        app: test-app
    spec:
      volumes:
      - name: nginx-volume
        configMap:
          name: nginx-config # volumeに割り当て

      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
        limits:
          memory: 64Mi
        requests:
          cpu: 100m
          memory: 64Mi
        volumeMounts:
          - mountPath: /etc/nginx/nginx.conf
             subPath: nginx.conf
             name: nginx-volume
             readOnly: true
      - name: hello-python # pythonコードは割愛
        image: hello-python:latest
        imagePullPolicy: Never
        env:
          - name: TEST_ENV_VALUE
             value: 0
        ports:
        - containerPort: 8080
        limits:
          memory: 1G
          cpu: 1000m

        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 5
          failureThreshold: 10

        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
          timeoutSeconds: 10

        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "sleep 20"]

pod_disruption_budget.yaml

停止状態として許容できる Pod 数を定義。

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: test-app
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: test-app

ingress.yaml

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  namespace: test-namespace
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: http://test.example1.com
     http:
       paths:
       - backend:
           serviceName: testsvc
           servicePort: 80

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: testsvc
  labels:
    app: test-app
  namespace: test-namespace
spec:
  selector:
    app: test-app
  ports:
  - protocol: TCP
     port: 80
     targetPort: 80

overlays

環境差分を記載するyamlはこちらに配置。
基本はスラッシュ区切りでプロパティを指定する。
配列要素はインデックスを指定する事でアクセスできる。

kustomization.yaml

ベースとなるディレクトリとパッチするリソースをここで設定する。
ここではIngressとDeploymentを指定。

bases:
  - ../../base

patchesJson6902:
- target:
    group: networking.k8s.io
    version: v1beta1
    kind: Ingress
    name: test-ingress
  patch: patch_ingress.yaml # 差分を記載したファイルを指定
- target:
    group: apps
    version: v1
    kind: Deployment
    name: test-app
  patch: patch_deployment.yaml # こちらも同様

patch_ingress.yaml

ドメインとannotationsを変更する例。
annotationsのスラッシュは「~1」でエスケープ。

- op: replace
   path: /spec/rules/0/host
   value: http://test.example2.com
- op: replace
   # スラッシュを「~1」に置き換える
   path: /metadata/annotations/nginx.ingress.kubernetes.io~1rewrite-target
   value: /another

patch_deployment.yaml

レプリカ数と環境変数を変更。

- op: replace
   path: /spec/replicas
   value: 3
- op: replace
    # 環境変数「TEST_ENV_VALUE」を変更
   path: /spec/template/spec/containers/1/env/0/value
   value: 1

build

差分が反映されるか確認する。

$ cd k8s/base

$ kustomize build ../overlays/staging
apiVersion: v1
data:
  nginx.conf: | -
    ....
kind: ConfigMap
metadata:
  labels:
    app: test-app
  name: nginx-config
  namespace: test-namespace
---
apiVersion: v1
... 
# ビルド結果が出力されるので内容を確認する