⚒️

Cloud Deploy で高度なデリバリーパイプラインを作りたい

2024/03/18に公開

2024 年 3 月 15 日に行われた Jagu'e'r Cloud Native #13 ハイブリッド Meetup - 俺の考える最強の CI/CD -に登壇させていただきました。

CI/CD を検討する流れで Cloud Deploy に注目して、基本機能から便利な機能まで紹介しています。Cloud Deploy ってサービスを知っているけど、概要を掴みきれていないという方はぜひお読みください!

Overview

デリバリーパイプラインを管理・実行する上で豊富な機能を提供

  • 何をどこの環境にどの順番でデプロイするかをあらかじめ設計したデリバリーパイプラインで管理・自動化してくれる
  • デプロイ戦略やデプロイ後の検証もデリバリーパイプラインに組み込める
  • 継続的デリバリーそのものの改善に必要な指標を可視化できる

所感

改めて触ってみると多くの機能が GA となっていて、知れば知るほど魅力を感じました。発表のストーリーでは、オーバースペック気味な点から CD はシンプルな技術選択をしましたが、実運用から見えてくることもあると考え PoC 的に採用しようと思います。

特にカナリアリリース後の新バージョンへの 100% ロールアウト/旧バージョンへのロールバックをデリバリーパイプラインに組み込めるので安全かつ容易にデプロイできる点が良いなと感じました。

また、Cloud Deploy の大きな要素である Scaffold についても興味が湧いてきているので Cloud Deploy から入って Scaffold にも今後深掘りしていきたいと思います。

キーワード

背景

本業のアプリケーションエンジニアとしてタスクをこなしている側で、SRE 領域にも興味がありオブザーバビリティに挑戦しているというところから話を始めました。

構築途中ではあるものの、Cloud Run や Cloud Operations を中心にアーキテクチャを考え Cloud Run の痒いところに手が届くような機能群に感謝しながら構築しています。

この図には CI/CD 部分が載っていない、、というより仕組みを導入していないのです。隙間時間というのもあり構築のメインは私自身がやっており、コマンド実行やコンソール操作による手動でやってしまっています。この点を今回機会をいただいたので検討してみたというのが本発表の背景となります。

Cloud Deploy と仲良くなりたい

今回の発表はこちらの記事Google Cloud Partner Tech Blog Challenge の 2023 年度受賞者発表でピックアップされたことからお声がけいただきました。そういったところから、改めて Github Actions + Cloud Deploy で CI/CD を構築を検討したことを主題としています。本記事では Cloud Deploy にフォーカスしています。

Cloud Deploy の基本を改めて

公開情報から Cloud Deploy の特性についてキャッチーなフレーズを集めてみたのがこちら。

初見ではピンとこない、、というのがの本音であるためばくっとした全体像を用意しました。また、全体像に合わせて各種サンプルも用意しました。ディレクトリ構造は下記です。以降、clouddeploy-sample 配下で実施している想定です。

clouddeploy-sample
|- scaffold.yaml
|- dev-manifest.yaml
|- stg-maniest.yaml
|- prod-manifest.yaml
|- clouddeploy.yaml

デリバリーパイプライン

一連のパイプラインを Cloud Deploy ではデリバリーパイプラインと呼び、「Create Release」「Promote to Stg/Prod」 などの利用者が行うアクション(CLI やコンソール操作から可能)を通してリリースコンテンツ各ターゲット環境にデプロイしていくというものでした。

デリバリーパイプラインの構成ファイルにはターゲット構成を含める場合と含めない場合があり、含める場合は clouddeploy.yaml、含めない場合は delivery-pipeline.yaml と呼ばれるようです。

clouddeploy.yaml
apiVersion: deploy.cloud.google.com/v1
kind: DeliveryPipeline
metadata:
  name: grafana-pipeline
serialPipeline:
  stages:
  - targetId: run-dev
    profiles: [dev]
  - targetId: run-stg
    profiles: [stg]
  - targetId: run-prod
    profiles: [prod]
---

apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: run-dev
run:
  location: projects/{project_id}/locations/asia-northeast1
---

apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: run-stg
run:
  location: projects/{project_id}/locations/asia-northeast1
---

apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: run-prod
run:
  location: projects/{project_id}/locations/asia-northeast1

下記のコマンドでデリバリーパイプラインを作成することができ、成功するとコンソール上から確認することができます。

Terminal
gcloud deploy apply \
  --file=clouddeploy.yaml \
  --region=asia-northeast1 \
  --project={project_id}

リリースコンテンツ

パイプラインに流すコンテンツには Scaffold に用いられる scaffold.yaml と必要に応じて各ターゲット環境の manifest.yaml があります。Scaffold とは何か? や Cloud Deploy に使われる理由についてはこちらの公式ドキュメントで紹介されています。

今回、scaffold.yaml では各ターゲット環境に対応した manifest.yaml を用意しています。また、ポイントとして deploy 項目で cloudrun:{} を指定することで Cloud Run Service へのデプロイが可能となります。

scaffold.yaml
apiVersion: skaffold/v4beta7
kind: Config
metadata:
  name: grafana-pipeline
profiles:
- name: dev
  manifests:
    rawYaml:
    - dev-manifest.yaml
- name: stg
  manifests:
    rawYaml:
    - stg-manifest.yaml
- name: prod
  manifests:
    rawYaml:
    - prod-manifest.yaml
deploy:
  cloudrun: {}

dev-manifest.yaml として下記を用意しました。こちらは Cloud Run service YAMLに沿ったものとなっていて、新規で作成するのであればこれくらいシンプルで良さそうです。既存の Cloud Run Service のものが必要であれば Cloud Run Service のコンソールから YAML を取得することが可能です。(YAML を取得した場合は、余分な項目も多いので上記 URL の YAML と見比べる必要がありました。)

dev-manifest.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: grafana-test
spec:
  template:
    spec:
      containers:
      - name: test-1
        image: grafana/grafana-enterprise
        ports:
        - name: http1
          containerPort: 3000

リリースの作成

各種ファイルが用意できたら下記のコマンドでリリースコンテンツを作成します。コマンドが実行されるとカレントディレクトリ配下のファイル群が圧縮されて Cloud Storage に格納されます。また、Cloud Deploy でバージョン管理されたのちに、実際のデプロイ作業は Cloud Build によって行われます。

Terminal
gcloud deploy releases create test-release-001 \
  --project={project_id} \
  --region=asia-northeast1 \ 
  --delivery-pipeline=grafana-pipeline

こちらのコマンドを実行する際に権限周りでとてつもなくハマったので後述のハマったポイントにて紹介しています。

リリースの昇格

Dev 環境へのデプロイ後に動作確認等で OK であれば次のステージに昇格させることができます。同イベントで Cloud Deploy を利用されている方は、複数のコンポーネントとデプロイタイミングを合わせるために昇格機能を活用しているとのことでした。

Terminal
gcloud deploy releases promote \
  --project={project_id} \
  --region=asia-northeast1 \
  --delivery-pipeline=grafana-pipeline \
  --release=test-release-001

便利な機能

カナリアリリース

特定の環境で複数バージョンにトラフィック分割するフェーズを実装することができます。clouddeploy.yamlstrategy 項目を追加することで段階的なデプロイが可能となります。

下記のように parcentages で 25, 50, 75 のいずれかを指定する(複数指定することも可能)で最初から 100% のロールアウトにならず指定した値でのトラフィック分割がされます。

注意点としては、manifest.yaml で最新のリビジョンへの 100% トラフィックの設定をしないことです。

clouddeploy.yaml
apiVersion: deploy.cloud.google.com/v1
kind: DeliveryPipeline
metadata:
  name: grafana-pipeline
serialPipeline:
  stages:
  - targetId: run-dev
    profiles: [dev]
  - targetId: run-stg
    profiles: [stg]
    strategy:
      canary:
        runtimeConfig:
          cloudRun:
            automaticTrafficControl: true
        canaryDeployment:
          percentages: [50]
          verify: false
---

apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: run-dev
run:
  location: projects/{project_id}/locations/asia-northeast1
---

apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: run-stg
run:
  location: projects/{project_id}/locations/asia-northeast1

Terminal
gcloud deploy apply \
  --file=clouddeploy.yaml \
  --region=asia-northeast1 \
  --project={project_id}

デプロイ後の検証

デリバリーパイプラインにデプロイ後に動作検証を組み込むことができます。scaffold.yamlverify 項目を追加することで Cloud Build がデプロイステップ後に検証ステップを実行してくれます。

ここでは、デプロイ後のエンドポイントに wget でアクセスできるかを確認する検証としています。

scaffold.yaml
apiVersion: skaffold/v4beta7
kind: Config
metadata:
  name: grafana-pipeline
profiles:
- name: dev
  manifests:
    rawYaml:
    - run-dev.yml
- name: stg
  manifests:
    rawYaml:
    - run-stg.yml
deploy:
  cloudrun: {}
verify:
- name: after-deploy-verification
  container:
    name: after-deploy-container
    image: alpine:3.16
    command: ["/bin/sh"]
    args: ["-c", "wget https://grafana-test.***"]
Terminal
gcloud deploy releases create test-release-002 \
  --project={project_id} \ 
  --region=asia-northeast1 \ 
  --delivery-pipeline=grafana-pipeline 

ハマったポイント

Cloud Deploy のデプロイ作業は Cloud Build が担っています。今回でいうと Cloud Run Service にデプロイするのに各種サービスへのアクセス権が必要となります。

当初は Cloud Build のサービスアカウントに権限付与していたのですが上手くいかず、失敗したビルドログの Cloud Build の実行詳細を確認したところ Compute Engine のデフォルトサービスアカウントで実行されていることがわかりました。

このサービスアカウントに各種権限を付与すれば動くのですが、デフォルトサービスアカウントへの権限付与は思わぬ事故を招くので Cloud Deploy でのデプロイ対応専用のサービスアカウントを作成して権限付与する形が良いと思います。

専用のサービスアカウントを指定するのが cloudeploy.yaml での executeConfig 項目になります。

clouddeploy.yaml
apiVersion: deploy.cloud.google.com/v1
kind: DeliveryPipeline
metadata:
  name: grafana-pipeline
serialPipeline:
  stages:
  - targetId: run-dev
    profiles: [dev]
  - targetId: run-stg
    profiles: [stg]
  - targetId: run-prod
    profiles: [prod]
---

apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: run-dev
run:
  location: projects/{project_id}/locations/asia-northeast1
executionConfigs:
- usages:
  - DEPLOY
  - RENDER
  - VERIFY
  serviceAccount: operation@{project_id}.iam.gserviceaccount.com
---

apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: run-stg
run:
  location: projects/{project_id}/locations/asia-northeast1
executionConfigs:
- usages:
  - DEPLOY
  - RENDER
  - VERIFY
  serviceAccount: operation@{project_id}.iam.gserviceaccount.com
---
apiVersion: deploy.cloud.google.com/v1
kind: Target
metadata:
  name: run-prod
run:
  location: projects/{project_id}/locations/asia-northeast1
executionConfigs:
- usages:
  - DEPLOY
  - RENDER
  - VERIFY
  serviceAccount: operation@{project_id}.iam.gserviceaccount.com

参考

さいごに

Jagu'e'r クラウドネイティブ分科会では初めての登壇となり緊張もしましたが、他のイベントで登壇されている方と一緒にイベントに望めて楽しかったです。今回は CI/CD に関するものでしたが、サーバーレスなどにフォーカスした Meetup の際にはまた登壇できるように頑張りたいと思います。

また、こちらの記事では発表した内容の中でも Cloud Deploy の基本機能から便利機能まで改めて触ってみた内容をまとめてみました。

最初は Scaffold などの要素技術に面を食らってしまいましたが、調べていく中でだんだん Cloud Deploy の良さがわかってきました。

現在構築中の環境に Github Actions + Cloud Deploy という形で CI/CD を実装して、運用してみたいと思います。

https://twitter.com/pHaya72

Discussion