NAT instance란?
목차
서론 #
해당 블로그 Bastion Host글에 따르면, 이제 우리는 public/private 서브넷 각각을 구성할 수 있으며 Bastion Host를 사용하여 개인 인스턴스에 접근할 수 있습니다. 그러나 private 인스턴스에서 라이브러리나 패키지등을 다운로드하려고 할 때, public internet에서 접근할 수 있어야합니다. 그래서 public 서브넷에 NAT 게이트웨이를 생성하여 인터넷 게이트웨이와 통신할 수 있도록 하고, private 인스턴스가 NAT 게이트웨이를 통해 public internet에 접근할 수 있게 합니다.
NAT 게이트웨이 #
resource "aws_eip" "default_nat_gateway_static_ip" {
vpc = true
lifecycle {
create_before_destroy = true
}
}
resource "aws_nat_gateway" "default_nat_gateway" {
allocation_id = aws_eip.default_nat_gateway_static_ip.id
subnet_id = aws_subnet.public_subnet.id
tags = {
Name = "NAT-Gateway"
}
}
# add nat_gateway to private_route_table
resource "aws_route" "nat_gateway_association" {
route_table_id = aws_route_table.private_route_table.id
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.default_nat_gateway.id
}
NAT 인스턴스 #
AWS는 간단하고 자동으로 확장 가능한 NAT 게이트웨이 서비스를 제공합니다. 하지만 NAT 게이트웨이의 월간 비용은 개인이 사용하기에 상당한 부담이 될 수 있습니다. 그래서 NAT 게이트웨이 대신 NAT 인스턴스를 생성하는 것도 가능합니다 (AWS 공식문서에 따르면, NAT 인스턴스보다는 NAT 게이트웨이를 추천합니다).
resource "aws_security_group" "nat_instance_security_group" {
name = "nat_instance_security_group"
description = "Allow all traffic"
vpc_id = aws_vpc.default_vpc.id
ingress {
description = "Allow SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "Allow HTTP in private subnet"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = [aws_subnet.private_subnet.cidr_block]
}
ingress {
description = "Allow HTTPS in private subnet"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [aws_subnet.private_subnet.cidr_block]
}
egress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "nat_instance" {
# NAT 인스턴스용 Linux AMI
ami = "ami-0abd4c49376ea5dbb"
instance_type = "t2.micro"
key_name = aws_key_pair.vpn_key.key_name
network_interface {
device_index = 0
network_interface_id = aws_network_interface.nat_instance_network_interface.id
}
tags = {
Name = "nat_instance"
}
}
resource "aws_network_interface" "nat_instance_network_interface" {
subnet_id = aws_subnet.public_subnet.id
security_groups = [aws_security_group.nat_instance_security_group.id]
# 인스턴스를 NAT 인스턴스로 설정하기 위해 false로 설정 필요
source_dest_check = false
tags = {
Name = "nat_instance_network_interface"
}
}
# NAT 인스턴스에 대한 elastic IP 할당
resource "aws_eip" "nat_instance_static_ip" {
instance = aws_instance.nat_instance.id
network_interface = aws_network_interface.nat_instance_network_interface.id
vpc = true
}
NAT 인스턴스를 설정하기 위해서는 여러 설정이 필요하지만, NAT 인스턴스 전용 AMI(Amazon Machine Image)를 사용하면 이러한 단계들을 건너뛸 수 있습니다. 또한 인스턴스의 source_dest_check
는 false여야 합니다. source/dst 검사는 트래픽의 소스 또는 목적지가 인스턴스 자체여야 함을 보장합니다. 그러나 NAT 인스턴스는 source 혹은 destination이 자신이 아닌 경우에도 트래픽을 보내고 받을 수 있어야 합니다.
마지막으로, NAT 인스턴스의 ENI(Elastic Network Interface)를 private_route_table에 추가합니다.
resource "aws_route" "nat_instance_association" {
route_table_id = aws_route_table.private_route_table.id
destination_cidr_block = "0.0.0.0/0"
network_interface_id =
aws_network_interface.nat_instance_network_interface.id
# instance_id = aws_instance.nat_instance.id
}