【Cloud Tasks】キューの滞留と失敗をアラート通知する方法

【Cloud Tasks】キューの滞留と失敗をアラート通知する方法 GCP

Cloud Tasks のキューは、処理先の URL や権限が壊れても、タスクが静かに溜まるか、再試行を使い切って消えるだけで、何も知らせてくれません。この記事では、Cloud Monitoring のアラートポリシーで「タスクが失敗した」「タスクがキューに残り続けている」の2つを検知して通知する方法を、gcloud と Terraform の両方で説明します。前提は、HTTP ターゲットのキュー(Cloud Run などへ配送するもの)が既にあり、Cloud Monitoring の通知チャネル(Slack・メールなど)を作成済みであることです。gcloud は Google Cloud SDK 590 で確かめた内容です。

使うメトリクス

Cloud Tasks がキューごとに出すメトリクスのうち、アラートに使うのは次の2つです。どちらもモニタリング対象リソースは cloud_tasks_queue で、queue_id ラベルにキュー名が入ります。

メトリクス 種類 内容
cloudtasks.googleapis.com/queue/task_attempt_count DELTA / INT64 タスクの試行回数。response_code ラベルで結果ごとに分かれる。成功は ok
cloudtasks.googleapis.com/queue/depth GAUGE / INT64 キューに残っているタスクの数

どちらも60秒ごとにサンプリングされ、値が見えるようになるまで最大2〜3分かかります。アラートの通知もその分だけ遅れる前提で閾値を決めてください。

Cloud Tasks には「いちばん古いタスクの経過時間」にあたるメトリクスがありません。そのため滞留は、queue/depth が0より大きい状態が一定時間続いたかどうかで判定します。

通知チャネルの名前を調べる

アラートポリシーには、通知チャネルの表示名ではなくリソース名を渡します。channels は beta のコマンドです。

gcloud beta monitoring channels list \
  --format="table(displayName, name)"

出力の name 列にある projects/<プロジェクトID>/notificationChannels/<ID> の形の値を控えておきます。

失敗した試行を通知する(gcloud)

1. ポリシーを JSON で書く

task_attempt_count のうち response_code が ok 以外のものを60秒ごとに合計し、0を超えたらすぐ通知します。my-queue は自分のキュー名に置き換えてください。

{
  "displayName": "Cloud Tasks の失敗した試行(my-queue)",
  "combiner": "OR",
  "conditions": [
    {
      "displayName": "non-ok task attempts",
      "conditionThreshold": {
        "filter": "resource.type = \"cloud_tasks_queue\" AND resource.labels.queue_id = \"my-queue\" AND metric.type = \"cloudtasks.googleapis.com/queue/task_attempt_count\" AND metric.labels.response_code != \"ok\"",
        "comparison": "COMPARISON_GT",
        "thresholdValue": 0,
        "duration": "0s",
        "aggregations": [
          {
            "alignmentPeriod": "60s",
            "perSeriesAligner": "ALIGN_SUM",
            "crossSeriesReducer": "REDUCE_SUM",
            "groupByFields": ["metric.labels.response_code"]
          }
        ]
      }
    }
  ],
  "alertStrategy": {
    "autoClose": "1800s"
  },
  "documentation": {
    "mimeType": "text/markdown",
    "content": "my-queue で、配送先への試行が ok 以外で終わった。配送先のログと IAM を確認する。"
  }
}

groupByFields に response_code を入れておくと、通知に結果の種類が出るので、権限の問題か配送先のエラーかの見当がつきやすくなります。

2. ポリシーを作る

gcloud monitoring policies create \
  --policy-from-file=tasks-non-ok.json \
  --notification-channels=projects/<プロジェクトID>/notificationChannels/<ID>

キューの滞留を通知する(gcloud)

1. 閾値の時間を決める

滞留の判定時間は、1つのタスクがキューに残りうる最長の時間より長くします。目安は「配送の期限 + キューの再試行期間(maxRetryDuration)」です。キューの設定は次のコマンドで確かめられます。

gcloud tasks queues describe my-queue --location=asia-northeast1

出力の retryConfig に maxAttempts と maxRetryDuration が入っています。たとえば再試行期間が40秒で、配送先が数秒で応答するキューなら、タスクは1分以内に消えるはずなので、2分残っていれば配送が止まっていると判断できます。再試行期間が長いキューで同じ閾値を使うと、正常な再試行のたびに鳴ってしまいます。

2. ポリシーを JSON で書く

queue/depth を60秒ごとの最小値で揃え、それが0を超えた状態が120秒続いたら通知します。最小値を使うのは、タスクが入ってすぐ消える普段の動きでは、期間中に一度は0に戻るためです。

{
  "displayName": "Cloud Tasks の滞留(my-queue)",
  "combiner": "OR",
  "conditions": [
    {
      "displayName": "tasks left in the queue for 2 minutes",
      "conditionThreshold": {
        "filter": "resource.type = \"cloud_tasks_queue\" AND resource.labels.queue_id = \"my-queue\" AND metric.type = \"cloudtasks.googleapis.com/queue/depth\"",
        "comparison": "COMPARISON_GT",
        "thresholdValue": 0,
        "duration": "120s",
        "aggregations": [
          {
            "alignmentPeriod": "60s",
            "perSeriesAligner": "ALIGN_MIN"
          }
        ]
      }
    }
  ],
  "alertStrategy": {
    "autoClose": "1800s"
  },
  "documentation": {
    "mimeType": "text/markdown",
    "content": "my-queue にタスクが2分以上残っている。キューの停止、配送先の URL・権限を確認する。"
  }
}

3. ポリシーを作る

gcloud monitoring policies create \
  --policy-from-file=tasks-stuck.json \
  --notification-channels=projects/<プロジェクトID>/notificationChannels/<ID>

Terraform で書く場合

google_monitoring_alert_policy リソースで同じ内容を書けます。キュー名を google_cloud_tasks_queue リソースから参照すると、キュー名を変えたときにフィルタだけ古いまま残る事故を防げます。

resource "google_monitoring_alert_policy" "tasks_stuck" {
  display_name = "Cloud Tasks の滞留(my-queue)"
  combiner     = "OR"

  conditions {
    display_name = "tasks left in the queue for 2 minutes"
    condition_threshold {
      filter          = <<-EOT
        resource.type = "cloud_tasks_queue"
        AND resource.labels.queue_id = "${google_cloud_tasks_queue.my_queue.name}"
        AND metric.type = "cloudtasks.googleapis.com/queue/depth"
      EOT
      comparison      = "COMPARISON_GT"
      threshold_value = 0
      duration        = "120s"
      aggregations {
        alignment_period   = "60s"
        per_series_aligner = "ALIGN_MIN"
      }
    }
  }

  alert_strategy {
    auto_close = "1800s"
  }

  notification_channels = [var.notification_channel]
}

失敗した試行のポリシーも同じ形で、filter に metric.labels.response_code != "ok" を足し、duration = "0s"、aggregations を ALIGN_SUM と REDUCE_SUM、group_by_fields = ["metric.labels.response_code"] にします。

動作を確認する

作ったポリシーが登録されたかを確かめます。

gcloud monitoring policies list \
  --format="table(displayName, enabled, name)"

2つのポリシーが enabled が True で並んでいれば登録できています。

滞留のアラートが実際に鳴るかは、検証用のキューを一時停止して試せます。本番のキューでは試さないでください。

gcloud tasks queues pause my-test-queue --location=asia-northeast1
# この間にタスクを1件投入し、数分待って通知が届くかを見る
gcloud tasks queues resume my-test-queue --location=asia-northeast1

キューに残っているタスクは次のコマンドで見られます。

gcloud tasks list --queue=my-test-queue --location=asia-northeast1

うまくいかないとき

アラートが鳴らない

  • queue_id に入れたキュー名が実際のキュー名と違っていると、フィルタが何にも当たらず、エラーも出ません。Metrics Explorer で同じフィルタを入れ、グラフが出るかを先に確かめてください
  • タスクが1件も流れていないキューでは、task_attempt_count のデータ点が出ません。トラフィックの少ないキューでは、アラートが鳴らないことを正常の証拠にしないでください

滞留のアラートが頻繁に鳴る

  • 判定時間が再試行期間より短いと、正常な再試行の間にも鳴ります。gcloud tasks queues describe の retryConfig を見て、duration を延ばしてください
  • スケジュール時刻を未来に指定してタスクを入れている場合、そのタスクは時刻まで正常にキューに残ります。この使い方をするキューでは、queue/depth だけで滞留を判定できません

通知は来たが原因が分からない

  • 失敗した試行のアラートでは、通知の response_code を見ます。配送先へ届いていない(認証・権限)のか、配送先がエラーを返したのかで、見る場所が配送先のログか IAM かに分かれます
  • 滞留のアラートでは、まずキューの state を確かめます。PAUSED や DISABLED なら、キューが止まっています
gcloud tasks queues describe my-queue --location=asia-northeast1 --format="value(state)"

参考

  • Google Cloud metrics(cloudtasks): https://cloud.google.com/monitoring/api/metrics_gcp_c
  • Monitored resource types(cloud_tasks_queue): https://cloud.google.com/monitoring/api/resources
  • REST Resource: projects.alertPolicies: https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.alertPolicies
  • gcloud monitoring policies create: https://cloud.google.com/sdk/gcloud/reference/monitoring/policies/create
  • gcloud beta monitoring channels list: https://cloud.google.com/sdk/gcloud/reference/beta/monitoring/channels/list
  • gcloud tasks queues describe: https://cloud.google.com/sdk/gcloud/reference/tasks/queues/describe
  • Terraform google_monitoring_alert_policy: https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/monitoring_alert_policy
この記事を書いた人

渋谷で働くよわよわエンジニア。TypeScript(Next.js/Node.js)/Golang/AWS/Flutterなど
LINE API Expert(2023/1~)

tokkuをフォローする
オススメ記事
在宅ワークが多くなって、デスクの配線周りに困っている方は、拡張デスクの導入がおすすめです。Windows/MacOS/Linuxの複数の機器をスッキリとデスク周りに収める事ができました!リモートからサーバーメンテを行うインフラエンジニアは必見です!
GCP
シェアする
tokkuをフォローする

コメント

タイトルとURLをコピーしました