2024.10.10
将来は卵1パックの価格が2倍に? 多くの日本人が知らない世界の新潮流、「動物福祉」とは
本番環境にホットフィックスをリリースして破壊した話(全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.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.12
自分の人生にプラスに働く「イライラ」は才能 自分の強みや才能につながる“良いイライラ”を見分けるポイント
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.11
気づいたら借金、倒産して身ぐるみを剥がされる経営者 起業に「立派な動機」を求められる恐ろしさ
2024.11.11
「退職代行」を使われた管理職の本音と葛藤 メディアで話題、利用者が右肩上がり…企業が置かれている現状とは
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.12
先週まで元気だったのに、突然辞める「びっくり退職」 退職代行サービスの影響も?上司と部下の“すれ違い”が起きる原因
2024.11.14
よってたかってハイリスクのビジネスモデルに仕立て上げるステークホルダー 「社会的理由」が求められる時代の起業戦略
2024.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.12
自分の人生にプラスに働く「イライラ」は才能 自分の強みや才能につながる“良いイライラ”を見分けるポイント
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.11
気づいたら借金、倒産して身ぐるみを剥がされる経営者 起業に「立派な動機」を求められる恐ろしさ
2024.11.11
「退職代行」を使われた管理職の本音と葛藤 メディアで話題、利用者が右肩上がり…企業が置かれている現状とは
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.12
先週まで元気だったのに、突然辞める「びっくり退職」 退職代行サービスの影響も?上司と部下の“すれ違い”が起きる原因
2024.11.14
よってたかってハイリスクのビジネスモデルに仕立て上げるステークホルダー 「社会的理由」が求められる時代の起業戦略