Cloud Run jobsのジョブ実行エラー通知をTerraformで作成する

記事タイトルとURLをコピーする

G-gen の佐々木です。当記事では、Cloud Run jobs で実行されるジョブのエラー通知を、 Cloud Logging と Cloud Monitoring で作成します。リソースの作成には IaC である Terraform を使用します。

はじめに

Cloud Run jobs は Google Cloud のサーバーレス コンテナ コンピューティング サービスである Cloud Run の実行モデルの1つであり、コンテナ化されたバッチジョブの長時間実行に特化したサービスです。

サーバーレス、つまりユーザーによるインフラの管理を必要とせず、またコンテナ化されていればランタイムを問わずバッチジョブを実行することができます。

Cloud Run jobs は非常に扱いやすい強力なサービスですが、ジョブ実行が失敗したときなど、ユーザーへの何かしらの通知を実装したい場合には、別途モニタリングの仕組みを構成する必要があります。

当記事では、Google Cloud のモニタリングサービスである Cloud Logging および Cloud Monitoring を使用することで、Cloud Run jobs のジョブ実行失敗をメール通知する仕組みを構成していきます。

各サービスの詳細な解説は以下の記事をご一読ください。

blog.g-gen.co.jp

blog.g-gen.co.jp

blog.g-gen.co.jp

アラートのリソース構成

Cloud Run jobs は、ジョブ実行の失敗時にエラーログを出力します。 当記事では、Cloud Logging に記録されたエラーログを Cloud Monitoring のログベースの指標として取り込み、アラートポリシーを使用してアラートの通知を送信します。

ログベースの指標とアラートポリシーを使用したアラート通知の構成

Terraform コード全文

バージョン定義

当記事で使用する Terraform および Terraform の Google Cloud プロバイダのバージョンは以下の通りです。

# versions.tf
terraform {
  required_version = ">= 1.13"
  
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = ">= 7.7"
    }
  }
}

リソース定義

アラート通知のために以下の3つのリソースを定義します。

  • ログベースの指標
  • 通知チャンネル
  • アラートポリシー

なお、モニタリングの対象となる Cloud Run ジョブはすでに作成してあるものとします。

リソース定義の詳細は後ほど解説していきます。

# monitoring.tf
locals {
  project_id         = "sample-project"
  location           = "asia-northeast1"
  job_name           = "sample-job"
  notification_email = "sample@g-gen.co.jp"
}
  
# ログベースの指標
resource "google_logging_metric" "this" {
  project = local.project_id
  name    = "error_metric_for_${local.job_name}"
  
  # Cloud Logging のクエリを定義
  filter = <<-EOT
  severity>=ERROR
  resource.type="cloud_run_job"
  resource.labels.job_name="${local.job_name}"
  resource.labels.location="${local.location}"
  logName=~"cloudaudit.googleapis.com%2Fsystem_event"
  EOT
  
  metric_descriptor {
    metric_kind = "DELTA"
    value_type  = "INT64"
  }
}
  
# 通知チャンネル
resource "google_monitoring_notification_channel" "this" {
  project      = local.project_id
  display_name = "ジョブエラー通知用メールアドレス"
  type         = "email"
  force_delete = false
  
  labels = {
    email_address = local.notification_email
  }
}
  
# アラートポリシー
resource "google_monitoring_alert_policy" "this" {
  project               = local.project_id
  display_name          = "Error Alert for ${local.job_name}" # アラートの表示名
  combiner              = "OR"
  severity              = "ERROR" # アラートの重大度(CRITICAL / ERROR / WARNING)
  enabled               = true
  notification_channels = [google_monitoring_notification_channel.this.id]
  
  conditions {
    display_name = "Error Condition for ${local.job_name}"
  
    condition_threshold {
      # filterのmetric.typeにログベースの指標を指定(resource.typeの指定も必須)
      filter          = "resource.type=\"cloud_run_job\" AND metric.type=\"logging.googleapis.com/user/${google_logging_metric.this.name}\""
      comparison      = "COMPARISON_GT" # threshold_value の値よりも大きいときにアラート作成
      threshold_value = 0
  
      aggregations {
        alignment_period   = "60s"
        per_series_aligner = "ALIGN_COUNT"
      }
  
      duration = "60s"
      # ログベースの指標にデータがないときにアラートを止める
      evaluation_missing_data = "EVALUATION_MISSING_DATA_INACTIVE"
    }
  }
  
  alert_strategy {
    # アラート作成時のみ通知を送信する
    notification_prompts = ["OPENED"]
  }
  
  documentation {
    subject = "ジョブ($${resource.label.job_name})の実行に失敗しました"
  
    content = <<-EOT
    ## Google Cloudプロジェクト
    $${resource.label.project_id}
    ## Cloud Runジョブ名
    $${resource.label.job_name} 
    ## アラートの説明
    Cloud Runジョブ**($${resource.label.job_name})**の実行に失敗しました。
    ジョブの実行ログおよびTerraformテンプレートの設定値を確認してください。
    EOT
  
    mime_type = "text/markdown"
  }
}

Terraform コード解説

ローカル変数

当記事では、通知対象のジョブ名や通知先メールアドレスなどの情報は locals に定義しています。

locals {
  project_id         = "sample-project"     # プロジェクトID
  location           = "asia-northeast1"    # ジョブが存在するリージョン
  job_name           = "sample-job"         # ジョブ名
  notification_email = "sample@g-gen.co.jp" # 通知先メールアドレス
}

当記事のコードをモジュール化し、複数のジョブで同様のアラート通知を設定するようなケースでは、これらの変数は variables で定義し、モジュールの外から値を渡せるようにするのがよいでしょう。

ログベースの指標

ログベースの指標として、通知対象ジョブのエラーログを取り込む Cloud Monitoting 指標を定義します。

ログベースの指標では、Cloud Logging の特定のログエントリの数などを Cloud Monitoring の指標として記録することができます。

resource "google_logging_metric" "this" {
  project = local.project_id
  name    = "error_metric_for_${local.job_name}"
  
  # Cloud Logging のクエリを定義
  filter = <<-EOT
  severity>=ERROR
  resource.type="cloud_run_job"
  resource.labels.job_name="${local.job_name}"
  resource.labels.location="${local.location}"
  logName=~"cloudaudit.googleapis.com%2Fsystem_event"
  EOT
  
  metric_descriptor {
    metric_kind = "DELTA"
    value_type  = "INT64"
  }
}

ログベースの指標としてエラーログを取得するために、Cloud Logging のクエリ言語を使用してログをフィルタリングします。このクエリを filter の値として定義しています。

Cloud Logging に出力されるジョブ実行エラーログは以下のフィールドが含まれています。これをクエリに使用します。

フィールド名
severity ERROR
resource.type cloud_run_job
resource.labels.job_name ジョブの名前
resource.labels.location ジョブが存在するリージョン
logName projects/<プロジェクトID>/logs/cloudaudit.googleapis.com%2Fsystem_event

Cloud Run jobs のジョブ実行エラー時のログ

通知チャンネル

Cloud Monitoring で作成されるアラートの通知先として通知チャンネルを設定します。

当記事ではメール通知を設定しますが、通知先チャンネルとしては Slack や SMS、Pub/Sub などを設定することも可能です。

resource "google_monitoring_notification_channel" "this" {
  project      = local.project_id
  display_name = "ジョブエラー通知用メールアドレス"
  type         = "email"
  force_delete = false
  
  labels = {
    email_address = local.notification_email
  }
}

アラートポリシー

実際にアラートを作成するリソースである Cloud Monitoring のアラートポリシーを設定します。

resource "google_monitoring_alert_policy" "this" {
  project               = local.project_id
  display_name          = "Error Alert for ${local.job_name}" # アラートの表示名
  combiner              = "OR"
  severity              = "ERROR" # アラートの重大度(CRITICAL / ERROR / WARNING)
  enabled               = true
  notification_channels = [google_monitoring_notification_channel.this.id]
  
  conditions {
    display_name = "Error Condition for ${local.job_name}"
  
    condition_threshold {
      # filterのmetric.typeにログベースの指標を指定(resource.typeの指定も必須)
      filter          = "resource.type=\"cloud_run_job\" AND metric.type=\"logging.googleapis.com/user/${google_logging_metric.this.name}\""
      comparison      = "COMPARISON_GT" # threshold_value の値よりも大きいときにアラート作成
      threshold_value = 0
  
      aggregations {
        alignment_period   = "60s"
        per_series_aligner = "ALIGN_COUNT"
      }
  
      duration = "60s"
      # ログベースの指標にデータがないときにアラートを止める
      evaluation_missing_data = "EVALUATION_MISSING_DATA_INACTIVE"
    }
  }
  
  alert_strategy {
    # アラート作成時のみ通知を送信する
    notification_prompts = ["OPENED"]
  }
  
  documentation {
    subject = "ジョブ($${resource.label.job_name})の実行に失敗しました"
  
    content = <<-EOT
    ## Google Cloudプロジェクト
    $${resource.label.project_id}
    ## Cloud Runジョブ名
    $${resource.label.job_name} 
    ## アラートの説明
    Cloud Runジョブ**($${resource.label.job_name})**の実行に失敗しました。
    ジョブの実行ログおよびTerraformテンプレートの設定値を確認してください。
    EOT
  
    mime_type = "text/markdown"
  }
}

L15~L16
ジョブ実行失敗時のエラーログが1つでも記録されたときにアラートを作成したいため、conditions.condition_threshold.comparison の値を COMPARISON_GT(閾値より上)、conditions.condition_threshold.threshold_value の値(閾値)を 0 に指定します。


L25
conditions.condition_threshold.evaluation_missing_data の値を EVALUATION_MISSING_DATA_INACTIVE にすることで、ログベースの指標にデータが記録されないときにアラートを止める(復旧させる)ようにしています。

これは、今回設定しているログベースの指標が「Cloud Logging にジョブ失敗のエラーログが記録されたとき」だけ取得されるものであり、エラーログがないときは値が何も取得されないため、アラートが一度作成されると復旧しない(指標の値として0が記録されないと復旧しない)ためです。

もし、エラーの対処後にアラートを手動で復旧させたい場合は、conditions.condition_threshold.evaluation_missing_data は記述しないか、値に EVALUATION_MISSING_DATA_NO_OP を設定します(参考)。


L29~L32
alert_strategy.notification_prompts では OPENED を指定し、アラートの作成時のみメール通知を送信するように設定しています。

ここで CLOSED も一緒に記述した場合、アラート復旧時にもメール通知が送信されます。しかし、先述したように今回設定しているログベースの指標には復旧時の手がかりがないため、アラートは作成後すぐに止める(復旧させる)ように設定しています。この場合、アラート作成のメール通知のすぐ後に復旧時のメール通知も送信されてしまうため、復旧時の通知はあえて行わないようにしています。


L34~L48
documentation にはアラート通知メールの本文(ドキュメント)を定義できます。

ドキュメントはマークダウンで記述することができ、${varname} の形式で変数を使用することもできます。これにより、アラート対象となっているジョブのプロジェクト ID やジョブ名など、そのアラート固有の情報をドキュメントに含めることができます。


動作確認

アラート通知対象のジョブを失敗させ、アラートを作成してみます。

Cloud Run のジョブを失敗させる

Google Cloud コンソールのポリシーの詳細画面でアラートポリシーを確認すると、ジョブ実行の失敗を示すエラーログがログベースの指標として記録されています。アラート閾値は0であり、アラート作成条件は閾値よりも上のため、Cloud Monitoring によってアラートが作成されます。

ジョブ失敗時のエラーログがログベースの指標に記録されている

同じくポリシーの詳細画面のインシデント欄に、作成されたアラートが表示されています。

アラートポリシーによって作成されたアラート

通知チャンネルに設定したメールアドレスに対しては、アラートポリシーによって作成されたアラートメールが alerting-noreply@google.com から送信されています。

Cloud Monitoring のアラートメール

メール本文は以下のようになっており、アラートポリシー作成時にマークダウンで記述したドキュメントのほか、対象のアラートおよびエラーログのリンクも含まれています。

アラートメールの本文

佐々木 駿太 (記事一覧)

G-gen 最北端、北海道在住のクラウドソリューション部エンジニア

2022年6月に G-gen にジョイン。Google Cloud Partner Top Engineer に選出(2024 / 2025 Fellow / 2026)。好きな Google Cloud プロダクトは Cloud Run。

趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。