latestタグのままdocker imageを本番運用してどうなったか

latestタグや書き換えるためのタグ(develop, stagingなど)を使って、本番で運用するのはやめましょう。 コンテナイメージのキャッシュ状況やリリースフローによっては予期しない形で 予期しないバージョンが本番で起動する可能性があります。

本記事では、どのプラットフォームやツールで発生したかについては記載しません。 本題はそこではないのと、そもそも運用が間違っているので 記述しても余計な枝葉になるからです。

この記事ではどういうことが起きたか、について書きます。

どういうことが起きたか

サービスで、dockerイメージのlatestタグを使って本番運用していた。 全コンテナをgraceful restartしたようだ。(つもりだったが・・・)

別の作業中、管理画面の表示がおかしくなっているという話が出てきた。 そこで調べてもらったところ、なぜかリリースしたはずの機能が正常に機能していない、という連絡を受けた。 また、影響範囲としてはデータの欠損が発生しているようだということも分かった。

そこで、用意してあったビルド時のgitのコミットハッシュを調べるエンドポイントを何回かリロードしたところ 二種類のハッシュが帰ってくることを確認した、

このことから、ロードバランサーの下に複数のバージョンのコンテナが紐づいていることが分かったので コミットハッシュからどういう状態のアプリケーションがデプロイされているかを確認したところ とある機能が実装されているバージョンとされていないバージョンがデプロイされていることが分かった。 データの欠損もこれが原因だと分かった。 また、プラットフォームの画面からコンテナを見ると、実行開始時間が直近の物とちょっと古いものが混ざっているのも確認できた。

ここで幸運だったのが、元々latest運用されていたが どういう対応でバージョンを固定するかを考えていたので、以下の状態にしていったのが幸運だった。

  • latestではなく書き換えしない前提のgitのコミットハッシュでタグ付けしたdocker imageがある状態
  • 本番で運用しているバージョンをすぐに変更できる状態

だが、まず本番で運用しているバージョンを変更する前にトリアージをする必要があると考え 問題を対処している時間はサービスのピークタイムを過ぎていたので、データ欠損の影響を少なくするために、古いコンテナをぶつり落とした。 落としたタイミングでリロードをしてみたところ、何件かロードバランサーから502が帰ってきたようだ。 その後、新しいコンテナが立ち上がってきたのを確認した。

が、しかし、今度は新しすぎるコンテナが立ち上がってきたのを観測した(本番に影響のある差分がなかったのが幸運だった)

ここで、本来あるべきバージョンで固定するために 本番で運用しているバージョンをlatestからgitのコミットハッシュのバージョンに固定化して 難を逃れた。

まとめ

今回は、latestイメージを運用していてどうなったか、という話を書いた。

少し振り返ると、 幸運だったのは

  • 動いているアプリケーションがどういう状態で動いているか外から調べられるように作っていたこと
  • latestイメージでの運用がダメということが分かっていた
  • 本番で動作するバージョンをすぐに変更できるようにしていたこと
  • データの欠損が直接サービスに影響するものでなかったこと(リアルタイム性が必要のないデータだったこと)
  • latestイメージで運用することがどういうことかを分かってもらえたこと
  • サービスに大きい影響は出ず、サービスの利用に問題がなかったこと

不幸だったのは

  • latestイメージで運用していたこと
  • latestイメージで運用していてバージョン違いのコンテナが混ざったこと
  • データの欠損が発生してしまったこと
  • 利用中にエラーが発生せず、気づくのが遅れてしまったこと
    • 実装の方向性を直しておけば回避できたように思う(requiredなカラムがnullableだった)

こんな感じだったように思う。 サービスに大きい影響は出ず、利用に問題がなかったのは良かったことだが、発見が遅れてしまった原因でもある。 全体的に見ると、幸運だったように思う。

最後に僕から言いたいことは「latestタグや書き換える前提のタグで運用をするのはやめましょう」です。

僕はデータの欠損を直すタスクを新たに積みました。