PagerDutyのアプリ連携(Slack/JIRA/Custom Incident Action)

PagerDutyは実に多くのアプリケーションと連携を取ることができます。よく使われると思われる連携について説明していきたいと思います。
Slackとの連携
チャットツールと連携させることで、わざわざWebブラウザで画面を開くことなく、チャットでAcknowledgeできるようになります。メニューのConfigurationからExtensionsを選択し、New Extensionボタンをクリックします。

Extension TypeにSlackを入力し、Nameに連携の名前を入力し、連携させるPagerDutyのServiceを選びます。そしてSlackへの通知に対してアクションを起こせる人は誰なのかをActions available toのプルダウンから選択します。any Slack userであれば誰でもAcknowledgeしたりできますし、PagerDuty users onlyにすればPagerDutyにアカウントを持っていなければなにもできません。そして何を通知するかをチェックボックスで選んでAuthorizeボタンをクリックします。

するとSlackのOAuth認可画面になりますので、通知を行いたいSlackのチャンネルを選び、Authorizeボタンをクリックすれば設定は終わりです。

通知を行う場所はすべてのサービスに対するインシデントをまとめておくチャンネルを用意するのがよいのではないかと思います。プライベートチャンネルへの通知に設定することも可能ですが、当然ながら設定をする人がそのチャンネルにアクセスできる必要があります。
実際にインシデントがトリガーされると、次のように設定したチャンネルへメッセージが通知され、そこにAcknowledgeとResolveのボタンが設置されています。

Acknowledgeは複数の人が行えるようになっているので、誰かがAcknowledgeしてもボタンはそのまま残ります。誰が対応しているのかはっきりさせるため、複数人で対応する場合はかならず全員Acknowledgeするようにしたほうがよいでしょう。

一方でResolveボタンは誰かが操作するとボタンは非表示になります。操作した人と日時も表示されているため、チャットツール上で基本的な操作は完結します。
このSlack連携のボタン操作は、Slackがメッセージに対してボタンなどをつけることができるようになる前から連携を使用している場合は表示されません。そういう場合は一度連携を解除し、もう一度連携を設定し直す必要があります。
JIRAとの連携
課題管理ツールであるJIRAと連携し、インシデントと関連付けてJIRAの課題(Issue)を作成できます。インシデント発生に対して、一次対応以外の固定的な作業が発生する場合、例えば翌営業日に担当者がインシデントレポートを読むとか、インシデントの振り返り会議をセッティングするとかの際に便利でしょう。
まずJIRA側でアドオンの設定を行います。SettingsからAdd-onsへ行きFind new add-onsでPagerDuty アドオンをインストールします。

特に設定は必要ありません。次にPagerDuty側の設定です。Slack連携と同様にNew Extensionから設定を行います。

JIRA Cloudのサブドメインを入力し、Connect JIRA Accountをクリックします。

連携させるPagerDutyのサービスと、Issueを起こすJIRAのプロジェクトを選択します。するとダイアログが表示されるのでIssue TypeとIssueのStatusを設定します。先に述べたような使い方の場合、PagerDutyのStatusがOpenのときにJIRA IssueをOpen、ResolvedのときはNo status changeという設定がよいでしょう。

Create Test Issueをクリックしてみましょう。特にメッセージが表示されませんが、JIRA側にIssueが出来上がっています。


設定が終わると、インシデントの詳細画面にJIRA Issueを作るメニューが追加されます。ここからIssueを作成すると、JIRA IssueにPagerDutyのインシデントへのリンクとStatusが追加されているのが確認できます。

しかし残念なことにJIRA IssueのタイトルはIncidentのタイトルが固定的に付与されてしまうため、「Incident reportを読む」などと具体的な記述をすることは現時点ではできません。
また、1つのインシデントに対して、JIRA Issueは1つしか作ることができませんので注意が必要です。
もっと具体的で細かいIssueを作りたい、1つ以上のIssueをPagerDutyから作りたい、という場合には次に紹介する機能を使えば実現可能です。ただし、若干のコーディングが必要になります。
カスタムインシデントアクション
ExtensionからCustom Incident Actionを選択すると、好きなWebhookを呼び出すボタンを作成できます。


URL Endpoint へは HTTP POST で インシデントの詳細が JSON 形式でデータが渡されます。データの詳細については公式ドキュメントを参照ください。contents という key の中にエスケープされた状態で JSON が渡ってきます。定形作業をスクリプト化しておくことで、例えば特定のプロセスを再起動するなどということが簡単にできるようになります。

この時重要なのは、インシデントのメッセージ中にサーバ(あるいはサーバ群)を特定できる情報を含めておくことです。また、このエンドポイントはインターネット上に公開されたものでなければいけないので、実装には注意が必要です。不用意な実装をすると、知らない誰かが勝手にサーバをシャットダウンできてしまう可能性があります。
curl -s https://app.pagerduty.com/webhook_ips
上記のAPIから JSON形式で現在PagerDutyがWebhookを起動するときに使用しているIPアドレスを得ることができるので、これを利用してホワイトリスト化するのがよいでしょう。このIPアドレスは特に予告なく変更される可能性があるため、ファイヤウォールで弾くようにする場合は、定期的にチェックして更新する必要があります。公式ドキュメントではこちらのスクリプトが紹介されていました。
カスタムインシデントアクションは様々な用途で使えると思いますが、例えば以下のような用途が思いつきます。
- サーバやプロセスの再起動
- JVMの Heap dumpやThread dumpの取得
- サーバのスケールアウト
- 前回動作していたアプリケーションへのロールバック
- 前述したJIRA Issueをもっと細かく制御
このWebhookを受けるためだけにサーバを用意したくない、という場合もあるでしょう。AWSであればAPI GatewayとLambdaを組み合わせて、サーバレスでWebhookを受けるのがお勧めです。もっと単純、お手軽にやりたいということであれば、Google Apps ScriptをWebアプリケーションとして公開し、doPost関数を実装するというやり方もあります。
また、Custom Incident ActionはPagerDutyのモバイルアプリから起動することもできます。

Custom Incident Actionをうまく設定しておくことで、PCが手元にない状態であってもインシデントの一次対応、ないしはその補助をすることができるようになります。
まとめ
PagerDutyのExtensionsで設定できる、Slack連携・JIRA連携・Custom Incident Actionについて紹介しました。どの機能も便利ですが、中でもCustom Incident Actionはかなり強力な機能です。自分で実装が必要な分、他の機能よりもハードルが高いですが、実質なんでもできるのが魅力です。ぜひ活用してインシデント対応を楽にこなせるようにしましょう。
今回はSlackとJIRAとの連携を解説しました。PagerDutyはほかにもたくさんのツールとの連携が可能です。連携についての日本語の解説はこちらから参照できます。