タイトル長い
前提
ECSをterraform管理しようとした場合、タスク定義に以下のようなtfファイルを書きますよね
resource "aws_ecs_task_definition" "my_web_server_task" {
family = "my-web-server-task"
container_definitions = "${file(format("%s/my-web-server-task.json", path.module))}"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "256"
memory = "512"
task_role_arn = "${aws_iam_role.ecs_task_role.arn}"
execution_role_arn = "${aws_iam_role.ecs_task_role.arn}"
}
[
{
"name": "nginx",
"image": "nginx:1.16.1",
"essential": true,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 8080
}
]
}
]
問題
上記tfファイルの定義の場合, my-web-server-task.json
などに変更があった場合、 terraform apply
コマンドの動作としてはreplaceになります
+++ b/terraform/ecs/my-web-server-task.json
@@ -1,7 +1,7 @@
[
{
"name": "nginx",
- "image": "nginx:1.16.1",
+ "image": "nginx:1.17.3",
"essential": true,
"portMappings": [
{
$ terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# module.m_ecs.aws_ecs_task_definition.my_web_server_task must be replaced
-/+ resource "aws_ecs_task_definition" "my_web_server_task" {
~ arn = "arn:aws:ecs:ap-northeast-1:<user>:task-definition/my-web-server-task:1" -> (known after apply)
~ container_definitions = jsonencode(
~ [ # forces replacement
~ {
- cpu = 0 -> null
- environment = [] -> null
essential = true
~ image = "nginx:1.16.1" -> "nginx:1.17.3"
~(略)~
「古いrevisionが削除され、新しいrevisionが作成される」という感じですね
せっかくaws側でrevision管理されているのだから過去分は残して欲しいところ
対策
count
パラメタで新しいリソースを追加する形にしてあげれば、旧revisionを残したまま新しいrevisionを作成することができます
locals {
revision = 1
}
resource "aws_ecs_task_definition" "my_web_server_task" {
family = "my-web-server-task"
count = "${local.revision}"
container_definitions = "${file(format("%s/my-web-server-task.json-%d", path.module, count.index+1))}"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "256"
memory = "512"
task_role_arn = "${aws_iam_role.ecs_task_role.arn}"
execution_role_arn = "${aws_iam_role.ecs_task_role.arn}"
}
jsonファイル名にはrevisionが入ります
[
{
"name": "nginx",
"image": "nginx:1.16.1",
"essential": true,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 8080
}
]
}
]
更新する場合は新たなrevisionに対応するjsonファイルを用意し、countの数値をひとつ増やします
diff --git a/terraform/ecs/task.tf b/terraform/ecs/task.tf
index 5b43885..c494b15 100644
--- a/terraform/ecs/task.tf
+++ b/terraform/ecs/task.tf
@@ -15,7 +15,7 @@
# }
locals {
- revision = 1
+ revision = 2
}
[
{
"name": "nginx",
"image": "nginx:1.17.3",
"essential": true,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 8080
}
]
}
]
$ terraform/local terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
createのみになりましたね
欠点
ただし、この方法を使用する場合、一度に複数revisionを作ろうとした場合に
Error: ClientException: Too many concurrent attempts to create a new revision of the specified family.
が出て作成できません、revisionがsequentialな番号を必要とするのに対してterraform側が並列に作りに行くのが理由ですね
仮に複数段作成の対応をするならrevisionをインクリメントしつつ terraform apply
を実行してくれる外部ツールなどが必要ですね