配信システムの障害を撲滅してみんなで幸せになった話

ogp

こんにちは、MA部の谷口(case-k)です。私達のチームでは配信システムの開発や運用をしています。

ZOZOでは配信システムを内製化しており、メルマガやPush通知、LINEメッセージ配信などを自社で実施しています。本記事では配信システムの障害対応の取り組みについてご紹介します。

現在の障害の発生頻度は週に数件程度ですが、1年ほど前までは連日障害が発生していました。障害のない日の方が珍しい状態で、ほぼ毎日数件の障害が発生していました。現在も週に数件程度は発生してますが、障害が丸一週間ない日もでてきました。1年ほど前と比べると月間の障害件数は70%〜90%減少しました。最近発生している障害もリリース起因やオペレーションミスによるものです。

本記事では障害が多かった理由やどのようにして改善していったのかご紹介します。同じように障害の対応に課題を抱えている方々の参考になると幸いです。

配信システム特有の障害と実施した対策

まず、配信システムにおける障害の性質をご紹介します。配信システムでは、主にスケジューラーを使用して配信処理を制御しています。アクセスログなどのイベントをトリガーにした配信もありますが、ほとんどはマイクロバッチを含むバッチ処理です。このため、ユーザ起因による新規の障害は少なく、ほとんどの障害は過去に一度発生したことがあるものになります。恒久対応をすることで、障害は解消されますが、対応しなければ問題は改善されません。

配信システムの障害・アラートの種類は、大きく3つの性質に分類できます。

障害の種類 事例 優先度
即時対応が必要かつ運用で対応できない障害 重複配信、秘密情報の漏洩等 超高い
即時対応が必要だが運用で対応できる障害 配信処理やデータ連携処理の中断 高い
通知のみで対応不要なアラート 配信処理に影響がないと即時断定できるアラート 低い

実際に発生した障害を例にご紹介します。

同じお客様への重複配信

まず最初にご紹介する障害はお客様へ重複配信してしまう障害です。配信処理が冪等になっておらず、リトライによって重複配信されてしまいました。

対処

まず配信が継続している場合は配信を止めます。次に重複配信してしまったお客様を特定します。並行してCSとも連携してお客様に対する謝罪文を用意し、お詫びのご連絡を入れます。

原因

重複配信が起きてしまうのは配信処理が冪等になっていなかったのが原因です。配信処理の前に配信済みかチェックするための処理は入っていましたが、不十分でした。同じワークフローを2度実行してしまうケースを想定しておらず重複配信されてしまいました。

対応

配信処理の前に配信済みかチェックするための処理を見直し改善しました。また、現在実装の不備で重複配信されてしまった場合は検知できるよう監視を整備しています。「即時対応が必要かつ運用で対応できない障害」はほとんど発生しませんが、発生した場合はこれまでも即日で再発防止策を導入してきました。

配信処理の中断

次にご紹介するのはメモリリークやスケーリングの失敗等様々な利用で配信処理が中断してしまう問題です。配信システムではメールやLINE、Push等様々なチャンネルに対して配信処理をしています。

しかし、様々な問題が原因で配信処理が中断されてしまい、手動での復旧が必要でした。理由は本当に様々で、配信処理に必要なワーカーのスケーリングに失敗したり、メモリのリーク、リトライの未実装、Cloud SQLのメンテナンス起因の障害、GKEのノード障害、Postgresのロックが解放されない問題など様々です。

これらの障害は長年放置されてきたこともあり、運用負荷を高めていました。また、障害対応には手動の対応が発生します。オペレーションミスによって、重複配信されてしまうことも過去にありました。

LINE配信のメモリリークに関する問題は以前以下の記事にも書いています。

techblog.zozo.com

対処

配信中断系の障害の多くは対応手順が決まっています。対応順に従い障害対応者が再配信できるよう対応しました。リカバリに時間がかかってしまうものは、関係者と連絡を取り合いながら対応してきました。

原因

配信処理が中断してしまう原因は様々ですが、根本的には障害に対し恒久対応を入れる習慣の欠如、優先度の低さが理由です。

対応

配信処理が中断されないように原因を特定したり、原因特定に至らないものは手動のオペレーションを自動化するなどして対応してきました。具体的にどのようにして、優先度をあげ、習慣を作ったのかは後述の「障害対応の体制を見直す」でご紹介します。

配信処理に影響がないと即時断定できるアラート

次に紹介するのは自動でリトライされるなどして、実際には配信処理への影響がないアラートです。配信システムでは、PushやLINE配信など、メッセージングキューを利用するシステムが多く存在しています。これらのシステムではリトライで成功する一時的なエラーも頻繁に発生していました。その他にもバッチ処理のSLAが超過している処理も数多くありました。発生しているものはアラートとして通知はされますが、確認のうえ対応不要として静観されているものがありました。

対処

電話はなるため深夜でも叩き起こされますが、配信処理に影響のないと判断し静観します。

原因

監視すべき対象やバッチ処理を作成した当時からSLAの見直しが行われてこなかったのが原因です。これらも根本的には障害に対し恒久対応を入れる習慣の欠如、優先度の低さが理由です。

対応

これらの障害に対しては、最終的なアウトプットに焦点を当てた監視を設定したり、障害を警告レベルに抑えて緊急対応が不要となるように恒久対応を入れてきました。また、バッチ処理のSLAを見直し、各種バッチのSLAの調整しました。さらに、要件に必要なSLAを超過してしまうバッチは、処理を見直すなどの根本対応を実施しました。具体的にどのようにし習慣を作ったのかは後述の「障害対応の体制を見直す」でご紹介します。

障害対応の課題

これまでも配信基盤チームでは障害対応をしてきました。当番制で運用しており、障害対応の当番は当番週に発生した障害の対応をし、週次で実施している障害振り返りのタイミングで発生障害をチームに共有していました。以降「アラート当番」と記載します。前述したとおり、即時対応が必要かつ運用で対応できない障害に対しては恒久対応を施してきました。しかし、即時対応が必要で、運用で対応できる障害や対応が不要な障害は長年放置されてきました。配信チームで抱えていた障害対応の課題についてご紹介します。

増え続ける障害

前述の通り、緊急性の高い障害に対しては即日で恒久対応してきました。しかし、緊急性が高いものでも、運用で対処可能な障害や対応が不要な障害は長年放置されてきました。配信システムの性質上、同じ障害が何度も発生することが多く、古いものでは数年前から週数回程度の頻度で発生している障害も存在しました。新規施策や新しい取り組みを実施することで、障害は増加し続け、結果として障害のない日が珍しい状況となっていました。

alert_up

開発業務に集中することが難しい

運用で対処できるとは言っても、緊急性の高い障害には即時対応が必要です。開発などの他の業務を行っていても、障害対応を最優先しなければなりません。アラート当番ではなくても、対応に詳しい人が限られている場合、Slackのハドルに次々と集まり、本来集中すべき開発業務に専念できない状況が続いていました。

slump_bad_man_study

連日の対応による幸福度の低下

障害のない日が珍しい状況では、アラート当番週であれば深夜に連日起こされることも珍しくありませんでした。休日も基本的に障害が発生するため、待機当番は外出が困難になります。障害の発生頻度が低ければ、PCを持ち歩き、モバイルWi-Fi等で対応する方法を採用できます。しかし、障害が当たり前のように発生する状態では、外出を控えざるを得ません。その結果、生活体験が損なわれ、幸福度が低下してしまいます。なお、休日の2日間待機した場合は待機休暇が半日つきます。

buranko_businessman_sad

対応者の偏りと成長機会の損失

障害の一次対応は、これまで二人で行われていました。二人で対応すると経験の多い一方が主導して対応することが多くなります。対応できる人が偏り、対応できない人はスキルが身につき難い状態となっていました。実施した経験がないため、いざやってみるとDB接続やSSH、権限不足等ですぐに対応できない状態になっていました。緊急の対応が必要になるため、熟練者の運用負荷はあがる一方で、経験のすくないメンバーは成長機会を得られない状態が続いていました。

お客様の体験を損なう

運用で対応できるとはいっても、対応に時間がかかってしまう障害もありました。配信効果を最大化できるタイミングで配信できなかったり、オペレーションミスによって、重複配信してしまうなどお客様の体験を損なってしまうこともありました。

恒久対応を施す習慣の欠如

これまでも週次の障害の振り返りを行う時間を設けていました。 前週のアラート当番が発生した障害をチームに共有することで、障害の理解度を測っていました。しかし、原因の調査深掘りや対応方針の策定、恒久対応をいれる責務はアラート当番から外されていました。簡単に対応できるものであれば、すぐにPull Requestを作り改善するのが理想的ですが、恒久対応をいれる習慣がなかったため放置されてきました。

障害対応の体制を見直す

前述したように、配信システムの性質上、恒久対応をすることで同じ障害が発生しなくなります。ここでは、恒久対応を実現するために実施した施策をご紹介します。

まず、障害振り返りの運用体制を見直しました。これまでも障害振り返りは週次で実施していました。

これまでのアラート当番の役割は以下の通りでした。

  • アラート当番は当番週に発生した障害の対応をすること
  • 障害振り返りで発生した障害をチームに共有すること
  • 新規の障害に対して手順書を作成すること

体制を見直す以前は、アラート当番週の障害対応と、チーム内に発生した障害を共有するまでを責務としていました。

改善後は恒久対応までをアラート当番の責務としました。数十分程度で恒久対応できる障害はアラート当番が実施することにしました。

アラート当番の責務として以下のような運用ルールを定めました。障害振り返り実施の流れについてはこの後ご説明します。

alert_mtg

アラート振り返りの改善点・相談・連絡事項

まずアラート振り返りの冒頭で障害や体制自体の相談時間を設けています。障害対応の体制を継続的に改善できるようにするためです。

以下のように相談したい内容があれば書き出します。 alert_ask_about_mtg

アラートログの黙読

アラート当番が先週発生した障害をチーム内に共有します。先週発生した障害はスプレッドシートにまとめられています。スプレッドシートには障害ごとに発生した件数と手順書がまとめられています。チームメンバーは発生した障害を確認し、不明点等あればアラート当番に確認します。対応が不明確な障害はこのタイミングで議論します。

alert_log

アラートタスクの確認

これまで障害タスクの管理が十分でなかったため、障害対応の体制を見直し、恒久対応を実施するようになりました。障害は、振り返り時にタスク化し、担当者と期日を設定して進捗を把握できるようにしています。軽微な障害は、アラート当番が恒久対応を担当しています。

時間がかかる恒久対応タスクについては、障害振り返りのタイミングで担当者を決定します。タスクの進捗はJIRAを用いて管理しています。

alert_task

エスカレーションポリシーの見直し

また、障害の一次対応は二人体制で行っていました。一時対応者の二人が対応できない場合は、全員にエスカレーションが行きます。

しかし、前述の通り一次対応者が二人体制だと、対応する人が偏りがちでした。熟練者と新人が組んだ場合、急ぎ対応が必要な障害対応では熟練者に頼る傾向があります。新人の育成に問題が生じていました。

連日のように障害が発生している状態では障害が同時多発的に発生するため、一人で対応することは困難です。しかし、障害がある程度落ち着いた時期には、一次対応者を一人にする方が望ましいと思います。一次対応者のペースで原因調査から、エスカレーションを含む対応の意思決定の経験を積めるからです。

配信チームでは、障害が落ち着いた時期に一次対応者を一人に変更しました。一次対応者が対応できない場合は、二次対応者に通知され、さらに対応できない場合は全員に障害が通知される体制をとっています。

一次対応者を一人にすることで、育成面と運用負荷の両面で改善されました。

障害対応の体制を見直した結果

かつて連日のように発生していた障害は、半年間で週に数件程度にまで抑えることができました。先日ついに7日間連続して障害のない日が続きました。

ちょうど1年前の月間の障害件数を見比べたものです。約70%減少しました。当時は1日あたり平均2〜3件障害が発生してる計算になります。また、当時は同じ障害が繰り返し発生していたことも分かります。

  • 2022年4月に発生した障害:65件 alert_April_2022

  • 2023年4月に発生した障害:9件 alert_April_2023

    運用負荷が減った

    運用負荷が軽減されました。体感できるレベルで減りました。以前は障害が発生する度にSlackへ集まる動きがありましたが、障害が減少し、開発業務にも注力できるようになりました。連日叩き起こされることもなくなりました。また、障害の一次対応も障害が減ったことで2人から1人になり、一次対応が必要なケースは半減しました。アラート当番の運用も楽になりました。

    当たり前に恒久対応を入れる習慣が根付いた

    障害対応者が発生した障害に対して自然とPull Requestを作り、恒久対応を入れる習慣がチーム内に根づきました。

軽めの障害だと、障害発生時に恒久対応のPull Requestをその場で作る動きも観測できるようになりました。感動です。 alert_pr

連日の対応がなくなり幸福度UP

連日のように障害対応をすることもなくなり、連日深夜に叩き起こされることもなくなりました。基本的には障害が発生しなくなったので、アラート当番でもPCは持ち歩き週末出かけられるようになりました。みんな幸せになった気がします。 bird_aoitori_bluebird

対応者の偏りがなくなり、成長機会が増えた

一次対応者を一人にしたことで対応者が偏らなくなり、スキルの向上にも繋がっているように思います。障害に対して原因を調査し、対応できるようになっています。最初はいざ一人で対応するとSSHやDB接続に苦戦し、GCPリソースの権限が不足しているなどもありました。一次対応者が一人で対応できるようになることで、「対応できそう」から「対応できる」ようになったように思います。

障害対応の体制改善後の課題と解決策

障害の対応体制を見直した後に発生した課題とその解決策についてもご紹介します。

積まれていく未消化のタスク

障害の発生件数が安定しているときには、担当者を割り当てることで問題を解決可能です。しかし、連日障害が発生している状況下では、担当者だけでは対応が追いつきません。未消化の障害タスクが蓄積されてしまいます。

連日のように障害が発生している状態では、迅速な対応が重要となります。障害担当者に関係なく、高い発生頻度の障害に優先的に対処することが必要です。そうでなければ、障害タスクがたまり、対策自体が形骸化してしまうことになります。対応においてもできるだけ、即効性のある対応が必要です。このあたりは障害の発生頻度にもよると思います。クエリのパフォーマンスを改善しなくても要件を満たせる場合はSLAを緩めたり、OSSの修正に時間がかかる場合やOSSを使わないような判断もしてきました。

障害改善と運用改善が区別できていない

これまで発生した障害に対して優先度は設定されていませんでした。障害の発生頻度が低い場合、優先度も低くなります。優先度が設定されていないと、未着手の障害対応タスクが蓄積されてしまいます。

そこで、発生した障害に優先度を設定することにしました。優先度が低い障害は「運用課題」として別途対応することになりました。優先度は、発生頻度が高いものや運用でのリカバリが困難なものに限定しました。障害に対して優先度をつけ、障害改善の優先度をあげ、運用改善を区別するようにしました。

発言者の偏り

前述した「アラートログの黙読」の際には、質問タイムが設けられています。この時間では、発生した障害に関する質問や対応策について話し合われます。以前は発言者が一部に偏っていたため、ルールの変更が行われました。現在の質問タイムでは、先週のアラート当番が質問をするようになっています。

習慣を作る上で大切だと思ったこと

体制を見直していく上で個人的に大切だと思ったことをご紹介します。

障害対応を優先的にすること

恒久的な障害対応を実施する際、人それぞれ障害の優先度が異なるため、説得が必要でした。実際に施策を進める中で、障害対応よりも開発業務に注力した方が良いという意見もありました。当初の賛否は、半々くらいでした。しかし、LINE配信のメモリリーク対応など多い時では週に3回程度発生し、リカバリも複数人で2時間程度使っていました。状況を整理し、チーム内で納得感を持って説得し、障害対応の優先度を高くしていく必要がありました。

障害を改善していく気持ち

常態的に障害が発生している場合は習慣だけだと捌ききれません。ある程度集中して、障害の発生頻度を抑える必要があります。連日のように障害が発生している状態では担当関係なく、開発業務と並行して週に2〜5つ程度のペースで恒久対応を入れていきました。障害を改善していく気持ちも大切です。

継続的に改善していくこと

新しい開発や施策の実施により、新規の障害も発生します。一定の抑制ができた後も、チーム内で継続的に改善する習慣が必要です。そうしないと、徐々にまた障害が増えていきます。恒久対応が当たり前になるよう、チームで取り組むことが望ましいです。継続的に施策を改善できるよう振り返りの時間を設けることも大切だと思います。

今後の課題

障害の対応体制を見直した結果、週数件程度にまで障害は減りました。発生頻度が高く、繰り返し発生する障害には何らかの恒久対応が入っています。障害が減ったことは嬉しいですが、今後の課題としては以下のようなものがあると思います。

オペレーション起因の障害

配信システムでは、配信セグメントの作成などの配信施策はマーケターによって行われています。一部の自動化できないオペレーションもあるため、オペレーションミスによる障害が発生しています。全ての改善はできませんが、CIでの確認や権限管理等で防げる部分もあるため、今後対応していけたらと思います。

障害対応の経験が積み難くなった

喜ばしい悩みではありますが、障害が減少したことで、障害対応の経験が積みにくくなったように感じます。恒久対応が施された障害の9割以上は手順が決まっているものでしたが、障害が発生するとログやコードを読み原因を調べる機会もありました。障害がすくなくなったことで経験を積み難くなったように思います。とはいえ、手順の決まっている障害で障害対応力を鍛えることは難しいため、このあたりは課題に感じます。昔半年間ほど2人で障害対応をしていた時期があり、障害対応力をかなり鍛えられましたが健康に悪いのでお勧めはできません。

最後に

配信基盤チームの障害対応の事例についてご紹介しました。一年前だと過酷な状態でしたが、今では障害も少なく健康的に働け、開発業務にも集中できるようになっています。

この記事を読んで、もしご興味をもたれた方は是非採用ページからお申し込みください。

corp.zozo.com

カテゴリー