Terraform 공부를 시작해보자
최근 들어 Terraform이라는 말을 여러번 듣기도 했고, Naver Cloud 로 클라우드 공부를 하기 시작했는데 IaC 툴인 Terraform을 사용해서 공부를 하면 더 좋을 것 같다는 생각이 들어 해보기로 했다.
우선 사용하기에 앞서 어떤 개념인지부터 알아보자
Terraform
HashiCorp 에서 만든 IaC 도구

이렇게 말하면 처음 본 사람들은 당연히 어떤건지 모를 것이다
IaC 란 Infrastructure as Code 의 줄임말로, 말 그대로 인프라를 코드로 다룬다는 뜻을 가지고 있다.
그리고 Terraform 은 그 IaC를 가능하게 해주는 도구다
사용자는 구성 파일에 원하는 인프라를 정의할 수 있고, Terraform은 이 구성을 바탕으로 가상머신, 네트워크, 스토리지 같은 온프레미스와 클라우드 자원을 생성/변경/삭제한다.
-> 여기서 프로비저닝이란 필요한 인프라 자원을 준비하고 구성해서 사용할 수 있도록 해준다는 뜻이다
Terraform은 선언적으로 동작한다
사용자가 인프라 자원들에 대하여 원하는 최종 상태를 코드로 설명해놓으면 Terraform이 나머지를 처리해준다
plan 이나 apply를 통해 실행 계획을 생성하고, 리소스 간의 종속성을 식별하고, 구성 요소를 올바른 순서로 프로비저닝 해준다
그냥 코드만 제대로 짜놓으면 그 코드의 상태에 맞게 인프라를 관리해주는 역할을 한다고 보면 될 것 같다
Terraform 은 일반적인 프로그래밍 언어처럼 위에서 아래로 실행되지 않기 때문에, 리소스를 작성하는 순서는 크게 중요하지 않다
리소스 간의 참조를 분석해서 의존 관계를 파악한다
만약 파악할 수 없는 경우는 depends_on을 사용해서 의존성을 직접 명시해줄 수 있다
Terraform 작동 방식
큰 개념을 알아 봤으니 작동 방식도 간단하게 알아보고 넘어가자
실습은 후반부에 진행한다
Terraform 은 Provider를 통해 플랫폼이나 외부 서비스의 API를 호출해서 리소스를 다룬다
각 CSP는 자사의 클라우드 리소스를 Terraform 으로 관리할 수 있도록 전용 Provider를 개발해서 제공해준다
1. 작성
개발자는 사람이 읽을 수 있는 구성 파일에 원하는 인프라의 최종 상태를 정의한다
위에서 말했듯이 선언형 방식으로 작성한다
사용자는 리소스를 어떤 순서와 절차로 생성할지 작성하는 것이 아니라, 어떤 리소스가 어떤 상태로 존재해야 하는지를 작성하는 것이다
내가 지금까지 일반적으로 해왔던 프로그래밍이랑은 다른 결인 것 같다
이렇게 만든 구성 파일은 버전 관리를 할 수 있고, 재사용하거나 공유할 수 있다
인프라의 구조를 버저닝 할 수 있다는 장점도 좋은 것 같다
인프라계의 Github
2. 계획
Terraform 은 구성 파일에 정의된 상태와 현재 인프라의 상태를 비교한다
이 과정에서 Terraform 상태 파일과 Provider를 통해 확인한 실제 리소스 정보를 활용한다
비교 결과를 바탕으로 어떤 리소스를 생성/변경/삭제할 지 실행 계획을 만든다
현재의 코드와 다른 인프라 상태를 맞춰주기 위한 계획을 생성하는 것이다
terraform plan 명령어를 실행하면 실제 인프라를 변경하기 전에 어떤 작업이 예정되어 있는지 확인할 수 있다
3. 적용
사용자가 실행 계획을 확인하고 승인하면 Terraform이 계획된 작업을 실제 인프라에 적용한다
Terraform이 리소스 간의 의존 관계를 분석해서 필요한 순서대로 작업을 수행할 수 있다
서로 의존하지 않는 리소스는 병렬로 처리할 수 있다고 한다
작업이 완료되면 변경된 리소스 정보를 상태 파일에 반영한다
작동 방식은 크게 이렇게 3단계이다
다음으로는 구성 요소를 알아보자
구성 요소
구성 파일
Terraform 으로 관리할 리소스와 원하는 설정을 정의하는 파일이다
사용할 Provider, 생성할 리소스, 조회할 데이터, 입력 변수나 출력값 같은 필요한 요소들을 정의해둔다
.tf 확장자를 사용해서 파일을 만들어준다
버전 관리가 가능하고 수정과 재사용, 공유도 당연히 가능하다
공급자
위에서도 간단하게 설명을 했었다
Terraform과 외부 플랫퐁의 API를 연결해준다
AWS, Naver Cloud, Azure, K8s, Github 등 각 서비스에 맞는 Provider가 존재한다
Terraform 리소스의 생성, 조회, 변경, 삭제 작업을 실제 서비스 API 호출로 변환해준다
Terraform 과 별도로 배포되고 각각 독립된 버전을 가진다
상태 파일

Terraform이 관리하는 리소스와 실제 인프라 객체 사이의 연결 관계를 저장한다
리소스의 ID 값, 속성값, 의존 관계 계산에 필요한 메타데이터 등을 가지고 있다
상태 정보를 이용해서 기존에 생성한 실제 리소스들을 식별한다
plan과 apply 과정에서 Provider를 통해서 실제 인프라를 확인하고 상태를 갱신한다
그 후 구성 파일과 비교해서 필요한 변경 사항을 계산한다
기본적으로 terraform.tfstate 파일에 저장한다
비밀번호나 토큰처럼 유출되면 안되는 값이 포함될 수 있어 외부 저장소에 그대로 올리면 안된다
모듈
여러개의 Terraform 리소스들을 하나의 단위로 묶은 재사용 가능한 것을 모듈이라고 한다
이 파일들도 .tf 확장자를 가진다
가상머신, 네트워크, 보안 그룹과 같이 함께 사용되는 자원을 하나의 모듈로 구성할 수 있다
반복되는 인프라 구성을 재사용해서 중복을 줄이고 일관성을 유지할 수 있따
직접 작성을 하거나 Terraform Registry에 공개된 모듈을 사용할 수도 있따
레지스트리
Terraform 에서 사용할 Provider, Module, Policy Library를 검색하고 배포한다
공개 레지스트리뿐만 아니라 조직 내부에서 사용하는 Private 한 환경도 구성할 수 있따
Terraform CLI
CLI 를 통해 Terraform 작업을 수행하기 위한 도구다
작업 디렉토리 초기화, 구성 검증, 실행 계획 확인, 인프라 변경 적용 등을 제공한다
Terraform init, Terraform fmt, Terraform validate, Terraform plan, Terraform apply, Terraform destory 등의 명령어를 제공한다
나도 아직 잘은 모른다
쓰면서 알아봐야 할듯
이 중 몇개는 실습에서 사용하긴 한다
이제 재미없는 개념은 치우고 실습을 해보자
나는 맥북에서 VSCode로 Naver Cloud를 사용해서 실습을 진행했다
Terraform 으로 Naver Cloud 리소스 생성하기
우선 가장 중요한 Terraform을 설치해야 한다
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
Homebrew에 공식 패키지 저장소를 추가하고 Terraform CLI 를 설치한다는 의미이다.
# terraform --version
Terraform v1.15.7
on darwin_arm64
+ provider registry.terraform.io/hashicorp/local v2.9.0
+ provider registry.terraform.io/navercloudplatform/ncloud v4.0.5
그러면 이렇게 설치가 된 것을 확인할 수 있다
그럼 이제 코드를 한 번 살펴보자
저도 처음이라 설명이 틀릴 수도 있습니다.
# terraform.tf
terraform {
required_providers {
ncloud = {
source = "NaverCloudPlatform/ncloud"
}
}
required_version = ">= 0.13"
}
provider "ncloud" {
access_key = var.access_key
secret_key = var.secret_key
region = var.region
support_vpc = true
}
module "network" {
source = "./network_module"
}
module "server" {
source = "./server_module"
vpc_no = module.network.vpc_no
subnet_public_id = module.network.subnet_public_id
}
terraform.tf
루트 파일로 Provider 설정과 모듈 호출을 담당한다
- required_providers : 사용할 NCP Provider를 지정해
- required_version : 최소 버전 지정
- provider "ncloud" : Provider 에 대한 키, 지역, VPC 사용 여부를 설정
- module "network" : VPC, Subnet 생성 네트워크 모듈을 호출
- module "server" : 네트워크 모듈의 출력값을 전달받아 서버 모듈을 호출
- vpc_no, subnet_public_id 를 server 모듈에 전달해줌
- 서버가 앞에서 생성한 네트워크에 연결되도록 구성해줌
- server 모듈은 network 모듈의 output을 직접 참조하지 않고, 루트에 있는 terraform.tf 를 통해서 모듈 간 의존성이 없음
# variables.tf
variable "access_key" {
description = "NCP access_key"
type = string
default = "액세스 키 값"
}
variable "secret_key" {
description = "NCP secret_key"
type = string
default = "시크릿 키 값"
}
variable "region" {
description = "NCP region"
type = string
default = "KR"
}
variable "support_vpc" {
description = "NCP support vpc"
default = "true"
}
위의 terraform.tf 파일에서 사용되는 변수들을 정의하는 파일이다
NCP API 사용을 위한 키 값, 리소스 생성 지역 지정을 위한 region, VPC 사용 여부를 위한 영역들이 있다
변수로 분리하면 설정값을 한 파일에서 관리할 수 있어서 편리하다
물론 민감 정보는 그대로 노출되지 않도록 해줘야 한다
다음으로는 서버가 올라갈 네트워크 환경을 구성해준다
network_module 에서 VPC와 Public Subnet 을 생성하고, 생성된 리소스의 식별자를 Output을 통해 외부에 노출해야 한다
이후에 루트 모듈이 Output 값을 server_module의 입력 변수로 전달한다
# network_module
## providers.tf
terraform {
required_providers {
ncloud = {
source = "navercloudplatform/ncloud"
}
}
required_version = ">= 0.13"
}
이 파일도 크게 다르지 않다
Naver Cloud 를 사용하고 최소 버전을 지정해준다
# network_module
## vpc.tf
resource "ncloud_vpc" "vpc" {
name = "${var.name_terra}-vpc"
ipv4_cidr_block = var.vpc_cidr
}
VPC 환경 네트워크를 생성해준다
ncloud_vpc 리소스를 사용해서 VPC를 생성한다
아래에 첨부할 variable.tf 파일에 존재하는 변수명을 가져와서 같은 이름으로 만들어준다
resource "ncloud_vpc" "vpc" 부분에서 첫번째 ncloud_vpc 는 사용할 리소스의 종류고, vpc는 Terraform 내부에서 참조할 때 사용하는 이름이다
ipv4_cidr_block 은 사설 IP 주소 범위를 지정한다
나는 192.168.0.0/24 대역을 지정해줬다
이후에 subnet.tf는 여기서 생성한 VPC의 번호, CIDR, NACL 번호를 참고해서 Subnet 을 생성한다
# network_module
## subnet.tf
resource "ncloud_subnet" "subnet_public" {
name = "${var.name_terra}-public"
vpc_no = ncloud_vpc.vpc.vpc_no
subnet = cidrsubnet(ncloud_vpc.vpc.ipv4_cidr_block, 0, 0)
zone = var.zones
network_acl_no = ncloud_vpc.vpc.default_network_acl_no
subnet_type = "PUBLIC"
}
위에서 만든 VPC 내부에 Public Subnet 을 생성해주는 파일
- name : 전달받은 이름에 public 을 붙여서 Subnet 이름을 만든다
- vpc_no : 만들어진 VPC의 번호를 참고한다
- subnet : VPC의 CIDR 블록을 기준으로 Subnet 대역을 계산한다
- cidrsubnet : 기존 CIDR 에서 새로운 서브넷 대역을 계산
- 2번째 인자로 들어오는 0은 prefix 의 길이를
- 3번째 인자로 들어오는 0은 몇번째 서브넷 대역을 사용할지에 대한 의미이다
- zone : 서브넷을 생성할 zone 지정
- network_acl_no : 어떤 NACL을 사용할지 지정. 이번의 경우 기본 NACL 을 사용했다
- subnet_type : 서브넷의 타입을 지정. 이번의 경우 Public을 사용하여 외부 통신이 가능하도록 해줬다
여기서 만들어진 서브넷의 아이디는 outputs.tf를 통해서 루트 모듈로 전달된다
거기서 server_module의 subnet_public_id 변수로 전달되어 사용된다
# network_module
## variables.tf
variable "zones" {
default = "KR-1"
}
variable "name_terra" {
default = "jk"
}
variable "vpc_cidr" {
default = "192.168.0.0/24"
}
network_module에서 사용할 입력 변수를 정의하는 파일
위에서 사용된 변수들에 대한 실제 값을 넣어놓는다
# network_module
## outputs.tf
output "vpc_no" {
value = ncloud_vpc.vpc.vpc_no
}
output "subnet_cidr" {
value = ncloud_vpc.vpc.ipv4_cidr_block
}
output "subnet_public_id" {
value = ncloud_subnet.subnet_public.id
}
network_module 에서 생성된 리소스 정보를 모듈 외부로 전달하는 파일
Terraform 모듈 내부에서 생성된 리소스는 다른 모듈이 직접 참조할 수 없기 때문에, 다른 모듈에서 필요한 값을 output으로 외부에 노출해야 한다
만들어진 VPC의 번호, Subnet의 CIDR, ID 들을 노출하고 루트 모듈에 전달하고, 루트 모듈에서는 참조에 따라 server_module 로 다시 전달해준다
다음은 server_module 이다
# server_module
## providers.tf
terraform {
required_providers {
ncloud = {
source = "navercloudplatform/ncloud"
}
}
required_version = ">= 0.13"
}
server_module 에서 사용할 Provider과 Terraform 최소 버전을 선언하는 파일이다
required_provieers 에서는 이 모듈이 Naver CLoud 를 사용했다는 것을 명시하고 최소 버전도 지정해준다
# server_module
## server.tf
resource "ncloud_login_key" "server_key" {
key_name = "${var.name_terra}-svr-key"
}
resource "local_file" "ncp_pem" {
filename = "${ncloud_login_key.server_key.key_name}.pem"
content = ncloud_login_key.server_key.private_key
}
#ACG
resource "ncloud_access_control_group" "acg_01" {
name = "${var.name_terra}-acg01"
description = "${var.name_terra} Access controle group"
vpc_no = var.vpc_no # ncloud_vpc.vpc.id
}
resource "ncloud_access_control_group_rule" "acg_rule_01" {
access_control_group_no = ncloud_access_control_group.acg_01.id
inbound {
protocol = "TCP"
ip_block = "0.0.0.0/0"
port_range = "22"
description = "accept 22 port(all ip)"
}
outbound {
protocol = "TCP"
ip_block = "0.0.0.0/0"
port_range = "1-65535"
description = "accept TCP 1-65535 port"
}
outbound {
protocol = "UDP"
ip_block = "0.0.0.0/0"
port_range = "1-65535"
description = "accept UDP 1-65535 port"
}
outbound {
protocol = "ICMP"
ip_block = "0.0.0.0/0"
description = "accept ICMP"
}
}
#NIC
resource "ncloud_network_interface" "nic" {
#count = "1"
name = "${var.name_terra}-nic"
subnet_no = var.subnet_public_id
access_control_groups = [ncloud_access_control_group.acg_01.id]
}
resource "ncloud_server" "server" {
subnet_no = var.subnet_public_id
name = "${var.name_terra}-svr"
server_image_number = data.ncloud_server_image_numbers.rocky94.image_number_list[0].server_image_number
server_spec_code = data.ncloud_server_specs.g3_spec.server_spec_list[0].server_spec_code
login_key_name = ncloud_login_key.server_key.key_name
network_interface {
network_interface_no = ncloud_network_interface.nic.id
order = 0
}
}
data "ncloud_server_image_numbers" "rocky94" {
server_image_name = "rocky-9.4-base"
filter {
name = "hypervisor_type"
values = ["KVM"]
}
}
data "ncloud_server_specs" "g3_spec" {
filter {
name = "server_spec_code"
values = ["s2-g3"]
}
}
# Export Root Password
data "ncloud_root_password" "default" {
server_instance_no = ncloud_server.server.instance_no # ${ncloud_server.vm.id}
private_key = ncloud_login_key.server_key.private_key # ${ncloud_login_key.key.private_key}
}
resource "local_file" "svr_root_pw" {
filename = "${ncloud_server.server.name}-root_password.txt"
content = "${ncloud_server.server.name} => ${data.ncloud_root_password.default.root_password}"
}
# Public IP
resource "ncloud_public_ip" "public_ip" {
server_instance_no = ncloud_server.server.id
description = "for ${ncloud_server.server.name} public ip"
}
server.tf 파일이다
서버 생성에 필요한 리소스를 정의하는 파일이다
키, ACG, NIC, 이미지, 스펙, 서버, 공인 IP를 만들어준다
전체적인 의존성 흐름은 이렇다
Login Key
- Pem 파일 저장
- 서버 생성
- 관리자 비밀번호 조회
- 비밀번호 파일 저장
ACG
- ACG Rule
- NIC
- 서버 생성
- Public IP 연결
파일 내용이 좀 길어서 잘라서 설명을 해보자
- Login Key 생성
- NCP 서버에 접속할 때 사용할 로그인 키를 생성한다
- 생성된 키에 초기 관리자 비밀번호 확인에 사용되는 개인키가 포함된다
- 개인키 PEM 파일로 저장
- Login Key 에서 생성된 개인키를 로컬 .pem 파일로 저장한다
- 서버 관리자 비밀번호 확인이나 SSH 접속에 사용
- 절대로 Git 같은 외부에 노출시키면 안된다!! .gitignore 필수
- ACG 생성
- 서버 네트워크 접근 제어를 위한 ACG 생성 -> 일종의 방화벽이라고 생각하면 된다
- 이름과 설명, VPC의 번호를 지정해준다
- ACG 규칙 설정
- 위에서 만들어진 ACG의 규칙을 설정해준다
- 인바운드 규칙으로 22번 포트를 열어주고 아웃바운드 규칙으로 모든 포트와 IP에 대하여 통신을 허용해줬다
- 연습이라 그런것이지 각 서버의 정책에 맞는 방화벽 설정이 필요하다.
- NIC 생성
- 서버에 연결할 네트워크 인터페이스를 생성해준다
- 전달 받은 Public Subnet ID 를 사용해준다
- 그리고 위에서 생성한 ACG 를 연결해주는 것을 볼 수 있다
- 서버 생성
- 위에서 설정한 내용들을 바탕으로 한 서버를 생성해준다
- 전달 받은 Public Subnet ID를 통해 서버가 생성될 네트워크를 지정해준다
- OS 이미지는 Rocky 9.4 버전을 사용해줬다 - 9.7을 사용하려 했지만 없는건지 실패했다
- 서버 스펙들도 원하는 스펙으로 설정을 해줄 수 있다
- 사용될 키와 NIC 까지 연결을 해준다
- Rocky 9.4 이미지 조회
- Naver Cloud 에 존재하는 Rokcy 9.4 이미지를 조회해준다
- hypervisor_type 은 잘 모르지만 KVM 기반으로 설정해두었다
- 여기에서 조회된 결과는 server_image_number 에 사용된다
- 실제로 이미지가 존재하는지 확인이 필요하다
- 서버 스펙 조회
- 이 부분은 잘 몰라서 그냥 기본으로 보이는 스펙을 사용했다
- 초기 비밀번호 조회
- 생성된 서버의 초기 root 비밀번호를 조회한다
- Server Instance 번호와 로그인 키의 Private Key가 필요하다고 한다
- server_instance_no가 서버를 참조하기때문에 당연히 서버가 생성된 후에 비밀번호를 조회한다
- private key 에는 서버 생성 시 사용한 로그인 키의 개인키를 전달해준다
- 초기 비밀번호 로컬 파일로 저장
- 조회한 비밀번호를 로컬 환경에 텍스트 파일로 저장한다
- 나는 해당 파일이 있는 경로로 와서 SSH 접속을 진행했다
- 공인 IP 생성 및 서버 연결
- 외부에서 접속할 수 있도록 공인 IP를 생성하고 서버에 연결한다
- 서버 ID를 참조하기 때문에 서버 생성 이후에 생성된다
어우 너무 길다...
대략적인 리소스 생성 흐름을 한 번 보고 넘어가자
- OS 이미지 조회
- 서버 스펙 조회
- 로그인 키 생성
- PEM 로컬 파일로 저장
- ACG 생성
- 로컬 파일로 저장
- ACG 정책 생성
- NIC에 연결
- 서버 생성
- 이미지 + 스펙 + 로그인 키 + NIC 을 통한 서버 생성
- 패스워드를 TXT 파일로 로컬에 저장
- 서버와 공인 IP 연결
이렇게 된다
크게 이해못할 내용은 없는 것 같으니 넘어가자
아무래도 Terraform 은 처음이라 깊게는 다루지 못한다
좀 더 공부해서 다른 글에 써야곘다
# server_module
## variables.tf
variable "region" {
default = "KR"
}
variable "zones" {
default = "KR-1"
}
variable "name_terra" {
default = "jk"
}
variable "login_key_name" {
default = "jk-key"
}
variable "vpc_no" {
description = "vpc number"
#type = number
}
variable "subnet_public_id" {
description = "public subnet id"
#type = number
}
이건 이제 알다시피 위에서 사용한 변수들을 정의해놓은 파일이다
코드는 이 정도로 설명을 마친다
전체 코드의 구성을 한 번 보자
- module
- terraform.tf
- variables.tf
- network_module/
- providers.tf
- variables.tf
- vpc.tf
- subnet.tf
- outputs.tf
- server_module/
- providers.tf
- variables.tf
- server.tf
루트에 존재하는 terraform.tf 가 전체 지휘를 맡아준다
네트워크 모듈의 output 을 전달받아 서버 모듈에 전달해준다
서버 모듈은 네트워크 모듈을 직접 참조하지 않고 루트를 통해 전달 받는다
Terraform 명령 실행
이제 작성한 코드를 바탕으로 실제로 어떻게 동작하는지 살펴보자
루트 모듈이 있는 곳에서 명령어를 실행한다
Terraform init
# terraform init
terraform init
Initializing modules...
Initializing provider plugins found in the configuration...
- Reusing previous version of navercloudplatform/ncloud from the dependency lock file
- Reusing previous version of hashicorp/local from the dependency lock file
- Using previously-installed navercloudplatform/ncloud v4.0.5
- Using previously-installed hashicorp/local v2.9.0
Initializing the backend...
Initializing provider plugins found in the state...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
terraform init 의 실행 결과는 위와 같다
현재 디렉터리를 Terraform 작업 디렉터리로 초기화해준다
루트 모듈에서 호출하는 모듈들을 확인하고, NCP 리소스 생성을 위한 ncloud Provider 를 준비한다
local Provider 를 준비하고 Terraform State 를 저장할 Backend 를 초기화한다
나는 이미 실행한 적이 있어 이전에 선택된 버전을 다시 사용한다고 나와있따
Terraform Plan
# terraform plan
module.server.data.ncloud_server_image_numbers.rocky94: Reading...
module.server.data.ncloud_server_specs.g3_spec: Reading...
module.server.data.ncloud_server_image_numbers.rocky94: Read complete after 1s
module.server.data.ncloud_server_specs.g3_spec: Read complete after 1s
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
<= read (data resources)
Terraform will perform the following actions:
# module.network.ncloud_subnet.subnet_public will be created
+ resource "ncloud_subnet" "subnet_public" {
+ id = (known after apply)
+ name = "jk-public"
+ network_acl_no = (known after apply)
+ subnet = "192.168.0.0/24"
+ subnet_no = (known after apply)
+ subnet_type = "PUBLIC"
+ usage_type = (known after apply)
+ vpc_no = (known after apply)
+ zone = "KR-1"
}
# module.network.ncloud_vpc.vpc will be created
+ resource "ncloud_vpc" "vpc" {
+ default_access_control_group_no = (known after apply)
+ default_network_acl_no = (known after apply)
+ default_private_route_table_no = (known after apply)
+ default_public_route_table_no = (known after apply)
+ id = (known after apply)
+ ipv4_cidr_block = "192.168.0.0/24"
+ name = "jk-vpc"
+ vpc_no = (known after apply)
}
# module.server.data.ncloud_root_password.default will be read during apply
# (config refers to values not yet known)
<= data "ncloud_root_password" "default" {
+ id = (known after apply)
+ private_key = (sensitive value)
+ root_password = (sensitive value)
+ server_instance_no = (known after apply)
}
# module.server.local_file.ncp_pem will be created
+ resource "local_file" "ncp_pem" {
+ content = (sensitive value)
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "jk-svr-key.pem"
+ id = (known after apply)
}
# module.server.local_file.svr_root_pw will be created
+ resource "local_file" "svr_root_pw" {
+ content = (sensitive value)
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "jk-svr-root_password.txt"
+ id = (known after apply)
}
# module.server.ncloud_access_control_group.acg_01 will be created
+ resource "ncloud_access_control_group" "acg_01" {
+ access_control_group_no = (known after apply)
+ description = "jk Access controle group"
+ id = (known after apply)
+ is_default = (known after apply)
+ name = "jk-acg01"
+ vpc_no = (known after apply)
}
# module.server.ncloud_access_control_group_rule.acg_rule_01 will be created
+ resource "ncloud_access_control_group_rule" "acg_rule_01" {
+ access_control_group_no = (known after apply)
+ id = (known after apply)
+ inbound = [
+ {
+ description = "accept 22 port(all ip)"
+ ip_block = "0.0.0.0/0"
+ port_range = "22"
+ protocol = "TCP"
# (1 unchanged attribute hidden)
},
]
+ outbound = [
+ {
+ description = "accept ICMP"
+ ip_block = "0.0.0.0/0"
+ protocol = "ICMP"
# (2 unchanged attributes hidden)
},
+ {
+ description = "accept TCP 1-65535 port"
+ ip_block = "0.0.0.0/0"
+ port_range = "1-65535"
+ protocol = "TCP"
# (1 unchanged attribute hidden)
},
+ {
+ description = "accept UDP 1-65535 port"
+ ip_block = "0.0.0.0/0"
+ port_range = "1-65535"
+ protocol = "UDP"
# (1 unchanged attribute hidden)
},
]
}
# module.server.ncloud_login_key.server_key will be created
+ resource "ncloud_login_key" "server_key" {
+ fingerprint = (known after apply)
+ id = (known after apply)
+ key_name = "jk-svr-key"
+ private_key = (sensitive value)
}
# module.server.ncloud_network_interface.nic will be created
+ resource "ncloud_network_interface" "nic" {
+ access_control_groups = (known after apply)
+ description = (known after apply)
+ id = (known after apply)
+ instance_type = (known after apply)
+ is_default = (known after apply)
+ name = "jk-nic"
+ network_interface_no = (known after apply)
+ private_ip = (known after apply)
+ server_instance_no = (known after apply)
+ status = (known after apply)
+ subnet_no = (known after apply)
}
# module.server.ncloud_public_ip.public_ip will be created
+ resource "ncloud_public_ip" "public_ip" {
+ description = "for jk-svr public ip"
+ id = (known after apply)
+ instance_no = (known after apply)
+ internet_line_type = (known after apply)
+ kind_type = (known after apply)
+ public_ip = (known after apply)
+ public_ip_no = (known after apply)
+ server_instance_no = (known after apply)
}
# module.server.ncloud_server.server will be created
+ resource "ncloud_server" "server" {
+ base_block_storage_disk_detail_type = (known after apply)
+ base_block_storage_disk_type = (known after apply)
+ base_block_storage_size = (known after apply)
+ cpu_count = (known after apply)
+ description = (known after apply)
+ hypervisor_type = (known after apply)
+ id = (known after apply)
+ init_script_no = (known after apply)
+ instance_no = (known after apply)
+ is_encrypted_base_block_storage_volume = (known after apply)
+ is_fee_charging_monitoring = (known after apply)
+ is_protect_server_termination = (known after apply)
+ login_key_name = "jk-svr-key"
+ memory_size = (known after apply)
+ name = "jk-svr"
+ placement_group_no = (known after apply)
+ platform_type = (known after apply)
+ port_forwarding_external_port = (known after apply)
+ port_forwarding_internal_port = (known after apply)
+ port_forwarding_public_ip = (known after apply)
+ private_ip = (known after apply)
+ public_ip = (known after apply)
+ region = (known after apply)
+ server_image_name = (known after apply)
+ server_image_number = "100524418"
+ server_image_product_code = (known after apply)
+ server_product_code = (known after apply)
+ server_spec_code = "s2-g3"
+ subnet_no = (known after apply)
+ vpc_no = (known after apply)
+ zone = (known after apply)
+ network_interface {
+ network_interface_no = (known after apply)
+ order = 0
+ private_ip = (known after apply)
+ subnet_no = (known after apply)
}
}
Plan: 10 to add, 0 to change, 0 to destroy.
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if
you run "terraform apply" now.
terraform plan 명령어는 실제 인프라를 변경하지 않고, 작성된 파일과 Terraform State 를 비교해서 앞으로 수행할 작업들을 보여준다
위에 코드에서 정의한 대로 OS 이미지와 서버 스펙을 조회하고 서브넷이나 VPC 같은 다양한 것들을 계획한다
known after apply 는 실제 서버가 생성된 후 알 수 있다는 뜻으로 계획 단계에서는 아직 알 수 없는 것들을 말한다
created 와 Plan :10 to add, 0 to change, 0 to destroy 를 보면 알 수 있듯이, 처음 실행하다보니 모든 요소들을 새로 생성해주는 모습이다
Terraform apply
# terraform apply
terraform apply
module.server.data.ncloud_server_specs.g3_spec: Reading...
module.server.data.ncloud_server_image_numbers.rocky94: Reading...
module.server.data.ncloud_server_image_numbers.rocky94: Read complete after 0s
module.server.data.ncloud_server_specs.g3_spec: Read complete after 0s
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
<= read (data resources)
Terraform will perform the following actions:
# module.network.ncloud_subnet.subnet_public will be created
+ resource "ncloud_subnet" "subnet_public" {
+ id = (known after apply)
+ name = "jk-public"
+ network_acl_no = (known after apply)
+ subnet = "192.168.0.0/24"
+ subnet_no = (known after apply)
+ subnet_type = "PUBLIC"
+ usage_type = (known after apply)
+ vpc_no = (known after apply)
+ zone = "KR-1"
}
# module.network.ncloud_vpc.vpc will be created
+ resource "ncloud_vpc" "vpc" {
+ default_access_control_group_no = (known after apply)
+ default_network_acl_no = (known after apply)
+ default_private_route_table_no = (known after apply)
+ default_public_route_table_no = (known after apply)
+ id = (known after apply)
+ ipv4_cidr_block = "192.168.0.0/24"
+ name = "jk-vpc"
+ vpc_no = (known after apply)
}
# module.server.data.ncloud_root_password.default will be read during apply
# (config refers to values not yet known)
<= data "ncloud_root_password" "default" {
+ id = (known after apply)
+ private_key = (sensitive value)
+ root_password = (sensitive value)
+ server_instance_no = (known after apply)
}
# module.server.local_file.ncp_pem will be created
+ resource "local_file" "ncp_pem" {
+ content = (sensitive value)
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "jk-svr-key.pem"
+ id = (known after apply)
}
# module.server.local_file.svr_root_pw will be created
+ resource "local_file" "svr_root_pw" {
+ content = (sensitive value)
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "jk-svr-root_password.txt"
+ id = (known after apply)
}
# module.server.ncloud_access_control_group.acg_01 will be created
+ resource "ncloud_access_control_group" "acg_01" {
+ access_control_group_no = (known after apply)
+ description = "jk Access controle group"
+ id = (known after apply)
+ is_default = (known after apply)
+ name = "jk-acg01"
+ vpc_no = (known after apply)
}
# module.server.ncloud_access_control_group_rule.acg_rule_01 will be created
+ resource "ncloud_access_control_group_rule" "acg_rule_01" {
+ access_control_group_no = (known after apply)
+ id = (known after apply)
+ inbound = [
+ {
+ description = "accept 22 port(all ip)"
+ ip_block = "0.0.0.0/0"
+ port_range = "22"
+ protocol = "TCP"
# (1 unchanged attribute hidden)
},
]
+ outbound = [
+ {
+ description = "accept ICMP"
+ ip_block = "0.0.0.0/0"
+ protocol = "ICMP"
# (2 unchanged attributes hidden)
},
+ {
+ description = "accept TCP 1-65535 port"
+ ip_block = "0.0.0.0/0"
+ port_range = "1-65535"
+ protocol = "TCP"
# (1 unchanged attribute hidden)
},
+ {
+ description = "accept UDP 1-65535 port"
+ ip_block = "0.0.0.0/0"
+ port_range = "1-65535"
+ protocol = "UDP"
# (1 unchanged attribute hidden)
},
]
}
# module.server.ncloud_login_key.server_key will be created
+ resource "ncloud_login_key" "server_key" {
+ fingerprint = (known after apply)
+ id = (known after apply)
+ key_name = "jk-svr-key"
+ private_key = (sensitive value)
}
# module.server.ncloud_network_interface.nic will be created
+ resource "ncloud_network_interface" "nic" {
+ access_control_groups = (known after apply)
+ description = (known after apply)
+ id = (known after apply)
+ instance_type = (known after apply)
+ is_default = (known after apply)
+ name = "jk-nic"
+ network_interface_no = (known after apply)
+ private_ip = (known after apply)
+ server_instance_no = (known after apply)
+ status = (known after apply)
+ subnet_no = (known after apply)
}
# module.server.ncloud_public_ip.public_ip will be created
+ resource "ncloud_public_ip" "public_ip" {
+ description = "for jk-svr public ip"
+ id = (known after apply)
+ instance_no = (known after apply)
+ internet_line_type = (known after apply)
+ kind_type = (known after apply)
+ public_ip = (known after apply)
+ public_ip_no = (known after apply)
+ server_instance_no = (known after apply)
}
# module.server.ncloud_server.server will be created
+ resource "ncloud_server" "server" {
+ base_block_storage_disk_detail_type = (known after apply)
+ base_block_storage_disk_type = (known after apply)
+ base_block_storage_size = (known after apply)
+ cpu_count = (known after apply)
+ description = (known after apply)
+ hypervisor_type = (known after apply)
+ id = (known after apply)
+ init_script_no = (known after apply)
+ instance_no = (known after apply)
+ is_encrypted_base_block_storage_volume = (known after apply)
+ is_fee_charging_monitoring = (known after apply)
+ is_protect_server_termination = (known after apply)
+ login_key_name = ""
+ memory_size = (known after apply)
+ name = "jk-svr"
+ placement_group_no = (known after apply)
+ platform_type = (known after apply)
+ port_forwarding_external_port = (known after apply)
+ port_forwarding_internal_port = (known after apply)
+ port_forwarding_public_ip = (known after apply)
+ private_ip = (known after apply)
+ public_ip = (known after apply)
+ region = (known after apply)
+ server_image_name = (known after apply)
+ server_image_number = "100524418"
+ server_image_product_code = (known after apply)
+ server_product_code = (known after apply)
+ server_spec_code = "s2-g3"
+ subnet_no = (known after apply)
+ vpc_no = (known after apply)
+ zone = (known after apply)
+ network_interface {
+ network_interface_no = (known after apply)
+ order = 0
+ private_ip = (known after apply)
+ subnet_no = (known after apply)
}
}
Plan: 10 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: yes
module.server.ncloud_login_key.server_key: Creating...
module.network.ncloud_vpc.vpc: Creating...
module.server.ncloud_login_key.server_key: Creation complete after 3s [id=]
module.server.local_file.ncp_pem: Creating...
module.server.local_file.ncp_pem: Creation complete after 0s [id=]
module.network.ncloud_vpc.vpc: Creation complete after 6s [id=]
module.network.ncloud_subnet.subnet_public: Creating...
module.server.ncloud_access_control_group.acg_01: Creating...
module.server.ncloud_access_control_group.acg_01: Creation complete after 0s [id=]
module.server.ncloud_access_control_group_rule.acg_rule_01: Creating...
module.server.ncloud_access_control_group_rule.acg_rule_01: Creation complete after 5s [id=365103]
module.network.ncloud_subnet.subnet_public: Still creating... [00m10s elapsed]
module.network.ncloud_subnet.subnet_public: Creation complete after 11s [id=]
module.server.ncloud_network_interface.nic: Creating...
module.server.ncloud_network_interface.nic: Creation complete after 1s [id=]
module.server.ncloud_server.server: Creating...
module.server.ncloud_server.server: Still creating... [00m10s elapsed]
module.server.ncloud_server.server: Still creating... [00m20s elapsed]
module.server.ncloud_server.server: Still creating... [00m30s elapsed]
module.server.ncloud_server.server: Still creating... [00m40s elapsed]
module.server.ncloud_server.server: Still creating... [00m50s elapsed]
module.server.ncloud_server.server: Still creating... [01m00s elapsed]
module.server.ncloud_server.server: Still creating... [01m10s elapsed]
module.server.ncloud_server.server: Still creating... [01m20s elapsed]
module.server.ncloud_server.server: Still creating... [01m30s elapsed]
module.server.ncloud_server.server: Still creating... [01m40s elapsed]
module.server.ncloud_server.server: Still creating... [01m50s elapsed]
module.server.ncloud_server.server: Still creating... [02m00s elapsed]
module.server.ncloud_server.server: Still creating... [02m10s elapsed]
module.server.ncloud_server.server: Still creating... [02m20s elapsed]
module.server.ncloud_server.server: Still creating... [02m30s elapsed]
module.server.ncloud_server.server: Creation complete after 2m34s [id=]
module.server.data.ncloud_root_password.default: Reading...
module.server.ncloud_public_ip.public_ip: Creating...
module.server.data.ncloud_root_password.default: Read complete after 0s [id=]
module.server.local_file.svr_root_pw: Creating...
module.server.local_file.svr_root_pw: Creation complete after 0s [id=]
module.server.ncloud_public_ip.public_ip: Creation complete after 2s [id=]
Apply complete! Resources: 10 added, 0 changed, 0 destroyed.
terraform apply 명령어는 말 그대로 실제로 리소스들을 생성/변경/삭제 해주는 작업을 실행한다
실행 계획 을 다시 보여주고 진짜로 실행할건지 확인 과정을 거친다
yes 입력하면 바로 실행된다
과정은 위의 내용을 참고하길 바란다
너무 길다;;
Naver Cloud Console 확인
실행을 시키고 Naver Cloud Console 로 들어가서 확인을 해보자


그럼 위와 같이 생성이 되고 있는 것을 볼 수 있다

시간이 좀 지나면 이렇게 내가 만든 서버가 생성되었다
실행 계획을 바탕으로 필요한 리소스들을 생성해서 참조하여 생성된 서버이다


이렇게 로컬에 키도 생성된 것을 확인할 수 있다
그렇다면 이제 만들어진 서버에 직접 접속을 해보자

나는 터미널로 ssh 접속을 해줬다
ssh -i [key 이름] root@[공인IP]
key 가 존재하는 경로에서 실행해줘야 한다
password.txt 파일에 있는 비밀번호를 통해 접속을 하면 된다!

cat /etc/redhat-release 명령어를 통해 OS 버전 확인을 해주면 내가 설정한 Rocky 9.4 로 잘 설치가 된 것을 확인할 수 있따

공인 IP 도 잘 들어갔다
Terraform Destory
이번 실습의 목적은 생성까지이므로 이제 삭제를 해보자
콘솔에서 하나하나 삭제할 필요 없이 명령어 하나로 내가 코드로 구성한 리소스들이 삭제가 된다
# terraform destroy
module.network.ncloud_vpc.vpc: Refreshing state... [id=142259]
module.server.ncloud_login_key.server_key: Refreshing state... [id=jk-svr-key]
module.server.data.ncloud_server_image_numbers.rocky94: Reading...
module.server.data.ncloud_server_specs.g3_spec: Reading...
module.server.local_file.ncp_pem: Refreshing state... [id=99985718aefe2184765bafb0561ebae50ce5e3e2]
module.network.ncloud_subnet.subnet_public: Refreshing state... [id=308511]
module.server.ncloud_access_control_group.acg_01: Refreshing state... [id=365103]
module.server.data.ncloud_server_image_numbers.rocky94: Read complete after 0s
module.server.ncloud_access_control_group_rule.acg_rule_01: Refreshing state... [id=365103]
module.server.ncloud_network_interface.nic: Refreshing state... [id=5810203]
module.server.data.ncloud_server_specs.g3_spec: Read complete after 0s
module.server.ncloud_server.server: Refreshing state... [id=142758304]
module.server.ncloud_public_ip.public_ip: Refreshing state... [id=142758379]
module.server.data.ncloud_root_password.default: Reading...
module.server.data.ncloud_root_password.default: Read complete after 0s [id=142758304]
module.server.local_file.svr_root_pw: Refreshing state... [id=cdad4da82428b0319e5970d2000417c2c793c9ae]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
- destroy
Terraform will perform the following actions:
# module.network.ncloud_subnet.subnet_public will be destroyed
- resource "ncloud_subnet" "subnet_public" {
- id = "308511" -> null
- name = "jk-public" -> null
- network_acl_no = "192081" -> null
- subnet = "192.168.0.0/24" -> null
- subnet_no = "308511" -> null
- subnet_type = "PUBLIC" -> null
- usage_type = "GEN" -> null
- vpc_no = "142259" -> null
- zone = "KR-1" -> null
}
# module.network.ncloud_vpc.vpc will be destroyed
- resource "ncloud_vpc" "vpc" {
- default_access_control_group_no = "365102" -> null
- default_network_acl_no = "192081" -> null
- default_private_route_table_no = "298942" -> null
- default_public_route_table_no = "298941" -> null
- id = "142259" -> null
- ipv4_cidr_block = "192.168.0.0/24" -> null
- name = "jk-vpc" -> null
- vpc_no = "142259" -> null
}
# module.server.local_file.ncp_pem will be destroyed
- resource "local_file" "ncp_pem" {
- content = (sensitive value) -> null
- content_base64sha256 = "kklPhEk0f5+74503KVaGev8KePtt+yQeTX2prg9c1bg=" -> null
- content_base64sha512 = "7m7Nm7fsvKNpgnNJPArrq8lcQh1yTd73GoRD7NCvhuRRneUKqZGtssVH1AkHtfz65gFZPYhbVoVIwIiNhobZJg==" -> null
- content_md5 = "a12e4da48fd0b8c2a25db489c9d9e3d1" -> null
- content_sha1 = "99985718aefe2184765bafb0561ebae50ce5e3e2" -> null
- content_sha256 = "92494f8449347f9fbbe39d372956867aff0a78fb6dfb241e4d7da9ae0f5cd5b8" -> null
- content_sha512 = "ee6ecd9bb7ecbca3698273493c0aebabc95c421d724ddef71a8443ecd0af86e4519de50aa991adb2c547d40907b5fcfae601593d885b568548c0888d8686d926" -> null
- directory_permission = "0777" -> null
- file_permission = "0777" -> null
- filename = "jk-svr-key.pem" -> null
- id = "99985718aefe2184765bafb0561ebae50ce5e3e2" -> null
}
# module.server.local_file.svr_root_pw will be destroyed
- resource "local_file" "svr_root_pw" {
- content = (sensitive value) -> null
- content_base64sha256 = "dfyhPR82gMOMVtZawxOCWQx/Qi6RAwCA/poyZjTlOaE=" -> null
- content_base64sha512 = "Kz0AuA5Pp/c3ocALXA1SuImTC/Hce8/pJqUKj85Fgjt0M1rJ/f7uU8z6O1JABHGV9WteMh2edHBYCb07TEMmaA==" -> null
- content_md5 = "7f0f84499461fd9da5cb42a4b8eb4540" -> null
- content_sha1 = "cdad4da82428b0319e5970d2000417c2c793c9ae" -> null
- content_sha256 = "75fca13d1f3680c38c56d65ac31382590c7f422e91030080fe9a326634e539a1" -> null
- content_sha512 = "2b3d00b80e4fa7f737a1c00b5c0d52b889930bf1dc7bcfe926a50a8fce45823b74335ac9fdfeee53ccfa3b5240047195f56b5e321d9e74705809bd3b4c432668" -> null
- directory_permission = "0777" -> null
- file_permission = "0777" -> null
- filename = "jk-svr-root_password.txt" -> null
- id = "cdad4da82428b0319e5970d2000417c2c793c9ae" -> null
}
# module.server.ncloud_access_control_group.acg_01 will be destroyed
- resource "ncloud_access_control_group" "acg_01" {
- access_control_group_no = "365103" -> null
- description = "jk Access controle group" -> null
- id = "365103" -> null
- is_default = false -> null
- name = "jk-acg01" -> null
- vpc_no = "142259" -> null
}
# module.server.ncloud_access_control_group_rule.acg_rule_01 will be destroyed
- resource "ncloud_access_control_group_rule" "acg_rule_01" {
- access_control_group_no = "365103" -> null
- id = "365103" -> null
- inbound = [
- {
- description = "accept 22 port(all ip)"
- ip_block = "0.0.0.0/0"
- port_range = "22"
- protocol = "TCP"
# (1 unchanged attribute hidden)
},
] -> null
- outbound = [
- {
- description = "accept ICMP"
- ip_block = "0.0.0.0/0"
- protocol = "ICMP"
# (2 unchanged attributes hidden)
},
- {
- description = "accept TCP 1-65535 port"
- ip_block = "0.0.0.0/0"
- port_range = "1-65535"
- protocol = "TCP"
# (1 unchanged attribute hidden)
},
- {
- description = "accept UDP 1-65535 port"
- ip_block = "0.0.0.0/0"
- port_range = "1-65535"
- protocol = "UDP"
# (1 unchanged attribute hidden)
},
] -> null
}
# module.server.ncloud_login_key.server_key will be destroyed
- resource "ncloud_login_key" "server_key" {
- id = "jk-svr-key" -> null
- key_name = "jk-svr-key" -> null
- private_key = (sensitive value) -> null
# (1 unchanged attribute hidden)
}
# module.server.ncloud_network_interface.nic will be destroyed
- resource "ncloud_network_interface" "nic" {
- access_control_groups = [
- "365103",
] -> null
- id = "5810203" -> null
- instance_type = "VSVR" -> null
- is_default = true -> null
- name = "jk-nic" -> null
- network_interface_no = "5810203" -> null
- private_ip = "192.168.0.6" -> null
- server_instance_no = "142758304" -> null
- status = "USED" -> null
- subnet_no = "308511" -> null
# (1 unchanged attribute hidden)
}
# module.server.ncloud_public_ip.public_ip will be destroyed
- resource "ncloud_public_ip" "public_ip" {
- description = "for jk-svr public ip" -> null
- id = "142758379" -> null
- instance_no = "142758379" -> null
- public_ip = "101.79.31.51" -> null
- public_ip_no = "142758379" -> null
- server_instance_no = "142758304" -> null
}
# module.server.ncloud_server.server will be destroyed
- resource "ncloud_server" "server" {
- base_block_storage_disk_detail_type = "SSD" -> null
- base_block_storage_disk_type = "NET" -> null
- cpu_count = 2 -> null
- hypervisor_type = "KVM" -> null
- id = "142758304" -> null
- instance_no = "142758304" -> null
- is_protect_server_termination = false -> null
- login_key_name = "jk-svr-key" -> null
- memory_size = 8589934592 -> null
- name = "jk-svr" -> null
- platform_type = "LNX64" -> null
- public_ip = "101.79.31.51" -> null
- server_image_number = "100524418" -> null
- server_image_product_code = "SW.VSVR.OS.LNX64.ROCKY.09.G003" -> null
- server_product_code = "SVR.VSVR.STAND.C002.M008.G003" -> null
- server_spec_code = "s2-g3" -> null
- subnet_no = "308511" -> null
- vpc_no = "142259" -> null
- zone = "KR-1" -> null
- network_interface {
- network_interface_no = "5810203" -> null
- order = 0 -> null
- private_ip = "192.168.0.6" -> null
- subnet_no = "308511" -> null
}
}
Plan: 0 to add, 0 to change, 10 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
module.server.local_file.ncp_pem: Destroying... [id=99985718aefe2184765bafb0561ebae50ce5e3e2]
module.server.local_file.svr_root_pw: Destroying... [id=cdad4da82428b0319e5970d2000417c2c793c9ae]
module.server.local_file.svr_root_pw: Destruction complete after 0s
module.server.local_file.ncp_pem: Destruction complete after 0s
module.server.ncloud_public_ip.public_ip: Destroying... [id=142758379]
module.server.ncloud_access_control_group_rule.acg_rule_01: Destroying... [id=365103]
module.server.ncloud_public_ip.public_ip: Still destroying... [id=142758379, 00m10s elapsed]
module.server.ncloud_access_control_group_rule.acg_rule_01: Still destroying... [id=365103, 00m10s elapsed]
module.server.ncloud_public_ip.public_ip: Destruction complete after 11s
module.server.ncloud_server.server: Destroying... [id=142758304]
module.server.ncloud_access_control_group_rule.acg_rule_01: Still destroying... [id=365103, 00m20s elapsed]
module.server.ncloud_server.server: Still destroying... [id=142758304, 00m10s elapsed]
module.server.ncloud_access_control_group_rule.acg_rule_01: Still destroying... [id=365103, 00m30s elapsed]
module.server.ncloud_server.server: Still destroying... [id=142758304, 00m20s elapsed]
module.server.ncloud_access_control_group_rule.acg_rule_01: Destruction complete after 33s
module.server.ncloud_server.server: Still destroying... [id=142758304, 00m30s elapsed]
module.server.ncloud_server.server: Still destroying... [id=142758304, 00m40s elapsed]
module.server.ncloud_server.server: Still destroying... [id=142758304, 00m50s elapsed]
module.server.ncloud_server.server: Destruction complete after 55s
module.server.ncloud_login_key.server_key: Destroying... [id=jk-svr-key]
module.server.ncloud_network_interface.nic: Destroying... [id=5810203]
module.server.ncloud_network_interface.nic: Destruction complete after 3s
module.server.ncloud_login_key.server_key: Destruction complete after 3s
module.server.ncloud_access_control_group.acg_01: Destroying... [id=365103]
module.network.ncloud_subnet.subnet_public: Destroying... [id=308511]
module.server.ncloud_access_control_group.acg_01: Destruction complete after 2s
module.network.ncloud_subnet.subnet_public: Still destroying... [id=308511, 00m10s elapsed]
module.network.ncloud_subnet.subnet_public: Destruction complete after 11s
module.network.ncloud_vpc.vpc: Destroying... [id=142259]
module.network.ncloud_vpc.vpc: Still destroying... [id=142259, 00m10s elapsed]
module.network.ncloud_vpc.vpc: Destruction complete after 11s
Destroy complete! Resources: 10 destroyed.
terraform destroy 명령어를 실행하면 삭제가 되는 것을 볼 수 있다


중간에 캡처했는데 정지 후 반납까지 잘 된다
마무리
이렇게 Terraform 을 이용한 Naver Cloud IaC 실습을 해봤다
코드로 인프라를 관리하면 콘솔 사이트에 들어갈 필요도 없고, 인프라 구조의 버전 관리도 되어서 좋다는 생각이 든다
근데 이렇게 사용하려면 각 리소스들에 대해서 좀 알고 있어야 할 것 같긴 하다
이건 Naver Cloud 공부와 병행해봐야겠다
이제 이걸 올해 초에 진행한 사이드 프로젝트를 띄워보는 것을 목표로 공부를 해봐야겠다
'클라우드' 카테고리의 다른 글
| 네이버 클라우드 시작해보기 (1) | 2026.06.22 |
|---|---|
| 가상 인프라 설계 및 통로 개척(OVS 기반) (0) | 2026.01.19 |