AWS Step Functionsで実行する処理にメンテナンスモードを実装する
この記事は株式会社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からのキャプチャです。以下のようにメンテナンスモードを実装しています。
この図をもとにメンテナンスモードを実装する方法を紹介します。流れを簡単に説明すると以下となります。
- メンテンスかどうかを管理するSSM Parameter Storeから値を取得
-
Choice
を使って条件分岐を行う - メンテナンス中の場合は、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"
},
(後続)
.
.
.
Choice
を使って条件分岐を行う
2. 前段で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が実行時に受け取った引数を取り出すことができます。
メンテナンスモード解除後は...
メンテナンスモード解除後はSQSにキューとしてpushしたものをRecieveMessageで取り出して、StepFuntionのStartExecutionを直接実行するなどして、バッチを再実行します。
例としてはShellScript等で運用者が実行するような形にしてあります。
終わりに
今回はStep Functionsでメンテナンスモードを実装してみました。DBの移行作業等、メンテナンス中はバッチやデーモン処理を一時停止したいケースはよくあるケースだと思いますので、何かしらの参考になればと思います。
Discussion