Terraform で Amazon ECS タスク定義を作りつつ,アプリケーションのライフサイクルとして GitHub Actions などの「Terraform 以外で」 イメージタグを差し替えて Amazon ECS タスク定義を更新(正確には更新ではなくリビジョン追加)する運用を選択することがあると思う.さらにデプロイを繰り返すと使わなくなった Amazon ECS タスク定義が増えるため,定期的に「登録解除 (INACTIVE)」 をすることもあると思う.ちなみに2023年2月からは削除もできるように なっているけど〜 \( 'ω')/
track_latest
とは
しかし Amazon ECS タスク定義を登録解除すると Terraform でリソースを追跡できず,terraform plan を実行すると Amazon ECS タスク定義を作り直そうとしてしまう.少し前置きは長くなったけど,2024年2月16日にリリースされた Terraform AWS Provider v5.37.0 で aws_ecs_task_definition に新しく track_latest
オプションが追加された❗️
track_latest - (Optional) Whether should track latest task definition or the one created with the resource. Default is false.
この track_latest
を使うと Terraform 側は常に「最新の」 Amazon ECS タスク定義を追跡して比較してくれるため,Amazon ECS タスク定義の作り直しがなくなり,運用しやすくなる可能性がある👏
github.com
とは言え実際に試さないとイメージが沸かず,プルリクエストに書いてあるシナリオを参考に試してみた.
github.com
デフォルト or track_latest = false
の場合
Step.1
今回はイメージの例として amazonlinux のタグを 2.0.20231218.0
→ 2.0.20240109.0
→ 2.0.20240131.0
と更新する流れを試す.まずは Terraform で Amazon ECS タスク定義(リビジョン1)を作る.
resource "aws_ecs_task_definition" "sandbox_track_latest_false" {
family = "sandbox-track-latest-false"
network_mode = "awsvpc"
requires_compatibilities = [ "FARGATE" ]
cpu = "256"
memory = "512"
container_definitions = jsonencode ([
{
name = "amazonlinux" ,
image = "amazonlinux:2.0.20231218.0"
}
] )
}
Terraform で Amazon ECS タスク定義(リビジョン1)を作った
Step.2
次は Terraform 以外(今回は AWS CLI を使う)でイメージタグを更新した Amazon ECS タスク定義を2個を作る(リビジョン2・リビジョン3).この状態でアプリケーションとして稼働する最新の Amazon ECS タスク定義は「リビジョン3」 となる.
$ aws ecs register-task-definition --cli-input-json fileb://taskdefinition-2.0 .20240109 .0 .json
$ aws ecs register-task-definition --cli-input-json fileb://taskdefinition-2.0 .20240131 .0 .json
📝 taskdefinition-2.0.20240109.0.json
{
"family ": "sandbox-track-latest-false ",
"networkMode ": "awsvpc ",
"requiresCompatibilities ": [
"FARGATE "
] ,
"cpu ": "256 ",
"memory ": "512 ",
"containerDefinitions ": [
{
"name ": "amazonlinux ",
"image ": "amazonlinux:2.0.20240109.0 "
}
]
}
📝 taskdefinition-2.0.20240131.0.json
{
"family ": "sandbox-track-latest-false ",
"networkMode ": "awsvpc ",
"requiresCompatibilities ": [
"FARGATE "
] ,
"cpu ": "256 ",
"memory ": "512 ",
"containerDefinitions ": [
{
"name ": "amazonlinux ",
"image ": "amazonlinux:2.0.20240131.0 "
}
]
}
AWS CLI で Amazon ECS タスク定義(リビジョン2・リビジョン3)を作った
Step.3
ここで使わなくなった Amazon ECS タスク定義(リビジョン1・リビジョン2)を登録解除する.
$ aws ecs deregister-task-definition --task-definition sandbox-track-latest-false:1
$ aws ecs deregister-task-definition --task-definition sandbox-track-latest-false:2
Amazon ECS タスク定義(リビジョン1・リビジョン2)を登録解除した
Step.4
最後に terraform plan を実行すると Amazon ECS タスク定義を作り直そうとする😨 ちなみに個人用の Terraform Cloud のキャプチャを載せている.
terraform plan を実行した
track_latest = true
の場合
Step.1
基本的には同じだけど,名前を sandbox-track-latest-true
に変更して,track_latest = true
も設定した.まずは Terraform で Amazon ECS タスク定義(リビジョン1)を作る.
resource "aws_ecs_task_definition" "sandbox_track_latest_true" {
family = "sandbox-track-latest-true"
network_mode = "awsvpc"
requires_compatibilities = [ "FARGATE" ]
cpu = "256"
memory = "512"
track_latest = true
container_definitions = jsonencode ([
{
name = "amazonlinux" ,
image = "amazonlinux:2.0.20231218.0"
}
] )
}
Step.2
Step.2 も基本的には同じ.Amazon ECS タスク定義を2個作る(リビジョン2・リビジョン3).
$ aws ecs register-task-definition --cli-input-json fileb://taskdefinition-2.0 .20240109 .0 .json
$ aws ecs register-task-definition --cli-input-json fileb://taskdefinition-2.0 .20240131 .0 .json
📝 taskdefinition-2.0.20240109.0.json
{
"family ": "sandbox-track-latest-true ",
"networkMode ": "awsvpc ",
"requiresCompatibilities ": [
"FARGATE "
] ,
"cpu ": "256 ",
"memory ": "512 ",
"containerDefinitions ": [
{
"name ": "amazonlinux ",
"image ": "amazonlinux:2.0.20240109.0 "
}
]
}
📝 taskdefinition-2.0.20240131.0.json
{
"family ": "sandbox-track-latest-true ",
"networkMode ": "awsvpc ",
"requiresCompatibilities ": [
"FARGATE "
] ,
"cpu ": "256 ",
"memory ": "512 ",
"containerDefinitions ": [
{
"name ": "amazonlinux ",
"image ": "amazonlinux:2.0.20240131.0 "
}
]
}
Step.3
ここで使わなくなった Amazon ECS タスク定義(リビジョン1・リビジョン2)を登録解除する.
$ aws ecs deregister-task-definition --task-definition sandbox-track-latest-true:1
$ aws ecs deregister-task-definition --task-definition sandbox-track-latest-true:2
Amazon ECS タスク定義(リビジョン1・リビジョン2)を登録解除した
Step.4
track_latest = true
を設定してると Step.4 から挙動が変わってくる💡ここで terraform plan を実行すると Amazon ECS タスク定義を作り直しではなく「最新の」 Amazon ECS タスク定義を追跡して比較してくれる.実際に containerDefinitions.image
の値を最新の amazonlinux:2.0.20240131.0
から,Terraform コードで指定している amazonlinux:2.0.20231218.0
に戻すような差分が出ている❗️
terraform plan を実行した
次に Terraform コードを修正して最新の Amazon ECS タスク定義と一致させる📝
resource "aws_ecs_task_definition" "sandbox_track_latest_true" {
family = "sandbox-track-latest-true"
network_mode = "awsvpc"
requires_compatibilities = [ "FARGATE" ]
cpu = "256"
memory = "512"
track_latest = true
container_definitions = jsonencode ([
{
name = "amazonlinux" ,
image = "amazonlinux:2.0.20240131.0"
}
] )
}
もう一度 terraform plan を実行すると No changes で差分なしになる👌
なるほどー \( 'ω')/
terraform plan を実行した
まとめ
2024年2月16日にリリースされた Terraform AWS Provider v5.37.0 で追加された aws_ecs_task_definition
の新しいオプション track_latest
オプションを試してみた❗️ドキュメントを読むだけではイメージが沸かず,実際に試してみて良かった.とは言え track_latest = true
を設定するとアプリケーションを頻繁にデプロイするときに変更の追随も大変そうなので ignore_changes
で変更を無視する運用も引き続き残りそう.まずは track_latest = true
の存在を覚えておこうー💡