TT Lab
はじめる
学ぶ 学習パス コース

CNPE — クラウドネイティブプラットフォームエンジニア

アラートが途切れる三つの境界を修復する

TT Labで続きを見る

目標

実際のk3s・Prometheus Operatorで、選択されていないルール、発火だけしたアラート、通知しないAlertmanagerを、順に直します。 現在のPodの障害・復旧のWebhookを実際に受信したあと、証拠の不足と矛盾を区別する診断関数を実装します。

なぜ重要なのか

Kubernetes APIがルールを保存してくれたからといって、Prometheusがそのルールを読んだという意味ではありません。 発火したからといって、人に届いたわけでもありません。公式の構成の各境界を自分で直し、APIで 参照してみて初めて、誤った設定、まだ反映中の状態、実際の配信の失敗を区別できます。

個人VMの中に、Operator v0.94.0・Prometheus v3.14.0・Alertmanager v0.34.0と、払い出しアプリが 用意されます。実行プロセスがあるk3sであり、KWOKではありません。インストールには数分かかることがあります。 作業は55分を想定しています。もっと必要なら、有効期限が切れる前に時間を延長し、終了前に必要な記録は ダウンロードしてください。VMとファイルは、セッション終了時に回収されます。VMの外の本番クラスターには適用しません。

用意されているもの

observeは1回だけ参照します。captureにステップ番号を渡すと、最大150秒待ってから、決まったJSONを 保存します。どちらも、設定を直しません。timeoutになったら、再インストールせず、現在の設定と 動作を調べてから、もう一度観測してください。gradeにステップ番号を渡しても、保存したファイルは修正されません。

ステップ

  1. 用意されているServiceMonitor・PrometheusRuleを参照し、capture 1で/root/cnpe-alerts/baseline.jsonを保存してください。メトリクスの対象のupと、ルールのAPIへの保存を確認します。最初は、ルールが選択されていないため、ロードされません。あとでもう一度収集すると、そのときの実際の状態を記録することになり、最初の失敗を偽って記録することはしません。
  2. team-labネームスペースのlabhub.io/rulesラベルだけを、allowedに直してください。Prometheusのセレクターを、全ネームスペースに広げないでください。capture 2でnamespace.jsonを保存し、ほかのルール選択の条件がまだ残っていないかを確認してください。
  3. team-labのPrometheusRule provision-readyに、platform=trainingラベルを付けます。ルールのspecは変えません。capture 3でselected.jsonを保存し、Prometheus APIにprovisionルールグループが実際にロードされたかを確認してください。
  4. VM内部の払い出しアプリのPOST /modeに、JSON {"ready":false}を送って、依存関係の障害を作ってください。capture 4でfiring.jsonを保存します。払い出しのレスポンスは503、Prometheusはfiringですが、Alertmanager・Webhookにはアラートがない状態を確認します。外部のサービスには、障害を注入しません。
  5. platform-monitoringのPrometheus platformに、spec.alerting.alertmanagersを追加してください。namespace=platform-monitoring、name=alertmanager、port=webの項目が1つです。用意されている参照のRBACは維持します。capture 5でreceived.jsonを保存し、Alertmanagerの受信と、Webhookの未受信を分離してください。
  6. /root/cnpe-alerts/alertmanager.yamlに、内部のreceiverを書きます。route.receiver=local-webhook、group_by=[alertname]、group_wait=1s、group_interval=5s、repeat_interval=1hです。receiversのlocal-webhookは、URL(http://workbench.team-lab.svc:8080/hook과)とsend_resolved=trueを使います。同じネームスペースのSecret alertmanager-platform、キーalertmanager.yamlで適用したあと、capture 6でnotified.jsonを保存してください。このURLの外には送信しません。
  7. 現在のPodのfiringのWebhookを、先に確認してください。POST /modeに{"ready":true}を送って復旧し、capture 7でrecovered.jsonを保存します。201レスポンス、アクティブなアラートの解消、同じPodのfiring・resolvedの受信を、すべて確認します。以前のPodのresolvedを、今回の復旧として認めません。
  8. /root/cnpe-alerts/diagnose.pyにdiagnose(e)を実装してください。以下の診断契約に沿って、文字列を1つ返します。観測なし・矛盾・欠落・数値や文字列で書かれたboolは、unknownとして扱い、保存・発火・受信を1つの成功にまとめません。

ステップ8の診断契約

eには、observed・selected・loaded・firing・received・notified・recoveredの7つの実際のboolが、 すべて必要です。received・notifiedは、同じ障害がその境界を通過した履歴で、 firingは現在の発火の有無です。この関数は、すでに突き合わせ済みの証拠の要約を入力として受け取ります。

参考

正常なメトリクス収集のupは、業務の成功の指標ではありません。このラボのgaugeは、依存関係の状態を 再現する値であり、本番のSLOではありません。グループのstatusだけで、個々のアラートの状態を決めないでください。 今回のステップの記録は、rule UID・pod UID・ルールの内容と突き合わせます。Podを作り直したなら、 観測もやり直す必要があります。このファイルの比較は、暗号学的なリモート証明でも、不正防止の仕組みでもありません。 ステップ1・4・5・6は、保存した過去の観測を、ステップ2・3・7は、現在の状態も確認します。正常に復旧したあとも、 過去の障害の記録を正常なJSONで上書きしないでください。受信記録はアプリのメモリにだけあり、再起動すると消えます。 ステップの準備は、前の構成だけを要求し、現在の答えや観測ファイルは作りません。ステップ7は、 復旧する前に、firingの受信を先に待ってください。ステップ8は、独立したコードの課題です。

外部Webhook・メール・チャットの送信、高可用性のアラート経路、実ユーザーのSLO検証は扱いません。 公式ドキュメント: ルール選択・ServiceMonitorのトラブルシューティング・アラートの状態。

メトリクスと保存されたルールを区別する

用意されているServiceMonitor・PrometheusRuleを参照し、capture 1で/root/cnpe-alerts/baseline.jsonを保存してください。メトリクスの対象のupと、ルールのAPIへの保存を確認します。最初は、ルールが選択されていないため、ロードされません。あとでもう一度収集すると、そのときの実際の状態を記録することになり、最初の失敗を偽って記録することはしません。

targetsがupでも、rulesにprovisionがないことがあります。2つのAPIは、別の問いに答えます。

ネームスペースの選択を狭く直す

team-labネームスペースのlabhub.io/rulesラベルだけを、allowedに直してください。Prometheusのセレクターを、全ネームスペースに広げないでください。capture 2でnamespace.jsonを保存し、ほかのルール選択の条件がまだ残っていないかを確認してください。

ruleNamespaceSelectorは、Namespaceのラベルを読みます。PrometheusRuleのラベルは、次の条件です。

ラベルを直して、実際のロードを確認する

team-labのPrometheusRule provision-readyに、platform=trainingラベルを付けます。ルールのspecは変えません。capture 3でselected.jsonを保存し、Prometheus APIにprovisionルールグループが実際にロードされたかを確認してください。

kubectlが成功した直後から、実際にロードされるまでには、時間がかかります。宣言ファイルだけを見ず、Prometheus API(/api/v1/rules를)を確認してください。

発火したのに配信されない障害

VM内部の払い出しアプリのPOST /modeに、JSON {"ready":false}を送って、依存関係の障害を作ってください。capture 4でfiring.jsonを保存します。払い出しのレスポンスは503、Prometheusはfiringですが、Alertmanager・Webhookにはアラートがない状態を確認します。外部のサービスには、障害を注入しません。

for: 10sは、実際の評価で条件が続く必要があります。/healthzの成功は、/provisionの成功ではありません。

Alertmanagerに接続して受信を確認する

platform-monitoringのPrometheus platformに、spec.alerting.alertmanagersを追加してください。namespace=platform-monitoring、name=alertmanager、port=webの項目が1つです。用意されている参照のRBACは維持します。capture 5でreceived.jsonを保存し、Alertmanagerの受信と、Webhookの未受信を分離してください。

receiverを直す前に、Prometheusがどのalertmanagerへ送っているかと、Endpointsの参照権限を見てください。

内部のWebhookへ実際に送信する

/root/cnpe-alerts/alertmanager.yamlに、内部のreceiverを書きます。route.receiver=local-webhook、group_by=[alertname]、group_wait=1s、group_interval=5s、repeat_interval=1hです。receiversのlocal-webhookは、URL(http://workbench.team-lab.svc:8080/hook과)とsend_resolved=trueを使います。同じネームスペースのSecret alertmanager-platform、キーalertmanager.yamlで適用したあと、capture 6でnotified.jsonを保存してください。このURLの外には送信しません。

Secretの名前だけでなく、キーの名前とrouteのreceiver参照が合っている必要があります。構成の反映時間も待ってください。

今回の障害の復旧かどうかを突き合わせる

現在のPodのfiringのWebhookを、先に確認してください。POST /modeに{"ready":true}を送って復旧し、capture 7でrecovered.jsonを保存します。201レスポンス、アクティブなアラートの解消、同じPodのfiring・resolvedの受信を、すべて確認します。以前のPodのresolvedを、今回の復旧として認めません。

グループのstatus 1つの値だけを見ず、alerts内の個々のstatusとpodラベルを比較してください。

空の証拠を成功に変えない診断ツール

/root/cnpe-alerts/diagnose.pyにdiagnose(e)を実装してください。以下の診断契約に沿って、文字列を1つ返します。観測なし・矛盾・欠落・数値や文字列で書かれたboolは、unknownとして扱い、保存・発火・受信を1つの成功にまとめません。

すべての必須フィールドが実際のboolであることを確認してから、前の境界から見ます。下流の成功と上流の失敗が一緒にあれば、矛盾です。