エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

クラウド電子カルテサービスのSLO監視を再検討してみた話

本記事は エムスリー Advent Calendar 2020 の4日目の記事です。

こんにちは、エンジニアリンググループの高橋(@tshohe1)です。

これまでは全チームを横断的に見る SRE チームで主に働いていたのですが、数ヶ月前からサービス側のチーム(電子カルテチーム)にも参加するようになりました!
参加時のミッションはクラウド電子カルテ「エムスリーデジカル」(以下デジカル)のアーキテクチャ刷新にあたり監視周りの設定を1から検討する」というもので、本記事はその流れをまとめたものになります。

アーキテクチャ刷新の背景

デジカルの事業の成長速度は著しく(2年で利用施設数はなんと10倍!)、これまでの構成ではこれ以上スケールさせることが出来ないコンポーネントも出始めていました。そこで従来までの単一環境を辞め、一定利用施設数ごとに環境を用意(水平分割)する方針に変更することになりました。このあたりの詳しい経緯については下記記事にまとめられているので、気になる方はこちらをご参照下さい。

www.m3tech.blog

監視の再検討 / 解消したい課題

前述のアーキテクチャ刷新の伴い、監視の構成も少し見直す必要が出てきました。
また従来の監視設定には下記のような課題もあったため、これらの解消も目標としました。

  1. アラート設定項目が多く、頻繁に Slack に通知が来てしまい対応者が疲弊する
  2. 監視設定名と通知先が揃っていないものがある
    • Terraform 管理で通知先だけを切り替えるケースがあるせいか、Alarm 名は重要そうに見えても個人端末に通知が行かないものがあったりしました(紛らわしい)

監視設定の流れ

各種SRE本や色々な記事*1から、下記のような手順で監視を設定していくのがいいのではないかと考え実践してみました。

ステップ1: システム構成図整備

まずは構成図*2の作成が必要かなと思います。構成図があることによって下記のような作業が効率化されるはずです。

  • システムの構成についての理解が楽になる
  • パフォーマンス問題が発生した際の調査で役に立つ
    • ボトルネックとなりそうな箇所がわかりやすくなっている

今回は幸いにも私が参加する以前の新規構成の検討段階で作成された構成図が既に存在していたため、こちらの作業はスキップできました。

ステップ2: リソースリストの作成

システムの構成要素となる AWS のコンポーネントを SpreadSheet に列挙していきました。

  1. AWS サービスを列挙(例: AWS/ALB, AWS/RDS...)
  2. そのサービスで作成するリソースを列挙(例: ~alb, ~db...)

ステップ3: 利用可能なツールで取得可能なメトリクスを列挙

更に取得可能な全てのメトリクス(例: ActiveFlowCount, DatabaseConnections...)についても表にまとめていきます。またここでは、ツール選定の判断材料とするために、CloudWatch 以外の利用を検討している他の監視ツール(Datadog 等)で取得できるメトリクスについても列挙しました。

ステップ4: 通知のクラス分け

個別に通知先を個別に決めるのは大変なので、下記4パターンに分類しました。

クラス 通知先 概要
fatal - 個人端末のメールアドレス
- 緊急用Slack
即時対応が必要なもの。また自然回復する可能性が高いものでもシステム影響が大きいものについてはこちらの通知を設定する。
warn - 社内メールアドレス
- 社内用Slack
緊急性が低い、あるいは自然回復する可能性が高いが、念の為発生したことを通知しておきたいもの。監視が安定してきたらこのクラス不要になってくると考えられる。
ticket - 初回のみSlackのJIRA Integrationによる通知 即時の対応は不要だが、いずれは何らかの作業を実施しなければならないもの。リソース使用量が上がっていてキャパシティ不足になりそう等。
logging - 無し 調査用に残しておきたいイベントなど。通知は無しでCloudWatch Logsに残すだけ。

通知の流れは図で書くとこんな感じです。各クラスごとにトピックを作成し、上記通知ルールを設定しました。

f:id:tshohe:20201203181541p:plain
通知クラスごとの通知の流れ

ステップ5: SLIの選定

各システムの構成要素ごとに、医療施設の業務において重要な機能に影響する項目*3をステップ3で作成したリストにあるメトリクス or そのメトリクスの組み合わせで表現できるメトリクスからピックアップしました。

  • 重要な機能を提供するためのAPIのリクエスト成功率
  • 前段のLBのリクエスト成功率
    • 特定 URL でフィルタリングしない全体の監視
  • 重要な機能を提供するための非同期処理用のキューの滞留メッセージ数 等

またこの際 アラート設定が多く、頻繁に Slack に通知が来てしまい対応者が疲弊する を防ぐという目標のため、監視対象はシステム影響が出ているものに限定し、CPU使用率等のノイズになりうるものはなるべく除外するように意識しました。

ステップ6: SLOの設定

アラートの閾値を決めていくにあたって、設定対象が多い場合は個別に設定していくのは大変骨の折れる作業です。もちろん精度はそちらのほうが高くなるとは思いますが、アラート対象が増えると閾値を管理するコストも増加していきます。

今回の対象はデジカルという単一サービスではあるものの、内部では数多くのコンポーネントで構成されており、それぞれで SLO を設定したほうが良いと考えたため、設定対象がそれなりの数(20弱)になってしまいました。

それに対する解決法として、The Site Reliability Workbook(SRE本第二弾)に記載のあったクラス分けして設定する手法を採用しました。
※ SLI "リクエスト成功率" についてのみ

クラス 概要 設定SLO
CRITICAL 最重要機能
例: ログイン処理
リクエスト成功率 99.95%(+ 一定レスポンスタイムを超えたものはエラー扱い)
HIGH_FAST 重要性が高く、尚且早いレスポンスが求められるもの
例: 電子カルテ閲覧
リクエスト成功率 99.9%(+ 一定レスポンスタイムを超えたものはエラー扱い)
HIGH_SLOW 重要性は高いが処理時間も長いもの
例: バッチ処理
リクエスト成功率 99.9%
LOW 重要性が低いもの
例: ダウンしても影響が軽微なコンポーネント
リクエスト成功率 99%

ステップ7: アラート処理の実装

こちらの発表 でも紹介されていますが、新環境では AWS CDK で CloudFormation テンプレートを作成しインフラの変更を適用しています。そのため監視の設定も同様にリソースを定義している場所に入れていきました。

全シャード共通のリソースとして下記を定義

  • SNS Topic
  • Chatbot
    • Terraform では管理出来ないと思いますが、AWS CDK なら CloudFormation が対応しているものは大体対応しています
  • ticket トピックに入ったメッセージを整形して JIRA チケットを作成する Lambda Function
  • 共通 LB のログから処理時間やエラー数を取得するための MetricFilter

シャードごとのリソースとして下記を定義

  • CloudWatch Alarm

また 監視設定名と通知先が揃っていないものがある となっているのを改善するという目標のため、AWS CDK の CfnAlarm をそのまま利用するのではなく、ラッパーを用意することで命名規則や通知先の設定を強制させるようにしました。

ステップ8: ダッシュボード作成

上記で追加したCloudWatch Alarmのグラフを CloudWatch ダッシュボードへのアラームウィジェットの追加 を参考に共通ダッシュボード/シャード単位のダッシュボードにそれぞれ集約*4していきました。 これで各SLI、及びSLO超過状況のステータスが一覧できるようになりました!

また丁度この時期に CloudWatch MetricsExplorer というTagごとにグラフを分けて表示できるという新機能が発表されました。これはシャードごとのグラフ表示に使えそうだ! と思い試してみましたが、下記の点から今回の利用は見送ることにしました。ただ今後には超期待です。

  • 1つのグラフで表示できるのはリソースごとに決められたメトリクスかつ1つまでで、計算式などは使えない(成功率の計算が難しそう)
  • カスタムメトリクスは非対応

ちなみに他の選択肢として Datadog に集約することも考えていましたがコスト的に厳しく断念しました。Datadog 側に CloudWatch Metrics のデータを同期するために AWS Integration から CloudWatch の API をコールしているのですが、規模が大きいとそのコストがかなりの額になってしまっていました。さらにはデータ取得間隔(デフォルト10分)を短くしようとすると更にそのコストが大きくなるという感じでちょっと辛く...(加えてコスト以外の理由も少しあり...)

まとめ

どのようなステップを踏むべきかを考え直しそのステップを漏れなく実施することで、場当たり的ではない、そこそこ網羅的な監視設定が実現できた気がします!

ただ当初の課題の1つではあった監視対象を減らしてシンプルにするというところはあまり達成できなかった気がします。これは電子カルテというサービスの特性上単一のコア機能だけあれば診療業務を遂行できるというものではないという点、非同期処理が多くキューのメッセージ滞留監視設定などはどうしても必要になってしまう点が理由としてはあるかなと考えています。

今後

  • 適切な SLO への調整はまだまだこれからといったところ
  • 本番影響が軽微なアラートを減らす仕組みの導入
    • アーキテクチャ刷新直後ということもあり、閾値を緩めるのはなかなかに勇気がいることでもありまだ実現できていませんが、アラートが発生するたびにエンジニアが疲弊してしまうことを考えると早急に手を打ちたいと考えています
    • 具体的には バーンレートアラート の導入を検討しています。初期設定時には間に合わなかったのでこれから設定しようと思っています!

We're hiring!

成長著しく、社会的意義もめちゃくちゃ大きいクラウド電子カルテサービスを一緒に開発/運用していきたいというエンジニアを絶賛募集しております!
ご興味のある方はぜひ下記リンクからお問い合わせ下さい!

jobs.m3.com

またデジカルチームでは 12/14(月) 19:00~ に採用説明会の開催を予定しています! 本サービスに少しでもご興味湧いた方、ぜひお気軽にご参加下さい!

m3-engineer.connpass.com

*1:少し前に「詳解システムパフォーマンス」という本を読んでいたせいか Brendan Gregg 氏に感化されていたこともあり、氏のBlogの記事なども参考にしていたりもします。

*2:機能ブロック図レベルが望ましそうではありますが、あまり細かく書いても仕様変更のとき辛いので、辛くならない程度の粒度でいいかなと思っています。

*3:アーキテクチャ刷新前から定期的にチューニングチームでチェックしていた項目の一覧がありそれを主に参考にしました。そういうものがない場合は、業務知識の豊富な人にがっつりヒアリングするしかなさそうな気がします。

*4:初期設定は手動ではありますが、基本的にこれらもAWS CDKで管理する予定です。