ふり返る暇なんて無いね

日々のメモ書きをつらつらと

アプリケーションをメンテナンスモードにする方法について考えるメモ

前提

AWS上に構築されたwebサービス

構成要素

  • ALB
  • ECS上でうごいているアプリケーション
  • CloudWatch Eventのcronで起動するECSスケジュールタスク
  • RDSなどのデータストア

現状

terrafromのmaintainance_mode変数を見てtrueであれば、ALBで503を返すようにして、スケジュールタスクを止めるように記述している。

問題

  • メンテナンス入れるたびにterrafrom applyをする必要がある
  • 管理リソースが多いためterraform applyに時間がかかり、時間通りにメンテナンスの開始終了ができない

インフラ側で制御する

LambdaでAWSリソースの設定変更を行う

  • 既存のやり方と同じ、設定方法がLambdaに変わっただけ
  • terrafromのstateに一時的に差分ができてしまう。
    • メンテナンス中にAWSリソースの変更がしにくい
  • 既存の方法と同じ

アプリケーション側で制御する

データベースの値を参照する

  • DB(もしくはRedis等)に入っている値を参照してメンテナンスモードを切り替える
  • DBの値を参照するので即時でメンテナンスに入れることができる
  • メンテナンス時にRDSやElastiCacheを変更する際バッティングしてしまう

設定ファイルの値を参照する

  • 設定ファイルにメンテナンス時間を記述しておき、アプリケーションはその値を参照してメンテナンスであるかを判断する
  • メンテナンス開始の明示的な設定変更が不要であらかじめ設定しておける。
  • モノリスなら問題がないが、複数サービス存在する場合は複数箇所に設定を入れる必要がある
    • 次善策としてS3に設定を置いておき、それを参照することで設定値は1つにできる。

メンテナンスサービスの値を参照する

  • 現在メンテナンス中なのかどうかを返すAPIサービスを作る
    • 設定は直書きでも、S3上のファイルでも良い
    • Parameter Storeでもいいか
  • メンテナンスサービスがキャッシュ、プロキシ的に動くので設定が書かれてるAWSリソースへのリクエスト回数を減らすことができる
  • アプリケーションはメンテナンスサービスが返す値をもとにメンテナンスかどうかを判断する。

直接S3やParameterStoreを参照すればいいのでは?

  • メンテナンスサービスを設置せずに、各アプリケーションが直接設定が書いてあるリソースにアクセスする
  • リクエスト回数が極端に多くなければこれでも

まとまらない

1つの方法が良いというわけではなく、メンテナンス箇所がインフラなのかアプリなのかによって方法を組み合わせなければいけないこともあると思います。ECS サービスの変更であれば、アプリケーションのECSタスクが死んでしまうのでアプリをメンテナンスモードにしても無駄だったりします。そういう場合はインフラ側でメンテに入れる必要があったりします。

適材適所でいいのではないでしょうか?

全然他社事例を調べずに書いてるので、他になにかいい方法があったら追記します。