セキュリティアップデートは忘れたころにやって来る | docker 25 の tmpfs のデフォルトパーミッションが変わった件

こんにちは。 ATOM事業部の田村です。

今回はセキュリティアップデートによる予想外の障害に巻き込まれた件について書いてみました。

概要

今回障害があったシステムは、AWS 上で動いています。 オートスケーリングしていて、システム負荷によって動的に EC2 インスタンスが起動・停止するようにしてあります。 しかしこのインスタンスが起動中 (Pending) から勝手に終了 (Terminating) してしまうという問題が発生しました。挙動を見ていると、十数台に一台は起動するインスタンスがあるのですが、ほとんどが起動中→終了してしまっています。 そのため、現在起動しているインスタンスが落ちないようにしつつ調査を開始しました。

MySQL が Permission denied で起動しない

起動に失敗したインスタンスを確認すると、Docker コンテナ内の MySQL がエラーを出していました。

[Server] Could not open file '/var/log/mysql/mysql-error.log' for error logging: Permission denied
[ERROR] [MY-013236] [Server] The designated data directory /var/lib/mysql/ is unusable. You can remove all files that the server added to it.
[ERROR] [MY-010119] [Server] Aborting

MySQL が /var/lib/mysql や /var/log/mysql にアクセスできていません。インスタンスが正常起動したかどうかは mysql に接続できるかでチェックしているのですが、このせいで mysql が起動しなかったため、ASG のヘルスチェックで蹴られて終了させられていたようです。

このディレクトリは tmpfs でマウントしていたため、tmpfs のパーミッションまわりを確認します。

docker-compose.yml 修正

元はこうしていた tmpfs の設定

tmpfs:
  - /var/lib/mysql
  - /var/log/mysql

これを次のように uid/gid とパーミッションを明示的に指定したところ、正常に起動するようになりました。

tmpfs:
  - /var/lib/mysql:rw,uid=999,gid=999,mode=0770
  - /var/log/mysql:rw,uid=999,gid=999,mode=0770

(999 は公式 mysql イメージの mysql ユーザーの uid, gid)

つまり、docker の tmpfs のデフォルト権限が変わっていた のが原因でした。

docker のバージョンが 25 系に上がっていた

正常起動したインスタンスと、起動失敗するインスタンスの docker バージョンを比較すると、起動失敗するインスタンスには docker 25系 がインストールされていました。 しかし元となる AMI にはそれより前のバージョンの docker がインストールされていたはずです。なぜ新しいバージョンがインストールされているのか?

/var/log/yum.log を調べると、確かに起動後に docker 25 がインストールされたログがありました。さらにその原因を探っていくと、この設定にぶち当たりました。

/etc/cloud/cloud.cfg

repo_upgrade: security

実は、Amazon Linux 2 のセキュリティアップデートで docker 25 が入るようになったのが本当の原因でした。そのため、インスタンス起動時に自動的に走るセキュリティアップデートで、新規インスタンスだけ docker 25 が入るようになっていました。

docker 25 では tmpfs のデフォルトのパーミッションが変わっているようですが、しかし下のキャプチャの通り docker のドキュメントでは「デフォルトは 1777 」とあります。変わったという事については、公式にはドキュメントにもリリースノートにもその記述は見つかりませんでした。

tmpfs mounts | Docker Docs

github を探してみると、こんな issue がありました。これらもパーミッションが変わったことによる影響があったようです。 github.com github.com

なぜ動くインスタンスもあったのか?

しかしこれが原因なら、後から起動するすべてのインスタンスの起動に失敗するはずです。「十数台に一台は起動する」という謎現象を説明できません。いくつか理由を考えてみましたが、あくまで想像でしかなく、ちょっと原因までは突き止められませんでした。

  • セキュリティアップデート完了タイミングの差

自動起動した yum update --security で docker 25 がインストールされるより前に docker 起動に成功した?

  • セキュリティアップデートの反映タイミングの揺れ

yum パッケージのミラー元も複数台で分散しているはずなので、アップデートの反映タイミングにズレがあり、そもそもセキュリティアップデート対象にならない場合があった?

まとめ

たとえセキュリティアップデートだとしても、挙動が変わるようなメジャーバージョンアップは発生し得るという事は学びになりました。 自動アップデートを止めるとか、docker バージョンを固定するというのも一つの手ですが、セキュリティのためこの選択肢はあまり取るべきではなさそうです。

今回のような問題を防ぐためにも、デフォルト値は使用せず明示的に設定するように心がけましょう。