はじめに
こんにちは、メルペイのバックエンドエンジニアの cowsys です。
「どうすれば決済サービスで必要となる最高レベルの運用練度を有することができるのか」
メルペイという決済サービスを開発/運用するにあたって、向き合わざるを得ないテーマの1つです。
今回このテーマにあらためて向き合い、目指す運用練度に近づけた手応えを持てたので詳細についてお伝えしたいと思います。
取り組みの経緯
メルペイをリリースしてから1年がたち、新しいmicroserviceの開発をしています。
開発に取りかかるにあたって、新たに取り組むべきテーマを探していました。テーマを探すにあたって、まずはこれまでの、メルペイローンチ前の開発に目を向け、当時の課題を振り返ってみました。
メルペイリリース前に直面していた最大の課題。それは「どうすれば決済サービスで必要となる最高レベルの運用練度を有することができるのか」ということでした。
これまでの経験からどんなサービスでも一定レベルの運用練度を発揮できる自負は持っていたものの、初のmicroserviceで稼働するサービスであること、これまでにない運用練度を要求される決済サービスであることから、非常に強い危機感と不安感を持っていました。率直にリリース準備時点での運用練度と、決済サービスとして胸を張れるレベルの運用練度のあいだには大きなギャップがあると感じていました。
最終的に「リリース準備期間中、最大限準備を行い運用練度を上げ、本番リリース後の運用を通じて更に運用練度を高めていく」という、自身としては常套手段のアプローチをとり、結果的に問題ないレベルの運用練度まで高めることはできました。ただ、自身の理想を考えるとやはり目指したい状態はリリース直後すぐに100%の運用練度を発揮できること。「ベストな運用練度を有した状態で本番リリースに臨めること」にありました。
どうすればベストな運用練度を有した状態で本番リリースに臨むことができるのか。新たに取り組むべきテーマが見つかった手応えがありました。
何が課題なのか
これまでのアプローチ
どうすればベストな運用練度を有した状態で本番リリースに臨めるのか。
これまでのキャリアの中でも運用練度を高める必要性を感じては、以下のような手を打ってきました。
- ナレッジを参考にする
- 運用についての本を参考にする
- 他サービス/他チームの運用を参考にする
- サービス開発の各フェーズで準備をする
- 「設計」「実装」フェーズである程度運用を見越して仕込みを行っておく
- リリース直前の「リリース準備期間」で運用練度を高める
ただ、今回はこれまでと異なるレベルを目指していく。これまでやってきたことを繰り返しても同じ結果にしかならないので、別のアプローチを取り入れる必要性を感じていました。
また、先に上げたアプローチでこれまで対応してきたものの、長年「どこまで行っても想像/想定でしかない、架空の問題に対峙している感覚」が拭えず、地に足ついていないような違和感も課題として感じていました。
新たにtryするアプローチ
では、新たにどんなアプローチに挑むのか。
開発工程としてはこれまで主に「設計」「リリース準備」フェーズで運用練度を高めようとしていました。ただ今回は別のアプローチを取り入れたかったため単純にそれ以外の「開発/セルフQA」「QA」フェーズに注目したところ、不思議と狙いにフィットしそうな感触を持ちました。
当時は漠然とした、うまくいきそうな感覚としてしか捉えられていませんでしたが、思い返すとメルペイリリース前に起きた出来事が裏付けとしてあったように思います。
まずはその出来事についてと、その出来事がどんな変化をもたらしたかについて振り返ります。
メルペイリリース前の出来事
メルペイリリース前の開発佳境期、開発環境で担当していたmicroserviceのpodが突然落ちてしまうという問題が起こりました。そのmicroserviceは多くのチームが手を入れるmicroserviceで、多くのエンジニア/チームにとってクリティカルブロッカーになっていました。
にっちもさっちもいかず解決に乗り出してみたものの、結局解決までにおよそ1.5時間ほどかかってしまいました。
今振り返っても「清々しいほどの惨敗」といった思い出ですが、敗因としては「microservices環境での運用練度が低く、microservices環境で必要なトラブルシューティングのスキルがなかった」ことに尽きると思っています。
当時真っ先にしたことはpodにsshし、ログを見る、stats系コマンドで決定的な異常値を見つけるといった「非microservice環境で頼ってきたトラブルシューティングのアプローチ」でした。約1時間ほどそのアプローチで調査していたものの、pod数が多く、関わっているエンジニア/機能も多く、膨大なログが出力されていることもあり、何が問題を引き起こしているのか、切り分けの軸を見出すことさえできませんでした。
まさに手も足も出ない状態。幸いにも手も足も出ていないことは自覚できていたので、その後アプローチを旧来のものから変え、どうにか怪しいメトリクスを特定し、原因特定、解決まで持っていくことはできました。
問題は解消することができたものの「これまで頼ってきたトラブルシューティングのアプローチが、microservices環境では全く通用しない」「この状態で数カ月後の本番リリースに踏み込めるのか」という課題と危機感だけが残りました。
対応後、一緒に問題にあたっていたエンジニアが「いい避難訓練になったね」と声をかけてくれたのですが、本当に多くを得るきっかけとなったように思います。このあと述べていくような、アプローチを考えるにあたってのヒントをもたらしてくれました。
環境問わず「同じ運用練度」を持つ状態で「同じ問題」に遭遇したら「同じ解決時間」がかかる
そんな出来事のあと「同じ問題が本番環境で起きたとしたら、同じように解決に1.5時間要してしまうのだろうか?それも決済サービスで」という悩みに付きまとわれることになりました。
ただ何度考えてみても
環境問わず「同じ運用練度」を持つ状態で「同じ問題」に遭遇したら「同じ解決時間」がかかる
だろうことは明らかで、「本番環境だからといって解決時間が短縮されるということはまずない」のも明らかでした。
本番環境で発生する問題の難易度 > 開発環境で発生する問題の難易度
更にこの悩みを根深いものにしていたのは以下のような経験則でもありました。
本番環境で発生する問題の難易度 > 開発環境で発生する問題の難易度であり、 本番環境の問題は開発環境の3倍以上の難易度となりえる
どうしても本番環境で難易度が上がってしまうのは、以下のような背景があると思います。
- 本番環境なので時間の猶予がない。速く、間違わずに対応しなくてはならないというプレッシャーがある
- ワークロードが開発環境より跳ね上がることで、処理パターン及びデータのバリエーションが増え、問題の発生率と難易度が複合的に跳ね上がる
- 開発環境だから可能な、ダイナミックな切り分け/問題解決手法は使えない
- 問題解決と同時に、お客様へのサービスもしっかり担保する必要がある
何をして課題を解決するか
では、何をして課題を解決するのか。以下のような内証を経て、方針を決めました。
環境問わず「同じ運用練度」を持つ状態で「同じ問題」に遭遇したら「同じ解決時間」がかかる。また、本番環境で発生する問題の難易度 > 開発環境で発生する問題の難易度であり、本番環境の問題は開発環境の3倍以上の難易度となりえる。
この2つに加え、これまでの「ナレッジを参考にする」「サービス開発の各フェーズ(設計/実装フェーズ、 リリース準備期間)で準備をする」アプローチでは現状維持にしかならないので、それ以外のアプローチを試す。
では、具体的に何をするか。
- 環境問わず「同じ運用練度」を持つ状態で「同じ問題」に遭遇したら「同じ解決時間」がかかる
結果=「解決時間」を変えたい。
結果が依存する「問題」はランダム性が高く、自分自身では変えられない。
結果が依存する「運用練度」は、唯一自分自身で変えることができる。これを高めていければいい。
- 本番環境で発生する問題の難易度 > 開発環境で発生する問題の難易度であり、本番環境の問題は開発環境の3倍以上の難易度となりえる
本番環境の問題は開発環境の3倍以上の難易度となりえるのなら、
1/3の時間で開発環境の問題を解決できるようになればいい。
また、これまでの「ナレッジを参考にする」「サービス開発の各フェーズ(設計/実装フェーズ、 リリース準備期間)で準備をする」アプローチを取らないのなら、これまでフォーカスしてこなかった「開発/セルフQA」「QA」フェーズに着目する。
このような検討の結果、最終的な結論としては
「開発/セルフQA」「QA」フェーズ発生する問題を 本番環境で目指す1/3の時間で解決できるようにし 本番環境でも十分通用するような運用練度へと高めていく
というものとなりました。
結論は非常に地味ですが、腹落ちしきった結論であるため、ここに取り組まないことには次に進めないとも感じていました。
具体的に「開発/セルフQA」「QA」フェーズで何をしていたのか?
本番環境でのトラブルシューティングについて考えるとき、以下のような図を書きながら検討することが多くあります。
これまで触れてきませんでしたが「運用練度」とは、この全体工程にかかる時間を短縮する能力だと思っています。
この全体工程にかかった時間=問題解決までにかかる時間のはずなので、まずはこの全体を圧縮するためのアプローチを考え、実行していきます。プロセス的にはパフォーマンスチューニングに非常に似ていると思います。
具体的に「開発/セルフQA」「QA」フェーズで何をしていたのか?については、一言でいうと「トラブルシューティング力のパフォーマンスチューニングを開発/セルフQA、QAフェーズで行い、運用練度を高めていた」と言えます。
実際に行ったことを列挙してみると
- 問題発見/原因調査フェーズ
- monitoring graphを作って毎日眺める。把握できていないもののgraphを追加する
- 「開発/セルフQA」「QA」フェーズから監視を仕込む
- 全フェーズ
- サービス/システム/個々の機能の中で理解できていない機能を把握し、ドメイン知識を深める
- 把握/ハンドリングできていない未知のエラーをなくす
- 本番の問題解決に利用するツール類はすべて利用可能な状態にしておく
- いざというときは引き出しからツールを出して、使うだけの状態にしておく
と、ほとんど「リリース前準備」「リリース後対応」で行っていたことを進めています。
特にドメイン知識はすべての根幹となる土台で、それを把握できているからこそ、作成するgraphや、監視条件、準備しておくべきツール等が決まる。運用練度を高めるための必要不可欠な能力であると言えます。
tryしてみた結果どうだったか
現時点では新しいmicroserviceは未リリースでアプローチ適用の真っ最中ですが、手応えを感じているポイントについてまとめます。
運用練度を高められているか?
スキル面でも、心理面でも自信を持って運用練度を高められている手応えがあります。
スキル面では、先に上げた対応工程において個別及び全体の工程が最適化されてきており、結果解決にかかる時間を短縮化できています。全体的に迷いのない、なめらかな対応を行えるようになってきており、ストックしてきた問題対応のためのツール/枠組みを適用すればいいだけになっています。対応時間が真に重要な「問題解決」の時間で多く占めるようになってきています。
最大限本番環境に近しい環境で避難訓練を繰り返しているようなものなので、万一本番で何かが起きても瞬発力をもった対応ができるイメージが持てています。開発環境で高めてきた運用練度を、本番環境でそのまま発揮すればよいというわかりやすさが心強い。
心理面では、及び腰にならずに、迎え撃っていくようなイメージを持てています。本番環境で何かが起きても、開発環境で備えてきたアプローチを駆使して対応していける感覚があり、漠然と、おおまかにサービスとリスクを掌握できている感があります。本や、他サービスを参考にしているわけではないので地に足ついている感覚を持てています。
総じて、リリースに対する漠然とした不安感がかなり晴れているように思います。開発環境で高めてきた運用練度を、本番環境でそのまま発揮すればよいというわかりやすさが心強い。
全開発工程、一気通貫で運用練度を高めることができる
「これまでのアプローチ」で長年感じてきた運用の「噛み合ってなさ」について触れましたが、今回のアプローチを進める中でこの気持ち悪さが解消できているような手応えがあります。
これまでは「設計」「リリース準備」というように、「開発/セルフQA」「QA」フェーズ以外で運用練度を高めるアプローチを取ってきましたが、今回比較的重視していなかった「開発/セルフQA」「QA」フェーズに着目したことで「設計→開発/セルフQA→QA→リリース準備」の全工程を通じて一気通貫の「噛み合った」運用を作り上げれている感覚を持っています。
これまでのように個々の分断された工程の中で運用を最適化するのではなく、全工程で、早いうちから運用を抽象/想定ベースから具体/事実ベースへとフィットさせ、本番環境でも引けを取らないであろうレベルの運用練度へと高めることができる。
想定ベースの運用が事実ベースの運用へと変わるタイミングが早まることで、こんなにも運用が引き締まる実感を持てるのかという驚きを感じています。
チームとして行う避難訓練
あくまで個人的な取り組みとしてこのアプローチを試していましたが、同じような意識をチーム全体で持ち、チームとして取り組むことができるのなら、本番リリースに臨む前のこれ以上ない避難訓練になるだろうと思います。
問題の中には複数人で取り掛かり、それぞれの知識を持ち寄らなければ解決できないようなものもあります。対応難度としては1人で取り組むものよりも高く、特に初期は連携が取れずぎくしゃくしがちです。
なめらかな連携を阻害する要因として「調査/対応に使うツール、アプローチといった、対応における共通言語が異なる」ことや「時々の状況の認知が個々人で異なる」こと、「個々人ごとに原因調査、問題解決といった対応フェーズの同期にばらつきがある」ことがあると思います。共通言語、認知、同期のズレ。これらのズレが重なり、本来発揮できるはずの、チーム/全体としてのスループットが出せなくなってしまう。
あらかじめチーム一丸となって避難訓練に取り組んでおくことで、これらのズレをならし、チーム/全体としてのスループットを改善し、ひいてはチーム/全体としての運用練度を高めることができる。
チームの総力戦を必要とする問題に対処するための、非常に効果的なアプローチになると思います。
余談ですが、開発カルチャーとして避難訓練実施システムとも言えるカオスエンジニアリングを導入し、質の高い避難訓練をチームとして日常的に積み重ねることができれば、全体の運用練度の底上げも実現できるのかも知れません。
負荷は大きかったか?
これまで「リリース準備」フェーズで行ってきた準備を前倒しで行うことで「開発/セルフQA」「QA」フェーズにアドオンで乗る負荷を懸念していたのですが、思ったより負荷とは感じなかったのと、実は短期的にも中長期的にも負荷を下げているような印象を持っています。
短期的には「開発/セルフQA」「QA」フェーズで発生する問題の解決力が上がり、問題の対応時間が短くなり余裕を作れる。問題を早期発見・対処できるようになることで、対面する問題が単発の、軽微レベルの問題ばかりになり更に対応難易度が易しくなる。個々の問題のライフタイムが短くなって複合的な問題へと発展しにくくなり、更に問題の難易度が下がる。このような一つ一つのメリットが重ね合わさって、とても好ましいループに入っていると感じます。
他にも、これまでは開発佳境機に起こる問題は対応負荷的に目を背けたくなる気持ちが強かったのですが、「開発環境で起きる問題は本番環境の運用練度を高めるための糧になる」という意識を持てているので問題を「(運用練度を上げるための)エサだー!」とポジティブに対処できるようになっていることも、ささやかな後押しになっています。
中長期的には、これまで「リリース前準備」のフェーズでパツパツになりながらも追い込みをかけていましたが、前工程の「開発/セルフQA」「QA」フェーズでそれが行えるようになり、リリース前の最後の最後でラスボスと対峙するような負荷をうまく分散することができています。本番リリースに最大化されてしまいがちな言いようのない心理的プレッシャーも、乗りこなせるレベルの、いい塩梅のプレッシャーに変化してきているようにも思います。
「開発/セルフQA」フェーズよし、「QA」フェーズよし、「リリース前準備」フェーズもよし、「リリース後」フェーズとしてもよし。短期的、中長期的にも無理なく易しいペースづくりができるようになる。一石何鳥にもなるアプローチなのかもしれないな、と感じています。
まとめ
開発中のmicroserviceは未リリースで取り組み最中でもありますが、新しく取り組むべきテーマとしては非常に良いものとなり、運用練度を高めるための現時点のベストプラクティスを得た手応えを感じています。
「開発/セルフQA」「QA」フェーズ発生する問題を 本番環境で目指す1/3の時間で解決できるようにし 本番環境でも十分通用するような運用練度へと高めていく
改めて書くとアプローチとしては非常に地味ですが、「運用練度を高めた状態で本番リリースに臨む」という目的に対し非常にフィットし、運用以外の「開発/セルフQA」「QA」フェーズの負荷をも下げ、全フェーズの質を底上げしうる非常にパワフルなアプローチだと考えています。
microservicesをベースとしたサービスに限らず、どんな環境でも適用できるアプローチだとは思いますので、同じような課題を感じている方にとって、少しでも参考になれば嬉しく思います。
ただ、冒頭でも触れた「決済サービスとして胸を張れるレベルの運用練度」という理想と比較すると、練度を引き上げることはできているものの、依然として大きな隔たりがあるように感じています。
それについては、開発中のmicroserviceのリリース後運用、あるいはその次のmicroserviceの開発/運用の段階で、さらなる運用練度を高めるためのテーマを見つけることができるという期待感を持っているので、歯ごたえのあるテーマを見つけ、面白い取り組み結果が得られたらまた皆さんにお伝えしたいと思います。
【PR】これまで話してきたこと
tech.mercari.com
いま読むと文中でも触れた「microservice環境で通用していない現状にどう対応するか」という課題に対し、datadogを使いこなせるようになることで解決しようとしていたのが伺えます
speakerdeck.com
Goのいいところあるある言いたい案件。見返すとタイトルと内容に乖離がありますね😇