🧑‍🎓

Google Cloud 入門:Cloud Deploy ハンズオン

2024/11/13に公開

概要

初めて Cloud Deploy を使う方向けに、Cloud Deploy の概念と使い方をまとめた。使い方では、Cloud Run サービスのデプロイに焦点をあて、以下の機能について説明した。

  • Cloud Run サービスのデプロイ、ロールバック
  • リリースの破棄
  • カナリアリリース

Cloud Deploy とは

デリバリーパイプラインとデプロイターゲットを定義し、アプリケーションの配信を自動化するマネージドサービス。
デリバリーパイプラインによってリリースのライフサイクルを管理し、リリースを作成することで更新したアプリケーションをデプロイする。
Cloud Deployを使うことで様々なデプロイ手法を扱い易くできる。

  • デリバリーパイプライン:各ターゲットにアプリケーションを配信するワークフロー。上図では配信順序が dev→stg→prod となる。
  • ターゲット:アプリケーションをデプロイする特定のランタイム環境。Cloud Run 環境などがある。
  • リリース:デプロイされる内容。Cloud Run YAMLファイルなど。

Cloud Deploy の用語

Cloud Run サービスをデプロイする

Cloud Deploy を使って Cloud Run サービスにデプロイするための流れを記載する(参考:Cloud Deploy を使用してアプリを Cloud Run にデプロイする)。
構築するデリバリーパイプラインとターゲットは、prod環境のみの構成とする。

用意するファイルは次のとおり。

.
├── clouddeploy.yaml
├── run-service-prod.yaml
└── skaffold.yaml

デリバリーパイプライン・デプロイターゲットの作成

デリバリーパイプラインとデプロイターゲットの定義を clouddeploy.yaml に記載する。

clouddeploy.yaml
apiVersion: deploy.cloud.google.com/v1
kind: DeliveryPipeline
metadata:
  # デリバリーパイプラインの名前
  name: sample-delivery-pipeline
description: main application pipeline
serialPipeline:
  stages:
    - targetId: sample-target
      profiles: [prod]
---

apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  # ターゲットの名前
  name: sample-target
description: Cloud Run production service
run:
  location: projects/sample-project/locations/asia-northeast1

デリバリーパイプライン名を sample-delivery-pipeline、ターゲット名を sample-targetとしている。
gcloud deploy apply コマンドを実行すると、定義したデリバリーパイプラインとターゲットが作成される。

gcloud deploy apply --file=clouddeploy.yaml \
  --region=asia-northeast1 \
  --project=sample-project

Terraform を使う場合

Terraform を使ってデリバリーパイプラインとターゲットを作成する場合、google_clouddeploy_delivery_pipeline でデリバリーパイプラインを定義し、google_clouddeploy_target でターゲットを定義する。

deploy.tf
resource "google_clouddeploy_delivery_pipeline" "default" {
  location    = "asia-northeast1"
  name        = "sample-delivery-pipeline"
  description = "main application pipeline"
  serial_pipeline {
    stages {
      profiles  = ["prod"]
      target_id = google_clouddeploy_target.default.target_id
    }
  }
}

resource "google_clouddeploy_target" "default" {
  location          = "asia-northeast1"
  name              = "sample-target"
  description       = "Cloud Run production service"
  execution_configs {
    # デプロイアーティファクトを格納するGCSバケット(デフォルトのパス)
    artifact_storage  = "gs://asia-northeast1.deploy-artifacts.sample-project.appspot.com"
    execution_timeout = "3600s"
    # デプロイを実行するサービスアカウント(デフォルトのサービスアカウント)
    service_account   = "sample-project-id-compute@developer.gserviceaccount.com"
    usages            = ["RENDER", "DEPLOY"]
  }
  run {
    location = "projects/sample-project/locations/asia-northeast1"
  }
}

リリースの作成

run-service-prod.yaml に Cloud Run の構成を定義する。
これは YAML を使って Cloud Run をデプロイする時に使うものと同じもの。

run-service-prod.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: run-service-prod
spec:
  template:
    spec:
      containers:
        # my-app-imageは変数。リリース作成コマンド実行時に値を渡して解決する。
        - image: my-app-image

次に、skaffold.yamlを作成する。
Cloud Deployは skaffold を使ってターゲットにデプロイするため、基本的にはこのファイルが必要になる。必要な記述はヘッダー、使用するマニフェストファイル(Cloud Runサービス定義YAMLのファイル名)、ターゲット環境である(参考:Cloud Deploy を機能させるには何が必要ですか?)。

skaffold.yaml
apiVersion: skaffold/v4beta11
kind: Config
metadata:
  name: deploy-run-quickstart
profiles:
  - name: prod
    manifests:
      rawYaml:
        - run-service-prod.yaml
deploy:
  cloudrun: {}

apiVersionskaffold のレファレンスに記載されている Schema Versions の中から、使用するバージョンを選択する。
profiles.nameには、clouddeploy.yamlのprofilesで指定した名前であるprodを指定することで、sample-targetrun-service-prod.yaml を適用している。

ここまででリリースを作成する準備が整った。
リリースを作成するには、gcloud deploy releases create コマンドを実行する。

gcloud deploy releases create sample-release-001 \
      --delivery-pipeline=sample-delivery-pipeline \
      --skaffold-file=skaffold.yaml \
      --images my-app-image=gcr.io/cloudrun/hello:latest \
      --project=sample-project \
      --region=asia-northeast1 

--delivery-pipelineに先ほど作成したデリバリーパイプライン名を指定する。
--imagesmy-app-image変数の値として gcr.io/cloudrun/hello:latest を指定しており、これは Cloud Run URLにアクセスした時にリビジョン名などを表示してくれるチュートリアル用のイメージ、

コマンド実行後しばらくすると、Cloud Run サービスとリリースが作成される。

作成されたCloud Run サービスのURLを叩くと以下のような楽しげな画面が表示され、動作していることが確認できる。

リリースの名称を変えて、再度リリース作成コマンドを実行する。

gcloud deploy releases create sample-release-002 \
      --delivery-pipeline=sample-delivery-pipeline \
      --skaffold-file=skaffold.yaml \
      --images my-app-image=gcr.io/cloudrun/hello:latest \
      --project=sample-project \
      --region=asia-northeast1

実行すると、2個目のリリースと Cloud Runの新しいリビジョンが作成される。

Cloud RunのURLを叩くと、新しいリビジョンで動作していることが確認できる。

ロールバックする

リリースしたものに不具合が発覚した場合、前回の安定版に即座に戻すためにロールバックを行う。
gcloud deploy targets rollback コマンドを実行すると、前回のリリースをターゲットに反映することができる(参考:ターゲットのロールバック)。

gcloud deploy targets rollback sample-target \
      --delivery-pipeline=sample-delivery-pipeline \
      --region=asia-northeast1 \
      --project=sample-project

実行すると、Cloud Run サービスの前回リビジョンにトラフィックが向けられており、Cloud Run URL にアクセスすると前回リビジョンが表示される。

ちなみに --release でリリースを特定すると、前回よりも前のリリースにロールバックすることができる。

gcloud deploy targets rollback sample-target \
      --delivery-pipeline=sample-delivery-pipeline \
      --release=old-release \
      --region=asia-northeast1 \
      --project=sample-project

リリースを破棄する

一度作成したリリースは破棄することができる。リリースを破棄したいケースには次のようなものがある。

  • リリースにバグがある
  • リリースにセキュリティの問題がある
  • リリースに含まれている機能が非推奨になった

リリースを破棄すると、そのリリースにはロールバックされないようにできる。

例えば、次のようにリリースが4つ作成されており、現在の状態が sample-release-004 で、sample-release-003 に問題が見つかったためこのリリースを破棄したいとする。

リリースを破棄するには、gcloud deploy releases abandon を実行する(参考:リリースを破棄する)。

gcloud deploy releases abandon sample-release-003 \
       --delivery-pipeline=sample-delivery-pipeline \
       --region=asia-northeast1

実行すると、sample-release-003が放棄された。

この状態でsample-release-003にロールバックしようとしても、破棄されているためロールバックできなくなっている。

gcloud deploy targets rollback sample-target \
      --delivery-pipeline=sample-delivery-pipeline \
      --release=sample-release-003 \
      --region=asia-northeast1 \
      --project=sample-project
ERROR: (gcloud.deploy.targets.rollback) Cannot perform rollback. Release projects/sample-project/locations/asia-northeast1/deliveryPipelines/sample-delivery-pipeline/releases/sample-release-003 is abandoned.

カナリアリリースする

カナリアリリースとは、すでにデプロイされているバージョンと新しいバージョンの間でトラフィックを分割するアプリケーションの段階的なロールアウトのこと。
これにより、アプリケーションの新しいバージョンをすべてのユーザーに配布する前に、そのバージョンの信頼性を確認できる。

Cloud Deploy を使ったカナリアリリースのやり方を下記に記載する。

デリバリーパイプライン・デプロイターゲットの作成

標準デプロイの時に使った clouddeploy.yaml のパイプラインステージの strategy プロパティを次のように変更する(参考:カナリアデプロイを構成する)。

clouddeploy.yaml
serialPipeline:
  stages:
    - targetId: sample-target
      profiles: [prod]
      strategy:
        canary:
          runtimeConfig:
            cloudRun:
              automaticTrafficControl: true
          canaryDeployment:
            # カナリアの増分を表すパーセント値のカンマ区切りのリスト
            percentages: [25, 50, 75]
            verify: false

ここでは新バージョンへ流すトラフィック割合を、25% → 50% → 75% → 100% の順に増やしている(percentages に100を含めない)。

gcloud deploy applyコマンドを実行して、カナリア構成をデリバリーパイプラインに反映する。

gcloud deploy apply --file=clouddeploy.yaml \
      --project=sample-project \
      --region=asia-northeast1

リリースの作成

標準デプロイの時に使った skaffold.yaml と Cloud Run YAML をそのまま使用できる。
(Cloud Run YAML はtraffic スタンザが使えないこと以外は通常の Cloud Run サービス定義ファイルと同じ)

gcloud deploy releases create コマンドを実行してリリースを作成する。

gcloud deploy releases create sample-release-005 \
      --delivery-pipeline=sample-delivery-pipeline \
      --skaffold-file=skaffold.yaml \
      --images my-app-image=gcr.io/cloudrun/hello:latest \
      --project=sample-project \
      --region=asia-northeast1

コンソール画面でリリースの詳細を見ると、現在のロールアウトフェーズが canary-25 になっており、後続にcanary-50, canary-75, stableが控えていることが分かる。stableはトラフィック割合が100%を指す。

Cloud Runのリビジョンを確認すると、新バージョンのトラフィックは25%、前回バージョンは75%になっており、バージョン間でトラフィック分割されていることが分かる。
実際にCloud RunのURLに何度かアクセスすると、どちらかのバージョンが表示される動きになっている。

カナリアフェーズを進める

gcloud deploy rollouts advance コマンドでカナリアフェーズを進めることができる。
コマンド引数にロールアウト名を指定する。

gcloud deploy rollouts advance canary-release-001-to-sample-target-0001 \
      --release=canary-release-001 \
      --delivery-pipeline=sample-delivery-pipeline \
      --region=asia-northeast1

実行するとロールアウトが canary-50 フェーズになり、トラフィック割合は前回リリースが50%、今回リリースが50%となる。
もう一度上記コマンドを実行すると canary-75フェーズになり、さらに実行すると stableフェーズとなり最新のリビジョンにだけトラフィックが流れる。

オートカナリアリリースする

先ほどは手動でカナリアフェーズを進めたが、今度は時間経過とともにロールアウトが自動で進行するように設定する。
設定方法はドキュメント「Cloud Deploy でのリリースプロモーションとロールアウト進行の自動化」を参考にした。

Automation リソース

ロールアウトの自動化を行うには Cloud Deploy の Automation リソースを作成する必要があり、これは clouddeploy.yaml に次のような形式で定義する。

apiVersion: deploy.cloud.google.com/v1
kind: Automation
metadata:
  name: [PIPELINE_NAME]/[PURPOSE]
  labels:
  annotations:
description: [DESCRIPTION]
suspended: true | false
serviceAccount: [SERVICE_ACCOUNT_ID]
selector:
- target:
    id: [TARGET_ID]
rules:
- [RULE_TYPE]:
    name:[RULE_NAME]
  [RULE-SPECIFIC_CONFIG]
  • PIPELINE_NAME:自動化を使用するデリバリー パイプラインの名前。Automation は特定の1つのデリバリーパイプラインに属する形で作成される。
  • PURPOSE:Automation を表す任意の名前。
  • DESCRIPTION:Automation の説明。
  • SERVICE_ACCOUNT_ID:Automation の実行に使用されるサービスアカウント。ロールアウトフェーズを進めるための権限が必要。
  • TARGET_ID:Automation が使用されるターゲットID 。
  • RULE_TYPE:Automation で使用される自動化ルールの名前で、promoteReleaseRule または advanceRolloutRuleを設定する。今回はロールアウトの自動化なのでadvanceRolloutとなる。
  • [RULE-SPECIFIC_CONFIG]:構成はRULE_TYPEによって変わるが、advanceRolloutの場合は idsourcePhasewaitを指定する(参考:advanceRollout 自動化ルールを構成する)。
    • id:ルールに付ける名前。
    • sourcePhase:ロールアウトを自動的に進行させる起点となるフェーズ。指定されたいずれかのフェーズが正常に終了すると、そのフェーズから次のフェーズに自動的にロールアウトが進行する。この項目はオプションであり、省略するとロールアウトのすべてのフェーズが自動的に進行する。
    • wait:ロールアウトの準備が整った後、ロールアウトを進めるのを待機する時間(分単位)。

形式の詳細については「構成スキーマリファレンス:自動化の定義」を参考。

デリバリーパイプラインに Automation リソース定義を追加する

上記Automationリソースの説明を踏まえ、「カナリアリリースする」で作成した clouddeploy.yaml に次のような Automation 定義を追記する。

apiVersion: deploy.cloud.google.com/v1
kind: DeliveryPipeline
metadata:
  # デリバリーパイプラインの名前
  name: sample-delivery-pipeline
description: サンプル用のデリバリーパイプライン
serialPipeline:
  stages:
    - targetId: sample-target
      profiles: [prod]
      strategy:
        canary:
          runtimeConfig:
            cloudRun:
              automaticTrafficControl: true
          canaryDeployment:
            # カナリアの増分を表すパーセント値のカンマ区切りのリスト
            percentages: [25, 50, 75]
            verify: false
---

apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  # ターゲットの名前
  name: sample-target
description: Cloud Run production service
run:
  location: projects/sample-project/locations/asia-northeast1

++ ---
++
++ apiVersion: deploy.cloud.google.com/v1
++ kind: Automation
++ metadata:
++   name: sample-delivery-pipeline/auto-canary
++ description: カナリアリリースを自動進行させる
++ suspended: false
++ # ロールアウトフェーズを進行するサービスアカウント
++ serviceAccount: sample-sa@sample-project.iam.gserviceaccount.com
++ selector:
++   - target:
++       id: sample-target
++ rules:
++   - advanceRolloutRule:
++       name: "advance-rollout"
++       wait: 1m

ターゲット sample-target に対して Automation を定義し、advanceRolloutRule によってロールアウトが自動化されるようにしている。
また、sourcePhaseを指定しないことで全てのフェーズが自動的に進行されるように設定した。

gcloud deploy apply コマンドで、先ほど記載した Automation 定義を反映する。

gcloud deploy apply --file=clouddeploy.yaml \
      --project=sample-project \
      --region=asia-northeast1

実行すると、デリバリーパイプラインの「自動」タブに auto-canary が作成された。

リリースを作成する

標準デプロイと同じ skaffold.yaml と Cloud Run YAML を使用し、リリースコマンドを実行する。

gcloud deploy releases create auto-canary-001 \
      --delivery-pipeline=sample-delivery-pipeline \
      --skaffold-file=skaffold.yaml \
      --images my-app-image=gcr.io/cloudrun/hello:latest \
      --project=sample-project \
      --region=asia-northeast1

実行すると、まず canary-25 フェーズになる。

1分経過すると、自動で canary-50 フェーズに進行する。

次の1分後には canary-75 になり、さらに 1分後にstableへとロールアウトが進んだ後にリリースが完了する。

所感

Cloud Deploy を使うと様々なデプロイ手法を簡単に扱えて、マネージドサービスなので自前でリリース基盤を構築・管理する必要が無いのが魅力。
機能も日々進化しているため、自分たちのサービスのリリース基盤に合うかどうか検討する価値はあると感じた。

Discussion