기본 문법

LizzyLee·2025년 1월 17일

Terraform

목록 보기
3/6
post-thumbnail

📖학습 목표

✏️ 테라폼의 기본 문법을 숙지한다!
✏️ 간결하고 정리된 코드를 작성할 수 있는 팁을 익힌다!


📢 Hands-on

테라폼을 사용하여 GCP 클라우드 내 VPC 와 서브넷을 생성해보자!

// main.tf 

resource "google_compute_network" "vpc_network" {
    project = "my-project-id"
    name = "my-vpc"
    auto_create_subnetworks = false
    mtu = 1460
}

resource "google_compute_subnetwork" "subnetwork-ipv6" {
    name = "ipv6-test-subnetwork"
    ip_cidr_range = "10.0.0.0/22"
    region = "us-west-2"
    network = google_compute_network.vpc_network.id 
}
  • 여러 리소스를 한 파일에 구성하여 생성할 수 있다.
  • 서로 다른 클라우드 제공자의 리소스를 한 파일에 구성하여 생성 할 수 있다. 예를 들어, AWS VM 을 생성하는 코드와 GCP VM을 생성하는 코드를 한 파일에 작성하여 관리 할 수 있다.

리소스 구조

테라폼 내 모든 리소스는 아래와 같은 구조로 되어 있다. 다만 각 리소스당 정의해야하는 arguments 는 서로 다를 수 있다.

<type> <resource type> <resource name> {
	# arguments...
}
  • <resource type> <resource name> 은 파일 내에서 unique 한 값을 가져야 한다.
  • resource name 은 사용자가 정할 수 있는 값이지만, resource type 은 클라우드 제공자가 정한 값을 사용해야한다.
  • 해당 리소스를 생성하기 위해 사용해야하는 arguments 값에 대하여 보다 자세하기 알아보기 위해서는 공식문서 를 참고하기 바란다.

다른 리소스 값 참조하기

리소스 내에서 다른 리소스의 이름 또는 속성을 참고해야하는 경우 <resource_type>.<resource_name>.<argument_name> 을 사용하여 참조할 수 있다.

// main.tf 

resource "google_compute_network" "vpc_network" {
    project = "my-project-id"
    name = "my-vpc"
    auto_create_subnetworks = false
    mtu = 1460
}

resource "google_compute_subnetwork" "subnetwork-ipv6" {
    name = "ipv6-test-subnetwork"
    ip_cidr_range = "10.0.0.0/22"
    region = "us-west-2"
    network = google_compute_network.vpc_network.id 
}

위 파일을 통해 리소스 생성 시, "my-vpc" 라는 이름을 가진 GCP VPC 에 "ipv6-test-subnetwork" 라는 이름의 서브넷을 생성할 수 있다.


📢 Meta-arguments

Meta arguments 를 사용하여 여러 리소스를 생성하거나 특정 리소스의 설정값을 만들 수 있다.

종류

  • count : count 에 입력된 값 만큼 리소스를 생성한다.

  • for_each : map 또는 문자열 세트(set) 를 참고하여 여러 리소스를 생성한다.

  • depends_on : 의존성을 명시적으로 표기할 때 사용한다.

  • lifecycle : 리소스의 라이프사이클을 관리할 때 사용한다. 예를 들어, 사내 법규로 인해 삭제하면 안되는 리소스의 제거를 사전 방지 하거나 리소스 삭제가 이루어지기 전 새로운 리소스를 생성하여 대체하고 기존 리소스를 삭제할 수 있도록 한다.

  • provider : 기본값으로 설정된 클라우드 제공자가 아닌 다른 클라우드 제공자를 적용해야 할 때 사용한다.

더 자세히 알아보기

count

다음과 같이 똑같은 설정값을 가진 리소스를 여러개 생성해야하는 경우 count meta argument 를 사용하여 코드의 반복을 줄일 수 있다. 😄

원본코드

resource "google_compute_instance" "dev_VM1" {
	name = "dev_VM1"
  	// etc...
}

resource "google_compute_instance" "dev_VM2" {
	name = "dev_VM2"
  	// etc...
}

resource "google_compute_instance" "dev_VM3" {
	name = "dev_VM3"
  	// etc...
}

수정된 코드
💡 count.index 는 0 부터 시작하며 1 씩 증가한다.

resource "google_compute_instance" "Dev_VM" {
	count = 3
  	name  = "dev_VM${count.index + 1}"
}

for_each

완전히 똑같은 리소스를 여러 개 생성해야하는 경우 count 로 충분할 수 있지만 몇몇 값이 달라야하는 경우 for_each 를 사용하는 것이 적절하다.

원본코드

resource "google_compute_instance" "VM1" {
	name = "dev-us-central1-a"
	location = "us-central1-a"
}

resource "google_compute_instance" "VM2" {
	name = "dev-us-central1-b"
	location = "us-central1-b"
}

resource "google_compute_instance" "VM3" {
	name = "dev-us-central1-c"
	location = "us-central1-c"
}

수정된 코드

resource "google_compute_instance" "dev_VM" {
    for_each = toset(["us-central1-a", "us-central1-b", "us-central1-c"])
    name = "dev-${each.value}"
    zone = each.value
}

⛄ 우와 편하다

depends_on

Dependency graph

테라폼으로 리소스를 생성하다보면 리소스들이 어떻게 연결되어 있는지 의존성은 어떻게 형성 되어 있는지 시각적으로 확인하고 싶을 때가 있다. 이 때 Dependency graph 이 큰 도움이 될 것이다.

테라폼은 리소스 구성 계획을 생성하고 state 를 재구성하기 위해 Dependency graph 를 그린다. 이는 테라폼이 변수, 아웃풋 및 클라우드 제공자를 정의 할 수 있도록 도울 뿐만 아니라 어떤 연산자를 먼저 수행 해야하는지 알 수 있도록 한다. 또 여러 연산자가 병렬적으로 수행되었을 때 안전한 경우 병렬로 리소스를 생성한다.

Implicit dependency VS Explicit dependency

의존성에는 크게 두 가지 종류가 있다.

  • Implicit dependency

    • 정의: 두 리소스의 의존성이 통상적으로 잘 알려진 경우, 두 리소스는 Implicit dependency 을 가진다고 볼 수 있다.
    • 예시: 서브넷을 생성하려면 VPC 가 있어야 한다. 즉, 서브넷과 VPC는 의존성(dependency) 을 가진다. 이러한 사실은 공공연히 알려진 내용이므로 Implicit denpendency 라고 볼 수 있다.
  • Explicit dependency

    • 정의: 두 리소스의 의존성이 존재하나 통상적으로 의존성을 가지지 않는 경우.
    • 예시: Instance 와 Bucket 은 통상적으로 서로 의존성을 가지지 않는다. 즉, 따로 생성해도 문제가 없다. 그러나 Instance 에 올려야 할 애플리케이션이 Bucket 을 사용하고 있어 Bucket 을 Instance 보다 먼저 생성해야하는 경우 서로 의존성이 존재하므로 Explicit denpendency 를 가진다고 볼 수 있다.

    👉 이 경우 depends_on 을 사용하여 두 리소스 간의 의존성을 명시적으로 설정 할 수 있다.

예시

Implicit dependency

resource "google_compute_instance" "my_instance" {
    network = google_compute_network.my_network.name // [1]
    access_config {
    }
}

resource "google_compute_network" "my_network" {
  name = "my_network"
}

이 경우 테라폼이 [1]를 통해 두 리소스 사이에 Implicit dependency 가 있음을 알 수 있다.

이 파일에 대하여 terraform apply 실행 시 아래와 같이 VPC 가 먼저 생성되고 이후 instance 가 생성되는 것을 볼 수 있다. 테라폼이 리소스를 생성하는 순서는 다음과 같다.

  1. 테라폼 코드의 순서와 상관없이, 의존성을 고려하여 VPC 를 먼저 생성한다.
  2. state 에 VPC 에 대한 속성 정보를 저장한다.
  3. instance 생성 시, 속성 값에 저장해두었던 VPC 정보를 활용하여 리소스를 생성한다.

Explicit dependency

server VM 과 client VM 이 있다고 가정하자. client VM 은 server VM 이 성공적으로 생성 된 후에만 생성되어야 한다. 이 경우 depends_on meta arguments 를 통하여 두 리소스 간의 의존성을 표기하고 리소스 생성 순서를 정의 해줄 수 있다.

resource "google_compute_instance" "client" {
    // etc 
    depends_on = [ google_compute_instance.server ]
}

resource "google_compute_instance" "server" {
    // etc
}

💡 테라폼 코드 상의 리소스 생성 순서와 실제 리소스 생성 순서는 상이하다. 따라서, 리소스 생성 순서를 고려하여 코드를 작성할 필요 없다. 나와 우리 팀이 보기에 가장 적절한 순서대로 코드를 작성하자.

0개의 댓글