【GitHub Actions + OIDC】自作のコンテナイメージを Cloud Run にデプロイする
はじめに
個人開発のサービスを Cloud Run で運用しようと思ったので、練習がてら自作のコンテナイメージ(Fast API 公式のサンプル API)のビルドからプッシュ、Cloud Run へのデプロイまでを GitHub Actions で行ってみました。
コンテナイメージのプッシュ先は Artifact Registry です。
Google Cloud の各種リソースは Terraform を使用して作成しました。
Workload Identity について
GitHub Actions から Google Cloud への各種操作のために認証を行う必要があるのですが、今回は Workload Identity という機能を使用して行います。
Workload Identity とはサービスアカウントのキーを使用せずに Google Cloud と外部サービスの連携を行える機能です。
セキュリティ向上、キーの運用コスト軽減のために Google が推奨しているものです。
参照:キーなしの API 認証 - サービス アカウント キーを必要としない Workload Identity 連携によるクラウド セキュリティの向上
最近発生した CircleCI のインシデントでもセキュリティ対策のために使用が推奨されていました。
CI/CD と OpenID Connect については最近読んでわかりやすかった記事を貼っておきます。
CI/CDサービスのOpenID Connect対応 Dive Into
必要なもの
- Google Cloud アカウント
- Google Cloud コマンド
- Terraform コマンド
ディレクトリ構成
.
├── README.md
├── app
│ ├── Dockerfile
│ ├── main.py
│ ├── poetry.lock
│ └── pyproject.toml
├── docker-compose.yml
└── terraform
├── main.tf
├── outputs.tf
├── terraform.tfstate
├── terraform.tfstate.backup
└── variables.tf
手順
Doarakko/cloud-run-playground をフォーク
1.GitHub のリポジトリを作っていただければフォークしなくても大丈夫です。
2. Google Cloud のプロジェクトを作成
terraform/variables.tf
に入れる
3. GitHub のリポジトリ名と Google Cloud のプロジェクト ID を variable "project_id" {
default = "<Google Cloud project id>"
}
variable "repo_name" {
default = "<GitHub reposisotry name>"
}
terraform apply
実行のためにコマンドラインから Google Cloud にログイン
4. gcloud auth application-default login
terraform apply
してサービスアカウントと Workload Identity Provider の ID を取得
5. cd terraform
terraform apply
...
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
google_service_account = "<Google service account>"
google_workload_identity_provider = "<Google workload identity provider>"
.github/workflows/deploy.yml
に入れる
6. 5 で取得した ID を ...
- id: 'auth'
uses: 'google-github-actions/auth@v0'
with:
token_format: 'access_token'
workload_identity_provider: '<Google workload identity provider>'
service_account: '<Google service account>'
...
- name: Build and push
uses: docker/build-push-action@v3
with:
context: "{{defaultContext}}:app"
push: true
tags: asia-northeast1-docker.pkg.dev/<Google Cloud project id>/playground/fastapi:latest
- id: 'deploy'
uses: 'google-github-actions/deploy-cloudrun@v1'
with:
region: 'asia-northeast1'
service: 'cloudrun-srv'
image: 'asia-northeast1-docker.pkg.dev/<Google Cloud project id>/playground/fastapi'
7. コミットアンドプッシュ
8. 確認
補足
Terraform
GitHub Actions で使用する値を出力
terraform/outputs.tf
output "google_workload_identity_provider" {
value = google_iam_workload_identity_pool_provider.github-actions.name
}
output "google_service_account" {
value = google_service_account.github-actions.email
}
Cloud Run へのアクセス許可
resource "google_cloud_run_service_iam_binding" "default" {
location = google_cloud_run_service.default.location
service = google_cloud_run_service.default.name
role = "roles/run.invoker"
members = [
"allUsers"
]
}
GitHub Actions
サブディレクトリ内の Dockerfile でビルドする
context
フィールドでサブディレクトリを指定します。
- name: Build and push
uses: docker/build-push-action@v3
with:
context: "{{defaultContext}}:app"
push: true
tags: asia-northeast1-docker.pkg.dev/cloud-run-playground-373814/playground/fastapi:latest
参照:docker/build-push-action#git-context
特定ファイルの変更をトリガーにワークフローを実行
name: deploy
on:
push:
branches:
- main
paths:
- '.github/workflows/deploy.yml'
- 'app/*'
- 'terraform/*'
おわりに
ほぼ初めての Terraform でしたがとりあえずやりたいことはできました。
書いているときはしんどいですが、新しい環境を作るときにポチッとでできるのは最高ですね。
お作法などいろいろわかっていないところがあるので引き続きやっていく所存です。
Discussion