Room9

Terraform - NCP Networking 구성 본문

Terraform/NCP

Terraform - NCP Networking 구성

Room9_ 2021. 12. 29. 17:07

Overview

지난 글에서 Terraform 사용을 위한 포스팅을 진행하였습니다. Terraform Installation & Configuration 이제 Terraform을 가지고 NAVER Cloud 상의 인프라를 프로비저닝 하도록 하겠습니다. 이번 포스팅에서는 네트워크 부분만 설정을 해보도록 하겠습니다. 자주 사용하는 패턴으로 구성을 해두고 네트워크 부분만 다른 서비스 환경에서 재사용할 수 있는 장점이 있습니다.

실제 본인이 자주 사용하는 패턴으로 구성해보시는 걸 추천드립니다. 자주 사용하는 패턴으로 구성해 두면 어떠한 요청이 와도 약간의 수정만으로 코드를 재사용하여 프로비저닝하여, 실수를 최소화하거나 구축 시간을 단축시킬 수 있습니다.


Details

  • Architecture
  • VPC 구성
  • NACL 구성
  • NACL Rule 구성
  • Subnet 구성
  • Gateway 구성
  • Route Table 구성
  • Subnet - Route Table 연동 구성
  • Route 구성
  • VPC Peering 구성

Architecture

해당 포스트에서 만들어볼 구성입니다.

NAVER Cloud 내부에서 용도별로 VPC를 나누어 생성하였습니다.

  • VPC
    • FE-VPC : 외부에서 접근이 가능한 VPC
    • BE-VPC : 내부통신만 가능한 VPC
    • MGMT-VPC : 각 서버의 운영을 위한 VPC
  • NACL
  • NACL Rule
  • Subnet
    • Public Subnet 1 : FE-VPC에 위치
    • Private Subnet 2 : BE-VPC , MGMT-VPC에 위치
  • Gateway
    • Internet Gateway : 외부 통신을 위한 Gateway (Public Subnet 구성 시 자동생성)
    • NAT Gateway : 내부에 있는 서버가 외부로 나가기 위한 Gateway
  • VPC Peering
해당 구성이 검증된 구성은 아닙니다. 개인적으로는 선호하지 않지만 해당 포스트는 Terraform의 HCL에 익숙해지는 것을 목표로 하고 있어, 반복된 코드 작성에 맞을 것 같아 구성한 구성도입니다.
해당 구성은 아직도 의문이 가는 부분이라 혹시 해당 구성에 대해 의견을 남겨주시면 도움이 될 것 같습니다.


Terraform Docs

네이버 클라우드에서 제공하는 문법들을 확인할 수 있습니다. Terraform을 지원하는 벤더들은 여기서다 찾아볼 수 있고, 아래에서 작성하는 코드들은 해당 문서를 보고 참조한 내용들입니다.

예시로 가장 먼저 생성할 VPC에 리소스를 확인해봅시다. Basic Usage에서 기본적으로 사용되는 방식에 대해 보여주고 있습니다.

인수 참조 부분에서는 해당 리소스가 필요로 하는 인수들을 보여주고 있습니다. optional로 적혀있는 인수들은 필수항목이 아니며, required로 표시된 인수는 해당 리소스가 생성될 때 꼭 필요로 하는 인수입니다. VPC는 ipv4_cidr_block 인수만 있다면 생성이 되며 name 항목은 랜덤으로 작성되게 됩니다.

아래로 더 내려와 보면 리소스가 생성되면 생기는 속성들을 나열해두고 있습니다. VPC 리소스가 생성되면 해당 값들을 가지는 리소스가 생성되며, 이러한 속성들은 다른 리소스들에서 참조하여 사용할 수 있습니다. 


VPC 구성

resource "ncloud_vpc" "fe" {
  name            = "fe-vpc"             #Optional VPC이름 (fe-vpc)
  ipv4_cidr_block = "10.0.0.0/16"        #Required VPC IP대역 (10.0.0.0/16)
}

resource "ncloud_vpc" "be" {
  name            = "be-vpc"             #Optional VPC 이름 (be-vpc)
  ipv4_cidr_block = "10.1.0.0/16"        #Required VPC IP 대역 (10.1.0.0/16)
}

resource "ncloud_vpc" "mgmt" {
  name            = "mgmt-vpc"           #Optional VPC 이름 (mgmt-vpc)
  ipv4_cidr_block = "10.2.0.0/16"        #Required VPC IP 대역 (10.2.0.0/16)
}

NACL 구성

resource "ncloud_network_acl" "pubsub" {
  vpc_no = ncloud_vpc.fe.id                       #fe-vpc를 참조하여 해당 vpc안에 생성
  name   = "fe-pub-subnet-nacl"
}

resource "ncloud_network_acl" "prisub" {
  vpc_no = ncloud_vpc.be.id                       #be-vpc를 참조하여 해당 vpc안에 생성
  name   = "be-pri-subnet-nacl"

}
resource "ncloud_network_acl" "prisub2" {
  vpc_no = ncloud_vpc.mgmt.id                     #mgmt-vpc를 참조하여 해당 vpc안에 생성
  name   = "mgmt-pri-subnet-nacl"
}

NACL Rule 구성

resource "ncloud_network_acl_rule" "pubsub" {
  network_acl_no = ncloud_network_acl.pubsub.id
}

resource "ncloud_network_acl_rule" "prisub" {
  network_acl_no = ncloud_network_acl.prisub.id
}

resource "ncloud_network_acl_rule" "prisub2" {
  network_acl_no = ncloud_network_acl.prisub2.id
}

Subnet 구성

resource "ncloud_subnet" "pubsub" {
  vpc_no         = ncloud_vpc.fe.id
  subnet         = "10.0.0.0/16"
  zone           = "KR-2"
  network_acl_no = ncloud_network_acl.pubsub.id
  subnet_type    = "PUBLIC"
  name           = "pub-subnet"
  usage_type     = "GEN"
}

resource "ncloud_subnet" "prisub" {
  vpc_no         = ncloud_vpc.be.id
  subnet         = "10.1.0.0/16"
  zone           = "KR-2"
  network_acl_no = ncloud_network_acl.prisub.id
  subnet_type    = "PRIVATE"
  name           = "pri-subnet"
  usage_type     = "GEN"
}

resource "ncloud_subnet" "prisub2" {
  vpc_no         = ncloud_vpc.mgmt.id
  subnet         = "10.2.0.0/16"
  zone           = "KR-2"
  network_acl_no = ncloud_network_acl.prisub2.id
  subnet_type    = "PRIVATE"
  name           = "pri2-subnet"
  usage_type     = "GEN"
}

Gateway 구성

resource "ncloud_nat_gateway" "nat_gateway" {
  vpc_no      = ncloud_vpc.be.id
  zone        = "KR-2"
  name        = "nat-gw"
}

Route Table 구성

resource "ncloud_route_table" "fe_pub_rt" {
  vpc_no = ncloud_vpc.fe.id
  supported_subnet_type = "PUBLIC"
  name = "fe-pub-rt"
}
resource "ncloud_route_table" "be_pri_rt" {
  vpc_no = ncloud_vpc.be.id
  supported_subnet_type = "PRIVATE"
  name = "be-pri-rt" 
}
resource "ncloud_route_table" "mgmt_pri_rt" {
  vpc_no = ncloud_vpc.mgmt.id
  supported_subnet_type = "PRIVATE"
  name = "mgmt-pri-rt"
}

Subnet - Route Table 연동 구성

resource "ncloud_route_table_association" "fe_rt_sub" {
  route_table_no = ncloud_route_table.fe_pub_rt.id
  subnet_no = ncloud_subnet.pubsub.id  
}

resource "ncloud_route_table_association" "be_rt_sub" {
  route_table_no = ncloud_route_table.be_pri_rt.id
  subnet_no = ncloud_subnet.prisub.id
}

resource "ncloud_route_table_association" "mgmt_rt_sub" {
  route_table_no = ncloud_route_table.mgmt_pri_rt.id
  subnet_no = ncloud_subnet.prisub2.id
}

Route 구성

## NAT Gateway 라우팅
resource "ncloud_route" "natroute" {
  route_table_no = ncloud_route_table.be_pri_rt.id
  destination_cidr_block = "0.0.0.0/0"
  target_type = "NATGW"
  target_name = ncloud_nat_gateway.nat_gateway.name
  target_no = ncloud_nat_gateway.nat_gateway.id
}

## vpc peering 라우팅 필요
resource "ncloud_route" "peering_route" {
  route_table_no = ncloud_route_table.fe_pub_rt.id
  destination_cidr_block = "10.1.0.0/16"
  target_type = "VPCPEERING"
  target_name = ncloud_vpc_peering.peering.name
  target_no = ncloud_vpc_peering.peering.id
}

resource "ncloud_route" "peering2_route" {
  route_table_no = ncloud_route_table.be_pri_rt.id
  destination_cidr_block = "10.0.0.0/16"
  target_type = "VPCPEERING"
  target_name = ncloud_vpc_peering.peering2.name
  target_no = ncloud_vpc_peering.peering2.id
}
resource "ncloud_route" "peering3_route" {
  route_table_no = ncloud_route_table.be_pri_rt.id
  destination_cidr_block = "10.2.0.0/16"
  target_type = "VPCPEERING"
  target_name = ncloud_vpc_peering.peering3.name
  target_no = ncloud_vpc_peering.peering3.id
}

resource "ncloud_route" "peering4_route" {
  route_table_no = ncloud_route_table.mgmt_pri_rt.id
  destination_cidr_block = "10.1.0.0/16"
  target_type = "VPCPEERING"
  target_name = ncloud_vpc_peering.peering4.name
  target_no = ncloud_vpc_peering.peering4.id
}

resource "ncloud_route" "peering5_route" {
  route_table_no = ncloud_route_table.fe_pub_rt.id
  destination_cidr_block = "10.2.0.0/16"
  target_type = "VPCPEERING"
  target_name = ncloud_vpc_peering.peering5.name
  target_no = ncloud_vpc_peering.peering5.id
}

resource "ncloud_route" "peering6_route" {
  route_table_no = ncloud_route_table.mgmt_pri_rt.id
  destination_cidr_block = "10.0.0.0/16"
  target_type = "VPCPEERING"
  target_name = ncloud_vpc_peering.peering6.name
  target_no = ncloud_vpc_peering.peering6.id
}

VPC Peering 구성

resource "ncloud_vpc_peering" "peering" {
  name          = "vpc-peering"
  source_vpc_no = ncloud_vpc.fe.id
  target_vpc_no = ncloud_vpc.be.id
}
resource "ncloud_vpc_peering" "peering2" {
  name          = "vpc-peering2"
  source_vpc_no = ncloud_vpc.be.id
  target_vpc_no = ncloud_vpc.fe.id
}
resource "ncloud_vpc_peering" "peering3" {
  name          = "vpc-peering3"
  source_vpc_no = ncloud_vpc.be.id
  target_vpc_no = ncloud_vpc.mgmt.id
}
resource "ncloud_vpc_peering" "peering4" {
  name          = "vpc-peering4"
  source_vpc_no = ncloud_vpc.mgmt.id
  target_vpc_no = ncloud_vpc.be.id
}
resource "ncloud_vpc_peering" "peering5" {
  name          = "vpc-peering5"
  source_vpc_no = ncloud_vpc.fe.id
  target_vpc_no = ncloud_vpc.mgmt.id
}
resource "ncloud_vpc_peering" "peering6" {
  name          = "vpc-peering6"
  source_vpc_no = ncloud_vpc.mgmt.id
  target_vpc_no = ncloud_vpc.fe.id
}

이렇게 작성한 코드들을 main.tf 파일에 넣고 terraform apply 명령을 하게 되면

apply 이전에 plan을 자체적으로 동작하여 몇 개의 리소스가 생성되는지 결괏값으로 보여줍니다. 스크롤을 올려 본인이 생성한 리소스가 맞게 생성되었는지 확인 후 yes를 입력하면 terraform이 순서에 맞게 리소스를 생성하는 걸 볼 수 있습니다. 삭제는 terraform destroy 명령어로 삭제를 진행할 수 있습니다.

해당 블로그 글을 작성할 때에 NACL Rule 부분에서 에러가 발생합니다. 프로바이더에 문의하라고만 출력됩니다. 나머지 리소스에 생성에 크게 영향을 미치지 않기 때문에 실제로 위에서 19개의 리소스가 아닌 3개를 제외한 16개의 리소스만 생성되고 있습니다.
에러 메시지가 거슬린다고 생각되시면 NACL Rule에서 실제 inbound , outbound 룰을 추가해주시면 에러는 발생하지 않습니다.
이상한 점은 inbound, outbound는 required가 아닌 optional인데 에러가 발생하네요

마치며

Terraform의 HCL 코드를 이용하여 NAVER Cloud의 인프라 중 Networking 부분을 생성해보았습니다. 실제 사용할  코드면 더 좋겠지만 HCL을 숙달하기 위한 코드들이라 사용성이 크게 있을지는 의문입니다. 예시를 좀 더 범용적으로 정하여 사용 가능한 구조가 되었으면 하는 아쉬움이 남네요. HCL은 반복적으로 사용하고, 벤더에서 제공해주는 Docs만 잘 볼 줄 알아도 쉽게 작성이 가능합니다.( 물론 그전에 클라우드 인프라에 대한 구조나 사용처, 사용방법에 대해 숙달이 되어야 될 것 같습니다. 콘솔에서 인프라 생성에 익숙해 지시길 바랍니다. 물론 저도 포함입니다.)


References

https://registry.terraform.io/providers/NaverCloudPlatform/ncloud/latest/docs

 

https://registry.terraform.io/providers/NaverCloudPlatform/ncloud/latest/docs

 

registry.terraform.io

 

Comments