Terraformでログベースのアラートポリシーを作成してメール通知する

この記事は自身が実際に業務で使用した内容の復習 & 備忘録です。
理解不足の点や説明の誤りなどありましたら本ページ最下部のコメントでご指摘いただけると幸いです。

Cloud Monitoring のアラートポリシーには2種類あります。(詳しくは公式ドキュメント をご確認ください。)

  • 指標ベース
  • ログベース

この記事ではログベースのアラートポリシーについて記載します。

目的

  • Terraform でログベースのアラートポリシーを作成する
  • アラートを検知した際にメールで通知するように設定する

今回はCloud Functions でエラーが出力された際に、そのエラーログを検知してメール通知させます。

ログベースのアラートポリシーの概要図
今回作成するログベースのアラートポリシーの概要図

前提

  • Terraformコマンドが利用できること
  • GCPを利用するための準備ができていること

Terraform の書き方・実行方法に重点を置いているため、上記については説明しません。また、Terraform の構文などについても説明していません。

Terraform を書く

以下のようにTerraform を書きます。

# terraform.tfvars
credentials = "credentials.json"
project = "GCPのプロジェクトID"
region = "asia-northeast1"
zone = "asia-northeast1-a"
function_name = "test_function"
# variables.tf
variable "credentials" { type = string }
variable "project" { type = string }
variable "region" { type = string }
variable "zone" { type = string }
variable "function_name" { type = string }
# output.tf
output "notification_channel_name" {
  description = "Name of notification channel"
  value       = google_monitoring_notification_channel.email.display_name
}

output "alert_policy_name" {
  description = "Name of alert policy"
  value       = google_monitoring_alert_policy.policy.display_name
}
# main.tf
provider "google" {
  credentials = file(var.credentials)
  project     = var.project
  region      = var.region
  zone        = var.zone
}

# 通知先チャネルの作成
resource "google_monitoring_notification_channel" "email" {
  display_name = "Test Notification Channel"
  type         = "email"
  labels = {
    email_address = "xxxx@mail.com"
  }
}

# ログベースのアラートポリシーの作成
resource "google_monitoring_alert_policy" "policy" {
  display_name = "Cloud Functionsエラー監視"
  combiner     = "OR"

  conditions {
    display_name = "function-error-logs"
    condition_matched_log {
      filter = "resource.type=\"cloud_function\" resource.labels.function_name=${var.function_name} resource.labels.region=${var.region} severity=ERROR"
    }
  }

  notification_channels = [
    google_monitoring_notification_channel.email.id
  ]
  alert_strategy {
    notification_rate_limit {
      period = "300s"
    }
    auto_close = "604800s"
  }

  documentation {
    content = "test_functionでエラーが発生しました。"
  }
}

main.tf の記載内容の説明

provider

今回はGCPを使用するため、Googleを指定します。
{}の中に、自身のGCPプロジェクトの情報を記載します。

credentials
このtfファイルでリソースを作成するためのサービスアカウントの権限情報を指定します。
具体的には以下の通りです。

  • GCPのコンソール画面から[IAMと管理] –> [サービスアカウント] でTerraformで使用するサービスアカウントを作成または選択
  • そのサービスアカウントの [キー]タブ を表示して [鍵を追加] をクリックして [新しい鍵を作成] を選択
  • キーのタイプから「JSON」を選択して[作成]をクリックするとcredentials情報のJSONファイルがダウンロードされる
  • ダウンロードしたJSONファイルのパスをcredentialsに指定する

project
使用するGCPプロジェクトのIDを指定します。

region
使用するリージョンを指定します。

zone
リージョン内のゾーンを指定します。

provider の書き方の詳細につきましては 公式サイト をご覧ください。

resource:google_monitoring_notification_channel

google_monitoring_notification_channel はアラートの通知先チャネルを作成するためのリソースです。

display_name
コンソールに表示される名前を指定します。

type
通知する方法を指定します。
メール以外にもSlackやSMSなどで通知することができます。

labels
メール通知の場合は、通知先のメールアドレスを指定します。

詳細な書き方については、公式サイト をご参照ください。

resource:google_monitoring_alert_policy

google_monitoring_alert_policy はアラートポリシーを作成するためのリソースです。

display_name
コンソールに表示される名前を指定します。

combiner
複数の条件の結果を組み合わせて、インシデントをオープンすべきかどうかを判断する方法を指定します。

conditions.display_name
ダッシュボード、通知、およびインシデントの状態を識別するために使用される短い名前またはフレーズを指定します。

conditions.condition_matched_log.filter
ログのフィルターを指定します。
ここで指定したフィルターに該当するログが出力されるとアラートを検知して通知します。

notification_channels
通知先のチャネルを指定します。

補足

今回は通知先チャネルも一緒に作成するので、google_monitoring_notification_channel.email.idのように指定しています。

もし既に登録されている通知先を使用したい場合は、以下のコマンドを実行すると登録されている通知先のリストを確認することができます。

$ gcloud alpha monitoring channels list
---
creationRecord:
  mutateTime: '2022-04-30T01:53:46.009539531Z'
displayName: test-mail-address
enabled: true
labels:
  email_address: xxxxxxx@mail.com
mutationRecords:
- mutateTime: '2022-04-30T01:53:46.009539531Z'
name: projects/{プロジェクトID}/notificationChannels/12399999999912345678
type: email

コマンド実行結果のnameを指定します。

alert_strategy.notification_rate_limit.period
指定した期間ごとに1回まで通知します。例えば、5分(300s)を指定した場合、5分以内に監視対象のログが複数回出力されても1回しか通知されません。

alert_strategy.auto_close
インシデントを自動でクローズする期間を指定します。

documentation.content
通知するメッセージの本文を指定します。

詳細な書き方については、公式サイト をご参照ください。

ディレクトリ構成

ディレクトリ構成は次のようになります。

.
├── credentials.json
├── main.tf
├── output.tf
├── terraform.tfvars
└── variables.tf

Terraformを実行してアラートポリシーを作成する

Terraformコマンドを実行してアラートポリシーを作成します。

Terraformコマンドの実行

以下の順にコマンドを実行します。

terraform init
terraform plan
terraform apply

terraform applyコマンドを叩くと「Do you want to perform these actions?」と聞かれるので、yesを入力するとリソースの作成が開始されます。

完了すると、次のように表示されます。

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

alert_policy_name = "Cloud Functionsエラー監視"
notification_channel_name = "Test Notification Channel"

補足

Outputs:以降の内容は、output.tfに記載した項目が表示されます。

output項目を記載してない場合は、Outputs:以降の内容は表示されません。

作成されたリソースを確認

GCPのコンソールからTerraformで定義した内容通りにリソースが作成されたことを確認します。

通知先チャネル

[Monitoring] –> [アラート] –> [EDIT NOTIFICATION CHANNELS] の順に選択します。

作成された通知先チャネル
作成された通知先チャネル

アラートポリシー

[Monitoring] –> [アラート] –> [作成したアラートポリシー] の順に選択します。

下図の赤文字は アラートポリシーの設定に対応する main.tf に記載した項目名です。

作成されたアラートポリシー
作成されたアラートポリシー

アラートのメール通知を確認する

作成したアラートポリシーでメール通知されることを確認するために、テスト用のCloud Functions を適当に作成します。

# test_function
def is_number(request):
    num = request.args.get('num')
    if num.isnumeric():
        return f'num: {num}'
    else:
        raise ValueError(f'num is not a number:{num}')

numに数値以外が指定されていた場合、例外をraiseするので数値以外を指定して実行します。そうすると、以下のようなメールが送られてきました。

アラートメール
アラートメール

参考