본문 바로가기

infra/terraform

Terrafrom 기본 개념

Terraform 개요

Terraform은 HashiCorp에서 개발한 인프라스트럭처를 코드로 관리하는(IaC, Infrastructure as Code) 도구입니다. HCL(HashiCorp Configuration Language)이라는 선언적 언어를 사용하여 클라우드, 온프레미스 등 다양한 인프라를 정의하고 관리할 수 있습니다.

핵심 개념

  • 프로바이더(Provider): AWS, Azure, GCP 등 인프라 서비스를 제공하는 플랫폼과의 상호작용을 담당
  • 리소스(Resource): 생성하고 관리할 인프라 구성요소(서버, 네트워크, 스토리지 등)
  • 모듈(Module): 재사용 가능한 Terraform 코드 패키지
  • 상태(State): Terraform이 관리하는 인프라의 현재 상태를 저장하는 파일

워크플로우

1. Write (코드 작성)

HCL을 사용하여 원하는 인프라의 최종 상태를 정의합니다.

  • 프로바이더 설정 (AWS, Azure, GCP 등)
  • 리소스 정의 (EC2 인스턴스, VPC, 보안 그룹 등)
  • 변수와 출력값을 활용하여 코드 재사용성과 유연성 확보

2. Init (초기화)

Terraform 작업 디렉토리를 초기화하고 필요한 플러그인과 모듈을 다운로드합니다.

  • 정의된 프로바이더와 모듈에 필요한 플러그인을 다운로드
  • 백엔드 구성 초기화
  • .terraform 디렉토리에 필요한 설정 파일들이 저장됨

3. Plan (계획)

코드를 실행하기 전에 어떤 변경사항이 적용될지 미리 확인합니다.

  • 현재 상태와 정의된 코드를 비교하여 변경사항 확인
  • 리소스 생성, 수정, 삭제 계획을 상세히 보여줌
  • 변경 사항을 실제로 적용하기 전 검토 단계

4. Apply (적용)

계획된 변경사항을 실제 인프라에 적용합니다.

  • Plan 단계에서 확인한 변경사항을 실제 인프라에 반영
  • 변경 후 상태 파일(terraform.tfstate) 업데이트

5. Destroy (삭제)

Terraform으로 생성한 인프라를 완전히 제거합니다.

  • 더 이상 필요하지 않은 인프라 리소스를 안전하게 제거
  • 모든 리소스를 일괄 삭제하거나 특정 리소스만 타겟팅하여 삭제 가능
​그외 다른 terraform 명령어 확인
Terraform CLI overview | Terraform | HashiCorp DeveloperTerraform CLI overview | Terraform | HashiCorp Developer

 

협업/ 변경 관리

팀 환경에서 Terraform을 효과적으로 사용하기 위한 전략:

버전 관리

  • Git과 같은 버전 관리 시스템을 사용하여 코드 이력 관리
  • 브랜치 전략을 통한 변경사항 격리 및 테스트

원격 상태 관리

  • Terraform Cloud 또는 S3+DynamoDB와 같은 원격 백엔드 사용
  • 상태 잠금(State Locking)으로 동시 수정 방지
  • 팀원 간 상태 공유 및 협업 가능

모듈화와 재사용

  • 공통 인프라 패턴을 모듈화하여 재사용성 증가
  • 표준화된 모듈로 일관된 인프라 구성 유지

 

Terraform 설치 및 사용

브라우저 기반으로 AWS Console에서 사용 가능

AWS CloudShell에서 설치 가능 - 장점: AWS 계정정보 추가 설정 불필요

혹은 vs 코드에서 직접 설치해서 사용 가능

 CloudShell 사용하는 경우 설치 방법

Mac: brew tap hashicorp/tap && brew install hashicorp/tap/terraform

Linux: 공식 문서 참조 (Install | Terraform | HashiCorp Developer)

VS Code 설정

https://developer.hashicorp.com/terraform/install#darwin

mac에서 설치를 해주면 된다.

vs 코드 설치후에는 필수 확장 프로그램:

  • HashiCorp Terraform
  • IntelliCode
  • Prettier – Code formatter

JSON 설정 (F1 또는 Ctrl+Shift+P로 User Settings에서 설정):

{
    "[terraform]": {
        "editor.formatOnSaveMode": "file",
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "hashicorp.terraform",
        "editor.tabSize": 2
    },
    "[terraform-vars]": {
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "hashicorp.terraform",
        "editor.formatOnSaveMode": "file",
        "editor.tabSize": 2
    }
}

이후 aws 설정을 별도로 해줘야한다.

  • aws configure --profile myprofile: 새 프로필 생성
  • aws configure list: 현재 설정 확인
  • aws configure: 신규 설정 추가
  • aws configure list-profiles: 프로필 목록 확인
  • export AWS_PROFILE=myprofile: 프로필 변경
  • aws sts get-caller-identity (현재 계정 정보 확인)

ps IAM identity center

  • 이거로 유저 생성 간단하게 할 수 있음 (콘솔 주려면 주로 쓰는듯?)
    • iam 유저로하면 console 접근 못하게 할 수 있음
  • 권한 만들고 할당해주면 된다.
    • 기존이랑 크게 다르진 않은데 이메일 전송도 가고 그런게 좀 편한듯?

Terraform 주요 명령어

  • terraform init: 작업 디렉토리 초기화, 필요한 플러그인 및 모듈 다운로드
  • terraform plan: 현재 상태와 구성 파일의 차이를 분석하여 실행 계획 표시
  • terraform apply: 실행 계획에 따라 리소스 생성, 변경 또는 삭제 수행
  • terraform destroy: 관리 중인 모든 리소스 삭제 (-auto-approve 옵션으로 확인 과정 생략 가능)
  • terraform validate: 구성 파일의 구문 및 구조 유효성 검사
  • terraform fmt: 구성 파일의 형식을 표준 스타일로 자동 정렬
  • terraform state list: 현재 상태에 저장된 모든 리소스 목록 표시
  • terraform output: 정의된 출력 값 표시
  • terraform workspace: 여러 작업 환경(워크스페이스) 관리

 


HCL

Terraform 등 HashiCorp 제품에서 사용하는 구성 언어로 인프라를 코드로 선언하는 데 사용

 

HCL의 문법과 구조

1. 코드 블록

 

provider, resource, variable, output 등의 블록으로 구성

provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "example" {
  ami           = "ami-1234567890abcdef"
  instance_type = "t2.micro"
}

 

2. 키-값 쌍

  • 각 블록은 여러 개의 key = value 형식으로 작성
  • 예: region = "us-west-2"

 

3. 주석

  • 한 줄: # 또는 //
  • 여러 줄: /* 주석 */

Terraform 프로젝트 구조

파일명 역할 설명
main.tf 주요 인프라 코드 작성
variables.tf 변수 정의
outputs.tf 실행 결과 출력값 정의
terraform.tfvars 변수 실제 값 할당
providers.tf 사용할 클라우드 프로바이더 정의

 

디렉터리 예시 

/my-terraform-project
  ├── dev/
  ├── test/
  └── production/
각 환경별로 main.tf, variables.tf 등 동일한 구조 유지

 

 

 

테라폼 프로바이더

프로바이더는 테라폼이 다양한 클라우드 서비스와 연동할 수 있도록 하는 플러그인입니다.

사용가능한 프로바이더 확인 및 예시 :  https://registry.terraform.io/search/providers?namespace=hashicorp

프로바이더 특징

  • 다양한 클라우드 서비스 지원: AWS, Azure, GCP, Kubernetes 등 여러 플랫폼과 통합
  • 표준화된 인터페이스: 각 프로바이더마다 일관된 방식으로 리소스 관리 가능
  • 버전 관리: 프로바이더별로 버전을 지정하여 호환성 보장

프로바이더 활용 모범 사례

  • 인증 정보 관리: 코드에 직접 작성하지 않고 환경변수나 AWS CLI 설정 파일로 관리
  • 프로바이더 버전 고정: 예상치 못한 변경을 방지하기 위해 특정 버전 지정
  • 멀티 프로바이더 구성: 하나의 프로젝트에서 여러 프로바이더 동시에 사용 가능

프로바이더 설정 예시

# AWS 프로바이더 설정
provider "aws" {
  region = "ap-northeast-2"
  # 인증 정보는 환경 변수나 AWS CLI 프로필로 관리
}

멀티 프로바이더 예시

# AWS 프로바이더 설정
provider "aws" {
  region = "ap-northeast-2"
}

# Kubernetes 프로바이더 설정
provider "kubernetes" {
  config_path = "~/.kube/config"
}

# Helm 프로바이더 설정
provider "helm" {
  kubernetes {
    config_path = "~/.kube/config"
  }
}

프로바이더 버전 

테라폼 버전 관련 공식 문서 설명 : 링크

연산자 설명
= (또는 연산자 없음) 정확히 하나의 버전 번호만 허용합니다. 다른 조건과 결합할 수 없습니다.
!= 특정 버전 번호를 제외합니다.
>, >=, <, <= 지정된 버전과 비교하여 참이 되는 버전을 허용합니다. >, >=는 최신 버전 요청 시, <, <=는 오래된 버전 요청 시 사용합니다.
~> 가장 오른쪽에 있는 버전 구성 요소만 증가할 수 있도록 허용합니다. 
(비관적 제약 연산자)

특정 마이너 릴리스 내의 새로운 패치 릴리스만 허용합니다.
ex)
~> 1.0.4
1.0.5와1.0.10 버전을설치할수있도록허용하지만1.1.0은허용하지않습니다

 

프로바이더 캐시 

 

프로바이더 블러그인 캐시 설정

https://developer.hashicorp.com/terraform/cli/config/config-file#provider-plugin-cache

 

기본적으로 terraform init 명령은 플러그인을 작업 디렉토리의 하위 디렉토리에 다운로드

→ 로컬 디렉토리를 공유 플러그인 캐시로 사용할 수 있도록 옵션 제공

각 플러그인 바이너리를 한번만 다운로드 하도록 설정

 

 

환경 변수 사용

• TF_PLUGIN_CACHE_DIR 환경 변수를 사용하여 특정 세션에서 캐시 디렉토리를 활성화하거나 전역 적용가능

mkdir C:\terraform-plugin-cache

setx TF_PLUGIN_CACHE_DIR "C:\terraform-plugin-cache"

 

-> 설정해도 폴더에는 프로바이더가 실제로 존재하는것 같지만 link가 되어있을뿐 캐시 dir에만 실제로 존재 

(테라폼은 한번 캐시에 추가된 플러그인을 스스로 삭제하지 않는다 (수동 삭제 필요) )

 

 

 

 

AWS 프로바이더 리소스/ 데이터 소스 

aws provider를 사용해서 생성할 수 있는 모든 리소스와 데이터 소스를 문서화 정보 공식문서 

https://registry.terraform.io/providers/hashicorp/aws/latest/docs

 

테라폼 블록

테라폼 코드는 여러 유형의 블록으로 구성되며, 각 블록은 인프라의 특정 측면을 정의합니다.

terrafrom 블록 예시 : 링크

 

블록의 종류 

terraform 블록

테라폼의 전반적인 설정을 지정하는 블록입니다.

  • 필요한 테라폼 버전, 프로바이더 버전 제약조건 설정
  • 사용할 플러그인 정보 정의
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

provider 블록

사용할 클라우드 서비스를 정의하는 블록입니다.

  • 특정 클라우드 또는 서비스와의 상호작용 방법 설정
  • 리전, 인증 방식 등 프로바이더별 설정 지정
provider "aws" {
  region = "ap-northeast-2"
  profile = "default"
}

backend 블록

테라폼 상태 파일 저장 위치를 정의하는 블록입니다.

  • 로컬, S3, Azure Blob Storage 등 다양한 옵션 지원
  • 팀 협업 시 원격 백엔드 구성으로 상태 파일 공유 가능
terraform {
  backend "s3" {
    bucket = "terraform-state-bucket"
    key    = "project/terraform.tfstate"
    region = "ap-northeast-2"
    encrypt = true
    dynamodb_table = "terraform-locks"
  }
}

resource 블록

실제 생성할 인프라 리소스를 정의하는 블록입니다.

  • 클라우드 리소스(EC2, S3 등)의 속성과 구성 지정
  • 리소스 간 의존성 관계 설정
  • 리소스 어떻게 쓸지 찾는건 google에서 terraform  리소스명 형태로 검색하면 금방 찾을 수 있다 
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  tags = {
    Name = "WebServer"
  }
}

data 블록

기존 리소스 정보를 참조하는 블록입니다.

  • 이미 존재하는 리소스의 정보를 읽기 전용으로 가져옴
  • AMI ID, VPC 정보 등 외부 데이터 참조에 활용
data "aws_ami" "ubuntu" {
  most_recent = true
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
  owners = ["099720109477"] # Canonical
}

variable 블록

코드에서 사용할 입력 변수를 정의하는 블록입니다.

  • 외부에서 값을 입력받아 코드의 재사용성 향상
  • 타입, 기본값, 설명 등을 지정하여 변수 문서화
variable "instance_type" {
  description = "EC2 인스턴스 타입"
  type        = string
  default     = "t3.micro"
}

variable "vpc_cidr" {
  description = "VPC CIDR 블록"
  type        = string
  default     = "10.0.0.0/16"
}

local 블록

프로젝트 내부용 임시 변수를 정의하는 블록입니다.

  • 복잡한 표현식을 간소화하거나 중복 코드 제거에 활용
  • 외부 입력과 달리 프로젝트 내부에서만 사용
locals {
  common_tags = {
    Environment = "production"
    Project     = "example"
    Owner       = "DevOps"
  }
  
  subnet_ids = ["subnet-1234", "subnet-5678", "subnet-9012"]
}

resource "aws_instance" "example" {
  # ... 다른 설정들 ...
  tags = merge(local.common_tags, {
    Name = "example-instance"
  })
}

output 블록

실행 결과로 출력할 값을 정의하는 블록입니다.

  • 생성된 리소스의 중요 정보(IP, URL 등) 출력
  • 모듈 간 데이터 전달에 활용
output "instance_ip" {
  description = "EC2 인스턴스의 공인 IP 주소"
  value       = aws_instance.web.public_ip
}

output "load_balancer_dns" {
  description = "로드 밸런서 DNS 이름"
  value       = aws_lb.example.dns_name
}

블록 간 관계

테라폼 블록들은 서로 연관관계를 가지며 함께 작동합니다:

  • variable 블록에서 정의한 변수를 resource 블록에서 참조
  • data 블록으로 가져온 정보를 resource 블록에서 활용
  • resource 블록으로 생성한 리소스 정보를 output 블록으로 출력

 

${path.moudle} 은 terraform 에서 모듈 경로를 가리키는 내장 변수다  
이 변수는 현재 모듈이 위치한 디렉터리의 상대경로를 나타낸다. 

 

테라폼 데이터 타입

테라폼에서는 다양한 데이터 타입을 사용하여 인프라 코드를 효율적으로 관리합니다. 주요 데이터 타입은 다음과 같습니다

데이터 타입에 대한 공식문서 : 링크 

기본 데이터 타입

string: 텍스트 데이터를 저장하는 타입

variable "instance_name" {
  type = string
  default = "my-instance"
}

locals {
  greeting = "Hello, Terraform!"
}

 

 

number: 숫자 데이터를 저장하는 타입. 정수와 소수점 모두 포함

variable "instance_count" {
  type = number
  default = 2
}

locals {
  pi_value = 3.14159
  port = 8080
}

 

bool: 논리값(참/거짓)을 저장하는 타입

variable "enable_monitoring" {
  type = bool
  default = true
}

locals {
  is_production = false
}

복합 데이터 타입

list: 순서가 있는 값의 집합

variable "availability_zones" {
  type = list(string)
  default = ["ap-northeast-2a", "ap-northeast-2c"]
}

locals {
  ports = [80, 443, 8080]
  mixed_list = ["string", 123, true] # any 타입의 리스트
}

 

map: 키-값 쌍의 집합

variable "tags" {
  type = map(string)
  default = {
    Environment = "dev"
    Project = "terraform-example"
  }
}

locals {
  instance_types = {
    dev = "t2.micro"
    staging = "t2.medium"
    prod = "t2.large"
  }
}

 

set: 순서가 없고 중복을 허용하지 않는 값의 집합

variable "allowed_ports" {
  type = set(number)
  default = [22, 80, 443]
}

# 중복된 값은 자동으로 제거됨
locals {
  unique_values = toset(["a", "b", "a", "c"]) # 결과: ["a", "b", "c"]
}

 

object: 각 속성이 다른 타입을 가질 수 있는 구조체

variable "server_config" {
  type = object({
    name = string
    cpu = number
    memory = number
    is_public = bool
    tags = map(string)
  })
  default = {
    name = "web-server"
    cpu = 2
    memory = 4
    is_public = true
    tags = {
      role = "web"
    }
  }
}

 

tuple: 각 요소가 다른 타입을 가질 수 있는 순서가 있는 집합

variable "instance_details" {
  type = tuple([string, number, bool])
  default = ["t2.micro", 1, true]
}

locals {
  server_info = ["web-server", 2, false, { environment = "dev" }]
}

특수 데이터 타입

null: 값이 없음을 나타내는 타입

variable "optional_value" {
  type = string
  default = null
}

locals {
  db_connection = var.environment == "prod" ? "prod-db-connection" : null
}

 

any: 어떤 타입이든 될 수 있는 타입. 주로 변수 선언에서 타입을 명시하지 않을 때 사용

variable "flexible_input" {
  type = any
  default = "can be anything"
}

# 타입 미지정 시 any로 간주됨
variable "another_flexible_input" {
  default = {
    name = "value"
    count = 5
  }
}

타입 변환

테라폼에서는 다음과 같은 함수를 사용하여 타입 변환을 할 수 있다

 

tostring: 다른 타입을 문자열로 변환

locals {
  port_number = 8080
  port_string = tostring(local.port_number) # "8080"
  
  bool_value = true
  bool_string = tostring(local.bool_value) # "true"
}

 

 

tonumber: 문자열을 숫자로 변환

locals {
  string_number = "42"
  converted_number = tonumber(local.string_number) # 42
  
  float_string = "3.14"
  pi = tonumber(local.float_string) # 3.14
}

 

tobool: 문자열을 불리언으로 변환

locals {
  string_true = "true"
  converted_true = tobool(local.string_true) # true
  
  string_false = "false"
  converted_false = tobool(local.string_false) # false
}

 

tolist: 다른 타입을 리스트로 변환

locals {
  my_set = toset(["a", "b", "c"])
  my_list = tolist(local.my_set) # ["a", "b", "c"]
  
  my_map = { a = 1, b = 2 }
  map_as_list = tolist([for k, v in local.my_map : { key = k, value = v }])
  # [{ key = "a", value = 1 }, { key = "b", value = 2 }]
}

 

tomap: 다른 타입을 맵으로 변환

locals {
  tuple_list = [["key1", "value1"], ["key2", "value2"]]
  converted_map = tomap(local.tuple_list) # { key1 = "value1", key2 = "value2" }
  
  object_list = [
    { key = "name", value = "server1" },
    { key = "environment", value = "dev" }
  ]
  object_map = { for item in local.object_list : item.key => item.value }
  # { name = "server1", environment = "dev" }
}

 

toset: 다른 타입을 세트로 변환

locals {
  my_list_with_duplicates = ["a", "b", "a", "c", "b"]
  unique_set = toset(local.my_list_with_duplicates) # ["a", "b", "c"]
  
  az_list = ["ap-northeast-2a", "ap-northeast-2b", "ap-northeast-2a"]
  unique_azs = toset(local.az_list) # ["ap-northeast-2a", "ap-northeast-2b"]
}

변수를 사용한 리소스 생성 예시

변수를 활용해 AWS EC2 인스턴스를 생성하는 예시

# 변수 정의
variable "instance_type" {
  type    = string
  default = "t2.micro"
}

# AWS 리소스 생성
resource "aws_instance" "example" {
  ami           = "ami-0c9c942bd7bf113a2" # Amazon Linux 2023 AMI
  instance_type = var.instance_type
}

 

 

 

 

 

테라폼 흐름제어와 반복문 정리

테라폼은 선언형 언어이지만 조건에 따라 리소스를 생성하거나 값을 할당할때 흐름제어를 할 수 있고

반복문도 사용이 가능하다.

1. 흐름제어

  • 조건 표현식 (삼항 연산자): condition ? true_value : false_value
    • ex) var.environment == "prod" ? "m5.large" : "t2.micro"
  • count로 리소스 생성 제어 가능
    • count 만큼 리소스를 생성한다 0 이면 생성 x
  • null 값 활용 해서 특정 속성 무시 하도록 할 수 있다.

2. 반복문

  • count: 동일한 리소스 여러 개 생성
    • ex) count = 3으로 설정 시 3개의 동일한 인스턴스 생성
    • count.index를 사용해 각 리소스에 고유 식별자 부여
resource "aws_instance" "example1" {
  count         = 3
  ami           = "ami-1234567890"
  instance_type = "t2.micro"

  tags = {
    Name = "Example-Instance-${count.index}" # 0, 1, 2
  }
}

 

  • for_each: 키/값 기반 리소스 정의
    • 리스트, 맵, 셋 등 컬렉션을 사용해 각기 다른 속성의 리소스 생성
    • each.key, each.value로 개별 요소 접근
resource "aws_instance" "example2" {
  for_each      = toset(["dev", "staging", "prod"])
  ami           = "ami-1234567890"
  instance_type = "t2.micro"
  tags = {
    Name = "Example-Instance-${each.key}" # ["dev", "staging", "prod"]
  }
}
  • for 표현식: 컬렉션 데이터 변환/필터링
    • 리스트, 맵, 셋 등의 데이터 구조 생성/변환
    • locals 블록에서 자주 사용
locals {
  name_tags = [for name in var.instance_names : "Name-${name}"]
}

variable "instance_names" {
  description = "태깅에 사용할 인스턴스 이름 목록"
  type        = list(string)
  default     = ["web1", "web2", "web3"]
}
  • dynamic 블록: 반복적인 하위 블록 생성
    • 보안 그룹 규칙 같은 중첩 블록을 반복 생성할 때 유용
resource "aws_security_group" "example" {
  name = "example-sg"

  dynamic "ingress" {
    for_each = var.ingress_rules
    content {
      from_port   = ingress.value.from_port
      to_port     = ingress.value.to_port
      protocol    = ingress.value.protocol
      cidr_blocks = ingress.value.cidr_blocks
    }
  }
}

 

 

Terraform 내장 함수

내장 함수 공식 문서 : https://developer.hashicorp.com/terraform/language/functions

숫자 함수 (Numeric Functions)

  • abs(): 절대값 반환
  • ceil(): 올림 값 반환
  • floor(): 내림 값 반환
  • max(): 최대값 반환
  • min(): 최소값 반환

문자열 함수 (String Functions)

  • join(separator, list): 리스트 요소들을 구분자로 연결
  • split(separator, string): 문자열을 구분자로 분리하여 리스트 생성
  • replace(string, search, replace): 문자열 내 특정 부분 교체
  • trimspace(string): 문자열 앞뒤 공백 제거
  • length(string): 문자열 길이 반환
# split 함수
locals {
  comma_separated = "web,app,db"
  servers = split(",", local.comma_separated)  # ["web", "app", "db"]
}

# join 함수
locals {
  tags = ["env:prod", "owner:ops", "project:example"]
  tags_string = join(",", local.tags)  # "env:prod,owner:ops,project:example"
}

컬렉션 함수 (Collection Functions)

  • merge(map1, map2, ...): 여러 맵을 하나로 병합
  • contains(list, value): 리스트에 특정 값이 있는지 확인
  • lookup(map, key, default): 맵에서 키로 값을 찾거나 기본값 반환
  • flatten(list of lists): 중첩 리스트를 단일 리스트로 평탄화
  • keys(map): 맵의 모든 키를 리스트로 반환
# lookup 함수 예시
locals {
  environment_to_instance_type = {
    dev  = "t2.micro"
    test = "t2.small"
    prod = "t2.medium"
  }
  
  instance_type = lookup(local.environment_to_instance_type, var.environment, "t2.nano")
}

변환 함수 (Type Conversion Functions)

  • toset(list): 리스트를 집합으로 변환
  • tolist(set): 집합을 리스트로 변환
  • tostring(value): 값을 문자열로 변환
  • tonumber(value): 값을 숫자로 변환
  • tobool(value): 값을 불리언으로 변환

네트워크 함수 (Network Functions)

  • cidrsubnet(prefix, newbits, netnum): CIDR 블록에서 서브넷 계산
  • cidrhost(prefix, hostnum): CIDR 블록 내 특정 호스트 IP 계산
  • cidrnetmask(prefix): CIDR 블록의 넷마스크 계산

파일 함수 (File Functions)

  • file(path): 파일 내용을 문자열로 읽기
  • filebase64(path): 파일 내용을 base64로 인코딩하여 읽기
  • templatefile(path, vars): 템플릿 파일을 변수와 함께 렌더링

테라폼의 Import와 Check 기능

Import 기능

테라폼의 import 기능은 이미 존재하는 인프라 리소스를 테라폼 상태로 가져오는 기능이다. 이를 통해 기존에 수동으로 생성된 리소스를 테라폼으로 관리할 수 있게 된다.

 

Import 사용 방법

# 코드 내 import 블록 사용 (테라폼 1.5+)
import {
  to = aws_s3_bucket.example
  id = "bucket-name"
}

# 리소스 정의
resource "aws_s3_bucket" "example" {
  bucket = "bucket-name"
  # 기타 필요한 속성들
}

 

Import 프로세스

  1. 기존 리소스를 테라폼 상태로 가져오기
    1. import 하면 일단 상태 가져오기만 한다 tfstate에 상태 저장
    2. 코드도 실제 상태랑 통일하려면 추가 작업 필요
  2. 실제 인프라 코드 추가
    1. 인프라 상태 확인 terraform state show aws_s3_bucket.example
    2. 인프라 상태 HCL 저장
      1. plan 수행시 오류 발생
      2. 실제로는 hcl에서 설정 불가능한 속성들도 있기 때문에 그런부분 제거 필요

Import 예시: AWS S3 버킷

# 기존 S3 버킷을 테라폼으로 가져오기
import {
  to = aws_s3_bucket.logging_bucket
  id = "my-existing-logging-bucket"
}

# 가져온 버킷의 테라폼 정의
# 가져온 뒤에는 상태 확인해서 실제 상태 부분은 코드로 추가 자것ㅇ 필요 
resource "aws_s3_bucket" "logging_bucket" {
  bucket = "my-existing-logging-bucket"
}

 

Check 기능

테라폼의 Check 블록은 리소스의 유효성을 검증하는 기능이다. 이를 통해 인프라 구성이 특정 조건이나 정책을 준수하는지 확인할 수 있다.

 

Check 사용 방법

테라폼 1.5 버전부터 도입된 check 블록을 사용하여 리소스 속성이 특정 조건을 만족하는지 검증할 수 있다.

check "bucket_naming_convention" {
  assert {
    condition     = length(aws_s3_bucket.example.bucket) >= 8
    error_message = "S3 버킷 이름은 최소 8자 이상이어야 합니다."
  }
}



 

테라폼의 리소스 흐름 관리

테라폼에서는 리소스의 생성주기를 관리해서 동작을 세밀하게 관리하는게 가능하다 

주요 Lifecycle 설정 옵션

1. prevent_destroy

중요한 리소스의 실수로 인한 삭제를 방지하는 설정입니다.

resource "aws_db_instance" "database" {
  # 데이터베이스 구성...
  
  lifecycle {
    prevent_destroy = true  # 삭제 방지 활성화
  }
}

2. ignore_changes

테라폼이 관리하는 속성이 변경되더라도 적용안되게해서 수동으로 관리하고 싶은 속성이 있을때 사용

resource "aws_instance" "example" {
  # 인스턴스 구성...
  
  lifecycle {
    ignore_changes = [
      tags,
      volume_tags,
    ]
  }
}

3. create_before_destroy

리소스를 교체할 때 새 리소스를 먼저 생성한 후 기존 리소스를 삭제합니다. 다운타임을 최소화하는 데 유용합니다.

resource "aws_instance" "web" {
  # 인스턴스 구성...
  
  lifecycle {
    create_before_destroy = true
  }
}

depends_on을 활용한 리소스 의존성 관리

테라폼은 기본적으로 리소스 간의 참조를 통해 의존성을 파악하지만, 명시적인 의존성 설정이 필요한 경우 depends_on을 사용한다.

  • 암시적 의존성이 없는 리소스 간의 순서 지정
  • 멀티 프로바이더 환경에서의 의존성 관리
    • ex) a가 배포후 b가 배포되길 바란다
  • 데이터 소스와 리소스 간의 의존성 설정
# 리소스 간 의존성 설정
resource "aws_security_group" "example_sg" {
  name = "example-sg" # 보안 그룹 이름 설정
}

# EC2 인스턴스 생성 전 생명 주기 제어
resource "aws_instance" "example_create_before_destroy_with_dependency" {
  ami           = local.ami  # 로컬 변수로 설정한 AMI ID 사용
  instance_type = "t2.micro" # EC2 인스턴스 유형 설정

  lifecycle {
    create_before_destroy = true # 인스턴스를 교체할 때 새 인스턴스를 먼저 생성하고 기존 인스턴스를 삭제하여 다운타임을 방지
  }

  depends_on = [
    aws_security_group.example_sg # 보안 그룹 생성 후 인스턴스를 생성하도록 의존성 설정
  ]
}



 

Terraform 모듈 개요

모듈은 일종의 코드 블록이다. 인프라 리소스를 구성하는 여러 요소를 묶어서

하나의 단위로 재사용 할 수 있는 구조 (.tf파일이 곧 모듈이다 )

모듈을 사용하면 동일한 구성을 여러 곳에서 반복적으로 사용해야할 때 한번에 정의

필요한 곳에서 간단히 호출해서 사용 가능하다

모듈의 주요 특징

  • 코드 재사용: 동일한 인프라 구성을 여러 환경에서 반복 사용 가능
  • 유지보수 용이성: 변경 사항을 한 곳에서 관리하여 일관성 유지

모듈 기본 구성 요소

  • main.tf
    • 모듈의 주요 리소스 정의 (꼭이름이 main.tf일 필요는없음)
  • variables.tf
    • 모듈을 호출할 때 전달받아야할 값들을 변수로 선언
  • outputs.tf
    • 모듈이 생성한 리소스의 중요한 정보를 반환하는 출력값을 정의하는 파일

모듈 사용방법

vpc라는 모듈이 있었을때 해당 모듈 사용하는 방법

# 모듈 호출
module "vpc" {
  source = "./modules/vpc"
  # VPC 모듈 설정
}

# 모듈 파일 
module "security_groups" {
  source = "./modules/security_groups"
  vpc_id = module.vpc.vpc_id  # VPC 모듈의 출력을 보안 그룹 모듈의 입력으로 사용
}
project-name/
├── main.tf
└── modules/
    └── vpc/ #이렇게 하위에도 프로젝트가 있는것 
        ├── main.tf
        ├── variables.tf
        └── outputs.tf

모듈 관리하는 git 리포지토리에서 가져오는 경우

source = "git::<https://github.com/user/repo.git//path/to/module>"

테라폼에서 제공하는 공식모듈 가져오는 케이스

source  = "terraform-aws-modules/vpc/aws"
version = "~> 2.0"