kustomize で kubernetes マニフェストを管理する

オブジェクトをカスタマイズできる Kustomize について紹介します。kustomization.yaml には専用のフィールドである secretGenerator, ConfigMapGenerator, ImageTagTransformer, LabelTransformer, NamespaceTransformer, PatchesStrategicMerge 等があり、それを直接定義しプラグインを暗黙的にトリガーする方法と、kustomization.yaml にgenerators もしくは transformers フィールドを介して 別の yaml に定義した内容を明示的にトリガーする方法があります。違いは前者はプラグインの引数のほとんどがデフォルトになる点、後者は完全なプラグインの引数の指定が可能な点です。

www.aimhighergg.com は Kubernetes で稼働していて、各オブジェクトは manifest で管理しています。 kustomize で環境ごとにカスタマイズして deploy を行っています。 www.aimhighergg.com のコンセプトはできる限り kustomization.yaml に変更箇所を集約し、環境ごとの管理を容易にすることです。
https://github.com/AbeYuki/aimhighergg-com

以下が www.aimhighergg.com の kustomization 周りの manifest の抜粋です。
コンテナイメージ、レプリカカウント、ストレージ、イングレスの設定が一目でわかるようになっており、変更も kustomization.yaml で完結します。 LabelTransformer, PrefixSuffixTransformer については transformers フィールでに yaml 明示的にトリガーし詳細な設定を記載しています。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: www-aimhighergg-com
generatorOptions:
  disableNameSuffixHash: true
bases:
  - ../../base
secretGenerator:
- name: kustomize-password
  files:
  - password=password.txt
- name: docker-registry
  files:
   - '.dockerconfigjson=docker-registry.json'
  type: kubernetes.io/dockerconfigjson
configMapGenerator:
- name: template-config
  literals:
  - WORDPRESS_DB_HOST=backend-db01
  - WORDPRESS_DB_NAME=wordpress
  - WORDPRESS_DB_USER=wordpress
  - MYSQL_DATABASE_WP=wordpress
  - MYSQL_USER_WP=wordpress
  - MYSQL_USER_MW=wordpress
  - MYSQL_DATABASE_MW=tips_wiki
transformers:
  - transformer-label.yaml
  - transformer-suffixprefix.yaml
images:
  - name: frontend-app01
    newName: wordpress
    newTag: "6.0.0-php8.1-apache"
  - name: backend-db01
    newName: mariadb
    newTag: "10.5"
  - name: frontend-app02
    newName: registry.gitlab.com/aimhighergg/docker-registry/mediawiki-wiki
    newTag: "1.36.3"
  - name: backend-db02
    newName: mariadb
    newTag: "10.5"
  - name: frontend-static01
    newName: registry.gitlab.com/aimhighergg/docker-registry/portfolio
    newTag: "1.0"
  - name: frontend-static02
    newName: registry.gitlab.com/aimhighergg/docker-registry/maintenance
    newTag: "1.0"
replicas:
- name: frontend-app01
  count: 2
- name: backend-db01
  count: 1
- name: frontend-app02
  count: 1
- name: backend-db02
  count: 1
- name: frontend-static01
  count: 2
- name: frontend-static02
  count: 1
patchesStrategicMerge:
- |-
  apiVersion: v1
  kind: PersistentVolumeClaim
  metadata:
    name: frontend-app01
  spec:
    accessModes:
    - ReadWriteMany
    resources:
      requests:
        storage: 10Gi
    storageClassName: longhorn
    volumeMode: Filesystem
- |-
  apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
    name: ingress-tls
  spec:
    ingressClassName: nginx 
    tls:
    - hosts:
        - www.aimhighergg.com
      secretName: tls-secret
    rules:
    - host: www.aimhighergg.com
      http:
        paths:
        - pathType: Prefix
          path: /
          backend:
            service:
              name: frontend-app01
              port:
                number: 80

transformers については LabelTransformer, PrefixSuffixTransformer で metadata 以外の PATH へ設定を反映しています。kind でどの種類のオブジェクトを対象にするか指定し、 path で対象の name を指定して反映するようにしています。 PrefixSuffixTransformer の留意点としては、metadata/name は kind を指定せずに全てに反映するようにしています。それにともなって、データベースの sevice 名も反映されるため、 wordpress の WORDPRESS_DB_HOST 変数にも PrefixSuffix を付与しすることで環境が変わった際もデータベースと接続できるようにしています。

apiVersion: builtin
kind: LabelTransformer
metadata:
  name: label-transformer
labels:
  environment: production
  app.kubernetes.io/managed-by: github
  app.kubernetes.io/created-by: controller-manager
fieldSpecs:
- path: metadata/labels
  create: true
- path: spec/selector/matchLabels
  kind: Deployment
  create: true
- path: spec/template/metadata/labels
  kind: Deployment
  create: true
apiVersion: builtin
kind: PrefixSuffixTransformer
metadata:
  name: prefixsuffix-transformer
prefix: www-aimhighergg-com-
suffix: "-001"
fieldSpecs:
  - path: metadata/name
  - path: spec/template/spec/containers/name
    kind: Deployment
  - path: spec/acme/privateKeySecretRef/name
    kind: ClusterIssuer
  - path: spec/tls/secretName
    kind: Ingress
  - path: data/WORDPRESS_DB_HOST
    kind: ConfigMap
  - path: metadata/annotations/cert-manager.io\/cluster-issuer
    kins: Ingress

以上、 www.aimhighergg.com の Kustomize 環境の紹介でした。
一般的なウェブアプリケーション構成の場合、1つテンプレートを作成してしまえば流用できるため、最初につくりこんでしまえば非常に yaml の作成が楽になります。
是非、kustomize を活用して Kubernetes Life を楽しみましょう。

以降については kustomization.yaml に記載する場合とプラグインを利用する場合の紹介です。

PrefixSuffixTransformer

全てのリソースの prefix suffix に名前を付与する

namePrefix: alices-
nameSuffix: -v2
apiVersion: builtin
kind: PrefixSuffixTransformer
metadata:
  name: not-important-to-example
prefix: baked-
suffix: -pie
fieldSpecs:
  - path: metadata/name

AnnotationTransformer

全てのリソースにアノテーションを追加

commonAnnotations:
  oncallPager: 800-555-1212
apiVersion: builtin
kind: AnnotationsTransformer
metadata:
  name: not-important-to-example
annotations:
  app: myApp
  greeting/morning: a string with blanks
fieldSpecs:
- path: metadata/annotations
  create: true

SecretGenerator

引数リストの各エントリにより、1つのシークレットリソースが作成される

secretGenerator:
- name: app-tls
  files:
  - secret/tls.cert
  - secret/tls.key
  type: "kubernetes.io/tls"
- name: app-tls-namespaced
  # you can define a namespace to generate
  # a secret in, defaults to: "default"
  namespace: apps
  files:
  - tls.crt=catsecret/tls.cert
  - tls.key=secret/tls.key
  type: "kubernetes.io/tls"
- name: env_file_secret
  envs:
  - env.txt
  type: Opaque
- name: secret-with-annotation
  files:
  - app-config.yaml
  type: Opaque
  options:
    annotations:
      app_config: "true"
    labels:
      app.kubernetes.io/name: "app2"
apiVersion: builtin
kind: SecretGenerator
metadata:
  name: my-secret
  namespace: whatever
behavior: merge
envs:
- a.env
- b.env
files:
- obscure=longsecret.txt
literals:
- FRUIT=apple
- VEGETABLE=carrot

ConfigMapGenerator

generatorOptions は
この option フィールドでは、生成されたインスタンスにラベルや注釈を追加したり、そのインスタンスの名前サフィックスハッシュを個別に無効化したりできる。
また、ここで追加されたラベルと注釈は、カスタマイズファイルの generatorOptions フィールドに関連付けられたグローバルオプションによって上書きされない
ただし、bool値の動作によっては、グローバルな generatorOptins フィールドが、disableNameSuffixHash: true を指定していた場合ローカルに対して上書きはされない。
behavior: [create|replace|merge] でオーバレイの既存の変更・置換ができる。

generatorOptions:
  labels:
    fruit: apple

configMapGenerator:
- name: my-java-server-props
  behavior: merge
  files:
  - application.properties
  - more.properties
- name: my-java-server-env-vars
  literals: 
  - JAVA_HOME=/opt/java/jdk
  - JAVA_TOOL_OPTIONS=-agentlib:hprof
  options:
    disableNameSuffixHash: true
    labels:
      pet: dog
- name: dashboards
  files:
  - mydashboard.json
  options:
    annotations:
      dashboard: "1"
    labels:
      app.kubernetes.io/name: "app1"
apiVersion: builtin
kind: ConfigMapGenerator
metadata:
  name: mymap
envs:
- devops.env
- uxteam.env
literals:
- FRUIT=apple
- VEGETABLE=carrot

ReplicaCountTransformer

レプリカ数の変更

replicas:
- name: deployment-name
  count: 5
apiVersion: builtin
kind: ReplicaCountTransformer
metadata:
  name: not-important-to-example
replica:
  name: myapp
  count: 23
fieldSpecs:
- path: spec/replicas
  create: true
  kind: Deployment
- path: spec/replicas
  create: true
  kind: ReplicationController

ImageTagTransformer

tag の変更

containers:
- name: mypostgresdb
  image: postgres:8
- name: nginxapp
  image: nginx:1.7.9
- name: myapp
  image: my-demo-app:latest
- name: alpine-app
  image: alpine:3.7

image のパスとタグを変更

images:
- name: postgres
  newName: my-registry/my-postgres
  newTag: v1
- name: nginx
  newTag: 1.8.0
- name: my-demo-app
  newName: my-app
- name: alpine
  digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
apiVersion: builtin
kind: ImageTagTransformer
metadata:
  name: not-important-to-example
imageTag:
  name: nginx
  newTag: v2

LabelTransformer

すべてのリソースとセレクターにラベルを追加

commonLabels:
  someName: someValue
  owner: alice
  app: bingo
apiVersion: builtin
kind: LabelTransformer
metadata:
  name: not-important-to-example
labels:
  app: myApp
  env: production
fieldSpecs:
- path: metadata/labels
  create: true

NamespaceTransformer

すべてのリソースに名前空間を追加

namespace: my-namespace
apiVersion: builtin
kind: LabelTransformer
metadata:
  name: not-important-to-example
labels:
  app: myApp
  env: production
fieldSpecs:
- path: metadata/labels
  create: true

PatchesJson6902

pathフィールドは、JSONパッチファイルの相対ファイルパス

- op: add
  path: /some/new/path
  value: value
- op: replace
  path: /some/existing/path
  value: new value
patchesJson6902:
- target:
    version: v1
    kind: Deployment
    name: my-deployment
  path: add_init_container.yaml
- target:
    version: v1
    kind: Service
    name: my-service
  path: add_service_annotation.yaml

インラインも可能

patchesJson6902:
- target:
    version: v1
    kind: Deployment
    name: my-deployment
  patch: |-
    - op: add
      path: /some/new/path
      value: value
    - op: replace
      path: /some/existing/path
      value: "new value"

plugin

apiVersion: builtin
kind: PatchJson6902Transformer
metadata:
  name: not-important-to-example
target:
  group: apps
  version: v1
  kind: Deployment
  name: my-deploy
path: jsonpatch.json

PatchesStrategicMerge

このリストの各エントリは、相対ファイルパスか、部分的または完全なリソース定義に解決されるインラインコンテンツのいずれかである必要があり
kusomization.yaml

patchesStrategicMerge:
- service_port_8888.yaml
- deployment_increase_replicas.yaml
- deployment_increase_memory.yaml

インライン可能

patchesStrategicMerge:
- |-
  apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: nginx
  spec:
    template:
      spec:
        containers:
          - name: nginx
            image: nignx:latest
patches:
- path: patch.yaml
  target:
    group: apps
    version: v1
    kind: Deployment
    name: deploy.*
    labelSelector: "env=dev"
    annotationSelector: "zone=west"
- patch: |-
    - op: replace
      path: /some/existing/path
      value: new value
  target:
    kind: MyKind
    labelSelector: "env=dev"

PatchTransformer

このリストの各エントリは、パッチとターゲットセレクタを含むパッチオブジェクトに解決される必要あり。
インライン可能。

patches:
- path: patch.yaml
  target:
    group: apps
    version: v1
    kind: Deployment
    name: deploy.*
    labelSelector: "env=dev"
    annotationSelector: "zone=west"
- patch: |-
    - op: replace
      path: /some/existing/path
      value: new value
  target:
    kind: MyKind
    labelSelector: "env=dev"
apiVersion: builtin
kind: PatchTransformer
metadata:
  name: not-important-to-example
patch: '[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value": "nginx:latest"}]'
target:
  name: .*Deploy
  kind: Deployment

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です