今回は、2023/8/10にサポートされた、NLBへのセキュリティグループアタッチをTerraformで実行してみました。
2023/8/18にリリースされたAWSプロバイダ5.13.0以降から、NLBへのセキュリティグループアタッチがTerraformでできるようになったようです。
構成図
Terraformのバージョン情報
筆者が使用したTerraformのバージョンは以下です。
Terraform Core :1.5.5
AWSプロバイダ :15.13.1
tfファイルの内容
今回の構築に使用したtfファイルは以下です。
※バックエンドやプロバイダ指定の動作設定は省略しています(AWSリソースのコードのみ記述しています)。
infra.tf
NLB用セキュリティグループのインバウンドは便宜上、0.0.0.0/0 としています。
EC2に設定しているセキュリティグループのインバウンドルールは、NLBにアタッチするセキュリティグループIDのみを許可しています。
メタ引数である「for_each」の使い方については、以下の記事でご紹介しています。
############################################################################
# VPC
############################################################################
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "test-vpc"
}
}
############################################################################
# インターネットゲートウェイ
############################################################################
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "test-igw"
}
}
############################################################################
# サブネット
############################################################################
# NLB用パブリックサブネット
resource "aws_subnet" "nlb_subnet" {
for_each = {
"a" = "10.0.0.0/24"
"c" = "10.0.1.0/24"
}
vpc_id = aws_vpc.vpc.id
cidr_block = each.value
availability_zone = "ap-northeast-1${each.key}"
tags = {
Name = "test-nlb-subnet-${each.key}"
}
}
# EC2用パブリックサブネット
resource "aws_subnet" "ec2_subnet" {
for_each = {
"a" = "10.0.4.0/24"
"c" = "10.0.5.0/24"
}
vpc_id = aws_vpc.vpc.id
cidr_block = each.value
availability_zone = "ap-northeast-1${each.key}"
tags = {
Name = "test-ec2-subnet-${each.key}"
}
}
############################################################################
# ルートテーブル
############################################################################
resource "aws_route_table" "public_route" {
vpc_id = aws_vpc.vpc.id
route {
gateway_id = aws_internet_gateway.igw.id
cidr_block = "0.0.0.0/0"
}
tags = {
Name = "test-public-route"
}
}
# サブネットとの紐づけ
resource "aws_route_table_association" "route_public_association_nlb" {
for_each = {
"a" = "1"
"c" = "2"
}
subnet_id = aws_subnet.nlb_subnet["${each.key}"].id
route_table_id = aws_route_table.public_route.id
}
resource "aws_route_table_association" "route_public_association_ec2" {
for_each = {
"a" = "1"
"c" = "2"
}
subnet_id = aws_subnet.ec2_subnet["${each.key}"].id
route_table_id = aws_route_table.public_route.id
}
############################################################################
# セキュリティグループ
############################################################################
# NLB用セキュリティグループ
resource "aws_security_group" "sg_nlb" {
name = "test-sg-nlb"
description = "Allow http from NLB"
vpc_id = aws_vpc.vpc.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = [
"0.0.0.0/0",
]
}
egress {
cidr_blocks = [
"0.0.0.0/0",
]
from_port = 80
protocol = "tcp"
to_port = 80
}
}
# EC2用セキュリティグループ
resource "aws_security_group" "sg_ec2" {
name = "test-sg-ec2"
description = "Allow http from NLB"
vpc_id = aws_vpc.vpc.id
egress {
cidr_blocks = [
"0.0.0.0/0",
]
from_port = 80
protocol = "tcp"
to_port = 80
}
egress {
cidr_blocks = [
"0.0.0.0/0",
]
from_port = 443
protocol = "tcp"
to_port = 443
}
}
# EC2用セキュリティグループのインバウンドへNLBのセキュリティグループをソースに指定
resource "aws_security_group_rule" "sg_ec2_rule" {
type = "ingress"
to_port = 80
protocol = "tcp"
source_security_group_id = aws_security_group.sg_nlb.id
from_port = 80
security_group_id = aws_security_group.sg_ec2.id
}
ec2.tf
AMIは、Data sourceでAmazon Linux 2 x86の最新バージョンを取得して指定しています。
user_dataで、apacheをインストールしてindex.htmlを作成します。
##############################################################################
# EC2インスタンス
##############################################################################
resource "aws_instance" "ec2" {
for_each = {
"a" = "1"
"c" = "2"
}
ami = data.aws_ssm_parameter.amzn2_ami.value
associate_public_ip_address = true
instance_type = "t2.micro"
subnet_id = aws_subnet.ec2_subnet["${each.key}"].id
vpc_security_group_ids = [aws_security_group.sg_ec2.id]
tags = {
Name = "test-ec2-${each.key}"
}
user_data = <<EOF
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
touch /var/www/html/index.html
echo "Hello AWS!" | tee -a /var/www/html/index.html
EOF
}
# 最新AMI取得用データ
data aws_ssm_parameter amzn2_ami {
name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}
elb.tf
AWSプロバイダ5.13.0以降は、リソースブロック「aws_lb」でパラメータ「load_balancer_type」の値が「network」でも(NLBでも)、パラメータ「security_groups」を記述できるようになっています。
※今までは「load_balancer_type」が「application」の場合のみ(ALBのみ)対応だった。
############################################################################
# ELB
############################################################################
#---------------------------------------------------------------------------
# NLB
#---------------------------------------------------------------------------
# NLB本体
resource "aws_lb" "nlb" {
name = "test-nlb"
internal = false
load_balancer_type = "network"
security_groups = [aws_security_group.sg_nlb.id]
subnets = [
aws_subnet.nlb_subnet["a"].id,
aws_subnet.nlb_subnet["c"].id
]
tags = {
Name = "test-nlb"
}
}
# NLBのターゲットグループ
resource "aws_lb_target_group" "tg_nlb" {
name = "test-tg-nlb"
port = 80
protocol = "TCP"
vpc_id = aws_vpc.vpc.id
target_type = "instance"
}
# NLBのターゲットグループへのターゲット紐づけ
resource "aws_lb_target_group_attachment" "tg_nlb_attachment" {
for_each = {
"a" = "1"
"c" = "2"
}
target_group_arn = aws_lb_target_group.tg_nlb.arn
target_id = aws_instance.ec2["${each.key}"].id
}
# NLBのリスナー設定(NLBとターゲットグループの紐づけ)
resource "aws_lb_listener" "listener_nlb" {
load_balancer_arn = aws_lb.nlb.arn
port = 80
protocol = "TCP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.tg_nlb.arn
}
}
NLBにセキュリティグループがアタッチされていた
terraform applyの実行後、NLBが作成されてセキュリティグループがアタッチされていることを確認しました。
NLBにアクセスしてみる
コピーしたDNS名をブラウザに入力して、無事アクセスできました。
NLBのセキュリティグループでアクセスを拒否してみる
NLBにアタッチしているセキュリティグループのインバウンドルールを削除すると、アクセスできなくなりました。
NLBにアタッチしているセキュリティグループが機能していることが分かりますね。
まとめ
今回は、TerraformでNLBへセキュリティグループをアタッチする方法をご紹介しました。
NLBのターゲットとなるEC2のセキュリティグループでは、NLBにアタッチされたセキュリティグループIDをインバウンドルールで許可するだけで、NLB以外からのアクセスを遮断できるのが便利ですね。
NLB自体はPrivateLink(VPCエンドポイント)を用いた各サービスとの通信要素としても使うので、利便性はまだまだありそう。
この記事をとおして、少しでも誰かのお役に立てれば幸いです。
参考情報
・AWS公式ドキュメント(Network Load Balancer now supports security groups)
https://aws.amazon.com/jp/about-aws/whats-new/2023/08/network-load-balancer-supports-security-groups/
・Terraform公式ドキュメント(Resource: aws_lb)
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb.html