Grafana Cloud IRM/OnCall と Google Cloud のアラートを連携する
はじめに
普段アラートを Slack へ通知することはしていても、四六時中 Slack をみているわけにもいかないです。また、寝てたら Slack の通知なんで気づくわけもないので、なにかしら叩き起こしてくれるものが欲しくなります。
今回は、OSS もあって最近 Cloud 版が東京にもできた[1]ということで気になっている Grafana の Grafana Cloud Incident Response & Management (IRM) の OnCall サービスをためしてみようと思います。
[2]
Grafana Cloud Incident Response & Management (IRM)概要
Grafana OnCall と Grafana Incident という 2 つのサービスを持つインシデントワークフローを効率化するためのツールらしいです。Cloud の場合はそれがフルマネージドで提供されます。
OnCall は担当者のスケジュールや通知、アラートからのインシデント起票などをおこない、Incident はタスク・進捗・状況を管理・Slack や GitHub との自動連携などを提供しています。
https://grafana.com/ja/products/cloud/irm/
料金
月間 3 アクティブユーザまでは無料ではじめることができ、超えた場合は月額 $20 ずつユーザごとに課金されます[3]。100 人いたら 97 人分課金で、293,673 円 (151.38 円/USD) ほどでしょうか。
IRM のアクティブユーザーとは何ですか?
アクティブな IRM ユーザーとは、OnCall のスケジュールやエスカレーションチェーンに含まれているか、次のいずれかの操作を行ったユーザーのことです。
- アラートグループや OnCall の設定のステータスを変更した
- ページを受信した、または他のユーザーにページを送信した
- インシデントを作成、編集、または更新した
気になるところが、アクティブユーザというところです。IRM を利用しないユーザは Grafana 上にいても課金されないのでダッシュボードしかみないよーってひとがいても財布が痛くなさそうです。
次の記事では Grafana Cloud の IRM へ移行したことで、年間数万ドルを節約をした事例が紹介されていました。
ちなみにコンプライアンス[4]はひととおりそろっていそうでした。
- ISO 27001 (ISMS)
- SOC 2 Type 2 Certification
- PCI Security Standards Council
- GDPR
- Cloud Security Alliance (CSA)
Grafana OnCall を使ってみる
セットアップ
Grafana Cloud へアクセスし、無料トライアルアカウントを作成します。プランごとの違いは Grafana Cloud features から確認できます。ほとんど機能を試すことができそうです。Stack URL と Deployment Region を選んだら利用開始です。
Set up your first Grafana stack
無料は 1 つの Stack を持つことができ、Pro プランでは 3 つの Stack を持てるので本番環境と開発用サンドボックスとしてそれぞれ Stack を作成するような運用ができそうです[5]。利用可能なリージョンは、Grafana Cloud services regional availabilityから確認できます。
作成後の Stack は、「My Account > Manage your Grafana Cloud stack > Details」から確認できます。「Manage your stack > Grafana > Details」を開くと、aws の Tokyo リージョンにデプロイされていることが確認できます。
Grafana Instance Details
通知設定
iOS と Android で OnCall 通知を受け取れる「Grafana IRM」というモバイルアプリが提供されています。Grafana Cloud から 「Profile > IRM > Mobile App Connection」 を開き、QR コードを読み取ると簡単に連携できます[6]。
Mobile App Connection
もしも、Mobile App 以外の SMS や Phone Call で通知を受け取るのであれば、「Alerts&IRM > OnCall > Users」 を開き、各ユーザの Edit から通知を設定できます。同じ画面から通常時と重大な通知のときにどんな通知を利用するか、それぞれの通知先を複数設定することもできます。
Alerts&IRM > OnCall > Users
User Info
Slack 連携
Slack と連携することで、通知をおこなったり、Incident の起票や対応チャンネルの自動作成などを行うことができます[7]。「Alerts & IRM > OnCall > Settings」を開いて、ChatOps タブを選択します。Slack Workspace と連携したら、 デフォルトで通知をおこなうチャンネルを選択します。専用のチャンネルを作成することが推奨されていました。今回は事前に grafana-notification
というチャンネルを用意しました。
Alerts & IRM > OnCall > Settings > Chat Ops
Integration 設定
Get started with Grafana OnCall を読みながら進めていきます。
「Alerts & IRM > OnCall > Integrations」を開きます。「Add Integration」からどのシステムからのアラートを受け取るか選択できます。候補にない場合は、Webhook を利用することもできます。今回は Webhook を選択します。MyWebhookIntegration
という名前で作成します。
New Webhook Integration
作成できたら、とりあえずデモを試してみるため右上の「Send demo alert」からそのまま「Send Alert」をクリックします。「Alerts & IRM > OnCall > Alert Groups」を開き、デモのアラートが確認できます。Slack を開くと、設定していたチャンネルへも投稿が来ていることがわかります。これは Integration の「Unmatched alerts routed to default route」が「Publish to ChatOps」になっているためです。
Slack Notification
Team の作成
通知先にするチームを作成します。「Administration > Users and access」から「Teams」を開きます。「New Team」からMyTeam
という名前で今回作成しました。
Administration > Users and access > Teams > MyTeam
Escalation chain 設定
Mobile App で通知を受け取るために Escalation chain を作成します。「Alerts & IRM > OnCall > Escalation chains」を開き、「New escalation chain」から作成します。Important Escalation
とDefault Escalation
という名前で 2 つ作成します。
どちらも Escalation Step で、Notify all team members
を選択します。
- Important Escalation では Start
Important
notification - Default Escalation では Start
Default
notification
となるようにします。宛先チームは作成した MyTeam
を指定します。
Alerts & IRM > OnCall > Escalation chains > Default Escalation
Alerts & IRM > OnCall > Escalation chains > Important Escalation
Escalation chain を Integration へ追加
作成した Integration を開きます。「Add Route」から「Alerts matched by Template matching」に{{ payload.severity == "critical" }}
を追加します。さらに「Trigger escalation chain」で「Important Escalation」を選択します。そして、「Unmatched alerts routed to default route」の「Trigger escalation chain」で「Default Escalation」を追加します。
これで、各ユーザが設定した通知先へアラートを飛ばす準備が整いました。
MyWebhookIntegration with Escalation
デモ実行
「Send demo alert」を再び実行すると、Mobile App に通知がくるはずです。
通常のプッシュ通知
つぎに、"severity": "critical"
を payload へ追加して実行します。「Copy as CURL」から以下のように実行してもいいです。マナーモードにしていても、通知が来るはずです。
curl -X POST https://oncall-prod-us-central-0.grafana.net/oncall/integrations/v1/webhook/xxxxxxxxxxxxxxxx/ \
-H 'Content-Type: Application/json' \
-d '{
"message": "This alert was sent by user for demonstration purposes",
"severity": "critical"
}'
重大なプッシュ通知
もしも iOS で通知が来ない場合は、設定から「重大な通知」がオンになってるかを確認してみてください。そのほかの設定は Push notifications を確認してみるといいです。
通知設定
Google Cloud と連携
さて、実際にアラートと OnCall を連携してみましょう。こんな感じで Google Cloud から Grafana Cloud へ Webhook 通知をします。メッセージを受け取った Cloud Run Functions が Webhook をたたくだけです。
イメージ図
準備
デプロイする Cloud Run Functions では、incident が open のときのみ Webhook 通知をするような仕組みになっています。通知する際に、incident から必要な情報を引っ張ってきてリクエストします。
各種リソースを作成していきます。PROJECT_ID
やGRAFANA_WEBHOOK_URL
は自身のものを設定します。
リソース作成コマンド
PROJECT_ID='YOUR PROJECT ID'
gcloud config set project $PROJECT_ID
SERVICE_ACCOUNT='pubsub-grafana-oncall-notifier'
SECRET_ID='grafana-webhook-url'
GRAFANA_WEBHOOK_URL='https://oncall-prod-us-central-0.grafana.net/oncall/integrations/v1/webhook/xxxxxxxxxxxxxxxx/'
TRIGGER_TOPIC='grafana-oncall-notifier'
SERVICE='pubsub-grafana-oncall-notifier'
# Cloud Run Functions で使うサービスアカウント
gcloud iam service-accounts create $SERVICE_ACCOUNT
# Webhook URL を格納する Secret Manager
echo -n "$GRAFANA_WEBHOOK_URL" | gcloud secrets create $SECRET_ID \
--replication-policy="automatic" \
--data-file=-
# Alert 通知先の PubSub Topic
gcloud pubsub topics create $TRIGGER_TOPIC
# サービスアカウントから、シークレットに対してアクセス権限を付与
gcloud secrets add-iam-policy-binding $SECRET_ID \
--member="serviceAccount:${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role='roles/secretmanager.secretAccessor'
# サービスアカウントから、ログを記録する権限を付与
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role='roles/logging.logWriter'
# Docker レジストリを作成
gcloud artifacts repositories create gcf-artifacts \
--repository-format=docker \
--location=asia-northeast1
# Cloud Build を使って、Cloud Run Functions のデプロイ
gcloud builds submit --project=$PROJECT_ID \
--config ./cloudbuild.yaml \
--substitutions=_SOURCE=.
# PuSub Subscription から Cloud Run Functions へのアクセス権を付与
gcloud run services add-iam-policy-binding $SERVICE \
--region=asia-northeast1 \
--member="serviceAccount:${SERVICE_ACCOUNT}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role='roles/run.servicesInvoker'
PROJECT_NUMBER=$(gcloud projects list --filter="$(gcloud config get-value project)" --format="value(PROJECT_NUMBER)")
# Alert から PubSub Topic に対してメッセージを送るための権限を付与
gcloud pubsub topics add-iam-policy-binding $TRIGGER_TOPIC \
--member="serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-monitoring-notification.iam.gserviceaccount.com" \
--role='roles/pubsub.publisher'
Cloud Monitoring の Alert を Alert Test Policy 1
とAlert Test Policy 2
と 2 つ作ります。1 の Severity は Warning
で、2 の Severity を Critical
にします。通知先は上で作成したTRIGGER_TOPIC='grafana-oncall-notifier'
を使います。全体的な設定は以下のとおりです。
gcloud alpha monitoring policies describe の結果
alertStrategy:
autoClose: 1800s
notificationRateLimit:
period: 300s
combiner: OR
conditions:
- conditionMatchedLog:
filter: |-
logName:"my-test-log"
textPayload:"A simple entry Warn"
displayName: Log match condition
name: projects/PROJECT_ID/alertPolicies/0000000000/conditions/0000000000
creationRecord:
mutateTime: 'yyyy-mm-dd'
mutatedBy: foo@example.com
displayName: Alert Test Policy 1
documentation:
content: this is test
mimeType: text/markdown
enabled: true
mutationRecord:
mutateTime: 'yyyy-mm-dd'
mutatedBy: foo@example.com
name: projects/PROJECT_ID/alertPolicies/0000000000
notificationChannels:
- projects/PROJECT_ID/notificationChannels/0000000000
severity: WARNING
alertStrategy:
autoClose: 1800s
notificationRateLimit:
period: 300s
combiner: OR
conditions:
- conditionMatchedLog:
filter: |-
logName:"my-test-log"
textPayload:"A simple entry Critical"
displayName: Log match condition
name: projects/PROJECT_ID/alertPolicies/000000/conditions/000000000
creationRecord:
mutateTime: 'yyyy-mm-dd'
mutatedBy: foo@example.com
displayName: Alert Test Policy 2
documentation:
content: this is test
mimeType: text/markdown
enabled: true
mutationRecord:
mutateTime: 'yyyy-mm-dd'
mutatedBy: foo@example.com
name: projects/PROJECT_ID/alertPolicies/0000000000
notificationChannels:
- projects/PROJECT_ID/notificationChannels/0000000000
severity: CRITICAL
Grafana 側 Integration の修正
MyWebhookIntegration
の 「Template」を変更します。今回は Web と Mobile push notifications を変更します。修正内容は単純で、payload
をそれぞれ利用するようにするだけです。
MyWebhookIntegration > Templates > Web
MyWebhookIntegration > Templates > Mobile push notifications
また、「Route」の条件もちょっとだけ修正します。小文字critical
を大文字Critical
にします。これは、Cloud Monitoring の Alert に合わせるためです。
MyWebhookIntegration > Routes > if
デモ
2 つのログエントリを順番に実施します。
# Warning 用
gcloud logging write my-test-log "A simple entry Warn"
# Critical 用
gcloud logging write my-test-log "A simple entry Critical"
無事に通知が来ました 📢
Alert groups - Web - Warn Result
Mobile - Warn Result
Alert groups - Web - Critical Result
Mobile - Critical Result
おわりに
Grafana Cloud IRM / OnCall をつかってみました。Webhook 連携をつかえば、だいたいなんとかなりそうなのでいいですね。Datadog も OnCall サービスがでたようなので、Google Cloud も公式ででないかなとか期待してます。
Discussion