オンコールを設計する際に考えたこと

本記事は SRE Advent Calendar 2022 20日目のエントリーです:christmas_tree::santa::gift:

あくまで弊社の例ではあるのですが、オンコール対応を始める際と運用時に考えた事をまとめてみました。

## オンコールとは？

オンコールとは、勤務時間外に緊急インシデントが発生した場合に、特定の従業員がその問題に気づき対応できるようにする仕組みのことです。

オンコール当番は、緊急インシデントの調査/修正ができるよういつでも連絡を取れる状態にしつつ、有事の際には問題を解決してサービスを正常な状態に戻すアクションを実行します。

以降、どのような観点でオンコール設計をしたかざっくりと紹介します。

## オンコールの必要性を考える
まず、オンコールの必要性について考えました。

対象とするサービス/システムについて

- 利用者から年中無休の可用性が期待されるサービスか？
- 停止すると事業継続ができなくなるものか？

等を考慮しつつ、 
`停止時のリスク/コスト vs オンコール対応のコスト` どちらを優先するかをステークホルダーと共に検討して決定しました。

停止時のリスク/コストは対象のサービスにより様々かと思いますが、オンコールのコストには、
`オンコールツールの料金 + オンコール手当て + 社用携帯費用 ...etc` がかかります。

これを踏まえてオンコール対象外と判断したサービスは、
`基本的に翌営業日対応、緊急を要する時でもベストエフォート対応になる点についてステークホルダーと合意を取る` ようにしました。

なお、オンコール当番を担当できるメンバーは、
`対象サービスの特性を熟知しており、アラートをトリアージして問題を修正できるスキル`[^1]を持っている必要がある事を共通認識としました。

## オンコールのコスト

具体的には以下のようなものがかかってきます。

#### オンコール手当+α

オンコール手当には歩合制等いろいろな考え方がありますが、弊社ではシンプルに `月額+α` で対応しています。

- オンコール手当：**1人数万円/月**
- 業務時間外の場合でも実働時間を計測できるよう打刻して対応
    - 業務時間外、休日及び深夜の割増賃金はオンコール手当と別に実働時間分きちんと支給(**これが+α**)されるよう制度を整える

オンコール当番の期間中、一度も業務時間外の対応が発生しなくてもオンコール手当は支給されます。
また、休日中にオンコール対応が一定時間以上発生した場合は代休が利用可能となりますが、有効期限内に代休消化ができなかった場合は賃金として還元されます(労基に則ります)。

現時点では上記のようなルールで運用していますが、内容はオンコールの発生頻度等を考慮し、随時見直す必要があると考えています。

**参考**

https://www.atlassian.com/ja/incident-management/on-call/on-call-pay


#### 社用携帯/ラップトップPC貸与のコスト

オンコール担当者には、外出時のテザリング/動作確認等で利用する為に、社用携帯/ラップトップPCを貸与します。
※既にラップトップPCが支給されている人には社用携帯のみを貸与します。

コストは **1人数千円/月** 程度です

#### ツール利用のコスト

様々なObservabilityソリューション/モニタリングツール等と連携して、システムアラートを集約・選別し、必要なアラートのみをオンコール当番にのみ確実に通知するため、オンコール用のツールを利用します。

コストは **1人数千円/月** 程度ですが、年間契約が必要になる場合もあります。


## オンコール設計
以下のようなルールで運用しています。

#### 体制
- SRE2名+Dev2名 計4名体制で当番を担当[^2]
- 1週間単位でローテーション
- 当番にもPrimary-Secondaryのような優先対応順位をつける
- 例)SREチームが4名体制の場合、大体月1回当番が回ってくる感じ
    - Secondary週 -> Primary週 -> 2週空き のようなローテーション
- オンコール当番は平日は通常業務をしつつ、夜間/休日等の業務時間外でもオンコール対応ができる状況にしてもらう
    - 外出は禁止ではないが、外出する際はPC/社用携帯を持参する
- どうしても対応が出来ない予定がある日は、別のメンバーとスケジュールを変わってもらう等、柔軟に対応できるようにする

#### ツール設定
- ツールはPagerDutyを利用
    - 通知とスケジューリングのみの用途で利用(Professionalプラン[^3])
- Criticalなアラートの通知先として設定
    - オンコール当番にのみPagerDuty経由で通知が飛ぶよう設定
- 通知ルールは個々におまかせ(以下は例)
    - **Immedietely:** slack, push→:iphone:(PagerDutyアプリ)
        - **:bulb:** PagerDutyへのPush通知はApple Watch:watch:にも来るので大体はここで気付ける
    - **5minutes:** :telephone_receiver: →:iphone:(社用携帯)
    - **10minutes:** :telephone_receiver: →:iphone:(私用携帯)
    - **30minutes:** :telephone_receiver: → :house:(家の固定電話ｗ)

特にトリッキーな設定を行う必要はなかったので、代理店の日本語ヘルプのサイトを見ながら割とスムーズに導入できました。

**参考**

https://pagerduty.digitalstacks.net/casestudy-vega-corporation/

#### その他
- 社用携帯/モバイルPC紛失時のリスク対策
    - 万が一の紛失時に備えてリモートワイプができるよう設定する
- SREオンボーディングのゴールの1つに `オンコール当番が担当できる事` を設定
    - 新メンバーに、オンコール対象システムの構成、過去のインシデント事例等を共有したり、担当者のスキルに応じて内容を変えながらオンコール当番が担当できるようレクチャーする


以上です。

## まとめ
いかがでしたでしょうか？

まだ伸びしろとして、Runbookの整備、インシデントの効率的な管理、レジリエンス(回復力)向上、等があるかなと考えていますが
現時点では、それほどインシデント発生頻度は多くなく（月0-3件？程度）そのうち、やっていこうかなという温度感です。

ちなみに余談ですが、弊社ではSREのヘルプデスクはオンコールSecondary当番がメインで担当するようにしています。

ヘルプデスクもSREの重要なタスクの一つですが、当番を決めずに運用すると

- 知識や定形業務に偏りが生じやすくなる
- 随時割り込みが発生し、自身のタスクに集中しづらくなる

などという問題が発生するため、オンコールスケジューリング機能を使ってヘルプデスクもローテーションで運用するようにしました。

もちろん初めてやる業務や知識不足なタスクに関しては他のメンバーに質問しつつも、ヘルプデスクのローテーションを導入することで業務/知識の平準化ができるようになってきたと感じています。

ざっくりとした内容にはなりましたが、オンコールをこれから検討するという人に弊社の事例が参考になれば幸いです。

#### 参考
https://www.atlassian.com/ja/incident-management/on-call#:~:text=%E3%82%AA%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%AB%E3%81%A8%E3%81%AF%E3%80%81%E5%BE%93%E6%A5%AD%E5%93%A1,%E3%82%92%E6%8F%90%E4%BE%9B%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82

https://ueokande.github.io/incident-response-docs-ja/oncall/being_oncall/#:~:text=%E3%82%AA%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%AB%E3%82%92%E5%A7%8B%E3%82%81%E3%82%8B%E3%81%A8%E3%81%84%E3%81%86%E3%81%93%E3%81%A8,%E3%81%93%E3%81%A8%E3%82%92%E6%84%8F%E5%91%B3%E3%81%97%E3%81%BE%E3%81%99%E3%80%82


[^1]:オンコール当番にもスキルの差はあるので、ベテランと若手、フロントとバックエンドのようになるべく広い守備範囲で対応ができるようメンバーのアサインを工夫します。

[^2]:弊社の場合、現状はこの体制で事業側と合意を取り問題なく回せていますが、インシデント発生状況等を踏まえて必要に応じて随時見直す必要があると考えています。

[^3]:上位のプランではインシデント管理機能が利用できたり、同時に5件以上に通知できたりしますが、現時点で弊社の場合はProfessionalプランで得に問題は無い状況です。