🛠️

Cloud Build の結果を Slack に通知する方法

2024/12/19に公開

クラウドエースの北野です。
Cloud Build の結果を Slack に通知する方法を紹介します。

概要

Cloud Build を以下のシステム構成で Slack に通知させます。
構成図

  • Pub/Sub に Cloud Build の結果の通知
  • Secret Manager、Cloud Storage に Slack の通知先情報と、通知するメッセージの内容の保存
  • Cloud Build Notifier を使い Slack に通知

はじめに

Cloud Build の承認機能の利便性や、Google Cloud に閉じたシステムで CI/CD パイプラインを構築できる点から、Cloud Build を使った CI/CD パイプラインを構築しているプロジェクトもあるかと思います。

CI/CD パイプラインはリポシトリに変更を追加すると、自動でインテグレーション、デプロイメントが実行されます。そのため、実行結果を通知しないと実行の成否が分からず、知らないうちにシステムが停止している可能性があります。Cloud Build には実行結果を通知する機能がないため、結果を通知する機構を構築しないと同じ問題に遭遇することがあります。

そこで、本記事では Google Cloud が提供している Cloud Build Notifier を使って Slack に通知する方法を紹介します。

システム設計

Google Cloud は Cloud Build の結果を任意の通知先にメッセージを送信する Cloud Build Notifier を提供しています。このアプリケーションは BigQuery, Slack, Mail, 任意の HTTP エンドポイントにメッセージを送信させることができます。アプリケーションを Cloud Run サービスにデプロイして通知させることができます。この記事では、以下の様な図のシステム構成で Slack にメッセージを通知させます。

構成図

Cloud Build はすべてのビルド更新メッセージを Pub/Sub の cloud-builds トピックに送信します。Cloud Build Notifier はこのトピックに送信された更新メッセージを使い、通知先にメッセージを通知させます。Cloud Build Notifier による Cloud Run への通知は、cloud-builds をサブスクライブする Pub/Sub サブスクリプションから通知させます。

また、Cloud Build Notifier は Secret Manager と Cloud Storage バケットに保存された情報を使い通知先にメッセージを送信します。
Secret Manager には通知先の情報を保存します。例えば、Slack に通知する場合、Slack の Webhook の URL を保存し、メールに通知する場合、メールアカウントのパスワードを保存します。その他の Secret Manager に保存する詳しい情報は、公式ドキュメントを参照してください。
Cloud Storage には Cloud Build Notifier のアプリケーションの設定情報と、通知するメッセージのテンプレートを保存します。

以下では、Slack の設定と Google Cloud のシステム構築方法について説明します。

Slack の設定

Cloud Build Notifier は、Slack の Webhook を使い Slack に結果を通知します。Slack api の Your Apps でアプリ作成し、Webhooks を有効にします。そして、通知先のチャンネルにメッセージが送信されるようワークスペースに Webhook を追加します。

より詳細な作成方法は公式ページの Sending messages using incoming webhooks を参照してください。

追加された URL に リクエストを投げて、以下の様に通知先のチャンネルにメッセージが届いていれば、Slack 側の設定は完了です。

Google Cloud のシステム構築

Cloud Build Notifier の構築は、以下の順で作成します。

  1. Secret Manager を作成し、通知先の Slack の Webhook 情報の保存
  2. Cloud Storage を作成し、Cloud Build Notifier の設定ファイル・通知するメッセージのテンプレートファイルの保存
  3. Cloud Build Notifier の Cloud Run サービスの作成
  4. Pub/Sub トピックとサブスクリプションの作成

以下、Google Cloud のリソースの作成には Terraform を使います。 作成手順で示している Terraform コードの <> で囲っている値は、構築する環境に合わせて書き換えてください。

Secret Manager の作成

Secret Manager を作成し、Slack の Webhook の URL を作成した Secret Manager に保存します。Secret Manager は以下の Terraform コードで作成します。

resource "google_secret_manager_secret" "main" {
  secret_id = "<SECRETMANAGER>"

  project = var.project
  replication {
    user_managed {
      replicas {
        location = "asia-northeast1"
      }
    }
  }
}

Cloud Storage の作成

Cloud Build Notifier の設定ファイルと、メッセージのテンプレートファイルを作成して、これらのファイルを Cloud Storage バケットに格納します。

Cloud Build Notifier の設定ファイルは、以下のように作成します。

apiVersion: cloud-build-notifiers/v1
kind: SlackNotifier
metadata:
  name: slack-cloudbuild-notifier
spec:
  notification:
    filter: build.status in [Build.Status.SUCCESS, Build.Status.FAILURE, Build.Status.TIMEOUT]
    delivery:
      webhookUrl:
        secretRef: webhook-url
    params: 
      buildStatus: $(build.status)
    template:
      type: golang
      uri: <MESSAGE-TEMPLATE>
      
  secrets:
  - name: webhook-url
    value: <SECRETMANAGER>

spec.notification.filter は Cloud Build のどの結果を通知させるかを指定する項目です。この指定は Common Expression Language (以下、CEL) によって指定でき、今回、ビルド結果が SUCCESS, FAILURE, TIMEOUT のときに通知されるよう指定しています。その他の CEL による指定は公式ドキュメントの CEL を使用したビルドイベントのフィルタリング を参照してください。
spec.notification.delivery.webhookUrl.secretRef に Slack の通知先情報が保存された Secret Manager を指定します。Secret Manager の情報は spec.secrets に指定します。今回の例では SECRETMANAGERprojects/<PROJECTID>/secrets/<SECRETMANAGER>/versions/<VERSION> の形式で記載します。
spec.notification.template に Slack メッセージのテンプレートを指定します。uri にそのテンプレートが保存されている Cloud Storage の保存先を指定します。今回の例では MESSAGE-TEMPLATEgs://<CLOUDSTORAGEBUCKET>/<SLACKMESSAGE-TEMPLATE> の形式で記載します。

通知されるメッセージのテンプレートは、Cloud Build <ビルドの結果のステータス> Log と Cloud Build のビルド結果の履歴ページに飛ぶボタン Logs が通知されるように以下のようにします。
Slack メッセージの作成に Slack の Block Kit を活用しているので、詳細な設定は公式ドキュメントを参照してください。

[
  {
    "type": "section",
    "text": {
      "type": "mrkdwn",
      "text": "Cloud Build {{.Params.buildStatus}} Log"
    },
    "accessory": {
      "type": "button",
      "text": {
        "type": "plain_text",
        "text": "Logs"
      },
      "value": "CloudBuildLog",
      "url": "{{.Build.LogUrl}}",
      "action_id": "button-action"
    }
  }
]

これらのファイルを保存する Cloud Storage バケットの作成と、これらのファイルをアップロードする Terraform コードは以下の通りです。
先の Cloud Build Notifier の設定ファイルを config.yaml、メッセージのテンプレートファイルを template.json としてローカルに保存しています。

resource "google_storage_bucket" "main" {
  name = <CLOUDSTORAGEBUCKET>

  project       = var.project
  location      = "asia-northeast1"
  storage_class = "STANDARD"
}

resource "google_storage_bucket_object" "config" {
  name = <CLOUDBUILDNOTIFIER-CONFIGFILE>

  content = "config.yaml" 
  bucket  = google_storage_bucket.main.name
}

resource "google_storage_bucket_object" "message_template" {
  name = <SLACKMESSAGE-TEMPLATE>

  source = "template.json"
  bucket = google_storage_bucket.main.name
}

Cloud Run サービスの作成

Slack にメッセージを通知する Cloud Build Notifier を us-east1-docker.pkg.dev/gcb-release/cloud-build-notifiers/slack のイメージを使って Cloud Run サービスを作成します。作成するとき、Cloud Build Notifier の設定ファイルの URI (gs://<CLOUDSTORAGEBUCKET>/<CLOUDBUILDNOTIFIER-CONFIGFILE>) を環境変数 CONFIG_PATH に指定して作成します。

また、Cloud Run のアプリケーションをセキュアにするため、以下の設定をします。

  • Cloud Run の権限の最小化
  • Cloud Run への通信の制限

Cloud Build Notifier は設定ファイルが保存されている Cloud Storage バケットのオブジェクトを参照し、Slack の Webhook 情報が保存されている Secret Manager を参照する必要があります。そのため、Cloud Run のサービスアカウントに以下の権限を設定します。

付与する権限 権限によりアクセス許可するリソース
roles/storage.objectViewer Cloud Build Notifier の設定ファイルが保存されている Cloud Storage バケット
roles/secretmanager.secretAccessor Slack の Webhook の URL が保存されている SecretManager

Cloud Build Notifier の Cloud Run は Pub/Sub サブスクリプションからのみ通知させるため、ネットワーク上りを内部のみになるよう制限します。

上記の内容を設定する Terraform コードは以下の通りです。

resource "google_service_account" "cloud_run" {
  account_id = <CLOUDRUN-SERVICEACCOUNT>
  project    = var.project
}

resource "google_secret_manager_secret_iam_member" "main" {
  secret_id = google_secret_manager_secret.main.secret_id

  project = var.project
  role    = "roles/secretmanager.secretAccessor"
  member  = google_service_account.cloud_run.member
}

resource "google_storage_bucket_iam_member" "main" {
  bucket = google_storage_bucket.main.name

  role   = "roles/storage.objectViewer"
  member = google_service_account.cloud_run.member
}

resource "google_cloud_run_v2_service" "main" {
  name = <CLOUDBUILDNOTIFIER>

  project  = var.project
  location = "asia-northeast1"
  ingress  = "INGRESS_TRAFFIC_INTERNAL_ONLY"

  template {
    service_account = google_service_account.cloud_run.email
    containers {
      image = "us-east1-docker.pkg.dev/gcb-release/cloud-build-notifiers/slack"

      env {
        name  = "CONFIG_PATH"
        value = format("%s/%s", google_storage_bucket.main.url, google_storage_bucket_object.config.name)
      }
    }
  }
}

Pub/Sub の作成

Cloud Build の結果を通知する Pub/Sub トピックと、そのトピックをサブスクライブするサブスクリプションを作成します。Cloud Build の仕様から cloud-builds という名のトピックを作成します。そして、このトピックをサブスクライブし、Cloud Build Notifier の Cloud Run にメッセージ内容をプッシュするサブスクリプションを作成します。そのため、サブスクリプションが Cloud Build Notifier の Cloud Run をプッシュできるようにサブスクリプションのサービスアカウントに以下の権限を設定します。

付与する権限 権限によりアクセス許可するリソース
roles/run.invoker Cloud Build Notifier の Cloud Run サービス

上記の内容を構築する Terraform コードは以下の通りです。

resource "google_service_account" "pubsub_subscription" {
  account_id = <PUBSUBSUBSCRIPTION-SERVICEACCOUNT>
  project    = var.project
}

resource "google_cloud_run_v2_service_iam_member" "call_gcb_pubsub_sa" {
  name = google_cloud_run_v2_service.main.name

  project  = var.project
  location = "asia-northeast1"
  role     = "roles/run.invoker"
  member   = google_service_account.pubsub_subscription.member
}

resource "google_pubsub_topic" "main" {
  name = "cloud-builds"

  project = var.project
}

resource "google_pubsub_subscription" "main" {
  name = <CLOUDRUN-INVOKER>

  project = var.project
  topic   = google_pubsub_topic.main.id

  push_config {
    push_endpoint = google_cloud_run_v2_service.main.urls[0]
    oidc_token {
      service_account_email = google_service_account.pubsub_subscription.email
    }
  }
}

上記の内容を構築し、任意の Cloud Build のトリガーを実行すると、以下のように Slack に通知されます。

Logs ボタンをクリックすると、 Cloud Build ビルド結果の履歴ページに飛ぶことができます。

さいごに

Cloud Build Notifier を使うと、さまざまな通知先に実行結果を通知できます。メッセージ内容をうまく設計すると、ビルドがエラーしたときに障害対応のグループ宛てにメッセージを通知させることも可能になります。みなさんも Cloud Build Notifier を使い Cloud Build の結果を適切な宛先に通知させ、Cloud Build を運用に取り入れてください。

Discussion