🏃

【GitHub Actions + OIDC】自作のコンテナイメージを Cloud Run にデプロイする

2023/01/10に公開

はじめに

個人開発のサービスを 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. Doarakko/cloud-run-playground をフォーク

GitHub のリポジトリを作っていただければフォークしなくても大丈夫です。

2. Google Cloud のプロジェクトを作成

3. GitHub のリポジトリ名と Google Cloud のプロジェクト ID を terraform/variables.tf に入れる

variable "project_id" {
  default = "<Google Cloud project id>"
}

variable "repo_name" {
  default = "<GitHub reposisotry name>"
}

4. terraform apply 実行のためにコマンドラインから Google Cloud にログイン

gcloud auth application-default login

5. terraform apply してサービスアカウントと Workload Identity Provider の ID を取得

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>"

6. 5 で取得した ID を .github/workflows/deploy.yml に入れる

...
      - 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