概要
以前ECSの記事を幾つか書きましたが、
TerraformでECS環境の構築 - Carpe Diem
TerraformでECS環境の構築【オートスケール編】 - Carpe Diem
当時のECSは1インスタンス1コンテナにしないとポートが競合して同じ種類のコンテナを載せることはできませんでした。
しかし今ではALBが導入され、動的ポートマッピングといってコンテナ側のポートは80で、ホスト側にマッピングする際は動的に変えてよろしくやってくれる。ALBはその動的なポートに紐づくという機能が付いています。
これによって1インスタンスに同じ種類のコンテナがいくつもたてられるようになりました。
環境
- terraform 0.11.0
- terraform-provider-aws 1.3.1
成果物
今回のコードはこちら
コード
インスタンスの設定
Auto Scaling Group
resource "aws_autoscaling_group" "dev_api" { availability_zones = ["ap-northeast-1a"] name = "dev-api" max_size = 4 min_size = 1 health_check_grace_period = 300 health_check_type = "EC2" desired_capacity = 1 force_delete = true launch_configuration = "${aws_launch_configuration.dev_api.id}" vpc_zone_identifier = ["${aws_subnet.private_1a.id}"] enabled_metrics = [ "GroupMinSize", "GroupMaxSize", "GroupDesiredCapacity", "GroupInServiceInstances", "GroupPendingInstances", "GroupStandbyInstances", "GroupTerminatingInstances", "GroupTotalInstances", ] ...
ポイント
- ASG自体にLB(
load_balancers
やtarget_group_arns
)を紐付けないこと
です。でないとコンテナとマッピングされたポートとは別で、紐付けたポートがくっついてしまいます。コンテナとはつながっていないので当然unhealthyのままです。
ECS
Service
resource "aws_ecs_service" "api_service" { name = "api-service" cluster = "${aws_ecs_cluster.api_cluster.id}" task_definition = "${aws_ecs_task_definition.api.arn}" desired_count = 1 deployment_minimum_healthy_percent = 50 deployment_maximum_percent = 100 iam_role = "${aws_iam_role.ecs_service_role.arn}" load_balancer { target_group_arn = "${aws_alb_target_group.dev_api.arn}" container_name = "nginx" container_port = 80 } } resource "aws_ecs_task_definition" "api" { family = "api" container_definitions = "${file("task-definitions/api.json")}" }
ポイント
load_balancer
に
- ALBのtarget group
- コンテナ名
- コンテナ側のポート
を設定します。
task definition
[ { "name": "nginx", "image": "nginx", "cpu": 10, "memory": 200, "portMappings": [ { "containerPort": 80, "hostPort": 0 } ] } ]
ポイント
portMappings
で、hostPort
を0
に指定
こうするとAWS側で1024
以降の空いているポートを動的に割り当ててくれます。
ALB
resource "aws_alb_target_group" "dev_api" { name = "dev-api" port = 80 protocol = "HTTP" vpc_id = "${aws_vpc.vpc.id}" deregistration_delay = 30 health_check { interval = 30 path = "/" protocol = "HTTP" timeout = 5 healthy_threshold = 2 unhealthy_threshold = 4 matcher = 200 } ...
ポイント
health_check
ではport
は指定しない
動的にポートを割り振られるため、固定したportを指定することはできません。
指定しない場合、デフォルトのtraffic-port
になるため、疎通できるportに対して行うため問題ありません。
動作確認
こんな感じに空いているポートに紐付ける形で、1つのインスタンス上に複数のコンテナを起動できるようになります。
まとめ
通常のECSの設定から動的ポートマッピングに対応させるためには
- ASGではLBの指定をしない
hostPort
を0
にhealth_check
ではport
は指定しない
とすれば問題なく利用できます。