SREチームの藤原です。今回はAmazon ECSのサービス内のタスクを定期的に再起動することで、日々のメンテナンスコストを削減する話です。SRE連載 3月号になります。
ECS Fargateでサービスを運用していると、数ヶ月に一度ほどの頻度でこのようなお知らせがやってきます。
[要対応] サービス更新のお知らせ - AWS Fargate で実行されている Amazon ECS サービスの更新が必要です[Action Required] Service Update Notification - Your Amazon ECS Service Running on AWS Fargate Needs an Update
Fargateをホストしている基盤に更新があったりセキュリティパッチが当たった場合、その上で動いているタスクを起動し直す必要があるためです。
このお知らせを放置していても、予告された期限を過ぎると自動的に新しいタスクが起動し、今動いているタスクは終了するため、サービス自体はダウンタイムなく維持されます(されるはずです)。なので基本放置でよいかというと……これが原因で障害を起こした例が過去にありました。
今動いているタスクと同じタスク定義だとしても、そのタスク定義から新しいタスクが起動できるかは、実際に起動してみるまでは分からないのでした。
サービス内のタスクを再起動するには、例えばaws cliで以下のようなコマンドを実行するだけです。--force-new-deployment
オプションによって、サービス内のタスクを強制的に入れ換えます。簡単ですね。
$ aws ecs update-service \ --service service_name \ --cluster cluster_name \ --force-new-deployment
しかしコマンドを一発打つだけの簡単な作業とはいえ、多数のAWSアカウントで多数のECSサービスを運用している場合、それら全てについて一つ一つCLIを実行するのも面倒です。
ECSサービスのタスクはいつ入れ替わってもよいように作られているべきです(そうでなければアプリケーションの作りを見直しましょう)。単にこの作業を自動化し、毎日再起動してしまえばよいでしょう。
デプロイ頻度が少ないサービスではとても長い間、数年間動き続けているタスクがあったりします。このようなサービスでは、実際に再起動が必要になったタイミングでタスクが新しく起動できるか不安になってしまいます(人間が)。
常に新鮮なタスクに入れ換えることで、以下の要因を取り除くことができます。
定期的にタスクを再起動する処理を実装する方法はいろいろ考えられますが、この程度の作業にaws cliやSDKを使ったLambdaなどを用意するのも大袈裟です。今回はStep FunctionsのAWS SDK統合を利用して実装してみました。
実装するState Machineはごくシンプルなものです。リトライなどの考慮はありませんが、仮に失敗したところで次回の実行で成功すれば問題ないものなので、シンプルに徹しました。
このState MachineはTerraformで管理しています。
terraformのコードは以下のようになりました。ECSクラスターmycluster
に存在しているECSサービスservice1
,service2
を再起動するState Machineをそれぞれ定義するものです。
locals{ecs_services =["service1","service2"]// サービス名}resource"aws_sfn_state_machine""refresh-ecs-service"{for_each =toset(local.ecs_services)name ="refresh-ecs-${each.value}"role_arn = aws_iam_role.refresh-sfn.arn// ecs:UpdateService できる権限を持ったroledefinition =jsonencode({Comment ="ECS Service ${each.value} タスク入れ換え"StartAt ="UpdateService"States ={UpdateService ={Comment ="ECS Service ${each.value} refresh"End =trueParameters ={Cluster ="mycluster"Service = each.valueForceNewDeployment =true// 強制的にタスクを入れ換える}Resource ="arn:aws:states:::aws-sdk:ecs:updateService"Type ="Task"}} })}
jsonencode
関数でJSON文字列化して与えますarn:aws:states:::aws-sdk:ecs:updateService
です。u
が小文字なことに気をつけてくださいあとは、このState Machineを適宜EventBridgeから定期実行してやるだけです。
今回は些細な工夫ですが、Amazon ECSサービス内のタスクを定期的に再起動する作業を自動化し、対応コストを減らす取り組みを紹介しました。
クラウドで動いているコンピューティングリソース(ECSタスク、オートスケールしているEC2のインスタンスなど)はあまり長期間動かしたままにせず、定期的に新しいものに交換していくことをお勧めします。結果的に人間が手を動かして対応するコストを減らすことに繋がることが多いためです。
カヤックでは楽をするためのに手を動かすことが好きなエンジニアを募集しています!
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。