本記事はSansan Advent Calendar 2024の24日目の記事です。
こんにちは。技術本部 Strategic Products Engineering Unit Contract One Devグループの髙野です。2024年4月に新卒で入社し、契約データベース「Contract One」の開発をしています。5人チームのリーダーとして、新規機能開発に向き合っています。
Cloud Run jobsのジョブ構成の管理に、KubernetesのManifest管理ツールであるKustomizeを導入したので紹介します。
バッチ処理実行基盤としてのCloud Run jobs
Contract Oneでは、バッチ処理の実行基盤としてCloud Run jobsを使用しています。基盤上にバッチ処理を実装していき、実行時にジョブ名を指定することで、目的のバッチ処理を動かします。コンテナイメージは1つですが、Google Cloud上では各ジョブが独立したリソースになっています。
ジョブ構成はCloud Run job YAMLで管理されており、gcloud run jobs replace
コマンドの引数にYAMLを指定することでジョブをデプロイできます。Contract Oneの実行基盤では、バッチ処理ごと・環境ごとに実行パラメータが違うCloud Run job YAMLファイルを定義しています。
Contract OneでのYAML管理の課題
事業のグロースとともにバッチ処理が増えていて、新しいバッチ処理を作る際には既存のCloud Run job YAMLファイルをコピペして作られることが多いです。しかし、どのパラメータがそのジョブ固有のものかすぐに判断できず、無駄なパラメータが指定されていることもあったため、Cloud Run job YAMLファイルの管理が課題となっていました。
そこで、KubernetesのManifest管理ツールであるKustomizeを導入し、課題解決に取り組みました。
Kustomizeの導入
次のようなディレクトリ構造で管理をしていきます。
. ├── base └── overlays ├── production │ ├── base │ ├── service-a │ └── service-b └── staging ├── base ├── service-a └── service-b
base
ディレクトリ
すべてのジョブの基本となるパラメータを定義していきます。
まずは、cloud-run-jobs.yaml
で、次のようにCloud Run job YAMLの雛形を定義します。
apiVersion: run.googleapis.com/v1 kind: Job metadata: name: batch-job spec: template: spec: parallelism: 1 # ジョブ毎にpatchする taskCount: 1 # ジョブ毎にpatchする template: spec: serviceAccountName: dummy # 環境毎にpatchする maxRetries: 0 # ジョブ毎にpatchする timeoutSeconds: "86400" # ジョブ毎にpatchする containers: - image: dummy # 環境毎にpatchする resources: limits: cpu: "2" # ジョブ毎にpatchする memory: 2Gi # ジョブ毎にpatchする env: [ ] # 環境、ジョブ毎にpatchする
次に、shared-env.yaml
で、全環境で共通の環境変数を定義します。
# key value のペアで環境変数を設定する - op: add path: /spec/template/spec/template/spec/containers/0/env/- value: name: SERVICE_NAME value: batch-job # Secret Managerからも値を取ってこれる - op: add path: /spec/template/spec/template/spec/containers/0/env/- value: name: SERVICE_KEY valueFrom: secretKeyRef: key: latest name: service-key
最後に、kustomization.yaml
で、これら2つのファイルを参照するベースファイルを定義します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - cloud-run-jobs.yaml # 雛形 patches: - path: shared-env.yaml # 環境変数のパッチ target: kind: Job name: batch-job
overlays/{環境名}/base
ディレクトリ
環境毎に固有の値をoverlays/{環境名}/base
の中で定義します。staging環境であればoverlays/staging/base
を、production環境であればoverlays/production/base
を作成します。
まず、patch.yaml
でサービスアカウントとコンテナイメージ名を置き換えます。
- op: replace path: /spec/template/spec/template/spec/containers/0/image value: us-docker.pkg.dev/cloudrun/container/job:latest - op: replace path: /spec/template/spec/template/spec/serviceAccountName value: サービスアカウント名
次に、kustomization.yaml
で、nameにsuffixをつけたり、上で行った置き換えを適用させるベースファイルを定義します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization nameSuffix: -prod resources: - ../../../base patches: - path: patch.yaml target: kind: Job name: batch-job
これで環境毎のベースファイルの定義は完了です。環境固有の環境変数がある場合は、shared-env.yaml
と同様にファイルを作成し、patchesに追加します。
overlays/{環境名}
ディレクトリ
overlays/{環境名}
ディレクトリの下に、各バッチ処理のパラメータを定義していきます。
今回は、環境変数とタスク数/並列数を変更したいservice-aと、環境変数のみを変更したいservice-bがあると仮定します。
このとき、service-aの定義は次のようになります。
# overlays/production/service-a/kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namePrefix: service-a- resources: - ../base patches: - path: patch.yaml target: kind: Job name: batch-job - path: env.yaml target: kind: Job name: batch-job # overlays/production/service-a/env.yaml - op: add path: /spec/template/spec/template/spec/containers/0/env/- value: name: JOB_NAME value: JOB_A # overlays/production/service-a/patch.yaml - op: replace path: /spec/template/spec/parallelism value: 2 - op: replace path: /spec/template/spec/taskCount value: 2
service-bの定義は次のようになります。
# overlays/production/service-b/kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namePrefix: service-b- resources: - ../base patches: - path: env.yaml target: kind: Job name: batch-job # overlays/production/service-b/env.yaml - op: add path: /spec/template/spec/template/spec/containers/0/env/- value: name: JOB_NAME value: JOB_B
最終的なファイル構造
上記の手順を環境毎に行うと、次のようなファイル構造になります。
. ├── base │ ├── cloud-run-jobs.yaml │ ├── kustomization.yaml │ └── shared-env.yaml └── overlays ├── production │ ├── base │ │ ├── kustomization.yaml │ │ ├── patch.yaml │ │ └── shared-env.yaml │ ├── service-a │ │ ├── env.yaml │ │ ├── kustomization.yaml │ │ └── patch.yaml │ └── service-b │ ├── env.yaml │ └── kustomization.yaml └── staging ├── base │ ├── kustomization.yaml │ ├── patch.yaml │ └── shared-env.yaml ├── service-a │ ├── env.yaml │ ├── kustomization.yaml │ └── patch.yaml └── service-b ├── env.yaml └── kustomization.yaml
レンダリング
kubectl kustomize ./overlays/{環境名}/{ジョブ名}
コマンドで、最終的なCloud Run job YAMLファイルをレンダリングします。
試しに、production環境のservice-aをレンダリングすると、次のようなYAMLが生成されます。parallelismやenvなどの値が置き換えられていることがわかります。
apiVersion: run.googleapis.com/v1 kind: Job metadata: name: service-a-batch-job-prod spec: template: spec: parallelism: 2 taskCount: 2 template: spec: containers: - env: - name: SERVICE_NAME value: batch-job - name: SERVICE_KEY valueFrom: secretKeyRef: key: latest name: service-key - name: JOB_NAME value: JOB_A image: us-docker.pkg.dev/cloudrun/container/job:latest resources: limits: cpu: "2" memory: 2Gi maxRetries: 0 serviceAccountName: サービスアカウント名 timeoutSeconds: "86400"
Contract Oneでは、レンダリングをCDパイプラインに組み込み、デプロイを自動化しています。
まとめ
Kustomizeを使用して、Cloud Run jobsのジョブ構成を管理する方法を紹介しました。すべての環境に共通なbase overlayを元に、環境ごとに差異がある部分のみのoverlayを作成することで、複数ジョブを複数環境でわかりやすく管理できるようになりました。
実は、Kustomizeの導入検討はオフィスのふらっとした立ち話から始まり、開発チームのフットワークの軽さを感じました。そんなContract Oneでは、プロダクトの価値向上に向き合っていく仲間を募集しています! 詳しくは採用情報をご確認ください。