オンコールローテをチームに導入してみた (AWS Incident Manager + Slack連携)

## 雑談
先日何気なくグーグルマップで近所を眺めていたら、全然しらなかったおしゃれな雰囲気の銭湯をみつけました。早速シャンプーやタオルなどの入ったお風呂セットを抱えて銭湯の門を開くと、そこに湯舟はなく、代わりにコーヒーの良い香りが漂っており、おしゃれな店員さんがいました。なんと銭湯をリノベしたカフェだったのです。完全にお風呂にきた人の恰好だったので、めちゃくちゃ恥ずかしかったです。

さて、今日は私の所属しているチームでオンコールローテを導入することになったので、導入時の取り組みについて紹介できればと思います！

## 対象読者

* Incident Manger をこれから触ってみたい方
* オンコールローテ導入を検討していてどんな感じで回しているか知りたい方

## 導入の背景

私のチームでの従来の障害対応方法はシンプルに「気づいた人がやる」でした。
が、皆さんご想像の通り以下のような課題感がありました

:cry: 対応する/できる人が固定化されていて負荷が偏っている
:cry: 障害対応の知見の属人化している。対応できる人が長期のお休みしたらつらそう

当時入社1か月目だった私は、本番環境の障害対応になかなか手をあげられずにいました
その時の自分の心境も書いておくと以下のような感じです

:cry: 中途半端に口を出して障害対応の時間を延ばしたくない
:cry: 知見がない中のオペレーションででうっかり本番環境やお手製ツールを壊さないか不安

システム規模も大きく古くから稼働しているシステムだったので、AWSのマネコンなどから見えないお手製のツールやバッチも多く、余計抵抗を感じていました。

とはいえシステム障害というのは、性質上どうしても夜間対応なども発生し得るもので、負荷が偏っている人の辛みは計り知れず、ローテーションを導入してスキトラを進めていきたいということになりました。

## オンコールローテの回し方

SRE 本などに紹介されていた一般的なプラクティスに沿ってローテーションの方針決めをしました
ざっくりと以下のような方針となりました
* 障害対応の経験豊富な人と、経験浅い人がペアを組んで対応にあたる
* 他チームの人がエスカレーションでオンコールする際、今日の当番が誰か探して... みたいな手間はなるべく減らす
* オンコール当番の人がすぐ対応できなかった時、その時のエスカレーション自体も自動化する

## オンコール管理ツールの構築

最低限、ローテーションの回し方さえ決めればオンコールローテは始められます

> * 他チームの人が自チームにオンコールする際、今日の当番が誰か探して... みたいな手間はなるべく減らす
> * 当番の人が対応できなかった時、その時のエスカレーション自体も自動化する

ただそれだけだと上で決めたような方針は満たせないので、ツールを使うことにしました。過去採用実績もあり、契約周りを含めて導入しやすかった AWS Incident Manager を選びました。他ツールもざっと見た感じ機能面で大きな差はあまりなさそうという感触だったので、導入しやすいものを選ぶといいのかなと思っています。

作ったツールの全体の構成は以下で、結構シンプルです。
メインは incident manager ですが、他チームから Slack 上でエスカレーションを受けてオンコール対応するケースもあったので、そこの対応も行っています。

![oncall3.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591507/f32f84ea-eeed-b22a-fcfe-5e986ebf44de.png)


### Incident Manager
オンコールローテを管理するメインのリソースです。
機能の構成要素としては以下のようなものがあります。
* **オンコールスケジュール**: オンコール当番を管理するためのシフト表みたいな役割のリソースです。今週の担当はAさん、来週はBさんみたいな設定をここでしていきます。
* **エスカレーションプラン**: オンコール担当者が対応できなかった時のエスカレーション先を設定します。今回は障害発生時に当番の人が外出先にいたり、すぐに対応できないケースを想定して設定しました。
* **対応プラン**: 「特定の種類の問題にどのように対応するか」の具体的な手順を定めたものです。今回は(本来の用途とは若干ずれる気もしますが)チームへオンコールする専用のプランを設定していきます。

**オンコールスケジュール**
前提としてコンタクト(連絡先)の追加が必要になりますので、作成しておいて貰えればと思います。
[参考ドキュメント](https://docs.aws.amazon.com/ja_jp/incident-manager/latest/userguide/contacts.html#contacts-channels)

`qiita-a,b` さんが経験豊富なメイン担当、`qiita-c,d,e` さんが新規参入者のイメージで設定しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591507/9ce5abf5-74e2-de3d-7a67-bd6540d0839d.png)

↑の画像はメイン側ですが、サブも同様に設定します。
するとこんな感じで、シフト表がでてきます。わかりやすいですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591507/88a7c676-8aa5-9f7b-fd38-5d7b9a75b34d.png)


**エスカレーションプラン** 
続いてエスカレーションプランを設定します。以下のような設定になっています。

* **ステージ1:** 上で作った `qiita-test` というオンコールスケジュールに沿って連絡します。ステージ期間(30分間)リアクションがなかったらステージ2にエスカレーションします。
* **ステージ2:** メイン担当の `qiita-a,b` さんに再度連絡します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591507/93bdaa95-ab7c-e928-86f8-af5e695db5d8.png)

**対応プラン** 
最後に対応プランを作成していきます。本来は自動化したい障害対応の操作の単位で作っていくもののようです。若干本来の用途から外れる気もしますが、今回は「自チームにオンコールする」するための汎用的な対応プランを作っていきます。
名前や概要などは適切に入力してもらって、「**エンゲージメント - オプション**」に先ほど作ったエスカレーションプランを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591507/c55edc5d-da73-423c-0998-acb73fd73c5d.png)


**インシデントを作成**
ここまできたら準備完了です。最後に、Incident Manager のトップ画面から「インシデント開始」を押します。
今オンコール担当になっている人の連絡先に、設定した通知(電話なり、SMS通知なり)が飛んでくるかと思います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591507/56438d6c-9dc7-271b-c6a4-704ff8f46e0d.png)


### Slack との連携
他チームからエスカレーションを Slack 上でうけることが多かったので、Slack からオンコールできるようにしました。**Slack WorkFlow** でフォームの表示と AWSCLI の組み立て、**AWS Chatbot** で組み立てた CLI を実行して AWS 上にリソース作成(インシデントの開始)を行っています。

#### Slack WorkFlow

具体的な役割としては、オンコール用のフォームを表示して、記入内容から AWSCLI を組み立てを行っています。
(現状していないですが webhook をトリガーにして workflow 呼び出しもできるので、フォーム入力のような手動のトリガーでない場合にも使えそうです)

**フォーム**
障害対応時は文章を書く余裕がないと思うので、なるべくシンプルな入力項目にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591507/6c44d6e7-21a7-a653-f315-f087b42bb582.png)

**組み立てる AWS CLI**
```
@aws ssm-incidents start-incident --impact {{{{steps.incident_detail_form.fields.Xxx}}}} --response-plan-arn arn:aws:ssm-incidents::Xxx:Xxx/Xxx --related-items [{"identifier":{"type":"INCIDENT","value":{"url":"{{{{steps.incident_detail_form.fields.Xxx}}}}"}},"title":"IncidentSlackLink"}] --title {{{{steps.incident_detail_form.fields.incident_title}}}} --region ap-northeast-1
```

#### AWS Chatbot
これは Slack 上のメンションを拾って AWS Incident Manger にインシデントチケットを作成する目的で使っています。
今回は Slack から AWS リソースの操作するのに使っていますが、逆に AWS 起因のアラートを Slack に投げたりも出来ますね。

複雑なものではないので、具体的な設定手順はクラメソさんの記事の紹介に留めて割愛したいと思います
https://dev.classmethod.jp/articles/aws-chatbot-supports-managing-aws-resources-in-slack/

↑の設定をしたあと Slack ワークフローを実行すれば、自動でオンコールされるようになったかと思います。

### やってみて感想
* 導入してまだ数か月くらいですが、スキトラの１つのきっかけになっているとは思います。
* チーム全体で障害対応の知見共有するような会話が増えた気がします。個人的にはローテーションに参加したこと自体が、障害対応の学習モチベアップに繋がった感もあります。
* 担当の人が絶対でないといけない...は逆にプレッシャー増える可能性もありそうです。たまたま外出中ということも全然あると思いますので、最終的にはチーム全体でうまく回す前提の雰囲気作りは必要だと思います。

### 今後やりたいこと
Incident Manager の機能の一つに、インシデントが発生した際のランブックの自動実行があり、これを活用したいなと考えています。
今は前段階として、インシデントの発生原因や解消操作などをポストモーテムにまとめることに注力していますが、そのおかげで少しずつオペレーションが自動化できそうなところも見えてきています。

復旧までの時間がぐんと短くなるのに加え、開発者の操作が必要な障害の数も減るので、ビジネス的にも開発者の負荷的にも嬉しいはずで、このあたりの実施を次の目標にしていければと思っています。