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 프로세스
- 기존 리소스를 테라폼 상태로 가져오기
- import 하면 일단 상태 가져오기만 한다 tfstate에 상태 저장
- 코드도 실제 상태랑 통일하려면 추가 작업 필요
- 실제 인프라 코드 추가
- 인프라 상태 확인 terraform state show aws_s3_bucket.example
- 인프라 상태 HCL 저장
- plan 수행시 오류 발생
- 실제로는 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"