🤖

AWS Step Functionsで実行する処理にメンテナンスモードを実装する

2024/12/05に公開

この記事は株式会社FOLIOアドベントカレンダーの5日目の記事です。

まとめ

  • SSM Parameter Storeを使ってメンテナン中か否かのステータスを持つ
  • Step Functionsのアクション System Manager: GetParameter を実行してスタータスを取得
  • Choiceで判定を行い、メンテナンス中の場合受け取っていたInputをSQSにSendする

前提

サービス運用に関わっているとメンテナンスを行うかと思います。そして、メンテナンス中には以下のようなことを行うケースがあると思います。

  • サービスページの表示をメンテナンスページに切り替え
  • 定時バッチや非同期処理を行うデーモン等を一時停止

今回はStep Functionsでバッチやデーモン処理を行っている場合、メンテナンスモードを実装するパターンを考えていきたいと思います。

Step Functionsとは

Step Functionsの細かい説明は割愛させていただきますが、複数のステップを組み合わせて複雑な処理を行うワークフローが実装できるサービスになっています。

Step Functionsのステップでは自身で実装することなくAWSリソース対してAPIを実行できます。以下はSSMのParameter StoreのGetParameter APIを実行するようにGUIで実装しています。

また、AWSリソースのAPIを実行する以外にも条件分岐や並行・再帰処理などのアルゴリズムのようなものが実現できます。以下は Choice と言われる条件分岐のステップです。

全体図

上記はStep FunctionsのWorkflow Studioというワークフローが構築できるGUIからのキャプチャです。以下のようにメンテナンスモードを実装しています。

Step Functionsでメンテナンスモードを実装する例

この図をもとにメンテナンスモードを実装する方法を紹介します。流れを簡単に説明すると以下となります。

  1. メンテンスかどうかを管理するSSM Parameter Storeから値を取得
  2. Choice を使って条件分岐を行う
  3. メンテナンス中の場合は、SQSにキューをpushする

詳細

上記の流れを詳細に説明します。

1. メンテンスかどうかを管理するSSM Parameter Storeから値を取得

Step Functions上からAWSリソース対してAPI実行する機能を用いて、GetParameterを実行します。Parameter Storeに保存する値としては以下のような値になります。

メンテナンスモードに切り替える場合は値を true にして有効化するように想定しています。

resource "aws_ssm_parameter" "is_maintenance" {
  name  = "/application/{env}/is-maintenance"
  type  = "String"
  value = "false" # メンテナンス中は `true` にする
}

Step Functions側からは以下のようにParameter Storeにアクセスします。

{
  "Comment": "sample batch",
  "StartAt": "IsMaintenance",
  "States": {
    "IsMaintenance": {
      "Type": "Task",
      "Parameters": {
        "Name": "/application/stg/is-maintenance"
      },
      "Resource": "arn:aws:states:::aws-sdk:ssm:getParameter",
      "Next": "ExecOrNot"
    },
   (後続)
   .
   .
   .

2. Choice を使って条件分岐を行う

前段でParameter Storeから取得した値を用いて、条件分岐を行います。

メンテナンス中でなければ、通常通りバッチ処理を行うためにECSのrun taskやLambdaのinvoke等を実行することになります。

メンテナンス中であれば、バッチ実行はしない代わりにStep Functionsが受け取ったInputをSQSにキューとしてpushし、メンテナンス解除された場合に改めて実行できるようにします。

Step Functionsとして以下のように Choice を実装します。前段のParameter Storeから取得した値は $.Parameter.Value のように指定することで参照できます。

{
  "Comment": "sample batch",
  "StartAt": "IsMaintenance",
  "States": {
    "IsMaintenance": {割愛},
    "ExecOrNot": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.Parameter.Value", # 前段で取得した値を参照する
          "StringEquals": "true",
          "Next": "PushAllMaintenanceSfnJobQueue" # メンテナンス中の場合はSQSのキューをpushする
        },
        {
          "Variable": "$.Parameter.Value",
          "StringEquals": "false",
          "Next": "通常時のバッチ処理"
        }
      ],
      "Default": "UnkownValue"
    },

3. メンテナンス中の場合は、SQSにキューをpushする

メンテナンス中だった場合は、メンテナンスモード解除後に実行できなかったバッチやデーモン処理を再実行したいため、実行できなかった処理に関してはSQSにキューとしてpushします。

{
  "Comment": "成果物生成を行うジョブ",
  "StartAt": "IsMaintenance",
  "States": {
    "IsMaintenance": {割愛},
    "ExecOrNot": {割愛},
    "通常時のバッチ処理": {割愛},
    "PushAllMaintenanceSfnJobQueue": {
      "Type": "Task",
      "Resource": "arn:aws:states:::sqs:sendMessage",
      "Parameters": {
        "QueueUrl": "{queue_url}",
        "MessageBody": {
          "context.$": "$$" # 実行におけるコンテキスト情報が取得できる
        }
      },
      "End": true
    },
    "UnkownValue": {
      "Type": "Fail"
    }
  }
}

"context.$": "$$" のようにすることで、SQSには {"context":" {...Step Functionsのコンテクスト情報}} といったような形でキューがpushされます。

実行におけるコンテキストは $$ と指定すれば取得できる使用となっており、 $$.Execution.Input のようにすれば、そのStep Functionsが実行時に受け取った引数を取り出すことができます。

https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/input-output-contextobject.html

メンテナンスモード解除後は...

メンテナンスモード解除後はSQSにキューとしてpushしたものをRecieveMessageで取り出して、StepFuntionのStartExecutionを直接実行するなどして、バッチを再実行します。

例としてはShellScript等で運用者が実行するような形にしてあります。

終わりに

今回はStep Functionsでメンテナンスモードを実装してみました。DBの移行作業等、メンテナンス中はバッチやデーモン処理を一時停止したいケースはよくあるケースだと思いますので、何かしらの参考になればと思います。

Discussion