Dev/DevOps, Infra

[AWS][Network][(IaC)Terraform] AWS Network의 구성 요소와 생성

HJChung 2021. 5. 2. 16:37

0. Infrastructure as Code

코드로써의 인프라란 인프라를 이루는 서버, 미들웨어 그리고 서비스 등의 인프라 구성요소들을 코드를 통해 구축하는 것이다. 

이렇게 코드로 구축하게되면 재사용성, 유지보수 등의 장점을 가진다.

1. AWS VPC

AWS VPC(Amazon Virtual Private Cloud)를 사용하면 AWS Cloud에서 논리적으로 격리된 공간을 프로비저닝하여 고객이 정의하는 가상 네트워크에서 AWS 리소스를 시작할 수 있다. 

 

클라우드 위에서 생성한 리소스(EC2, RDS....등)들은 네트워크를 통해 접근하는데, 클라우드 서비스인 AWS는 다양한 고객들이 사용하는 공용공간이다. 즉, 너무 많은 리소스들이 있다. 그리고 이 리소스들에도 하나의 계정에서 생성하는 리소스들만의 격리된 네트워크를 만드는 기능이 바로 VPC이다. 

 

VPC는 논리적인 독립 네트워크를 구성하는 리소스로, IPv4 CIDR block을 가진다. 

CIDR block은 아래의 terraform 코드에서도 cidr_block로 많이 등장한다. 

CIDR block에 대한 내용은 VPC의CIDR블록의 사용이유와 설정방법에 자세히 설명되어 있다. 

 

2. AWS VPC 구성

docs.aws.amazon.com/ko_kr/vpc/latest/userguide/VPC_Scenario2.html

[Network] 네트워크 계층과 네트워크 간의 연결만들면서 배우는 아마존 버추얼 프라이빗 클라우드(Amazon VPC)을 읽은 뒤 이 네트워크 개념을 AWS에 대입해서 보면 VPC 네트워크 구성에 대해서 더 이해가 잘 것이다. 

 

이미지 출처: https://graduation.tistory.com/378

  • Subnet
  • Route Table
  • Internet Gateway
  • NAT Gateway
  • Security Group
  • VPC 엔드포인트

3. AWS VPC, Subnet 생성

1) AWS console로 생성하는 방법

 

IPv4 CIDR block: aws vpc 네트워크망의 주소 범위를 말한다. 

 

 

 

 

 

 

 

 

 

 

 

Subnet이란 라우트 테이블에 연결되는 구조

 

Public subnet's IPv4 CIDR:

 

Private subnet's IPv4 CIDR:

 

Availability Zone:

 

NAT gateway 를 할당할 고정 IP를 할당

 

NAT gateway

 

 

2) Terraform으로 생성하는 방법

# provider.tf
provider "aws" {
	region = "ap-northeast-2" #seoul region
}

a. vpc 생성

# vpc.tf
# VPC 생성시 aws_vpc 리소스 사용

resource "aws_vpc" "main" {
	cidr_block = "10.0.0.0/16" #(필수) IP의 범위
    
    tags = { #리소스에 대한 정보
    	Name = "my_vpc"
    }
}
    

b. subnet 생성

# subnet.tf
# Subnet 생성시 aws_subnet 리소스 사용
   
# Public Subnet
resource "aws_subnet" "main-public-1" {
  vpc_id                  = aws_vpc.main.id #(필수) 이 subnet을 연결할 VPC의 ID, 어떤 VPC에 속할 것인지 
  cidr_block              = "10.0.1.0/24"  #(필수) 이 subnet의 IP의 범위로, 위의 VPC의 cidr block 범위 내 값ㅅ
  map_public_ip_on_launch = "true"
  availability_zone       = "ap-northeast-2a"

  tags = { #리소스에 대한 정보
    Name = "main-public-1"
  }
}

resource "aws_subnet" "main-public-2" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.2.0/24"
  map_public_ip_on_launch = "true"
  availability_zone       = "ap-northeast-2b"

  tags = {
    Name = "main-public-2"
  }
}


# Private Subnet
resource "aws_subnet" "main-private-1" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.4.0/24"
  map_public_ip_on_launch = "false"
  availability_zone       = "ap-northeast-2a"

  tags = {
    Name = "main-private-1"
  }
}
resource "aws_subnet" "main-private-2" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.5.0/24"
  map_public_ip_on_launch = "false"
  availability_zone       = "ap-northeast-2b"

  tags = {
    Name = "main-private-2"
  }
}

아니면 한꺼번에 아래와 같이 적어주어도 된다.

# Create var.az_count public subnets, each in a different AZ
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = element(["10.0.1.0/24", "10.0.2.0/24"], count.index)
  availability_zone       = element(["ap-northeast-2a", "ap-northeast-2b"], count.index)
  count                   = length(["10.0.1.0/24", "10.0.2.0/24"])
  map_public_ip_on_launch = true
}

# Create var.az_count private subnets, each in a different AZ
resource "aws_subnet" "private" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = element(["10.0.4.0/24", "10.0.5.0/24"], count.index)
  availability_zone = element(["ap-northeast-2a", "ap-northeast-2b"], count.index)
  count             = length(["10.0.4.0/24", "10.0.5.0/24"])
}

 

4. AWS Internet Gateway & NAT Gateway 생성

Internet Gateway과 NAT Gateway에 어떤 subnet을 넣느냐에 따라서 public subnet과 private subnet이 결정된다. 

Internet Gateway는 VPC 내부와 외부 인터넷이 통신하기 위한 게이트웨이 중 하나로, Internet Gateway와 연결된 Subnet은 public subnet이 된다. 

퍼블릭 서브넷의 인스턴스는 인터넷에 바로 아웃바운드 트래픽을 전송할 수 있는 반면, 프라이빗 서브넷의 인스턴스는 그렇게 할 수 없습니다. 반면, 프라이빗 서브넷의 인스턴스는 퍼블릭 서브넷에 있는 NAT(Network Address Translation) 게이트웨이를 사용하여 인터넷에 액세스할 수 있습니다. 

출처: https://docs.aws.amazon.com/ko_kr/vpc/latest/userguide/VPC_Scenario2.html https://docs.aws.amazon.com/ko_kr/vpc/latest/userguide/VPC_Scenario2.html

 

위의 그림을 보면 Public subnet안에 NAT gateway가 생성되어 있다. Public subnet안에 위치해있어야지 NAT gateway자체가 인터넷과 통신되기 때문이다. 

즉, NAT gateway는 Public subnet에 위치하고, Privatte subnet과 연결된다. 

# gateway.tf

# Internet gateway
resource "aws_internet_gateway" "main-gw" {
  vpc_id = aws_vpc.main.id #(필수) 이 subnet을 연결할 VPC의 ID, 어떤 VPC에 속할 것인지 

  tags = {
    Name = "main"
  }
}

# NAT gateway
# NAT gateway를 만들 때는 AWS Elastic IP도 함께 생성해야 한다. 
resource "aws_eip" "nat" {
  count = length(["10.0.4.0/24", "10.0.5.0/24"]) # private subnet만큼 Elastic IP생성
  vpc = true
  lifecycle {
  	create_before_destroy = true
  }
}

resource "aws_nat_gateway" "main-ngw" {
  count         = length(["10.0.4.0/24", "10.0.5.0/24"]) # private subnet만큼
  allocation_id = element(aws_eip.nat.*.id, count.index) 
  subnet_id     = element(aws_subnet.public.*.id, count.index) # 앞서 생성했던 public subnet에 NAT gateway가 생성된다. 
  depends_on    = [aws_internet_gateway.main-gw]
}

5.AWS Route Table 생성

Route table은 트래픽을 규칙에 맞게 전달해주기 위한 rule table이다. 

route table을 생성하고, subnet과의 연결해준다. 그리고 룰을 설정해준다. 

# routetable.tf

# Public Route table
# Route table 생성시 aws_route_table 리소스 사용
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id
}

# 어떤 route table에 도착지를 설정(룰 설정)할 때는 aws_route 리소스를 사용
resource "aws_route" "public" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"  #여기(도착지)로 나가게 될 것이라는 의미
  gateway_id             = aws_internet_gateway.main.id # public subnet에서는 internet gateway를 통해서
}
 
# Route table과 subnet을 연결 할 때는 aws_route_table_association 리소스 사용
resource "aws_route_table_association" "public" {
  count          = length(["10.0.1.0/24", "10.0.2.0/24"])
  subnet_id      = element(aws_subnet.public.*.id, count.index)
  route_table_id = aws_route_table.public.id
}


# Private Route table
# Route table 생성시 aws_route_table 리소스 사용
resource "aws_route_table" "private" {
  count  = length(["10.0.4.0/24", "10.0.5.0/24"])
  vpc_id = aws_vpc.main.id
}
 
# 어떤 route table에 도착지를 설정(룰 설정)할 때는 aws_route 리소스를 사용
resource "aws_route" "private" {
  count                  = length(compact(["10.0.4.0/24", "10.0.5.0/24"]))
  route_table_id         = element(aws_route_table.private.*.id, count.index)
  destination_cidr_block = "0.0.0.0/0" #여기(도착지)로 나가게 될 것이라는 의미
  nat_gateway_id         = element(aws_nat_gateway.main.*.id, count.index) # private subnet에서는 NAT gateway를 통해서
}
 
# Route table과 subnet을 연결 할 때는 aws_route_table_association 리소스 사용
resource "aws_route_table_association" "private" {
  count          = length(["10.0.4.0/24", "10.0.5.0/24"])
  subnet_id      = element(aws_subnet.private.*.id, count.index)
  route_table_id = element(aws_route_table.private.*.id, count.index)
}

 

※ Terraform 명령어

$ terraform list #생성된 리소스의 리스트를 볼 수 있다. 
$ terraform init
$ terraform plan
$ terraform apply

 

 

Reference

docs.aws.amazon.com/ko_kr/vpc/latest/userguide/VPC_Scenario2.html