2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
本番環境にホットフィックスをリリースして破壊した話(全1記事)
リンクをコピー
記事をブックマーク
小佐野洋氏(以下、小佐野):はい、よろしくお願いします。justInCaseTechnologiesの小佐野といいます。今回は「本番環境にホットフィックスをリリースして破壊した話」というタイトルでお話しします。私のこの話はガチの障害です。障害をどうやって回復したのかとかのお話をします。
そもそも本番環境にホットフィックスって、修正するためリリースするのに、なんでリリースして破壊すんねやと。謎なことが多いとは思いますが、ちょっとその謎に迫ってみたいと思います。
まず、私は小佐野といいます。フルスタックエンジニアで、Android、Webフロント、バックエンドのテックリードを渡り歩いてきたというか。だいたいなんでもできるような感じの人間です。エンジニア歴10年ぐらいで、そろそろ古株になってきた感触はなんかちょっとあります。
会社紹介させてください。justInCaseTechnologiesといいます。どういうことをやっているのかというと、今まで兄弟会社のjustInCaseという保険会社に対して、保険のデジタル化のようなものを提供してきましたが、それを第三者に対して提供しようということをやっている会社です。
ではさっそくですが、本番環境にホットフィックスをリリースしてどう破壊したのかと何が起こったのかの話を、何があったのか、そもそもどうなっていたのか、なぜ起こったのかの3本立てで話をしようと思います。
それはある日の午前中のことでした。SPAと書いてありますが、リアクトアプリケーションです。「データが表示されない問い合わせがきたので、ちょっと確認してもらえますか」と。
(スライドの)緑色は私です。「確認したところ不具合でした」「修正します」「ホットフィックスとして本番環境にリリースしました」「対応ありがとうございます」。ここで終わっていたら、今日の話はありませんでした。その後に、なにか雲行きが怪しくなります。
「お客さまから問い合わせがきて返信したんですが、今度はサインインができなくなったとの問い合わせがきました」と。このときはわりと楽観的で、「いつものブラウザーキャッシュかな」と思い、「フルリロードやってもらえますか」と返しました。
ところが「同じような問い合わせが、別の方からもきているのですが」と。あれ? なんかおかしいな、と思って調べてみました。そしたら驚愕の事実がわかります。
APIの接続先が、本番環境ではなくなっていました。(スライドに)demoと書いてありますが、上は本番環境で、下は本番環境ではないところです。「ええー!?」と。
そもそもホットフィックスリリースしたときは、そのAPIの接続先などにはまったく関係のないものです。いわゆる、“何もしてないのに壊れた”というやつです。
どうしてこうなったのかを話す前に、リアクトアプリケーションがどういうふうになっていたのか。デプロイフローからお話ししようと思います。
ざっくり書くとこんな感じです。本当はRoute53とかいろいろありますが、ちょっとそこは割愛します。
簡単に説明すると、GitHubのメインプランチのマージをトリガーにして、CircleCIのワークフローが起動します。
CircleCIのワークフローは本番環境とステージ環境の2つあり、同時に実行されます。上にあったものが、今回問題が発覚した本番環境です。
CircleCI上でリアクトアプリケーションというかSPAをビルドして、S3にアップロードして、キャッシュを削除する流れになっています。このあたりまでは、よく見る構成だと思います。若干古臭いのはちょっと置いといてください。
ではなぜあんなことが起こってしまったんだろう。どうしてこうなった、というところに迫ってみたいと思います。
CircleCIでビルドしたSPAをS3にアップロード。ここの“ビルドした”がなんかちょっと怪しいです。ではこの“ビルドしている”というプロセスは、いったいどうなっているのか。
また、本番環境とステージ環境、それぞれAPIの接続先は違う。環境設定情報を変えていますが、ではそれをビルドのところでどのように解決してるのかを次に話します。
ざっくり書くとこんな感じです。1番目が環境依存の設定を.envにコピー。cpでコピーするという、本当に単純なファイルコピーです。そのあとwebpack buildを実行して、3番で1番でコピーした.envを参照して、dotenvというライブラリが、ビルド中にビルド結果、ディストリビューションに埋め込むことをやります。
1番がおかしくなることは常識的にちょっと考えづらい。今回も変更してない。そのため、2番がちょっと怪しいです。では2番のwebpack build、またはそのwebpackの構成、設定はどうなっていたのかを、これから調べてみましょう。
webpack buildの設定ですが、実は、開発用の設定と本番用の設定が、一緒になっていました。ここですでに察する人もいるかもしれません。本番用の設定と一緒になってたんですが、開発効率向上のためにHardSorceWebpackPluginを使ってました。
「どうして開発効率を向上させるために?」と思われるかもしれませんが、ローカルで開発するときにlessのコンパイル、ビルドが走って1回保存すると、ものすごく時間がかかりました。そのため、そのlessのビルドなどの時間を省略するためにHardSorceWebpackPluginを入れていました。
このHardSorceWebpackPluginは、node_modulesの下にキャッシュを生成します。CircleCIのワークフローは一般的なので置いときます。キャッシュパスは、ブランチ名とyam.lockのハッシュ値をパスにしていました。「おや? なんか見えてきたぞ」と。
どこに注目するかは、前回のビルドと今回のビルドを、時系列で整理してみましょう。真ん中に注目してみてください。このCircleCIのキャッシュはブランチ名とyam.lockから生成されるので、yam.lockが変わらなければCircleCIのキャッシュパスは全部一緒です。
CircleCIのキャッシュ保存のほうが遅かったら? CircleCIのキャッシュ取得で使われるビルドキャッシュには、さていったい何が入ってるんでしょうか。問題は環境設定ファイルがビルドキャッシュの中に含まれてしまい、本来設定してほしい内容と、ビルドキャッシュの中身が別になっていた。なので、一時対処として、デプロイフローでnode_modulesのビルドキャッシュを削除したら解消しました。「やったぜ」という感じです。
今回の学び、大きくわけて3つです。CircleCIのキャッシュは大事。ただ、予期しないタイミングで壊れるので取り扱い注意。今回の場合はビルドキャッシュが環境ごとに変わるという意味で、冪等ではなかったので、そもそも壊れやすい状況だったと。そのため、「ある意味壊れて当然だったんじゃないの」と言われれば、ぐうの音も出ない感じです。
キャッシュしている中身は、ちゃんとサボらず確認しよう。アプリケーションだけでなく、ライブラリをインストールして使うとそれだけですぐ作成されてしまうキャッシュ、すごく見えづらいキャッシュもあります。そこまで含めてちゃんと調べましょうね、というのがあったと思います。
これで最後ですが、開発用の設定とデプロイ用の設定を一緒にするのは悪手。前からやりたいなとは思っていましたが、「今じゃなくていいだろう」と先延ばしにしていった結果、こんな障害を起こしてしまった。「これをやりたい」「あれをやりたい」という吟味はすごく重要ですが、それをしないことによってどんな影響が出てしまい得るのかも含め、やる・やらないは判断しなければいけなかったのではないかという反省です。
最後。公式ページには「分割することを推奨」「Typical Recommended」と書いてあるので、よい子のみなさんはやっていないと思いますが、やらないようにしましょう。webpack5だと、ビルドキャッシュ周りがwebpackの中に入ったりと、けっこう変わってます。そのため、HardSorceWebpackPluginを導入して同じ地雷を踏み抜く方は少なくなったのではないかと思います。
justInCaseではエンジニア募集しているので、興味がある方、エントリーをお願いします。以上です。ありがとうございました。
田仲紘典氏(以下、田仲):はい、ありがとうございました。環境、dotenv周りの話を一緒にすることはそもそもやったことがないですが、やっていてこんなこと起こるんだって思いながら聞いてました。
質問がきています。このケース自体、ステージング・プロダクションの区別をキャッシュに入れるべきなのかという疑問ですが、どうですか。
小佐野:うーん、それは悩ましいですね。冪等にするのであれば、やったほうがよかったのではないか。どちらかというと、キャッシュの中に入っていることを知らなかったこと自体が問題だった、かな?
その環境設定情報はビルドキャッシュというか、CircleCIのキャッシュの中に含まれてしまって、冪等でなくなってしまったことが本質であって、もし入れるなら分割したほうがいい。削除するなら、別に一緒でよかったんじゃないかという印象です。
田仲:なるほど。初期の段階の開発で、そのdotenv自体を、開発環境とステージング環境に分けるとこは考えませんでしたか?そもそもファイルを分けるという話です。
小佐野:いや、分けていました。ただ、それぞれのデプロイフローを分割するにあたり、dotenvとライブラリが、そのプロジェクトの中の.envというファイルを見てリゾルブする流れだったので、ちょっと特殊なデプロイフローになってしまった感じです。
そのため、それぞれ環境ごとの格納しているディレクトリやファイルパスは全部違います。それぞれデプロイするときに引っ張ってくるファイルが全部違う感じ。
田仲:失礼しました。一緒だと思っていました(笑)。
今回たぶんホットフィックスで、超早く開発して、ビルドして、アップしてという感じだったと思います。今後、どういったリリースフローなら、こういったことが絶対起こらないか。環境変数分けるとか、全部分ける以外で何かあったら教えてほしいです。
小佐野:正直そこは模索中なのであえて書きませんでした。デプロイパイプラインとか、リリースパイプラインが共用のCircleCIになってるのは、ちょっともしかしたらよくないのかもと思ったり。
それぞれの環境にリリースするもの、AWSアカウント側にデプロイするものがいてもいいのかなと思ってはいます。ちょっとまだ試行錯誤中というか、どうしたもんかと思っている節はあります。
田仲:なるほど。またどんなふうになったのか教えてください。ちょうど時間になったので終わります。小佐野さん、ありがとうございました。
小佐野:ありがとうございました。
関連タグ:
2024.12.20
日本の約10倍がん患者が殺到し、病院はキャパオーバー ジャパンハートが描く医療の未来と、カンボジアに新病院を作る理由
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.17
面接で「後輩を指導できなさそう」と思われる人の伝え方 歳を重ねるほど重視される経験の「ノウハウ化」
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05