Grafana OnCall で Twilio を使って電話を受ける

[Twilio Advent Calendar](https://qiita.com/advent-calendar/2022/twilio) 4日目の記事です。

今年 (2022年) の6月に「[Introducing Grafana OnCall OSS, on-call management for the open source community](https://grafana.com/blog/2022/06/14/introducing-grafana-oncall-oss-open-source/)」という記事で Grafana OnCall のオープンソース化が発表されました。PagerDuty みたいなやつです。

- [What is Grafana OnCall OSS?](https://grafana.com/oss/oncall/)
- [GitHub](https://github.com/grafana/oncall)
- [Grafana OnCall open source guide](https://grafana.com/docs/oncall/latest/open-source/)
- [Grafana OnCall documentation](https://grafana.com/docs/oncall/latest/)

![How does Grafana On Call work for  incident response management?](https://grafana.com/static/img/docs/oncall/oncall-alertworkflow.png)

(画像はドキュメントサイトより)

セルフホストの Grafana OnCall が電話を掛けるのに Twilio を使うらしいので試してみます。(Grafana Cloud なら無料ですぐ使えます :smile: )

現在の Grafana OnCall は通知の受け口として次のインテグレーションを持っています。PagerDuty と比べてしまうと少ないですね。でも Webhook があるからなんとかなるかな。

- Grafana Alertging
- Alertmanager
- Zabbix
- Webhook

Chat の通知先としては次の3つをサポートしています。

- Slack
- Telegram
- Microsoft Teams

Twilio の設定については [ここ](https://grafana.com/docs/oncall/latest/open-source/#twilio-setup) に次のように書かれています。

> ### Twilio Setup
> Grafana OnCall supports Twilio SMS and phone call notifications delivery. If you prefer to configure SMS and phone call notifications using Twilio, complete the following steps:
> 
> 1. Set `GRAFANA_CLOUD_NOTIFICATIONS_ENABLED` as **False** to ensure the Grafana OSS ↔︎ Cloud connector is disabled.
> 2. From your **OnCall** environment, select **Env Variables** and configure all variables starting with `TWILIO_`.


## Docker Compose で起動

お試し実行なので手元の mac で Docker Compose を使って実行します。

README の [Getting Started](https://github.com/grafana/oncall#getting-started) に手順があります。

GitHub にある docker-compose.yml を取得します。

```bash
curl -LO https://raw.githubusercontent.com/grafana/oncall/v1.1.5/docker-compose.yml
```

Grafana のコンテナイメージが `grafana/grafana:9.0.0-beta3` だったので最新の `9.3.0` に、[oncall](https://hub.docker.com/r/grafana/oncall) は `v1.1.5` を明示しておきます。 (macOS の sed じゃなくて GNU の sed を使うため `sed` ではなく `gsed` としています)

```bash
gsed -i \
  -e 's,grafana:9.0.0-beta3,grafana:9.3.0,' \
  -e 's,image: grafana/oncall$,image: grafana/oncall:v1.1.5,' docker-compose.yml
```

必要な環境変数を `.env` ファイルに設定

```bash
echo "DOMAIN=http://localhost:8080
COMPOSE_PROFILES=with_grafana  # Remove this line if you want to use existing grafana
SECRET_KEY=$(pwgen 64 1)" > .env
```

(これで docker compose の [profiles 機能](https://docs.docker.com/compose/profiles/)を知りました。便利)

いざ実行

```
docker-compose pull && docker-compose up -d
```

## Grafana 上で操作

Grafana OnCall は Grafana から操作することになります。OnCall サーバーは Grafana サーバーから HTTP(S) でアクセスできる場所にあればどこでも大丈夫です。今回はどちらも Docker Compose の中で実行されています。

ブラウザで http://localhost:3000/ を開くと Grafana にアクセスできます。
デフォルトでは Username: `admin` / Password: `admin` です。

ログインしたら画面左下の歯車アイコンから **Configuration** → **Plugins** を開きます。

![Configurations menu](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/494e42bf-1c40-6264-7fce-c923a8c664c8.png)

Search grafana plugins と書かれている入力欄に oncall と入れれば Grafana OnCall が見つかります。

![Search OnCall plugin](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/fb695f26-9080-cdab-bd04-adfb51b28968.png)

Grafana OnCall パネルをクリックして開きます。ここで青い **Enable** ボタンをクリックして有効化し、下の OnCall backend URL に `http://engine:8080` を入力して **Connect** ボタンをクリックします。

![Enabling Grafana OnCall](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/48476e9b-2ee0-3f4a-0bf6-d8fb742e9856.png)

接続されました。

![Grafana OnCall Connected](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/317964c9-e173-4ee0-a975-951d0a8583ae.png)

Plugin を有効化したことにより、左のバーに OnCall のアイコンが追加されました。
しかし、 Plugin has not been initialized と表示され、Retry しても Configure Plugin で backend URL を再設定しても解消されませんでしたが、ブラウザでページを reload したら initialize されました。

![Grafana OnCall Plugin not initialized](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/5bbeb3d7-c211-4d52-96b0-4594acace204.png)

そして、次のような画面に遷移しました。

![Grafana OnCall Plugin](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/24ae9b27-260b-d183-d72e-46ad2c0664e2.png)

ここで Env Variables タブに移動します。ここが[ドキュメントの Twilio Setup](https://grafana.com/docs/oncall/latest/open-source/#twilio-setup) に書かれていたやつですね。

- `GRAFANA_CLOUD_NOTIFICATIONS_ENABLED` を `False` にする
- `TWILIO_` で始まる項目を全部設定する

![Grafana OnCall Env Variables](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/dbe4847e-c185-5367-01ca-039ce401d629.png)

| Name | Description |
|------|-------------|
| TWILIO_ACCOUNT_SID | Twilio account SID/username to allow OnCall to send SMSes and make phone calls, see [here](https://support.twilio.com/hc/en-us/articles/223136027-Auth-Tokens-and-How-to-Change-Them) for more info. Required. |
| TWILIO_API_KEY_SECRET | Twilio API key secret/password to allow OnCall to send SMSes and make phone calls, see [here](https://www.twilio.com/docs/iam/keys/api-key) for more info. Either (TWILIO_API_KEY_SID + TWILIO_API_KEY_SECRET) or TWILIO_AUTH_TOKEN is required. |
| TWILIO_API_KEY_SID | Twilio API key SID/username to allow OnCall to send SMSes and make phone calls, see [here](https://www.twilio.com/docs/iam/keys/api-key) for more info. Either (TWILIO_API_KEY_SID + TWILIO_API_KEY_SECRET) or TWILIO_AUTH_TOKEN is required. |
| TWILIO_AUTH_TOKEN | Twilio password to allow OnCall to send SMSes and make calls, see [here](https://support.twilio.com/hc/en-us/articles/223136027-Auth-Tokens-and-How-to-Change-Them) for more info. Either (TWILIO_API_KEY_SID + TWILIO_API_KEY_SECRET) or TWILIO_AUTH_TOKEN is required. |
| TWILIO_NUMBER | Number from which you will receive calls and SMSes, [more info](https://www.twilio.com/docs/phone-numbers). |
| TWILIO_VERIFY_SERVICE_SID | SID of Twilio service for number verification. You can create a service in Twilio web interface. twilio.com -> verify -> create new service. |


## Twilio の設定

サインアップしたら Account SID と Auth Token は確認できます。

![Twilio Console](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/4502cda4-394c-72fd-c32e-3f402db057b0.png)

次に電話番号を取得する必要があるようです。青い **Get a Twilio phone number** ボタンをクリックすると You've got a phone number! と表示されてすぐにアメリカの電話番号が取得できました。

![Get a Twilio phone number](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/b1705936-917d-323c-3fe3-656cf2b14bd6.png)

次に進むと API 呼び出しの curl コマンドが表示されるのでこれをコピペして実際に電話がかかってくるか確認することができます。`To` に指定されているのが私の電話番号で `From` に指定されているのが先ほど発行されたアメリカの電話番号です。

![Make your first call](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/0cfd4ad2-5185-c740-5e34-a89b00048522.png)

Twilio Console の右上にある **Account** メニューから **API keys & tokens** にアクセスして Create API key に進めば、無効化の可能な API key を発行することが可能で、こちらを使うのがよりセキュアなようです。 `TWILIO_AUTH_TOKEN` ではなくて `TWILIO_API_KEY_SID` と `TWILIO_API_KEY_SECRET` を設定することにします。

Grafana OnCall という名前の Key を作成します。SID と Secret が作成されます。

![Create new API key](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/b683c5b1-52e0-0fea-1ce1-cd4464166959.png)

残すは `TWILIO_VERIFY_SERVICE_SID` なのだけれども、はて？ 

> SID of Twilio service for number verification. You can create a service in Twilio web interface. twilio.com -> verify -> create new service.

Twilio Console の左のメニューに Verify というのがない場合は **Explore Products** から **Account security** → **Verify** でたどり着けました。

![Explore Products](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/bfff99f1-2c1f-5349-b956-3fb11f7a2a20.png)

ピン留めアイコンをクリックしておけば左のメニューにも表示されるようになります。

![Services](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/7324b777-e6eb-4670-ceaf-63e3913467c0.png)

Grafana OnCall という名前で Service を作成しました。

![Create a new service](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/e8a0f465-1486-0dff-86da-7f501db3bec0.png)

やっと必要な情報が揃いました。

| Name | Description |
|------|-------------|
| TWILIO_ACCOUNT_SID | Twilio に singup すると発行される Account の ID |
| TWILIO_API_KEY_SECRET | Grafana OnCall 用として作成した API Key の Secret |
| TWILIO_API_KEY_SID | Grafana OnCall 用として作成した API Key の ID |
| TWILIO_AUTH_TOKEN | API Key を使うのでこれは設定しない |
| TWILIO_NUMBER | 発行した発信用電話番号 (トライアルアカウントなのでアメリカの番号) |
| TWILIO_VERIFY_SERVICE_SID | Verify Service の SID |

Grafana の UI からポチポチ設定すれば restart などは不要で使えるようになります。

## Grafana の user に電話番号を設定する

Grafana OnCall の Users タブを確認すると admin ユーザーの Status 列に `Phone not verified` と表示されています。

![Users](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/bb64b0ad-cbb2-bc5a-e5c3-77cd61779474.png)

ここで **Edit** をクリックして Phone Verification タブで電話番号を入力し、 **Send Code** ボタンをクリックすると SMS で6桁のコードが送られてきます。

![Phone Verification 1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/9e52f459-34cb-5506-cbb4-c165acfcd461.png)

受け取ったコードを入力して **Verify** ボタンを押せば登録完了です。

![Phone Verification 2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/c2607ead-d8c0-de7e-77fb-bacb72c0afb1.png)

これで **Make Test Call** ボタンをクリックすると電話がかかってきてテストメッセージが読み上げられます。

![Phone Verification 3](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/edf1c55d-b63f-29f6-cb20-bdcaf4498eab.png)

## Alert 通知をしてみる

### User 設定

**Users** タブで admin ユーザーの **Default Notifications** を `Notify by SMS` に、 **Important Notifications** を `Notify by Phone call` にします。

![Notification Setting](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/22fedad8-99f2-c9aa-49c5-ffa076675a95.png)

### Escalation Chain 設定

**Escalation Chains** タブで **New Escalation Chain** ボタンから **test** という Escalation Chain を作ってみました。
まず admin ユーザーに Default notification で通知し、1分待った後、今度は admin ユーザーに Inportant notification で通知します。

![Create Escalation Chain](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/fa80f6aa-6a78-0bd8-50ff-2be20b925ae9.png)

次に **Integrations** タブで **New Integration for receiving alerts** ボタンから **Grafana Alerting** でも **Webhook** でも **Formated Webhook** でも何でも良いので選択して

![Create Integration](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/f892a01f-4da4-f921-6a6a-ac055964ac6b.png)

Escalation 先に先ほど作成した `test` を選択します。 **Send demo alert** というボタンがあるのでこれをクリックすると SMS での通知が届き、放っておくと1分後に電話がかかってくるのが確認できます。

![Integrations](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/e34dd071-d2b6-2ce4-6fa1-96357068832e.png)

## Twilio の Monitoring 機能

費用や電話、SMS の回数などは Monitoring 画面で確認できます。

### Billing Usage

費用は重要ですね

![Billing Usage](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/8e6cfbbd-d5f4-1a79-59b3-61340f51c4bb.png)

### Calls

![Calls Insights](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/80da0124-1a45-bd06-dc24-94c1090c913f.png)

### Messages

![Messages Insights](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8739/5fb54a81-9b3b-3c4f-da93-07e1ddd6fed0.png)


## まとめ

今回はひとまず Twilio を使って SMS と電話で通知ができるというところまでを確認しました。
Grafana OnCall には通知先のスケジュールやローテーション設定もできます。
Alert の内容によって通知先を切り替えたりするルーティング設定もできます。
興味を持たれたら試してみてはいかがでしょうか。