Google Kubernetes Engine(GKE)クラスタのメンテナンス除外設定を定期更新するCronJobを作成してみた

 2025.02.15 XIMIX 山田

はじめに

今回の記事では、KubernetesのワークロードリソースであるCronJobを取り上げます。まず、公式ドキュメントを参考にCronJobの概要について説明します。その後、Google Cloud上でCronJobをデプロイする方法を解説します。
 
前回のブログ記事では、GKEクラスタの詳細設定の1つであるメンテナンス除外の設定をシェルスクリプトで実行する方法について解説しました。また、メンテナンス除外設定の自動更新を行う背景についても触れています。詳細が気になる方は、ぜひ前回の記事をご覧ください。
 

CronJobとは

CronJobは、Kubernetesのワークロードリソースの1つであり、定期的に実行したいジョブがある場合に使用されます。例えば、バックアップの実行やメール送信といった定期的、または頻繁に発生するタスクの解決に役立ちます。

ソースコード

本章では、実装に使用するyamlファイルの内容を解説します。
  • CronJob
  • Kubernetes Namespace、Kubernetes ServiceAccount

 CronJobのyamlファイル

apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjob-maintenance-ex
  namespace: ns-maintenance-ex
spec:
  schedule: "0 15 * * 0"
  jobTemplate:
    spec:
      backoffLimit: 0
      template:
        spec:
          serviceAccountName: sa-maintenance-ex
          containers:
          - name: c-maintenance-ex
            image: google/cloud-sdk:latest
            command:
            - "/bin/bash"
            - "-c"
            - |
              set -e;
              apt-get update;
              apt-get install -y jq;
              apt-get clean;
              CLUSTER_NAME='gke-pilot-versionup-dev-autopilot';
              ZONE='asia-northeast1';
              NEW_EXCLUSION_NAME="exclusion-$(date '+%Y%m%d')";
              PERIOD='20 days';
              gcloud container clusters update $CLUSTER_NAME --zone $ZONE --add-maintenance-exclusion-name $NEW_EXCLUSION_NAME --add-maintenance-exclusion-start $(date +"%Y-%m-%dT%H:%M:%S%z") --add-maintenance-exclusion-end $(date -d "$PERIOD" +"%Y-%m-%dT%H:%M:%S%z");
              echo 'New maintenance exclusion created successfully.';
              EXCLUSION_NAMES=$(gcloud container clusters describe $CLUSTER_NAME --zone $ZONE --format='json' | jq -r '.maintenancePolicy.window.maintenanceExclusions | keys[]');
              EXCLUSION_NAMES_ARRAY=($EXCLUSION_NAMES);
              if [ ${#EXCLUSION_NAMES_ARRAY[@]} -ge 2 ]; then
                for EXCLUSION_NAME in $EXCLUSION_NAMES; do
                  if [ $EXCLUSION_NAME != $NEW_EXCLUSION_NAME ]; then
                    echo 'Removing maintenance exclusion: $EXCLUSION_NAME';
                    gcloud container clusters update $CLUSTER_NAME --zone $ZONE --remove-maintenance-exclusion $EXCLUSION_NAME;
                  fi;
                done;
              fi
          restartPolicy: Never

Kubernetesリソースの指定

kind: CronJob

CronJobを指定しています。

メタデータ

metadata:
  name: cronjob-maintenance-ex
  namespace: ns-maintenance-ex

  • name:実装するCronJobの名前
  • namespace:実装するCronJobが所属するKubernetes Namespaceの名前

スケジュール設定

spec:
  schedule: "0 15 * * 0"

CronJobが実行されるスケジュールは、unix-cron 文字列形式で設定します。
今回の例では、毎週日曜日の15時(UTC)にCronJobが実行されるように設定されています。これは、日本時間(JST)で月曜日の0時に実行されることを意味します。

バックオフリミット設定

jobTemplate:
    spec:
      backoffLimit: 0

backoffLimitとは、Jobが失敗したときにJobの再実行を試みる回数を指定するパラメータです。再実行の待機時間は、指数関数的に増加する指数バックオフアルゴリズムに従います。デフォルト値は6ですが、今回はエラーを避けるために0に設定しています。

使用するKubernetes ServiceAccountの設定

template:
        spec:
          serviceAccountName: sa-maintenance-ex

ここで必要なのはKubernetes ServiceAccountの名前であり、Google Cloud ServiceAccountでないことに注意してください。

コンテナ設定

containers:
          - name: c-maintenance-ex
            image: google/cloud-sdk:latest

  • name:コンテナの名前
  • image:コンテナイメージ
コンテナイメージはJobに適したものを使用します。今回はgcloudコマンドを使用するため、Google Cloud SDKの公式コンテナイメージを使用しています。

ジョブ内容

command:
            - "/bin/bash"
            - "-c"
            - |
              set -e;
              apt-get update;
              apt-get install -y jq;
              apt-get clean;
            CLUSTER_NAME='test-gke-cluster';
              ZONE='asia-northeast1';
              NEW_EXCLUSION_NAME="exclusion-$(date '+%Y%m%d')";
              PERIOD='20 days';
              gcloud container clusters update $CLUSTER_NAME --zone $ZONE --add-maintenance-exclusion-name $NEW_EXCLUSION_NAME --add-maintenance-exclusion-start $(date +"%Y-%m-%dT%H:%M:%S%z") --add-maintenance-exclusion-end $(date -d "$PERIOD" +"%Y-%m-%dT%H:%M:%S%z");
              echo 'New maintenance exclusion created successfully.';
              EXCLUSION_NAMES=$(gcloud container clusters describe $CLUSTER_NAME --zone $ZONE --format='json' | jq -r '.maintenancePolicy.window.maintenanceExclusions | keys[]');
              EXCLUSION_NAMES_ARRAY=($EXCLUSION_NAMES);
              if [ ${#EXCLUSION_NAMES_ARRAY[@]} -ge 2 ]; then
                for EXCLUSION_NAME in $EXCLUSION_NAMES; do
                  if [ $EXCLUSION_NAME != $NEW_EXCLUSION_NAME ]; then
                    echo 'Removing maintenance exclusion: $EXCLUSION_NAME';
                    gcloud container clusters update $CLUSTER_NAME --zone $ZONE --remove-maintenance-exclusion $EXCLUSION_NAME;
                  fi;
                done;
              fi

詳しい解説は前回のブログ記事で行っています。
指定クラスタに新規のメンテナンス除外を設定したのちに、既存のメンテナンス除外設定を削除しています。
 

リスタートポリシー設定

restartPolicy: Never

ジョブが失敗したときに再起動しないように設定しています。
 

Kubernetes Namespace、Kubernetes ServiceAccountのyamlファイル

apiVersion: v1
kind: Namespace
metadata:
labels:
projectid: <プロジェクトID>
name: ns-maintenance-ex
---
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
iam.gke.io/gcp-service-account: <Google ServiceAccountのEメール>
labels:
projectid: <プロジェクトID>
name: sa-maintenance-ex
namespace: ns-maintenance-ex
CronJobを作成する際には、Kubernetes NamespaceとKubernetes ServiceAccountが必要です。これらは上から順番に実行され、Kubernetes Namespaceが作成された後にKubernetes ServiceAccountが作成されます。
Kubernetes ServiceAccountの設定では、アノテーションに対象のGoogle ServiceAccountを指定する必要があります。今回は、Compute Engineのデフォルトサービスアカウントを指定しました。
 

実装手順

本章では、CronJobをGKEクラスタに実装する手順を解説します。

Workload Identityの有効化

まず、GKEクラスタで実行されるCronJobなどのワークロードがGoogle Cloud APIsにアクセスできるようにする必要があります。そのために、Workload Identityを有効化する設定を行います。
 
$ gcloud container clusters update  <クラスタ名> \
--location=<クラスタのロケーション> \
--workload-pool=<PROJECT_ID>.svc.id.goog \
--project=<PROJECT_ID>

Kubectlの有効化

作ったyamlファイルを適用するためにKubectlコマンドを利用する必要があります。そのために、クラスタの認証情報を取得する必要があります。
 
$ gcloud container clusters get-credentials <クラスタ名> \
--location=<クラスタのロケーション> \
--project=$PROJECT

Kubernetes Namespace、Kubernetes ServiceAccountの作成

作成したyamlファイルを適用して、Kubernetes NamespaceとKubernetes ServiceAccountを作成します。yamlファイルを配置しているディレクトリで以下のコマンドを実行します(ファイルのパスを指定することも可能です)。
$ kubectl apply -f kns_ksa.yaml
出力例
namespace/ns-maintenance-ex created
serviceaccount/sa-maintenance-ex created
実際に作成できているかを確認するには、以下のコマンドを使用します。

$ kubectl get serviceaccounts -n ns-maintenance-ex

defaultとsa-maintenance-exが表示されていれば、成功です。

IAM許可ポリシーの作成

Kubernetes ServiceAccountにGoogle ServiceAccountの権限借用を許可するIAM許可ポリシーを作成します。任意のサービスアカウントにKubernetes ServiceAccountを紐づけします。

$ gcloud iam service-accounts add-iam-policy-binding <GSAのEメール> \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:<プロジェクトID>.svc.id.goog[ns-maintenance-ex/sa-maintenance-ex]" \
--project=<プロジェクトID>

CronJobの作成

作成したyamlファイルを適用してCronJobを作成します。Kubernetes NamespaceとKubernetes ServiceAccountを作成したときと同じ要領で進めます。

kubectl apply -f cronjob.yaml

出力例
cronjob.batch/cronjob-maintenance-ex created
実際に作成できているかを確認するために、以下のコマンドを使用します。
$ kubectl get cronjob -n ns-maintenance-ex
cronjob-maintenance-exが表示されていれば、成功です。

CronJobの実行

ここからはコンソール上で確認していきます。
ナビゲーションメニューから、Kubernetes Engine > ワークロード > cronjob-maintenance-exと画面遷移すれば、以下の画面にたどり着きます。
今すぐ実行をクリックすることでJobが実行されます。
また、ログを閲覧することでJobの実行状況が把握できます。特に、ジョブ実行時のエラーを確認するために役立ちます。
 

console_cronjob

実行結果

結果はコンソールのGKEクラスタ詳細画面から確認します。ナビゲーションメニューから、Kubernetes Engine > クラスタの画面に移動し、下にスクロールすると自動化という項目があります。実行した日付から20日間のメンテナンス除外が設定されていれば成功です。
このCronJobが正常に作動している限り、一週間毎に20日間のメンテナンス除外が設定され、既存の設定は削除されます。

after

まとめ 

CronJobは、Kubernetesのワークロードリソースの1つであり、定期的に実行したいジョブがある場合に使用されます。Kubernetesリソースの設定をyamlファイルで記述する方法について、CronJob、Kubernetes Namespace、Kubernetes ServiceAccountを具体例として紹介しました。また、GKEクラスタにCronJobを実装する過程について、準備段階も含めて詳細に解説しました。

参考


Google Cloud、Google Workspace に関するご相談はXIMIXへ!

Google Cloud、Google Workspaceに関する お問い合わせはこちら


Google Kubernetes Engine(GKE)クラスタのメンテナンス除外設定を定期更新するCronJobを作成してみた

BACK TO LIST