💭

GitHub Actions で Cloud Deploy 経由で Cloud Run をカナリアデプロイする

2024/01/09に公開

目標

GitHub Actions で Cloud Deploy 経由で Cloud Run をカナリアデプロイするための設定をまとめる。

今回の成果物は以下のレポジトリに格納されています。
https://github.com/tetsuya28/samples/tree/main/.github/workflows
https://github.com/tetsuya28/samples/tree/main/gcp/cloud-run

Cloud Deploy

Cloud Run のマニフェストを作成する

今回は Nginx をデプロイするだけのシンプルなマニフェストを利用します。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: sample
  labels:
    cloud.googleapis.com/location: asia-northeast1
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/maxScale: '1'
        run.googleapis.com/startup-cpu-boost: 'true'
    spec:
      containerConcurrency: 80
      containers:
      - name: nginx
        image: nginx
        ports:
        - name: http1
          containerPort: 80
        resources:
          limits:
            cpu: 1000m
            memory: 512Mi
        startupProbe:
          timeoutSeconds: 240
          periodSeconds: 240
          failureThreshold: 1
          tcpSocket:
            port: 80

Scaffold を定義する

全体

scaffold.yaml
apiVersion: skaffold/v4beta7
kind: Config
metadata:
  name: sample
deploy:
  cloudrun: {}
profiles:
  - name: dev
    manifests:
      rawYaml:
        - service.yaml

詳細

Cloud Run のマニフェストとして利用するため以下の設定を追加します。

deploy:
  cloudrun: {}

今回は環境は 1 つのみなので dev という profile を作成しています。
dev profile には対象の Cloud Run のマニフェストをレンダリングするように指定しています。

Cloud Deploy のパイプラインを定義する

全体

cloud-deploy.yaml
apiVersion: deploy.cloud.google.com/v1
kind: DeliveryPipeline
metadata:
  name: cloud-run-cloud-deploy
description: Cloud Run with Cloud Deploy
serialPipeline:
  stages:
    - targetId: sample
      profiles: [dev]
      strategy:
        canary:
          runtimeConfig:
            cloudRun:
              automaticTrafficControl: true
          canaryDeployment:
            percentages: [5, 90]
            verify: false
---
apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: sample
run:
  location: projects/tetsuya28-playground/locations/asia-northeast1
requireApproval: true # デプロイの承認を必要とする

詳細

Scaffold で作成した dev profile を利用するステージを作成します。
このステージでは Cloud Run のリビジョンの更新にカナリアリリースを行うための設定を追加しています。
以下の設定では 5% → 90% → 100% の順番で新しいリビジョンに自動的にトラフィックが移っていきます。

serialPipeline:
  stages:
    - targetId: sample
      profiles: [dev]
      strategy:
        canary:
          runtimeConfig:
            cloudRun:
              automaticTrafficControl: true
          canaryDeployment:
            percentages: [5, 90]
            verify: false

Cloud Run のデプロイ先を tetsuya28-playground プロジェクトの asia-northeast1 ( 東京 ) リージョンに指定します。

apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: sample
run:
  location: projects/tetsuya28-playground/locations/asia-northeast1

また、パイプラインの最初に承認を要求するために以下の設定を追加しています。

requireApproval: true # デプロイの承認を必要とする

GitHub Actions

ここまでの設定で Cloud Deploy の設定は完了したのでこれらを GitHub Actions で実行するための構成について整理します。

Pipeline

Cloud Deploy の pipeline 自体を変更した場合に GitHub Actions で pipeline を更新します。
GitHub Actions から Google Cloud への認証は既に完了していることを前提としています。
OIDC を利用した認証の仕組みは Google Cloud 公式でも紹介されています。
https://cloud.google.com/blog/ja/products/identity-security/enabling-keyless-authentication-from-github-actions

- uses: google-github-actions/setup-gcloud@v2
- run: |
    gcloud deploy apply --file gcp/cloud-run/cloud-deploy.yaml --region asia-northeast1

Pipeline の更新はそのまま gcloud コマンドを利用しています。

Deploy

設定した pipeline に対してリリースを行う際は Google Cloud が公式で提供している action を利用します。
https://github.com/google-github-actions/create-cloud-deploy-release

リリース名はユニークにする必要があり、 63 文字までしか利用できないため sha short を利用します。

- name: Set short git commit SHA
  run: |
    calculatedSha=$(git rev-parse --short ${{ github.sha }})
    echo "COMMIT_SHORT_SHA=$calculatedSha" >> $GITHUB_ENV

利用する pipeline の名前とリージョンと scaffold を指定します。
イメージの更新などもここで行う必要がありますが、今回は特に更新せずに nginx コンテナに nginx イメージを利用する設定を記載しています。

- uses: google-github-actions/create-cloud-deploy-release@v1
  with:
    name: ${{ inputs.called_by }}-${{ env.COMMIT_SHORT_SHA }}
    delivery_pipeline: cloud-run-cloud-deploy
    region: asia-northeast1
    skaffold_file: gcp/cloud-run/scaffold.yaml
    images: |
      nginx=nginx

この状態で GitHub Actions を実行すると Cloud Deploy 上でリリースが作成されます。

承認 を実行することで実際にリリースが始まります。
以下はカナリアリリースの最初の 5% が実行されている状態です。

実際に Cloud Run では最新のリビジョンに 5% だけトラフィックが流れていることを確認できます。

最後に

Cloud Run へのデプロイに Cloud Deploy を利用する方法について試してみましたが、比較的直感的に組むことができ、少人数からの開発でも重宝しそうなサービスでした。
また Cloud Deploy はデフォルトで Four Keys[1] のメトリクスなども可視化してくれるは嬉しいですね。

今後はカナリアデプロイをさらに発展させたプログレッシブデプロイも Cloud Deploy で組んで実際のサービスへの導入も進めていきたいと思います。

脚注
  1. https://cloud.google.com/blog/ja/products/gcp/using-the-four-keys-to-measure-your-devops-performance ↩︎

Discussion