Terraform 을 활용한 네이버 클라우드 플랫폼 VPC 인프라 구성하기

SangKyu Kim
NAVER CLOUD PLATFORM
39 min readDec 14, 2020

--

안녕하세요, 네이버 클라우드 플랫폼 입니다!
이번 포스팅에서는 인프라 자동화를 위한 IaC(Infrastructure as a Code) 오픈소스인 Terraform 으로 VPC 환경을 구성하는 방법을 소개해드리려 합니다.

VPC란?

VPC의 이해를 돕기 위해 아래와 같이 가정 해 보겠습니다.

  • ’N’ Company 라는 회사 에서는 동일한 솔루션을 3개 테넌트(A,B,C)에게 제공 합니다.
  • ’N’ Company 에서 관리하는 하나의 계정에서 각 테넌트 별 전용 인프라를 만들어 독립적으로 서비스 하고 있습니다.

기존 클래식(CLASSIC) 환경(VPC가 없는 환경)은 위 그림과 같습니다. 이 환경의 경우는 논리적으로 네트워크 환경을 공용으로 쓰고 있어 다음과 같은 어려움이 있습니다.

  • 하나의 계정에서 멀티-테넌트로 서비스를 할 경우 , 각 테넌트간 통신이 가능하기 때문에 ACG(Access Control Group)등을 통해 접근제어를 따로 설정해줘야 합니다. 시스템 복잡도가 증가 할 경우 이러한 설정은 더욱 더 어려워 집니다.
  • 각 서버의 사설 IP 를 직접 설정할 수 없기 때문에, 각 테넌트별 네트워크 환경을 동일하게 구성 할 수 없습니다.
    예) 테넌트 별 DB 서버의 사설 IP
    - A 테넌트 10.53.1.56
    - B 테넌트 10.46.12.41
    - C 테넌트 10.61.51.23
    위와 같이 같은 목적의 서버의 사설 IP 가 테넌트 별로 다르기 때문에, 테넌트 별로 IP 주소 설정이 필요 합니다.
  • 또한 서버의 사설 IP가 생성 시 무작위로 부여가 되기 때문에 IP 대역을 통한 접근제어가 어렵습니다.

그럼 VPC는 어떻게 문제를 해결 해 줄까요?

네이버 클라우드 플랫폼의 VPC(Virtual Private Cloud)는 퍼블릭 클라우드 상에서 제공되는 고객 전용 사설 네트워크를 의미합니다.

’N’ Company 의 VPC 환경 구성도

위와 같은 환경에서 VPC를 적용하면 다음과 같이 됩니다.

  • ’N’ Company 에서 제공하는 각 테넌트의 네트워크가 VPC를 통해 완전히 독립적으로 제공됩니다. 즉, ACG 를 따로 설정하지 않아도 격리된 네트워크 환경을 제공 합니다.
  • 각각 VPC 별로 독립적인 IP 대역을 제공하기 때문에, 서버 생성시 원하는 사설 IP로 설정이 가능 합니다, 각 테넌트 별로 동일한 설정값을 이용할 수 있고, 서버 생성 전에도 어떤 사설 IP 를 갖을지 예측 할 수 있습니다.
    예) 테넌트 별 DB 서버의 사설 IP
    - A 테넌트 10.0.1.7
    - B 테넌트 10.0.1.7
    - C 테넌트 10.0.1.7
  • Subnet 을 통해 원하는 사설 IP 대역을 설정할 수 있고, 이로 인해 IP 대역을 통한 보안관리 측면에서 효율적인 면을 보여줍니다.

위와 같이 VPC 는 격리된 네트워크를 제공하고 이를 통해 관리 및 보안측면에서 기존 CLASSIC 환경 보다 나은 점을 보여 줍니다.

VPC는 다른 VPC 네트워크와 논리적으로 분리되어 있으며, 기존 고객 데이터센터 네트워크와 유사하게 구현할 수 있습니다. Subnet(Subnet)은 VPC 네트워크 공간을 세분화하여 사용할 수 있는 기능입니다.

자세한 VPC 의 설명은 아래 가이드를 참고 해주시기 바랍니다.
참고: 사용자 가이드 > NETWORKING > VPC > 개요

VPC 시나리오

본 포스팅에서 Terraform 으로 구성할 시나리오는 아래와 같습니다
시나리오 2. Public과 Private Subnet

시나리오 2. Public과 Private Subnet 구성

위 시나리오에서는 하나의 VPC 환경에서 KR-2 ZONE의 Public Subnet 에 FE서버 를 두고, Private Subnet에 WAS와 같은 Server 를 한대씩 생성합니다.

구조의 이해를 돕고자 간단하게 구조에 대해 설명 하겠습니다.

  • VPC
    사용자 전용의 가상 네트워크이며, 모든 자원은 VPC 내에서 생성 됩니다. 예제의 VPC 는 10.0.0.0/16CIDR 블록을 가지며, 해당 VPC 내에서는 10.0.X.X 의 형식의 IPv4 주소를 65,536 (256²) 개를 제공 합니다.
  • Subnet
    VPC 내의 주소 범위를 지정할 수 있습니다. Private 과 Public 2개의 Subnet을 제공합니다. Subnet 이 속할 Zone 을 지정할 수 있습니다. KR Region을 기준으로 KR-1 또는 KR-2 에 생성할 수 있습니다. 고 가용성을 위해 두 개 Zone에 각각 서비스를 구성 할 수 있습니다.
  • Public Subnet
    예제에서는 10.0.0.0/24CIDR 블록을 가지며, 해당 서브넷 내에서는 10.0.0.X 형식으로 IPv4 주소를 250개(Reserved IP address 6개 제외)를 생성할 수 있습니다.
    Public Subnet 의 경우 기본적으로 Internet Gateway 와 연결 되어있어 외부 통신이 가능하며 외부에서도 Subnet 으로 접근이 가능 합니다. 바스티온 호스트를 두기에 적합합니다.
  • Private Subnet
    예제에서는 10.0.1.0/24CIDR 블록을 가지며, 해당 서브넷 내에서는 10.0.1.X 형식으로 IPv4 주소를 250개를 생성할 수 있습니다. 기본적으로는 외부 네트워크가 차단 되어있고, VPC 내에서만 통신이 가능합니다. 하지만 NAT Gateway 를 통해 인터넷 연결이 가능합니다. WAS 와 DB와 같은 서버들은 여기에 둡니다.
  • Internet Gateway
    VPC를 외부와 인터넷 통신이 가능 하게 합니다.
    (VPC 생성시 기본으로 제공되기 때문에 Terraform 에서는 해당 리소스를 다루지 않습니다)
  • NAT Gateway
    Private Subnet 이 외부와 통신이 가능 하게 합니다.
    (보통 OS 의 패키지를 업그레이드 하거나, 외부 인터넷의 API 호출을 하기 위해 연결 합니다)
    Private Route Table을 통해 연결 됩니다.
  • Route Table
    VPC 생성시 기본적으로 Public 과 Private 라우팅 테이블이 생성 됩니다. 라우팅 테이블은 VPC내에서 다른 인스턴스와 통신을 할 수 있게 해주며, Public 의 경우 Internet Gateway 과 연결되어 인터넷 통신이 가능하게 해주며, Private 의 경우 NAT Gateway 를 연결하여 인터넷 통신이 가능하게 할 수 있습니다.
  • Network ACL
    보안을 위해 ACG 또는 Network ACL 을 사용하지만, ACG 는 서버의 Inbound/Outbound 트래픽을 제어하고, Network ACL 은 서브넷의 Inbound/Outbound 트래픽을 제어할 수 있습니다. 기본적으로는 0.0.0.0/0 소스에 대해 allow 되어있기 때문에, 보안을 위해 ACL 룰 설정이 필요 합니다.

해당 예제에서 생성되는 리소스는 다음과 같습니다.

  • VPC 1개
  • Subnet 2개 (Public, Private)
  • NAT Gateway 1개
  • Network ACL 2개
  • Server 2개 (Frontend, Backend)
  • Public IP 1개

Terraform 설치

Terraform 은 https://www.terraform.io/downloads.html 에서 다운받을 수 있습니다.

$ wget https://releases.hashicorp.com/terraform/0.14.2/terraform_0.14.2_linux_amd64.zip
$ unzip terraform_0.14.2_linux_amd64.zip && mv terraform /usr/bin
$ terraform version # 설치 확인
Terraform v0.14.2

예제 코드 구조

본 예제에서는 아래와 같이 파일 구조를 갖습니다.

$ cd terraform/tf-vpc-scenario2
$ tree
.
├── main.tf # VPC 리소스를 정의합니다.
├── security.tf # Network ACL 룰을 지정 합니다.
├── versions.tf # 테라폼과 관련된 버젼을 지정 합니다.
└── variables.tf # variable 변수를 정의합니다.

versions.tf

# versions.tf terraform {
required_providers {
ncloud = {
source = "navercloudplatform/ncloud"
}
}
required_version = ">= 0.13"
}
  • versions.tf 에서는 네이버 클라우드 플랫폼 Provider 의 버젼을 설정합니다. 본 예제에서는 Provider 버젼 v2.0.3 이상 기준으로 작성 되었습니다.
  • 해당 예제에서는 Terraform 0.13 버젼 이상을 권장 합니다.

variables.tf

# variables.tf variable name_scn02 {
default = "tf-scn02"
}
variable client_ip {
default = "YOUR_CLIENT_IP" // To access ssh
}
variable access_key {
default = "YOUR_ACCESS_KEY"
}
variable secret_key {
default = "YOUR_SECRET_KEY"
}

해당 파일에서는 테라폼 코드내에서 자주 쓰이는 값들을 변수로 설정 합니다.

  • 리소스 이름을 쉽게 설정하기 위해 name_scn02 을 설정합니다. 해당 값은 원하시는 이름으로 변경 하셔도 됩니다.
  • SSH 접속시 Network ACL 설정을 위한 client_ip 을 입력 합니다.
  • 포탈에서 인증키 정보를 access_key, secret_key 에 입력 합니다.
    (해당 값은 포탈 로그인 후 마이페이지 > 인증키관리 에서 확인하실 수 있습니다)

main.tf

  • 해당 파일에서는 provider 설정과, VPC 를 포함한 대부분의 인프라 코드를 포함합니다.
# main.tfprovider "ncloud" {
support_vpc = true
region = "KR"
access_key = var.access_key
secret_key = var.secret_key
}

먼저 ncloud provider 설정을 합니다. 여기서 support_vpctrue로 설정하여 VPC 환경을 사용하도록 합니다. (중요)

1. VPC (ncloud_vpc)

VPC (Virtual Private Network) 생성

가장 먼저 ncloud_vpc 리소스를 이용하여 VPC 를 정의 합니다. 해당 리소스의 가이드는 아래 링크에서 확인할 수 있습니다.

위 그림과 같이 VPC 생성시에는 기본적으로 Internet Gateway, Route Table, Network ACL 그리고 ACG(Access Control Group)가 생성이 됩니다.

# main.tf# VPC
resource "ncloud_vpc" "vpc_scn_02" {
name = var.name_scn02
ipv4_cidr_block = "10.0.0.0/16"
}
  • ipv4_cidr_block10.0.0.0/16 으로 설정 합니다. 10.0.X.X 와 같은 형식의 IPv4 주소를 65536개(256 x 256) 가질 수 있다는 것을 의미 합니다.
  • vpc 의 이름은 variable.tf 에 있는 name_scn02을 참고 하여 “tf-scn02” 로 생성 될 예정입니다.

2. Subnet & Network ACL (ncloud_subnet, ncloud_network_acl)

Private Subnet과 Public Subnet 생성

그림과 같이 Private Subnet과 Public Subnet 그리고 Network ACL 을 정의합니다.

  • Public Subnet 은 기본으로 제공되는 IGW 를 통해 외부와 통신이 가능하기 때문에, Frontend(바스티온 호스트) 서버를 두고 서비스 합니다.
  • Private Subnet 은 VPC 내에서만 통신이 가능하며, Backend 서버인 WAS, DB 서버등을 두고 서비스 합니다.
# main.tf# Public Subnet
resource "ncloud_subnet" "subnet_scn_02_public" {
name = "${var.name_scn02}-public"
vpc_no = ncloud_vpc.vpc_scn_02.vpc_no
subnet = cidrsubnet(ncloud_vpc.vpc_scn_02.ipv4_cidr_block, 8, 0) // "10.0.0.0/24"
zone = "KR-2"
network_acl_no = ncloud_network_acl.network_acl_02_public.id
subnet_type = "PUBLIC" // PUBLIC(Public)
}
# Private Subnet
resource "ncloud_subnet" "subnet_scn_02_private" {
name = "${var.name_scn02}-private"
vpc_no = ncloud_vpc.vpc_scn_02.vpc_no
subnet = cidrsubnet(ncloud_vpc.vpc_scn_02.ipv4_cidr_block, 8, 1) // "10.0.1.0/24"
zone = "KR-2"
network_acl_no = ncloud_network_acl.network_acl_02_private.id
subnet_type = "PRIVATE" // PRIVATE(Private)
}
# Network ACL
resource "ncloud_network_acl" "network_acl_02_public" {
vpc_no = ncloud_vpc.vpc_scn_02.id
name = "${var.name_scn02}-public"
}
resource "ncloud_network_acl" "network_acl_02_private" {
vpc_no = ncloud_vpc.vpc_scn_02.id
name = "${var.name_scn02}-private"
}
  • Subnet 은 VPC 안에 만들어지기 때문에, vpc_no 를 지정해줘야 합니다. 위에서 설정한 VPC ncloud_vpc.vpc_scn_02.vpc_no로 설정 합니다.
  • ZONE 은 KR-2 로 정의 합니다.
  • 테라폼에서는 cidrsubnet(10.0.0.0/16, 8, 1) 과 같은 함수를 통해 CIDR 블록을 계산할 수 있습니다. 자세한건 cidrsubnet Function을 참고하시면 됩니다.
  • Subnet 생성시 Network ACL 을 필요로 하기 떄문에network_acl_no 를 지정 해 줍니다. VPC 생성시 기본으로 제공되는 Network ACL 로 설정할 수 있지만, Private 과 Public 의 ACL 설정을 따로 하기위해 각각 만들어 주었습니다. 보안을 위한 ACL 룰 설정은 7. Network ACL 에서 다루겠습니다.

3. Server (ncloud_server)

VPC 환경에서 서버를 생성 할 수 있는 Subnet 이 완성 되었습니다. 그럼 이제 Server 를 생성하는 방법에 대해 알아 보겠습니다.

각 Subnet 에 Server 생성하기
# main.tf# Login Key
resource "ncloud_login_key" "key_scn_02" {
key_name = var.name_scn02
}
# Server
# for Front-end (bastion) server
resource "ncloud_server" "server_scn_02_public" {
subnet_no = ncloud_subnet.subnet_scn_02_public.id
name = "${var.name_scn02}-public"
server_image_product_code = "SW.VSVR.OS.LNX64.CNTOS.0703.B050"
login_key_name = ncloud_login_key.key_scn_02.key_name
//server_product_code = "SVR.VSVR.STAND.C002.M008.NET.SSD.B050.G002"
}
# for Back-end (WAS) server
resource "ncloud_server" "server_scn_02_private" {
subnet_no = ncloud_subnet.subnet_scn_02_private.id
name = "${var.name_scn02}-private"
server_image_product_code = "SW.VSVR.OS.LNX64.CNTOS.0703.B050"
login_key_name = ncloud_login_key.key_scn_02.key_name
//server_product_code = "SVR.VSVR.STAND.C002.M008.NET.SSD.B050.G002"
}
  • VPC Server는 Subnet 을 지정 해 줘야 합니다, 예제에서는 각각 Public 과 Private Subnet 을 참조 하도록 하였습니다.
  • server_image_product_code 를 통해 서버 이미지를 설정할 수 있는데요, 예제에서는 CentOS 7.3으로 지정하였습니다. 서버 이미지 코드를 가져오는 방법은 Data Source: ncloud_server_images 를 참고 하시면 됩니다.
  • server_product_code 설정을 통해 서버의 스펙을 지정할 수 있는데, 미 입력시에는 가장 낮은 스펙으로 설정이 됩니다. 해당 코드의 경우 를 Data Source: ncloud_server_products 참고 하시면 됩니다.
# Public IP
resource "ncloud_public_ip" "public_ip_scn_02" {
server_instance_no = ncloud_server.server_scn_02_public.id
description = "for ${var.name_scn02}"
}

외부에서 우리 Frontend 서버를 접근하게 해주고, 관리자도 SSH 에 접속할 수 있게 공인 IP(Public IP )를 위와 같이 설정하여 서버와 연결 합니다.

4. NAT Gateway (ncloud_nat_gateway)

여기까지 모습을 보면 서비스를 위한 그림이 어느정도 완성이 되었습니다. 그런데 Private Subnet 에 있는 서버에서 외부 패키지를 다운받고 싶은데 인터넷 통신이 되질 않습니다.

어떻게 해야 할까요?

NAT Gateway 를 통해 Private Subnet 에서 외부 인터넷과 연결 할 수 있습니다.

NAT Gateway 생성
# main.tf
# NAT Gateway
resource "ncloud_nat_gateway" "nat_gateway_scn_02" {
vpc_no = ncloud_vpc.vpc_scn_02.id
zone = "KR-2"
name = var.name_scn02
}
  • NAT Gatway 를 KR-2 ZONE 에 생성 하도록 합니다.

5. Route 설정 (ncloud_route)

그런데 NAT Gateway 만 추가하니 외부 통신이 되질 않습니다. 문제는 Private Subnet에서 외부통신(0.0.0.0/0)이 NAT Gateway까지 갈수 있게 길을 만들어 줘야 하는데요. 이는 아래와 같이 Route 설정을 통해 합니다.

Route 설정

ncloud_route_table 리소스를을 통해 Route Table을 생성 할 수 있는데요,
1. VPC 에서 기본으로 생성되었던 Route Table을 사용 할 예정 입니다.

기본 Route Table 은 Public, Private 용으로 각각 1개씩 생성이 되는데 NAT Gateway를 붙이기 위해 Private Route Table 을 참조 하겠습니다.

# main.tf# Route
resource "ncloud_route" "route_scn_02_nat" {
route_table_no = ncloud_vpc.vpc_scn_02.default_private_route_table_no
destination_cidr_block = "0.0.0.0/0"
target_type = "NATGW" // NATGW (NAT Gateway) | VPCPEERING (VPC Peering) | VGW (Virtual Private Gateway).
target_name = ncloud_nat_gateway.nat_gateway_scn_02.name
target_no = ncloud_nat_gateway.nat_gateway_scn_02.id
}
  • destination_cidr_block0.0.0.0/0 으로 지정하여, 해당 주소로 가는 요청이 NAT Gatway 로 가도록 합니다.
  • target_typetarget_no을 위에서 정의한 NAT Gateway를 참조하도록 합니다.

6. SSH 접속 및 명령어 실행

테라폼에서는 Null Resource를 통해 ssh접속을 할수 있고, remote-exec Provisioner 를 통해 ls -al과 같은 명령어를 실행 할 수 있습니다. 아래 코드는 Network ACL 룰이 잘 적용되었는지 ls -al 명령어를 수행하여 출력할 예정입니다.

# main.tfdata "ncloud_root_password" "scn_02_root_password" {
server_instance_no = ncloud_server.server_scn_02_public.id
private_key = ncloud_login_key.key_scn_02.private_key
}
resource "null_resource" "ls-al" {
connection {
type = "ssh"
host = ncloud_public_ip.public_ip_scn_02.public_ip
user = "root"
port = "22"
password = data.ncloud_root_password.scn_02_root_password.root_password
}
provisioner "remote-exec" { // 명령어 실행
inline = [
"ls -al",
]
}
depends_on = [
ncloud_public_ip.public_ip_scn_02,
ncloud_server.server_scn_02_public
]
}

여기까지 코드를 작성하셨으면, 서비스를 위한 전반적인 인프라 준비가 되었다고 볼 수 있는데요, 보안을 위해 한가지 더 해야할 일이 있습니다

security.tf

2. Subnet & Network ACL 에서 Network ACL 을 생성하였지만, 기본 Network ACL 룰은 모든 IP와 port 에 대해 allow 되어 있는 상태입니다. 즉 외부에서 ssh 나 서비스에 접근하여 해킹시도를 할 수 있는 위험이 있다는 뜻인데요.

아래 예제에서는 보안을 위한 ACL 룰을 설정 해 보겠습니다.

7. Network ACL (ncloud_network_acl_rule)

네이버 클라우드 플랫폼은 VPC의 보안을 강화하기 위해 사용할 수 있는 ACG와 Network ACL 두 가지 기능을 제공합니다. 자세한 내용은 설명서 > NETWORKING > VPC > 보안 을 참고 하세요

먼저 Public Subnet과 연결되는 ACL 룰을 설정해보겠습니다.

  • Public Subnet : Inbound
  • Public Subnet : Outbound
# security.tf# Network ACL Rule
locals {
public_subnet_inbound = [
[1, "TCP", "0.0.0.0/0", "80", "ALLOW"],
[2, "TCP", "0.0.0.0/0", "443", "ALLOW"],
[3, "TCP", "${var.client_ip}/32", "22", "ALLOW"],
[4, "TCP", "${var.client_ip}/32", "3389", "ALLOW"],
[5, "TCP", "0.0.0.0/0", "32768-65535", "ALLOW"],
[197, "TCP", "0.0.0.0/0", "1-65535", "DROP"],
[198, "UDP", "0.0.0.0/0", "1-65535", "DROP"],
[199, "ICMP", "0.0.0.0/0", null, "DROP"],
]
public_subnet_outbound = [
[1, "TCP", "0.0.0.0/0", "80", "ALLOW"],
[2, "TCP", "0.0.0.0/0", "443", "ALLOW"],
[3, "TCP", "0.0.0.0/0", "9001-65535", "ALLOW"],
[4, "TCP", "${ncloud_server.server_scn_02_private.network_interface[0].private_ip}/32", "8080", "ALLOW"], // Allow 8080 port to private server
[197, "TCP", "0.0.0.0/0", "1-65535", "DROP"],
[198, "UDP", "0.0.0.0/0", "1-65535", "DROP"],
[199, "ICMP", "0.0.0.0/0", null, "DROP"]
]
}
resource "ncloud_network_acl_rule" "network_acl_02_rule_public" {
network_acl_no = ncloud_network_acl.network_acl_02_public.id
dynamic "inbound" {
for_each = local.public_subnet_inbound
content {
priority = inbound.value[0]
protocol = inbound.value[1]
ip_block = inbound.value[2]
port_range = inbound.value[3]
rule_action = inbound.value[4]
}
}
dynamic "outbound" {
for_each = local.public_subnet_outbound
content {
priority = outbound.value[0]
protocol = outbound.value[1]
ip_block = outbound.value[2]
port_range = outbound.value[3]
rule_action = outbound.value[4]
}
}
}

다음은 Private 의 Subnet의 ACL 룰을 다음과 같이 설정 하겠습니다.

  • Private Subnet : Inbound
  • Private Subnet : Outbound
# security.tflocals {
private_subnet_inbound = [
[1, "TCP", "${ncloud_server.server_scn_02_public.network_interface[0].private_ip}/32", "8080", "ALLOW"], // Allow 8080 port from public server
[2, "TCP", "0.0.0.0/0", "32768-65535", "ALLOW"],
[197, "TCP", "0.0.0.0/0", "1-65535", "DROP"],
[198, "UDP", "0.0.0.0/0", "1-65535", "DROP"],
[199, "ICMP", "0.0.0.0/0", null, "DROP"],
]
private_subnet_outbound = [
[1, "TCP", "${ncloud_server.server_scn_02_public.network_interface[0].private_ip}/32", "32768-65535", "ALLOW"], // Allow 32768-65535 port to public server
[197, "TCP", "0.0.0.0/0", "1-65535", "DROP"],
[198, "UDP", "0.0.0.0/0", "1-65535", "DROP"],
[199, "ICMP", "0.0.0.0/0", null, "DROP"]
]
}
resource "ncloud_network_acl_rule" "network_acl_02_private" {
network_acl_no = ncloud_network_acl.network_acl_02_private.id
dynamic "inbound" {
for_each = local.private_subnet_inbound
content {
priority = inbound.value[0]
protocol = inbound.value[1]
ip_block = inbound.value[2]
port_range = inbound.value[3]
rule_action = inbound.value[4]
}
}
dynamic "outbound" {
for_each = local.private_subnet_outbound
content {
priority = outbound.value[0]
protocol = outbound.value[1]
ip_block = outbound.value[2]
port_range = outbound.value[3]
rule_action = outbound.value[4]
}
}
}

위 코드에서는, 약 24개가 되는 룰을 하드코딩을 하게되면 소스코드가 너무 길어져서, localsdynamic Blocks를 사용하여 룰을 생성 합니다.

자 이제 테라폼 코드 작성이 끝났습니다. 이제 실제 인프라를 생성 해 보도록 하겠습니다.

리소스 생성 계획 (terraform plan)

$ cd terraform/tf-vpc-scenario2
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
------------------------------------------------------------------------An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
<= read (data resources)
Terraform will perform the following actions:# data.ncloud_root_password.scn_02_root_password will be read during apply
# (config refers to values not yet known)
<= data "ncloud_root_password" "scn_02_root_password" {
+ id = (known after apply)
+ private_key = (sensitive value)
+ root_password = (sensitive value)
+ server_instance_no = (known after apply)
}
# ncloud_login_key.key_scn_02 will be created
+ resource "ncloud_login_key" "key_scn_02" {
+ fingerprint = (known after apply)
+ id = (known after apply)
+ key_name = "tf-scn02"
+ private_key = (sensitive value)
}
# ncloud_nat_gateway.nat_gateway_scn_02 will be created
+ resource "ncloud_nat_gateway" "nat_gateway_scn_02" {
+ description = (known after apply)
+ id = (known after apply)
+ name = "tf-scn02"
+ nat_gateway_no = (known after apply)
+ public_ip = (known after apply)
+ vpc_no = (known after apply)
+ zone = "KR-2"
}
... 중략Plan: 14 to add, 0 to change, 0 to destroy.------------------------------------------------------------------------Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

코드가 잘 작성이 되었다면, 위와같이 Plan: 14 to add, 0 to change, 0 to destroy. 라고 표시 되며, 실제 적용 시 14개의 리소스가 생성 될 예정 입니다. 그러면 아래 terraform apply 통해 리소스를 생성 해 보도록 하겠습니다.

리소스 적용 (terraform apply)

아래와 같이 terraform apply 명령어를 수행해서 Plan 을 다시한번 확인하고, yes를 입력하여 리소스를 생성 합니다.

$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
<= read (data resources)
Terraform will perform the following actions:# ncloud_login_key.key_scn_02 will be created
+ resource "ncloud_login_key" "key_scn_02" {
+ fingerprint = (known after apply)
+ id = (known after apply)
+ key_name = "tf-scn02"
+ private_key = (sensitive value)
}
# ncloud_nat_gateway.nat_gateway_scn_02 will be created
+ resource "ncloud_nat_gateway" "nat_gateway_scn_02" {
+ description = (known after apply)
+ id = (known after apply)
+ name = "tf-scn02"
+ nat_gateway_no = (known after apply)
+ public_ip = (known after apply)
+ vpc_no = (known after apply)
+ zone = "KR-2"
}
... 중략Plan: 13 to add, 0 to change, 0 to destroy.Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yesncloud_login_key.key_scn_02: Creating...
ncloud_vpc.vpc_scn_02: Creating...
ncloud_login_key.key_scn_02: Creation complete after 1s [id=tf-scn02]
ncloud_vpc.vpc_scn_02: Still creating... [10s elapsed]
ncloud_vpc.vpc_scn_02: Creation complete after 13s [id=2988]
ncloud_network_acl.network_acl_02_public: Creating...
ncloud_nat_gateway.nat_gateway_scn_02: Creating...
ncloud_network_acl.network_acl_02_private: Creating...
ncloud_network_acl.network_acl_02_private: Creation complete after 3s [id=4250]
ncloud_subnet.subnet_scn_02_private: Creating...
ncloud_network_acl.network_acl_02_public: Creation complete after 3s [id=4249]
ncloud_subnet.subnet_scn_02_public: Creating...
ncloud_nat_gateway.nat_gateway_scn_02: Still creating... [10s elapsed]
ncloud_nat_gateway.nat_gateway_scn_02: Creation complete after 13s [id=5648219]
ncloud_route.route_scn_02_nat: Creating...
ncloud_subnet.subnet_scn_02_private: Still creating... [10s elapsed]
ncloud_subnet.subnet_scn_02_public: Still creating... [10s elapsed]
ncloud_subnet.subnet_scn_02_private: Still creating... [20s elapsed]
ncloud_subnet.subnet_scn_02_public: Still creating... [20s elapsed]
ncloud_subnet.subnet_scn_02_private: Creation complete after 22s [id=5506]
ncloud_server.server_scn_02_private: Creating...
ncloud_subnet.subnet_scn_02_public: Creation complete after 22s [id=5507]
ncloud_server.server_scn_02_public: Creating...
ncloud_server.server_scn_02_private: Still creating... [10s elapsed]
ncloud_server.server_scn_02_public: Still creating... [10s elapsed]
... 중략
ncloud_server.server_scn_02_public: Creation complete after 2m48s [id=5648223]
data.ncloud_root_password.scn_02_root_password: Reading...
ncloud_public_ip.public_ip_scn_02: Creating...
ncloud_network_acl_rule.network_acl_02_private: Creating...
data.ncloud_root_password.scn_02_root_password: Read complete after 0s [id=5648223]
ncloud_public_ip.public_ip_scn_02: Creation complete after 3s [id=5648227]
null_resource.ls-al: Creating...
null_resource.ls-al: Provisioning with 'remote-exec'...
null_resource.ls-al (remote-exec): Connecting to remote host via SSH...
null_resource.ls-al (remote-exec): Host: 110.165.17.xx
null_resource.ls-al (remote-exec): User: root
null_resource.ls-al (remote-exec): Password: true
null_resource.ls-al (remote-exec): Private key: false
null_resource.ls-al (remote-exec): Certificate: false
null_resource.ls-al (remote-exec): SSH Agent: false
null_resource.ls-al (remote-exec): Checking Host Key: false
null_resource.ls-al (remote-exec): Connected!
null_resource.ls-al (remote-exec): total 24
null_resource.ls-al (remote-exec): dr-xr-x---. 4 root root 138 May 26 2020 .
null_resource.ls-al (remote-exec): dr-xr-xr-x. 18 root root 257 May 26 2020 ..
null_resource.ls-al (remote-exec): -rw-------. 1 root root 1441 May 26 2020 .bash_history
null_resource.ls-al (remote-exec): -rw-r--r--. 1 root root 18 Dec 29 2013 .bash_logout
null_resource.ls-al (remote-exec): -rw-r--r--. 1 root root 176 Dec 29 2013 .bash_profile
null_resource.ls-al (remote-exec): -rw-r--r--. 1 root root 176 Dec 29 2013 .bashrc
null_resource.ls-al (remote-exec): drwx------. 3 root root 17 May 26 2020 .cache
null_resource.ls-al (remote-exec): -rw-r--r--. 1 root root 100 Dec 29 2013 .cshrc
null_resource.ls-al (remote-exec): drwxr-----. 3 root root 19 May 26 2020 .pki
null_resource.ls-al (remote-exec): -rw-r--r--. 1 root root 129 Dec 29 2013 .tcshrc
null_resource.ls-al: Creation complete after 1s [id=8315713944255249232]
ncloud_network_acl_rule.network_acl_02_private: Still creating... [10s elapsed]
ncloud_network_acl_rule.network_acl_02_private: Still creating... [20s elapsed]
ncloud_network_acl_rule.network_acl_02_private: Creation complete after 25s [id=4250]
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.

위와 같이 마지막에 Apply complete! 라고 뜨면 모든 리소스 생성이 완료 되었습니다. 그리고 null_resource에서 ssh 에 접속하여 ls -al 도 성공적으로 수행한 것을 확인 하실 수 있습니다.

그러면, 리소스중에 서버가 잘 생성 되었는지 콘솔에서 확인 해 보도록 하겠습니다.

위와 같이 서버가 2대가 잘 생성 된 것을 확인 하실 수 있습니다.

그 밖에 리소스는 Terraform 가이드를 참고 하셔서 추가 하실 수 있습니다

마치며

이번 포스팅에서는 Terraform 을 이용하여 VPC 환경에서 Server 를 생성하여 서비스 하는 방법을 알아 보았습니다. VPC 와 같이 복잡한 환경에서 Terraform 을 활용하면 대규모 인프라 환경을 더욱 효율적으로 관리 하실 수 있습니다.

해당 소스코드는 https://github.com/NaverCloudPlatform/terraform-provider-ncloud/tree/master/examples/vpc/scenario02 에서 전체 참고하실 수 있습니다.

감사합니다.

--

--