🐙

地雷を踏んだ日:ステージングではなく本番に上げたあの瞬間

に公開

こんにちは、WealthNaviでバックエンド開発を行っている藤原です。
今回は「真夏の怪談!ひやりハット特集」ということで入社してから初めてやらかした事件についてお話しさせていただきます。
タイトルで察する方もいらっしゃるかもしれませんが、デプロイ関係のインシデントがテーマとなっています。

この記事を読んでほしい対象者

  • コンテナイメージをECRで管理している方及び企業。
  • WealthNaviに入社したい若手エンジニアの方。

事件が起きるまでのいきさつ

その日は突然やってくる。Fさんはその日、とあるAPIの改修を行っていました。
改修を終えた後、変更内容をステージング環境でテストしようと、イメージをビルドするパイプラインを実行しました。完了には時間がかかるため、パイプラインが走る間に昼食を取りに行きました。
1時間後、オフィスに戻ってきたFさんは、何やら周りがざわついていることに気づきました。
その時突然、先輩のKさんから声をかけられました。

「F君、ちょっといい?このイメージってどうやって作った?」

その瞬間、Fさんはインシデントが発生していることを知り、冷汗が止まらなくなりました。

事件発生:本番環境でデグレードが起きる

なんとFさんの作ったイメージがいつの間にか本番環境にデプロイされていたようです。
さらに、このイメージは本番環境で使われていたイメージより古いものであったため、デグレが発生し一部サービスが使えなくなるインシデントが発生しました。

なぜデグレードが起きたのか

背景1:ECRでのイメージ管理とタグの仕組み

WealthNaviでは、AWSのECRというサービスでコンテナイメージを管理しています。
ECRではイメージに「タグ」を付けて管理でき、インシデントが起きたサービスではGitハッシュ値をタグとして使用していました。しかし、ここに大きな課題が潜んでいました。
ECRでは、同じタグが異なるイメージに付けられた場合、タグは後からプッシュされたイメージに「移動」します。(ECRの設定によって差異はあります)
今回のインシデントは、まさにこのタグの移動によって引き起こされました。

背景2:サービスの定期再起動によるリスク増加

このインシデントの数ヶ月前、負荷対策としてサービスの定期再起動が導入されました。以前はリリース時のみサービスを再起動していましたが、現在は毎日決まった時間に自動的に再起動されるようになっています。
この変更により、本番のタグが誤って移動している状態でサービスが再起動されると、意図しないイメージが本番環境にデプロイされるリスクが生まれました。なお、定期再起動が導入される前からタグの移動自体は起きていましたが、再起動はリリース時のみ行っていたため、誤ったイメージが本番環境にデプロイされることはありませんでした。

背景3:社内ライブラリの罠

問題の根本原因は、社内で使用している巨大ライブラリにありました。このライブラリは様々な社内サービスから依存されており、今回デグレが起きたサービスもこの社内ライブラリに依存していました。
ここでFさんの改修内容についてまとめてみます。

  • 改修したコードはライブラリのみでサービス自体は修正していない。
  • 使用していたブランチは本番で使われていたブランチから切っており、新規コミットは行なわなかった。
  • 改修したライブラリは本番で使われていたライブラリのコミットを取り込んでいなかった。

その結果、以下のような状況が発生しました。

  • 本番と同じGitハッシュ値でイメージがビルドされる。
  • 本番で使用していたイメージのタグが開発用イメージへと移動してしまう。

こうして、開発用のイメージが意図せず本番環境に反映される事態が発生しました。


障害発生時のECRコンソール画面。タグが移動していることがわかる

一時対応策:タグの上書き禁止

インシデント発生後の対策として、ECRに登録されたタグを上書きできないように設定しました。
この設定により、ECRに同じGitハッシュ値を持つイメージがすでに存在すると、ビルドが失敗するようになります。その結果、誤って開発用のイメージを本番環境にデプロイしてしまうことを防ぐことができます。

ただし、この方法には1つ欠点があります。それはライブラリ側のみの修正でも、「空コミット」を行わないとビルドが失敗する可能性があるということです。
当たり前ですが仮に空コミットせずにビルドが失敗した場合、空コミットをして再度パイプラインを実行する必要があります。そのため以前より開発生産性が下がってしまいました。

根本対応策:改善に向けたアプローチ

よって根本的な対応策として以下の実施を段階的に行う検討をしています。

改善策1: WARハッシュ値の活用

コンテナイメージのタグ生成時に、Gitハッシュ値ではなく、WARファイルやアーティファクトのハッシュ値を利用する予定です。
この方法により、社内ライブラリの変更だけにも対応可能で、再ビルドごとに異なるハッシュが生成されるため、意図しないタグの移動を防ぐことが可能です。

改善策2: 社内ライブラリからの脱却

今回の問題の根本原因は、複数のサービスで依存している巨大な社内ライブラリにあります。
このライブラリは運用上の課題が多く、技術的負債となっている状態です。実際に、このライブラリには以下のような課題点が存在しています。
課題1: 開発・デプロイ時の負担
社内ライブラリがあるとライブラリと依存先のサービスの2つを修正する場合も生じます。その結果、開発時、その2つのリポジトリ間を行き来するという手間が生じてしまいます。
デプロイ時にも余計な工数が発生しています。デプロイ時にはまずライブラリ自体をビルドし、次に依存先のサービスでライブラリのjarファイルを取り込む必要があります。この一連の流れが余計な工程となり、工数を増やす要因となっています。
課題2: 柔軟にサービスをリリースできない
もう1つの問題はサービス単位での柔軟なリリースができない点です。複数のサービスがこの社内ライブラリに依存しているため、ライブラリ側を修正すると、他の依存先サービスにも影響が出る可能性があります。その結果、ライブラリ側の修正はどうしても自由にリリースを行うことができません。

そこで、今後はこの巨大ライブラリへの依存をやめる方向性で検討しています。
具体的には、これまでライブラリが一括管理していた機能を、それぞれのマイクロサービスで独立して管理できるように改修する予定です。

おまけ

今回のインシデントを振り返ると、社内ライブラリの運用上の課題だけでなく、ドキュメント整備の不足も一因だったと考えられます。もしCI/CDに関するドキュメントが適切に整備され、社内で十分に共有されていたら、サービスの定期再起動を導入する際に今回のようなインシデントを予測し、防ぐことができたかもしれません。
今回の経験をきっかけに、CI/CDの仕組みを見直す重要性を再認識しました。このようなトラブルを未然に防ぐため、今後も定期的に見直しと改善を行っていきます。

WealthNavi Engineering Blog

Discussion