🎅terraformで理解する、"Fargate"と従来型ECSとの違い🎅
🎄 このエントリはAWS Fargate Advent Calendar 2017の8日目の記事です 🎄
従来型ECS(EC2/ECS)とFargateの違いについて、
.tfファイルの差分を見ることで理解を深めよう!! という試みです。
このエントリでは、以下のような流れで説明していきます。
step1. terraformでバーーンとインフラ一式(ECS含む)を立ち上げ
step2. terraformでstep1の状態からバーーンとFargateに移行
step3. step1とstep2の.tfファイルのdiffを眺める!👀
🙊 この記事執筆時点での事情
まず、そもそもterraformはFargateをサポートしているのか? という大事な話がありますが、
12/8時点で、masterではサポートしているようです!!🎉
ECS Fargate Support by apricote · Pull Request #2483 · terraform-providers/terraform-provider-aws
Depends on #2474 Closes #2471 Hello all, I have never before implemented something in Go, but the features promised by Fargate were just too impressive to wait for. I Implemented most (all?) endpoi…
しかし、このコメントで言われているとおり、「パブリックIPアドレスの自動付与」というオプションを指定することができず😥、、、結果として、VPC内でNATゲートウェイを運用したりしない限り、ネットワーク周りで支障をきたすらしいです。
私は最初これに気づかず、docker pullで失敗しまくってハマっていました😢
ということで、なにかしらやっていく必要があります。😊
💪 自分でビルド!💪
今回は、その部分が解消されている↓下記のPRのバージョンでterraform(-providers-aws)を動かしていくことにします。
Feature/fargate support v2 by johnnorton · Pull Request #2559 · terraform-providers/terraform-provider-aws
The previous merge for ECS Fargate support did not include the ability to ENABLE “Assign Public IP” when creating the ECS Service. From what I can tell, this is an option that only works for servic…
ちなみにこの時点のコミットで試しています。
terraform pluginのビルド方法は昨日書きましたので、どうぞご参考までに。
step1. terraformでバーーンとインフラ一式(ECS含む)を立ち上げる
今回のterraformの設定ファイルはこちらに上げました↓
hoshinotsuyoshi/study-fargate
Contribute to study-fargate development by creating an account on GitHub.
最初の状態は↓こんな感じ。resource名をそのままファイル名にしています。
$ tree
.
├── main.tf
└── modules
└── fastladder
├── aws_alb.tf
├── aws_alb_listener.tf
├── aws_alb_target_group.tf
├── aws_autoscaling_group.tf
├── aws_cloudwatch_log_group.tf
├── aws_db_instance.tf
├── aws_db_parameter_group.tf
├── aws_db_subnet_group.tf
├── aws_ecs_cluster.tf
├── aws_ecs_service.tf
├── aws_ecs_task_definition.tf
├── aws_iam_instance_profile.tf
├── aws_iam_role.tf
├── aws_iam_role_policy_attachment.tf
├── aws_internet_gateway.tf
├── aws_launch_configuration.tf
├── aws_route_table.tf
├── aws_route_table_association.tf
├── aws_security_group.tf
├── aws_subnet.tf
├── aws_vpc.tf
├── data.tf
├── output.tf
└── variable.tf
2 directories, 25 files
各.tfファイルが対応するものを、わかりやすく図の中に書いてみました↓
terraform applyし、webアプリ(今回は例としてfastladder使いました)が立ち上がることを確認したら、step2に移ります。
step2. step1.の状態からバーーンとFargateに移行
こんな感じの修正でterraform applyするとFargate化することができ、無事fastladderが動きました! 🎉 (注1.)
以下の3つのファイルがなくなりました。
- modules/fastladder/aws_autoscaling_group.tf
- modules/fastladder/aws_iam_instance_profile.tf
- modules/fastladder/aws_launch_configuration.tf
さっきと同様に.tfに対応するものを図の中に表記するとこんな感じです↓
Fargateなので当然ですが、オートスケーリンググループや起動設定が削除できていることがわかると思います。
ecs-agentやdockerデーモンの管理をAWSにやってもらえて、本当にラクそうですね👼
step3. step1.とstep2.の.tfファイルのdiffを眺める
では、動かすために何が必要だったのか、少し詳しく見ていきます。
手前味噌なコミット解説で、しかも表面上しかわかっていなくて恐縮なのですが、おつきあいください👼
✎「aws_ecs_task_definition(タスク定義)」に必要だった変更
+ cpu = 256
+ memory = 512
これは何をしているかというと、タスクのCPUの値を256(1CPU=1024に相当)、メモリの量を512MBにしています。
実はFargateでは、タスクは予めAWSが決めているメモリ量/CPU量の組み合わせにマッチしていないと動いてくれません。
メモリ量/CPU量 の組み合わせは以下のような形で定義されており(公式のFargate参照)、 例えば最小にするにはピッタリ0.5GB(=512MB)にする必要があります。
CPU (vCPU) Memory Values (GB)
0.25 0.5, 1, 2
0.5 1, 2, 3, 4
1 Min. 2GB and Max. 8GB, in 1GB increments
2 Min. 4GB and Max. 16GB, in 1GB increments
4 Min. 8GB and Max. 30GB in 1GB increments
また、タスク全体だけではなく、コンテナ定義のなかにもmemoryとcpuの設定が必要でした。
✎「aws_ecs_task_definition(タスク定義)」に必要だった変更 2
+ requires_compatibilities = ["FARGATE"]
+ network_mode = "awsvpc"
+ execution_role_arn = "arn:aws:iam::${var.aws_account_id}:role/ecsTaskExecutionRole"
ここでは3点変更しています。
requires_compatibilities
は、Fargateで動かすには 少なくともFARGATE
を入れる必要があるので入れました。network_mode
は、Fargateで動かすには “awsvpc” である必要があるので、そう設定しました。network_configuration
ecs-agentとDockerデーモンが引き受けるロールのとのこと。ecsTaskExecutionRole
という既存のロールを指定しました。
✎「aws_alb_target_group(ALBターゲットグループ)」に必要だった変更
+ target_type = "ip"
ターゲットグループの target_type
はデフォルト EC2
なのですが、Fargateの場合は必ずip
にする必要があるようでした。
✎「aws_ecs_service(ECSサービス)」に必要だった変更
--- a/terraform/modules/fastladder/aws_ecs_service.tf
+++ b/terraform/modules/fastladder/aws_ecs_service.tf
@@ -2,7 +2,7 @@ resource "aws_ecs_service" "fastladder_rails" {
cluster = "${aws_ecs_cluster.fastladder.id}"
deployment_minimum_healthy_percent = 50
desired_count = "${var.aws_ecs_service_desired_count_rails}"
- iam_role = "${aws_iam_role.fastladder_ecs.arn}"
+ launch_type = "FARGATE"
name = "${var.resource_base_name}_rails"
load_balancer {
@@ -11,5 +11,19 @@ resource "aws_ecs_service" "fastladder_rails" {
target_group_arn = "${aws_alb_target_group.fastladder_rails.arn}"
}
+ network_configuration {
+ subnets = [
+ "${aws_subnet.fastladder_public_a.id}",
+ "${aws_subnet.fastladder_public_c.id}",
+ ]
+
+ security_groups = [
+ "${aws_security_group.fastladder_alb.id}",
+ "${aws_security_group.fastladder_web.id}",
+ ]
+
+ assign_public_ip = "ENABLED"
+ }
+
ここでは3点変更しています。
- Fargateで動くサービスであることを明記する必要があるようで、
launch_type
なるものに「FARGATE」を指定しました。 - Fargateで動くサービスの場合、サービスにIAM RoleをつけることはできないようなのでIAM Roleの設定を削除しました。
network_configuration
というものを書く必要があります。- (AutoScalingGroupがなくなったので、そこでやっていたネットワーク設定がここに移ってきた、というように解釈しました。)
以上です
…主な差分は以上です!!
✎まとめ
- 表面上の説明だけにとどまりましたが、terraformでFargateに必要なインフラの説明を試みました。
- 今回の.tfファイルの差分は
52 insertions(+), 84 deletions(-)
程度でした。規模の小さいWebアプリなら、この程度のようです。 - terraformやっていきましょう