HCL 기본
HCL(HashiCorp Configuration Language)는 Terraform 뿐만 아니라 Vault, Consul 등Hashicorp의 다른 제품에서도 사용되는 언어로, 선언적 인프라 정의에 최적화 되어있음. JSON과 유사한 구조를 가지면서도 주석이나 더 유연한 구문을 지원
구문 이해
HCL의 기본 구성 요소는 블록, 인자, 표현식이다
블록 (Block)
- Terraform 구성의 가장 기본적인 컨테이너
- 중괄호로 둘러싸여 있으며 내부에 인자나 다른 중첩블록 포함가능
- 각 블록은 특정 종류의 리소스, 프로바이더, 변수 등을 정의하는데 사용됨
- 일반적으로 타입과 레이블을 가짐
#'resource'는 블록타입, 'aws_instance'는 첫 번째 레이블(리소스 타입), 'web_server'는 두 번째 레이블(리소스 이름)
resource "aws_instance" "web_server" {
#인자 또는 중첩 블록
}
#'variable'은 블록 타입, 'instance_type'은 레이블 (변수 이름)
variable "instance_type" {
#인자 또는 중첩 블록
}
인자 (Argument)
- 블록 내부에 정의되는 이름-값 쌍
- 특정 리소스의 속성이나 변수의 정의 등을 나타냄
#예시
resource "aws_instance" "web_server" {
ami = "ami-0eb26f391850125a1" #ami : Amazon Machine Image
instance_type = "t2.micro"
tags = {
Name = "MyWebServer"
}
}
표현식 (Expressions)
- 값이나 참조를 나타내는 방법
- 리소스의 속성, 변수, 함수호출, 산술 연산 등을 포함할 수 있음
- Terraform은 이 표현식들을 평가하여 실제 값을 결정
#변수 참조 (var.변수명)
instance_type = var.instance_type
#리소스 속성 참조 (리소스타입.리소스이름.속성)
value = aws_instance.web_server.public_ip
#함수 호출 (함수명(인자))
name = "${upper(var.server_name)}-DEV" #upper()함수로 문자열을 대문자로 변환
#리스트, 맵, 숫자, 불리언 등 다양한 데이터 타입 지원
list_example = ["item1", "item2"]
map_example = { key1 = "value1", key2 = "value2"}
number_example = 123
bool_example = true
주석
# 단일 라인 주석
/*
멀티
라인
주석
*/
주요 블록
리소스
Terraform 코드의 가장 핵심적인부분으로 실제 생성/수정/삭제 될 인프라 자원을 정의
- 리소스 블록의 구조와 역할 : 리소스 블록은 두 개의 레이블을 가짐
- 리소스 타입 (Type)
- 어떤 종류의 리소스를 생성할 것인지 정의
- 프로바이더가 제공하는 리소스 타입에 따라 달라짐 → 프로바이더 문서 참고 필요
- ex : aws_instance, aws_s3_bucket, azurerm_virtual_machine, google_compute_instance
- 리소스 로컬 이름 (Local Name)
- Terraform 구성 내에서 해당 리소스를 참조할 때 사용되는 고유한 이름
- Terraform 코드 내에서만 유효하며 실제 클라우드 환경에 배포되는 리소스 이름과 다를 수 있음
- 실제 리소스 이름은 tags나 특정 인자를 통해 지정 가능
- 리소스 타입 (Type)
#예시: AWS에 EC2인스턴스 생성
#main.tf
#프로바이더 설정: AWS 리전 정의
provider "aws" {
region = "ap-northeast-2"
}
#EC2 인스턴스 리소스 정의
resource "aws_instance" "web_server" {
ami = "ami-0eb26f391850125a1" # Amazon Linux 2023 AMI ID (서울 리전)
instance_type = "t2.micro" #인스턴스 타입
tags = {
Name = "MyTerraformEC2"
}
}
#- aws_instance : AWS 프로바이더가 제공하는 EC2 인스턴스 리소스 타입
#- web_server : 이 Terraform 구성 내에서 이 EC2 인스턴스를 참조할 때 사용할 이름
- 리소스 의존성 관리
- Terraform은 기본적으로 암시적 의존성을 자동 파악함
- 한 리소스가 다른 리소스의 속성 값을 참조하면 , 참조되는 리소스가 먼저 생성되어야 함을 자동으로 인지하고 순서를 결정한다는 의미
- 때로는 Terraform이 의존성을 파악하기 어려운 경우에는 depends on 을 이용한 명시적 의존성을 사용
- 자동 의존성 감지 실패 혹은 특정 순서가 논리적으로 필요한데 직접적인 참조가 없는 경우에만 사용
#S3 버킷 생성
resource "aws_s3_bucket" "my_website_bucket" {
bucket = "my-unique-website-bucket-01012025"
acl = "private"
tag. = {
Environment = "Dev"
Project = "Website"
}
}
#S3 버킷 정책 생성
resource "aws_s3_bucket_policy" "bucket_policy" {
bucket = aws_s3_bucket.my_website_bucket.id #암시적 의존성 : 버킷ID 참조
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = "*"
Action = [
"s3:GetObject"
]
Resource = [
"${aws_s3_bucket.my_website_bucket_arm}/*" #암시적 의존성 : 버킷 ARN 참조
]
}
]
})
}
#aws_s3_bucket_policy 리소스는
#aws_s3_bucket.my_website_bucket의 id와 arn 속성을 참조하고 있으므로
#Terraform은 자동으로 aws_s3_bucket이 aws_bucket_policy보다 먼저 생성해야한다고 판단
프로바이더
Terraform이 클라우드 서비스(AWS,Azure,GCP), SaaS(GitHub, DataDog), 온프레미스 솔루션(vSphere, Kubernetes)의 API와 상호작용할수 있도록 해주는 플러그인
- 개념과 역할
- Terraform은 자체적으로 인프라를 직접 제어하는 기능이 없음 대신 각 서비스의 API와 통신하기 위한 프로바이더를 사용
- 프로바이더는 해당 서비스의 리소스 타입과 데이터 소스를 정의하고 Terraform 명령(plan, apply)이 실행될 때 실제 API 호출을 수행
- 주요 클라우드 프로바이더 설정 예시
- 일관성과 안정성 및 재현성을 위해서 버전 지정이 권장됨
- ~> : 틸다와 함께 붙은 연산자, 지정된 최소 버전 이상이면서 다음 메이저 버전 미만 허용
#AWS
#main.tf or version.tf
#프로바이더 정의
terraform {
requiered_providers {
aws = {
source = "hashicorp/aws" #프로바이더 소스(필수)
version = "~> 5.0" #프로바이더 버전 제약 (권장)
}
}
}
#프로바이더 상세 설정
provider "aws" {
region = var.aws_region #프로바이더가 관리할 aws 리전/variables.tf 에 정의된 변수 사용
}
#Azure
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
}
}
provider "azurerm" {
features {} #최신 버전에서는 불필요 할 수도 있음
}
#GCP
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}
provider "google" {
project = "gcp-project-id"
region = "asia-northeast3"
}
변수
- Terrafomr 코드 유연성과 재사용성 부여하는 핵심 요소
- 하드코딩 값 제거하고 환경,리전,인스턴스 타입 등 배포 시점에 변경될 수 있는 값들을 외부에서 주입할 수 있도록 함
- 변수 타입
- string : 일반적인 텍스트 문자열
- number : 정수 또는 부동 소숫점 숫자
- bool : true/false
- list(<TYPE>) : 동일 타입 요소들을 순서대로 담는 컬렉션 (배열)
- set(<TYPE>) : 순서 없고 중복 허용않는 동일한 타입 요소 컬렉션
- map(<TYPE>): 문자열 키와 동일한 타입의 값을 가지는 컬렉션 (딕셔너리)
- object({<KEY> = <TYPE>, …}) : 여러 타입의 값들을 가질수 있는 키-값쌍 컬렉션, 키 타입 명시 필수
#입력 변수 정의
variable "my_string_variable" {
description = "설명"
type = string #자료형
default = "기본값"
}
#입력 변수 사용 : var.변수명
resource "aws_instance" "example" {
instance_type = var.my_string_variable
...
}
#object type 변수
variable "server_config" {
type = object({
name = string
instance_type = string
port = number
enabled = bool
})
default = {
name = "default-server"
instance_type = "t2.micro"
port = 80
enabled = true
}
}
- 기본값 설정
- default 인자는 변수에 값이 주입되지 않았을 때 사요될 값을 지정
- 항상 변수에 값을 주입하지 않아도 되는 편리함 제공
- 기본 값 없는데 변수 값 주입되지 않으면 plan 이나 apply 실행 시 사용자에게 값을 입력하라는 프롬프트 출력
- terraform.tfvars 파일
- 설치 및 기본 사용법 섹션 파일구조에서 다루었듯 실제 변수 값을 할당하기 위해 사용
- 환경 변수 및 CLI를 이용한 변수 전달
- 환경 변수
- TF_VAR_ 접두사를 사용해 환경변수로 변수값 설정 가능
- 스크립트나 CI/CD파이프라인에서 주로 사용
- terraform.tfvars 보다 높은 우선순위
- CLI 옵션
- terrafomr plan/apply 명령 실행시 -var,-var-file 옵션으로 변수 값 전달 가능
- -var-file 이 여러개인 경우 마지막 지정 파일이 이전 파일의 동일 변수 덮어씀
- terraform.tfvars 보다 높은 우선순위
- 환경 변수
출력
Terraform이 인프라 배포를 완료한 후, 특정 리소스의 속성 값이나 계산된 결과를 출력하도록 정의. 이 값들은 다른 Terraform 구성에서 사용되거나, 사용자에게 중요한 정보를 전달하는데 유용
- 역할
- 정보 전달 : 배포된 인프라의 IP 주소, DNS 이름, 연결 문자열, ID 등 필요 정보 출력
- 모듈 간 연동: 한 모듈에서 생성된 인프라 정보를 다른 모듈의 입력변수로 전달할 때 사용
- 스크립트 자동화 : Terraform 외부의 스크립트가 배포된 인프라 정보를 활용할 수 있도록 JSON 형식 등으로 출력 가능
- terraform apply 완료 후, 또는 terraform output 명령을 통해 출력 값 확인 가능
#outputs.tf
#웹 서버 퍼블릭 IP 주소 출력
output "web_server_public_ip" {
description = "The public IP address of the deployed web server"
value. = aws_instance.web_server.public_ip #리소스.로컬이름.속성 참조
}
#S3 버킷의 ARN(Amazon Resource Name)출력
output "s3_bucket_arn" {
description = "The ARN of the created S3 bucket"
value = aws_s3_bucket.my_website_bucket.arn
}
#여러 값을 맵 형태로 출력
output "resource_details" {
description = "Details of deployed resources"
value = {
ec2_id = aws_instance.web_server.id
s3_name = aws_s3_bucket.my_website_bucket.bucket
region = var.aws_region
}
}
로컬 값
locals 블록은 Terrafomr 구성 내에서 재사용 가능한 명명된 표현식ㄷ을 정의할 때 사용. 변수와 비슷하지만 로컬 값은 외부에서 주입되는 입력이 아니라 Terraform 코드 내부에서 계산되거나 정의되는 값
- 목적
- 복잡한 표현식 단순화 : 반복적으로 사용되는 복잡한 표현식을 로컬값으로 정의해 가독성 향상
- 계산된 값 재사용: 여러 리소스에서 공유될 필요가 있는 계산된 값(특정 패턴 이름 등)을 정의할 때 유용
- 코드 추상화: 코드의 특정 부분을 더 명확하게 만들고, 의도를 드러내는데 도움 줌
#locals.tf or main.tf
locals {
#프로젝트 이름과 환경을 조합해 리소스 접두사 정의
#var.project_name과 var.environment 변수가 있다고 가정
resource_prefix = "${var.project_name}-${var.envrionment}"
#웹서버 인스턴스 이름 생성
web_server_instance_name = "${local.resource_prefix}-web-server"
#복잡한 계산 결과 (ex: 네트워크 CIDR 불록)
vpc_cidr_block = "10.0.0.0/16"
subnet_cidr_blokcs = [
"10.0.1.0/24",
"10.0.2.0/24",
"10.0.3.0/24"
]
#조건부 값 설정
enable_monitoring = var.environment == "prod" ? true : false
}
resource "aws_instance" "webserver" {
ami = var.ami_id
instance_type = var.instance_type
tags = {
Name = local.web_server_instnace_name
Environment = var.environment
}
}
데이터 소스
data 블록은 Terraform 외부의 정보(클라우드에 이미 존재하는 리소스 , 파일시스템 파일 등)를 조회하고 그 정보를 Terraform 구성 내에서 활용할 수 있도록 해줌. 기존 인프라를 읽어오는 역할
- 기존 인프라 정보 조회 및 활용
- Terraform이 관리하지 않거나, 이미 존재하는 리소스를 활용해야할 때 사용
- ex : 특정 ami 코드를 하드코딩하는 대신 최신 AMI ID를 조회하는게 좋음
- 사용법
- 두 개의 레이블 사용
- 데이터 소스 타입 : 조회할 데이터의 종류를 정의 (ex: aws_ami, aws_vpc 등)
- 데이터 소스 로컬 이름 : Terraform 구성 내에서 이 데이터 소스를 참조할 때 사용되는 고유한 이름
- 예시 : 기존 VPC ID, AMD ID 조회
#최신 Amazion Linux AMI Id 조회
data "aws_ami" "amazone_linux_latest" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-kernel-6.1-x86_64"] #AMI 이름 패턴
}
filter {
name = "virtualization-ty[e"
values = ["hvm"]
}
}
#데이터 소스에서 얻은 AMI ID로 EC2 인스턴스 생성
resource "aws_instance" "web_server_with_latest_ami" {
ami = data.aws_ami.amazon_linux_latest.id #데이터 소스 참조
instance_type = "t2.micro"
tags = {
Name = "WebServerWithLatestAMI"
}
}
#이름 태그를 통해 기존 VPC 조회
data "aws_vpc" "existing_vpc" {
filter {
name = "tag:Name"
values = ["my-production-vpc"] #기존 VPC Name 태그
}
#또는 ID로 직접 지정 id = "vpc-xxxxxxxxxxxxxxxxx"
}
#조회된 vpc id를 사용해 서브넷 생성
resource "aws_subnet" "public_subnet" {
vpc_id = data.aws_vpc.existing_vpc.id
cidr_block = "10.0.10.0/24"
availability_zone = "ap-northeast-2a"
tags = {
Name = "MyPublicSubnet"
}
}
'IaC > Terraform' 카테고리의 다른 글
[IaC] Terraform(6) - 워크스페이스 (0) | 2025.09.25 |
---|---|
[IaC] Terraform(5) - 상태관리 (0) | 2025.09.25 |
[IaC] Terraform(4) - 모듈 (0) | 2025.09.25 |
[IaC] Terraform(2) - 설치 및 기본 사용법 (1) | 2025.09.15 |
[IaC] Terraform(1) - 개요 (0) | 2025.09.15 |