この記事は GMOアドマーケティング Advent Calendar 2023 7日目の記事です。
こんにちは、GMOアドマーケティングのM.Hです。
Google Cloud Platform(以下、GCP)のCloud Monitoringは、リアルタイムでクラウド環境のインフラストラクチャを監視し、アラートを提供できる強力なツールです。今回はこのCloud MonitoringとSlackを連携させ、GCPの各サービスから通知したい内容をリアルタイムでキャッチアップできる仕組みを、Terraformを用いてコード管理できる形で実装していきます。
前提
以下のことは事前に作成、設定済みとします。
- ローカル環境にTerraformが導入済みであり、provider定義が完了していること。
- GCPのアカウントのセットアップやプロジェクトの作成、必要なAPIの有効が完了済みであること。
- Slackのアカウント・ワークスペースの作成が既に完了済みであること。
事前準備
Slackへの通知を行うために、Slack APIを使用します。使用するためにはBot Tokenを取得する必要があります。ここの手順の詳細は検索すれば数多くのサイトや記事がヒットするかと思いますので適宜参照していただければ問題ないかと思いますが、本記事でも簡単に手順をまとめました。
- Slackアプリの作成
- Slack API: Applicationsにアクセス
- 「Create New App」をクリックし「From scratch」を選択。
- 使用するSlackワークスペースを選択して任意のアプリ名を入力。
- 機能と権限の設定
- アプリの設定ページの「OAuth & Permissions」セクションを選択。
- 「Scopes」で、「Bot Token Scopes」に対して必要な権限を追加。「chat:write」「chat:write.customize」「chat:write.public」あたりを付与しておけばとりあえずは問題ないかと思います。
- Botアプリインストールとトークンの取得
- 同じ「OAuth & Permissions」セクション内の「OAuth Tokens for Your Workspace」でワークスペースにアプリをインストール。
- インストール後表示される「Bot User OAuth Access Token」をコピーなどして控える。
この手順によって得られるトークンは「xoxb-」から始まる文字列になっています。問題なく設定できれば、次はGCPのコンソールを開いてシークレットを作成します。
-
- コンソールで「Secret Manager」の設定画面を開く。ログインを求められたらGCPプロジェクトをセットアップしたGoogleアカウントでログイン。
- 「シークレットを作成」を押して新規シークレットを作成。名前は「 blog-test-slack-alert 」、シークレットの値は先ほどコピーしたSlackのアクセストークンを貼り付けて保存。
これで事前の準備が完了です。
Terraformの設定
本記事では、GCPにSpotVMインスタンスを作成し、プリエンプトされたらslack通知が飛ぶような環境をコードベースで構築して行こうと思います。Terraformで管理し作成するためのコードは大きく分けて以下の4つになります。
- Compute EngineのSpotVMインスタンス
- Cloud LoggingでプリエンプトされたVMインスタンスを検知するためのログベースのメトリクス
- Cloud Monitoringのアラートポリシー
- Cloud MonitoringのSlack通知チャンネル設定
以下にコードを示します。project設定は環境に合わせて適宜変更可能です。
1. SpotVMインスタンス
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
resource "google_compute_instance" "example_instance" { project = "your-project-id" machine_type = "e2-micro" name = "example-instance" zone = "asia-northeast1-a" boot_disk { auto_delete = true initialize_params { image = "debian-cloud/debian-11" size = 10 type = "pd-standard" } } network_interface { network = "default" } scheduling { automatic_restart = false on_host_maintenance = "TERMINATE" preemptible = true provisioning_model = "SPOT" } } |
マシンタイプやインスタンス名、ゾーン指定やブートディスク周りの設定はできるだけ最小構成となるようハードコーディングされています。必要に合わせて変更可能です。
2. ログベースのメトリクス
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
resource "google_logging_metric" "instance_preempted_metric" { project = "your-project-id" name = "VM_preempted_Metric" filter = <<EOT protoPayload.methodName="compute.instances.preempted" resource.type="gce_instance" protoPayload.resourceName = "example-instance" EOT metric_descriptor { metric_kind = "DELTA" value_type = "INT64" labels { key = "instance_name" description = "The name of the instance" } } label_extractors = { "instance_name" = "REGEXP_EXTRACT(protoPayload.resourceName, \"${google_compute_instance.example_instance.name}\")" } } |
3. アラートポリシー
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
resource "google_monitoring_alert_policy" "preempted_vm" { project = "your-project-id" display_name = "Preempted VM Alert" combiner = "OR" conditions { display_name = "Preempted VM Instances" condition_threshold { filter = "metric.type=\"logging.googleapis.com/user/${google_logging_metric.instance_preempted_metric.name}\" resource.type=\"gce_instance\"" comparison = "COMPARISON_GT" duration = "0s" threshold_value = 0 trigger { count = 1 } aggregations { alignment_period = "60s" per_series_aligner = "ALIGN_COUNT" cross_series_reducer = "REDUCE_COUNT" group_by_fields = [ "metric.label.instance_name", "resource.label.zone" ] } } } documentation { content = <<EOT インスタンスがプリエンプトされました。 プロジェクト:$${project} インスタンス名:$${metric.label.instance_name} ゾーン:$${resource.label.zone} EOT mime_type = "text/markdown" } notification_channels = [google_monitoring_notification_channel.slack_alert.id] } |
4. Slack通知チャンネル設定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# SlackのBot OAuthトークンを取得 data "google_secret_manager_secret_version" "slack_bot_oauth_token" { secret = "blog-test-slack-alert" project = "your-project-id" } # Slack通知チャンネルの設定 resource "google_monitoring_notification_channel" "slack_alert" { display_name = "Slack Alert Channel" enabled = true labels = { channel_name = "#blog-test-alert" auth_token = data.google_secret_manager_secret_version.slack_bot_oauth_token.secret_data } project = "your-project-id" type = "slack" } |
ここで事前準備で登録しておいたシークレット情報を取得しています。また、通知チャンネルは本記事では #blog-test-alert としていますが適宜変更可能です。
Terraformの適用とテスト
これによりTerraformの構成ができました。この後はinit(初期化)、plan(計画)、apply(適用)と進めば問題なくGCPにSlack通知の環境が構築できるかと思います。
実際にインスタンスがプリエンプトされた際のSlack通知は次のようになります。テスト用で作ったインスタンスだとなかなかプリエンプトされなかったので、実運用しているインスタンスでの通知例になります。
まとめ
今回はTerraformを使ってGCPのCloud MonitoringとSlackを効果的に連携しアラート通知する方法について解説しました。Cloud Monitoringは他のGCPサービスとの深い統合がなされており、また本記事のようにメトリクスを設定することでCloud Loggingからログ抽出して通知することも可能なので、ぜひ活用いただければと思います。リアルタイムのアラートを直接チームと共有し、問題を迅速に対処することが可能になるかと思います。
明日はT.Mさんによる「コミュニケーションプラン」です。
引き続き、GMOアドマーケティング Advent Calendar 2023 をお楽しみください!
■採用ページはこちら!
https://recruit.gmo-ap.jp/
■GMOアドパートナーズ 公式noteはこちら!
https://note.gmo-ap.jp/