本番環境のEC2に自動でダウンタイムなくパッチを当てる

お疲れ様です。大木 @2357gi です。
とっておきの豆知識なのですが、スノーボードというものは滑走時は運動して体が温まり、リフトで体が冷えるので実質交互浴実質サウナであります。

本題ですが、今回はEC2のAWS Patch Managerを用いて本番環境のEC2に自動でパッチを当てる際のノウハウについて共有したいと思います。

背景

弊社のAWS環境は、DBの踏み台に至るまで基本的に全てECSで運用されており(踏み台ECSについてはこちら)、EC2のメンテナンスからは解放されているのですが、本番環境の一部ではEC2上でアプリケーションが動いているところがあります。
消える目処は立っているものの、それまでの期間はパッチ適用といったEC2のメンテナンスに一定のコストを払う必要があります。

そこで、AWS Patch Managerを使用することによりそこを解消しようとしました。 ただし、愚直にAWS Patch Managerを適用すると未検証のPatchが本番にそのまま適用されてしまうリスクであったり、EC2のリブートを伴うパッチが適用されたときに、ダウンタイムが存在しうるリスクがありました😢

例えば、本番のwebアプリケーションが動作するEC2が2台、ALB上にぶら下がっています。
AWS Patch Manager等の設定により、1台づつパッチの適用を行うように設定することができます。
しかし、再起動を伴うパッチの場合、再起動後にwebアプリケーションが起動するまでタイムラグがあり、ALB側でhealthcheckが通る前に次のパッチを実行してしまう恐れがあります。
「AWS Patch Manager上ではEC2の起動停止までは観測できるが、EC2内で動作するアプリケーションの状態までは考慮できない」ということですね。
これによりダウンタイムが発生しえます。

前述した一部のEC2でも2台構成で動いており、このリスクが存在するため、素直にAWS Patch Managerを適用することはできませんでした。

そこで、対策を講じ無事AWS Patch Managerを回すことができるようになったのでノウハウを共有したいと思います。

そもそもAWS Patch Managerとは

AWS AWS Patch ManagerとはAWS Systems Managerの機能の一つで、EC2などに自動でパッチを適用できるサービスです。

docs.aws.amazon.com

docs.aws.amazon.com

適用するパッチの種類や、パッチが発行されてから適用されるまでの期間などを柔軟に設定することができ、例えば「セキュリティ:クリティカルのパッチのみ、パッチが発行されてから5日後に自動で適用を行う」のように柔軟にパッチ適用ポリシーを設定することができます。

AWS Patch Managerの構成要素

AWS Patch Managerは「Patch Group」と「Patch Baseline」の定義が必要です。
また、パッチの実行には「Maintenance Window」を使用します。

Patch Baselineとは

適用するパッチのルールやパッチレベルの基準をまとめて定義することができるものです。

  • どのパッチを適用するか
  • どのパッチは適用しないか
  • 自動承認のタイミング

みたいなルールを設定することができます。
これにより、「セキュリティパッチの、レベルがクリティカル以上を、n日後に承認」みたいなルールを設けることができます。
ここの「自動承認」というのがミソでして、「パッチが適用されてからn日後にこのパッチを適用することを許可する」という設定をすることができます。
ここの日数を開発環境と本番環境でズラすことにより、「まず開発環境でパッチを適用し確認、問題なければn日後に本番環境に適用」という設定を行うことができます。

Patch Groupとは

EC2とPatch Baselineを紐付けすることができます。
これにより、開発環境はこのベースライン、本番環境はこっちのベースラインといった紐付けをすることができます。
リソースタグをPatch Group側で指定することによりEC2の指定をすることができます。

Maintenance Windowとは

RDSのMaintenance Windowのメンテナンスとかでも使うアレです。
あれをEC2にも設定することができます。
今回だと、承認されたパッチを適用するタイミングをMaintenance Windowで指定することができます。 Maintenance Windowでは同時実行数も設定することができ、1台づつ実行といった設定も可能です。

もう少し具体的なPatch BaselineやPatch Groupの説明はこの記事によくまとまっているので、こちらもお勧めです。
devlog.arksystems.co.jp

開発環境で検証されたパッチを本番環境に適用する

前述したPatch Baselineの設定により、パッチが発行されてから適用承認が行われるまでの日数を指定することができます。

そこで開発環境は0日 / 本番環境は14日と設定することにより、まず開発環境に適用させて、問題なければ本番にも自動適用といった運用が可能になります。

Maintenance Windowの設定を土日の深夜に設定します。これは開発環境も本番環境も同様です。
これにより、土日に適用承認されたパッチがあった場合自動で適用されます。

また、自動パッチが開発環境に適用された際に、CloudWatch EventsをトリガーにSlack通知もできます。
そのSlack通知を元に開発環境を確認し、問題なければそのまま本番にも適用、もしくは問題ある場合は自動適用を止めてトリアージといった処理を行うことができます。

1つ目の課題の、愚直にAWS Patch Managerを適用すると未検証のPatchが本番にそのまま適用されてしまうリスクを解決できました🎉

確実にダウンタイムを発生させずにパッチ適用を行う

EC2が3台存在する場合は1台づつパッチの適用を行なっても問題ないという判断ができるのですが、2台の冗長構成しか取っていませんでした。
パッチ適用のためだけにEC2をもう一台追加するのもナンセンスなので、2台でダウンタイム無しに実現する方法を考えました。

結論から言いますと、土曜日の深夜に適用するMaintenance Windowと、日曜日の深夜に適用するMaintenance Windowを用意し、EC2の半分を土曜日、残りを日曜日に設定することにしました。
土日でローリングパッチを行う感じです。 これにより、ALBのHealthCheckを気にせず、EC2のダウンタイムを気にせずパッチ適用を行うことができるようになりました。

終わりに

EC2、特にステートフルなEC2のお世話はとてもコストがかかります。
AWS Patch Managerを利用することでそれらからお手軽に解放されることができるので是非ともオススメです。