🦩
ECS+Fargate の Public IP を固定 IP にしたい
やりたいこと
Amazon ECS+Fargate を構築し、Public IP アドレスを割り当てています
Internet Gateway へのルートを持つ Public Subnet にこれを配置してます
遊びでやってるので、Public にしてます
(Private だと AWS 料金が増えるからです)
この Public IP アドレスがデプロイ時に ECS タスクを作り変えるたびに変わってしまうので、これを固定させたいと考えています
調べると 2 通りのやり方がありそう
- Network Load Balancer(NLB)を使う
- NLB に Elastic IP を割り当てる
- ちなみに Fargate に直接 Elastic IP を割り当てることは現状できない(ECS の起動タイプが EC2 ならいける)
- Fargate と同じ Subnet 内に NLB を配置する
- NLB に Elastic IP を割り当てる
- NAT Gateway を使う
- Fargate を Private Subnet に配置する
- Public Subnet に NAT Gateway を作成
- NAT Gateway に Elastic IP を割り当てる
- Public Subnet に Internet Gateway を作成
- Fargate は NAT Gateway を介して、インターネットに接続する
今回は NLB を使うやり方にします
理由は料金的な話で
- NAT Gateway の料金が高い、処理データ量(GB)単位で課金される
- ECS タスクを起動する際に Docker イメージを pull するが、Private Subnet に Fargate を配置すると、イメージの pull を NAT 経由で行ってしまうので、そのサイズ分課金されるらしい(確認してないけど)
- NAT を経由しない別ルーティングを用意する必要が出てくる
NLB を作成
VPC と Public Subnet は Fargate と同じやつを使う
AWS コンソールで作成
-
EC2 -> Elastic IP
から Elastic IP アドレスを作成 -
EC2 -> ターゲットグループ
からターゲットグループを作成設定項目 設定値 備考 Choose a target type IP addresses Fargate なので IP(インスタンスだとたぶん駄目) Target group name ターゲットグループの名前 Protocol TCP NLB は L4(TCP や UDP)のプロトコルをサポートしている Port 80 VPC Fargate と同じやつ 設定項目 設定値 備考 Health check protocol TCP 設定なし
-
EC2 -> ロードバランサー
から Network Load Balancer を作成設定項目 設定値 備考 Load balancer name ロードバランサーの名前 Scheme Internet-facing Public Subnet は Internet-facing(インターネット向け)、Private Subnet は Internal(内部向け) IP address type IPv4 設定項目 設定値 備考 VPC Fargate と同じやつ Subnet Fargate と同じやつ IPv4 settings 作成した Elastic IP 設定項目 設定値 備考 Protocol TCP Port 80 今回は HTTP プロトコルで待ち受ける Default action(type) Forward to 指定したターゲットグループにリクエストを転送する Default action 作成したターゲットグループ
Terraformで作成
Elastic IP
resource "aws_eip" "this" {
tags = {
Name = "sample"
}
}
ターゲットグループ
resource "aws_lb_target_group" "this" {
target_type = "ip"
name = "sample"
protocol = "TCP"
port = 80
vpc_id = aws_vpc.this.id
health_check {
protocol = "TCP"
}
}
NLB
resource "aws_lb" "this" {
load_balancer_type = "network"
name = "sample"
internal = false
ip_address_type = "ipv4"
subnet_mapping {
subnet_id = aws_subnet.pub_a.id
allocation_id = aws_eip.this.id
}
}
NLB リスナー
resource "aws_lb_listener" "this" {
load_balancer_arn = aws_lb.this.id
protocol = "TCP"
port = "80"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.this.arn
}
}
ECS のサービスを作り直す
AWS コンソールで作成
ロードバランサーは後から追加できないので、サービスを作り直す
設定項目 | 設定値 | 備考 |
---|---|---|
ロードバランサーの種類 | Network Load Balancer | |
ロードバランサー名 | 作成したロードバランサー | |
ターゲットグループ名 | 作成したターゲットグループ |
ECS サービスのセキュリティグループでロードバランサーからのアクセスを許可するため、インバウンドルールに VPC の IPv4 CIDR ブロック(例:10.0.0.0/16)を追加
Port range は Fargate 上で動かしているアプリケーションに合わせて適宜設定する
EC2 -> ターゲットグループ -> Targetsタブ
で Health status が healthy になればオッケー
(固定の)Elastic IP アドレスで疎通できるようになる
Terraformで作成
セキュリティグループ
インバウンドルールに VPC の IPv4 CIDR ブロックを追加
ポートは適宜設定
resource "aws_security_group" "this" {
name = "sample"
vpc_id = aws_vpc.this.id
}
resource "aws_security_group_rule" "nlb" {
type = "ingress"
description = "NLB"
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = [aws_vpc.this.cidr_block]
security_group_id = aws_security_group.this.id
}
ECS サービス
resource "aws_ecs_service" "this" {
...
load_balancer {
target_group_arn = aws_lb_target_group.this.arn
container_name = "sample"
container_port = 8080
}
}
Discussion