Cloud Deploy で高度なデリバリーパイプラインを作りたい
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
下記のコマンドでデリバリーパイプラインを作成することができ、成功するとコンソール上から確認することができます。
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 によって行われます。
gcloud deploy releases create test-release-001 \
--project={project_id} \
--region=asia-northeast1 \
--delivery-pipeline=grafana-pipeline
こちらのコマンドを実行する際に権限周りでとてつもなくハマったので後述のハマったポイントにて紹介しています。
リリースの昇格
Dev 環境へのデプロイ後に動作確認等で OK であれば次のステージに昇格させることができます。同イベントで Cloud Deploy を利用されている方は、複数のコンポーネントとデプロイタイミングを合わせるために昇格機能を活用しているとのことでした。
gcloud deploy releases promote \
--project={project_id} \
--region=asia-northeast1 \
--delivery-pipeline=grafana-pipeline \
--release=test-release-001
便利な機能
カナリアリリース
特定の環境で複数バージョンにトラフィック分割するフェーズを実装することができます。clouddeploy.yaml
に strategy
項目を追加することで段階的なデプロイが可能となります。
下記のように 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
gcloud deploy apply \
--file=clouddeploy.yaml \
--region=asia-northeast1 \
--project={project_id}
デプロイ後の検証
デリバリーパイプラインにデプロイ後に動作検証を組み込むことができます。scaffold.yaml
に verify
項目を追加することで 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.***"]
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
参考
- GitHub Actions と Google Cloud Deploy が連携
- GitHub Actions を使用して Cloud Run にデプロイする
- Google Cloud Partner Tech Blog Challenge の 2023 年度受賞者発表
- Cloud Run のための実践 Cloud Deploy
- Cloud Deploy で始める継続的デリバリーの継続的改善
- Google Cloud Deploy にデプロイ後に検証を行う機能を導入
さいごに
Jagu'e'r クラウドネイティブ分科会では初めての登壇となり緊張もしましたが、他のイベントで登壇されている方と一緒にイベントに望めて楽しかったです。今回は CI/CD に関するものでしたが、サーバーレスなどにフォーカスした Meetup の際にはまた登壇できるように頑張りたいと思います。
また、こちらの記事では発表した内容の中でも Cloud Deploy の基本機能から便利機能まで改めて触ってみた内容をまとめてみました。
最初は Scaffold などの要素技術に面を食らってしまいましたが、調べていく中でだんだん Cloud Deploy の良さがわかってきました。
現在構築中の環境に Github Actions + Cloud Deploy という形で CI/CD を実装して、運用してみたいと思います。
Discussion