ECS の dependsOn で HEALTHY に依存させて HEALTHY にならなければ無限に待ち続けることがある
ECS の dependsOn では condition
に HEALTHY を指定することができ、依存するコンテナのヘルスチェックが通るまで待つことができます。ところが、本来 essential なコンテナのヘルスチェックが通らないとタスク全体が終了するはずが、これを指定することで HEALTHY にならない限り、無限に PENDING な状態で待ち続けることがあるようです。後述の再現コードでは無限に待ち続けましたが、別のケース(ECS agent のバージョン等色々異なる)ではちょうど 10 分程度で stopped reason が launch timeout になったので、何らかの条件ではある程度の時間が経過すると timeout になるかもしれません。
再現コード
次のファイルに対して terraform apply
することで再現確認できます。今実行すると AMI は ami-01a818286958067c9 (amzn2-ami-ecs-hvm-2.0.20220318-x86_64-ebs) になり、ECS agent version は 1.60.0 になりました。
provider "aws" {}
locals {
application_name = "healthy-dependency-example"
}
data "aws_subnet" "default_1a" {
default_for_az = true
filter {
name = "availability-zone"
values = ["ap-northeast-1a"]
}
}
data "aws_ami" "most_recent_ecs_optimized" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-ecs-hvm-2.0.*-x86_64-ebs"]
}
}
resource "aws_ecs_cluster" "main" {
name = local.application_name
}
resource "aws_ecs_task_definition" "main" {
family = local.application_name
# fluetnd never becomes healhty
container_definitions = <<-JSON
[
{
"name": "main",
"image": "ubuntu",
"essential": true,
"memoryReservation": 50,
"dependsOn": [
{
"containerName": "fluentd",
"condition": "HEALTHY"
}
]
},
{
"name": "fluentd",
"image": "fluent/fluentd:v1.14.5-1.1",
"essential": true,
"memoryReservation": 50,
"healthCheck": {
"command": ["CMD", "nc", "-z", "127.0.0.1", "24225"],
"interval": 5,
"timeout": 5,
"retries": 10
}
}
]
JSON
}
resource "aws_ecs_service" "fluentd_forwarder" {
name = aws_ecs_task_definition.main.family
cluster = aws_ecs_cluster.main.name
task_definition = aws_ecs_task_definition.main.arn
desired_count = 1
}
resource "aws_instance" "main" {
ami = data.aws_ami.most_recent_ecs_optimized.image_id
instance_type = "c5.large"
subnet_id = data.aws_subnet.default_1a.id
associate_public_ip_address = true
iam_instance_profile = "ecsInstanceRole"
tags = {
Name = local.application_name
}
user_data = <<-DATA
#!/bin/bash
cat <<'EOF' >> /etc/ecs/ecs.config
ECS_CLUSTER=${aws_ecs_cluster.main.name}
ECS_AVAILABLE_LOGGING_DRIVERS=["awslogs","fluentd"]
EOF
DATA
}
次のスクリーンショットのように created at から起動しないまま 30 分以上経過したので明示的に stop しました。
startTimeout で終了させることもできるらしい
他の環境で試した時は startTimeout を指定しても効果がなかった気がするんですが、ヘルスチェックの設定を指定しているコンテナに startTimeout
を指定することで、その時間内に HEALTHY にならなければ stopped reason Task failed to start になることもあるようです。
次のスクリーンショットは fluentd コンテナの startTimeout
として 60 を指定した場合のタスク詳細です。
ただし、その場合は新しいタスクを起動するのに 5 分ぐらいかかるケースもあるようです。すぐに起動するケースもあるようですが…
なお、run task で起動した task も同様に startTimeout
で指定した時間が経過すると終了しました。startTimeout
として 120 を指定しています。
fluentd worker が gem を読み込む際に稀に stuck するようで、その場合にタスクを終了し、別のタスクを起動してくれることを期待したんですが、挙動が不安ですね…