처음부터 Terraform: HCL, 공급자 및 계획-적용-폐기 주기
2026년에는 코드형 인프라 시장이 Terraform을 무시하는 것과 동일할 정도로 성숙해졌습니다. 트랜잭션을 모르고 SQL을 작성하는 것은 기술적으로는 가능하지만 전문적으로는 위험합니다. HashiCorp의 Terraform은 현재 시장점유율 32.8% IaC 도구 중에서 Registry.terraform.io에 매월 400만 개의 공급자 설치. 이 가이드는 처음부터 안내합니다. 계획-적용-폐기 주기에 대한 확실한 이해를 바탕으로 AWS 및 Azure에서의 작업 설정 이는 생산 시 비용이 많이 드는 오류를 방지합니다.
IaC에 접근하는 개발자들로부터 가장 자주 듣는 질문은 다음과 같습니다. “왜냐면 난 그냥 사용하는 것이 아니기 때문에 bash 스크립트인가요, 아니면 AWS 콘솔인가요?”. 답은 '개념'에 있다 선언적 인프라: Terraform에 말하지 마세요 ~처럼 자원을 만들어라. 어느 주 당신은 달성하고 싶어합니다. 테라폼 작업 순서를 이해하고 리소스 간의 종속성을 관리하며 멱등성을 보장하는 데 관심이 있습니다.
무엇을 배울 것인가
- 여러 버전을 처리하도록 Terraform을 설치하고 tfenv를 구성합니다.
- HCL 구문: 블록, 속성, 표현식 및 내장 함수
- 보안 인증을 사용하여 AWS 공급자 및 Azure 공급자 구성
- 전체 수명주기:
terraform init,plan,apply,destroy - 상태 파일 이해: 파일이 무엇인지, 어디에 있는지, 수동으로 수정해서는 안 되는 이유
- 확장 가능한 방식으로 처음부터 Terraform 프로젝트 구성
- 변수, 로컬 및 출력: 전문적인 방식으로 구성 구성
전제조건 및 설치
HCL의 첫 번째 줄을 작성하기 전에 전문적으로 환경을 설정해 보겠습니다. 가장 흔한 초보자 실수는 패키지 관리자를 사용하여 Terraform을 전역적으로 설치하는 것입니다. 특정 버전에 멈춰 있는 자신을 발견하세요. 올바른 해결책은 티펜브, Terraform용 버전 관리자(Node.js의 nvm과 동일)
# Installa tfenv (macOS/Linux)
git clone https://github.com/tfutils/tfenv.git ~/.tfenv
echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# Installa l'ultima versione stabile di Terraform
tfenv install latest
tfenv use latest
# Verifica installazione
terraform version
# Output: Terraform v1.9.x on linux_amd64
# Installa una versione specifica se il progetto la richiede
tfenv install 1.8.5
tfenv use 1.8.5
# Lista versioni installate
tfenv list
Windows의 경우 2026년에 권장되는 접근 방식과 Ubuntu 또는 Chocolatey를 사용하는 WSL2:
# Windows con Chocolatey
choco install terraform
# Oppure scarica il binario da releases.hashicorp.com
# e aggiungilo al PATH manualmente
VS Code 플러그인도 설치하세요. HashiCorp 테라폼 (ID: hashicorp.terraform):
구문 강조, 자동 완성, 공급자 정의 이동 및 통합 기능을 제공합니다.
와 terraform fmt. HCL에 사용할 수 있는 가장 강력한 IDE 환경입니다.
HCL: HashiCorp 구성 언어
HCL(HashiCorp Configuration Language)은 특별히 설계된 선언적 언어입니다.
인프라 구성을 위해. 범용 프로그래밍 언어는 아닙니다.
명령형 루프가 없습니다(사용 for_each e count), 예외는 없습니다.
비동기 I/O가 없습니다. 이것은 특징, 한계가 아님: 단순성은
우발적인 구성의 복잡성.
모든 Terraform 프로젝트의 기본 파일 e main.tf. 공통 컨벤션
구성을 다음 파일로 분리합니다.
progetto-terraform/
├── main.tf # Risorse principali
├── variables.tf # Dichiarazione variabili
├── outputs.tf # Output values
├── versions.tf # Required providers e terraform block
├── locals.tf # Valori locali computati
└── terraform.tfvars # Valori delle variabili (non committare se contiene segreti)
기본 블록 유형을 포함한 HCL의 기본 구조는 다음과 같습니다.
# versions.tf — blocco terraform: configura il comportamento del core
terraform {
required_version = ">= 1.8.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.100"
}
}
}
# variables.tf — dichiarazione variabili di input
variable "environment" {
description = "Nome dell'ambiente (dev, staging, prod)"
type = string
default = "dev"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "L'ambiente deve essere dev, staging o prod."
}
}
variable "aws_region" {
description = "AWS Region dove deployare le risorse"
type = string
default = "eu-west-1"
}
variable "instance_count" {
description = "Numero di istanze EC2 da creare"
type = number
default = 2
}
variable "tags" {
description = "Tag comuni da applicare a tutte le risorse"
type = map(string)
default = {
ManagedBy = "Terraform"
Project = "demo"
}
}
# locals.tf — valori computati a partire da variabili
locals {
# Naming convention uniforme
name_prefix = "${var.environment}-${var.tags["Project"]}"
# Merge tag comuni con tag specifici per risorsa
common_tags = merge(var.tags, {
Environment = var.environment
CreatedAt = timestamp()
})
}
AWS 공급자 구성
I 공급자 Terraform이 외부 API와 상호작용할 수 있게 해주는 플러그인입니다. AWS, Azure, GCP, Kubernetes, GitHub, Datadog 등 거의 모든 서비스에는 Terraform 공급자가 있습니다. AWS 공급자는 1,200개 이상의 리소스 유형을 지원하는 가장 성숙한 공급자입니다.
AWS 인증의 경우, HCL 코드에 하드코딩된 액세스 키를 사용하지 마세요.. AWS 공급자는 우선순위에 따라 다음 모드를 지원합니다.
# main.tf — configurazione provider AWS
provider "aws" {
region = var.aws_region
# NON fare questo in produzione:
# access_key = "AKIA..." # MAI
# secret_key = "..." # MAI
# Metodo consigliato 1: assume role (best practice per CI/CD)
# assume_role {
# role_arn = "arn:aws:iam::123456789:role/TerraformRole"
# }
# I tag di default vengono applicati a tutte le risorse
default_tags {
tags = local.common_tags
}
}
# Configurazione autenticazione (fuori da main.tf)
# La best practice e usare il file ~/.aws/credentials oppure
# variabili di ambiente:
# export AWS_ACCESS_KEY_ID="..."
# export AWS_SECRET_ACCESS_KEY="..."
# export AWS_DEFAULT_REGION="eu-west-1"
#
# In produzione: IAM Instance Profile o OIDC con GitHub Actions
이제 첫 번째 AWS 리소스인 퍼블릭 및 프라이빗 서브넷이 있는 VPC를 생성해 보겠습니다.
# main.tf — prime risorse AWS
# Data source: recupera gli AZ disponibili nella region
data "aws_availability_zones" "available" {
state = "available"
}
# VPC principale
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${local.name_prefix}-vpc"
}
}
# Subnet pubblica (una per AZ)
resource "aws_subnet" "public" {
count = min(length(data.aws_availability_zones.available.names), 2)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${local.name_prefix}-public-${count.index + 1}"
Tier = "Public"
}
}
# Subnet privata
resource "aws_subnet" "private" {
count = min(length(data.aws_availability_zones.available.names), 2)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index + 10)
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "${local.name_prefix}-private-${count.index + 1}"
Tier = "Private"
}
}
# Internet Gateway per le subnet pubbliche
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${local.name_prefix}-igw"
}
}
# Route table pubblica
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = {
Name = "${local.name_prefix}-rt-public"
}
}
# Associazione route table - subnet pubblica
resource "aws_route_table_association" "public" {
count = length(aws_subnet.public)
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
# outputs.tf — valori di output
output "vpc_id" {
description = "ID della VPC creata"
value = aws_vpc.main.id
}
output "public_subnet_ids" {
description = "IDs delle subnet pubbliche"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "IDs delle subnet private"
value = aws_subnet.private[*].id
}
계획-적용-폐기 주기
Terraform 수명 주기는 네 가지 기본 명령으로 구성됩니다. 그것들을 철저히 이해하라 생산 과정에서 가장 흔히 발생하는 사고를 피하는 것이 중요합니다.
테라폼 초기화
# Inizializza il working directory:
# - Scarica i provider (plugin binaries)
# - Configura il backend per lo state
# - Installa i moduli referenziati
terraform init
# Output atteso:
# Initializing the backend...
# Initializing provider plugins...
# - Finding hashicorp/aws versions matching "~> 5.0"...
# - Installing hashicorp/aws v5.54.1...
# Terraform has been successfully initialized!
# Upgrade dei provider all'ultima versione compatibile
terraform init -upgrade
# Ricrea il .terraform.lock.hcl (file di lock dei provider)
terraform providers lock -platform=linux_amd64 -platform=darwin_amd64
.terraform.lock.hcl 파일
파일 .terraform.lock.hcl 저장소에 커밋해야 합니다.
모든 팀 구성원과 CI 파이프라인이 정확히 동일한 것을 사용하도록 보장합니다.
인프라에 대해 "내 컴퓨터에서 작동"을 피하는 공급자 버전입니다.
디렉토리 .terraform/ 대신에 그것은 .gitignore.
테라폼 계획
# Genera il piano di esecuzione (DRY RUN)
terraform plan
# Salva il piano in un file binario (consigliato per CI/CD)
terraform plan -out=tfplan
# Specifica le variabili inline
terraform plan -var="environment=staging" -var="instance_count=3"
# Usa un file di variabili
terraform plan -var-file="staging.tfvars"
# Output tipico di plan:
# Terraform will perform the following actions:
#
# # aws_vpc.main will be created
# + resource "aws_vpc" "main" {
# + arn = (known after apply)
# + cidr_block = "10.0.0.0/16"
# + enable_dns_hostnames = true
# ...
# }
#
# Plan: 8 to add, 0 to change, 0 to destroy.
상징 + 생성을 나타냅니다. ~ 내부 편집,
-/+ 파괴 및 재생성(강제 가동 중지), - 파괴.
표시된 블록을 항상 주의 깊게 읽으십시오. -/+:
이는 리소스를 다시 생성해야 함을 의미하며, 이로 인해 가동 중지 시간이나 데이터 손실이 발생하는 경우가 많습니다.
테라폼 적용
# Applica le modifiche (chiede conferma interattiva)
terraform apply
# Applica il piano salvato (NON chiede conferma - usare in CI/CD)
terraform apply tfplan
# Auto-approve per ambienti non critici (attento in prod!)
terraform apply -auto-approve
# Apply con variabili
terraform apply -var="environment=prod" -var-file="prod.tfvars"
# Output dopo apply:
# Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
#
# Outputs:
# vpc_id = "vpc-0123456789abcdef0"
# public_subnet_ids = [
# "subnet-0abc123def456gh78",
# "subnet-0def456abc789ij01",
# ]
테라폼 파괴
# Distrugge TUTTE le risorse gestite dallo state corrente
terraform destroy
# Destroy con auto-approve (ATTENZIONE: irreversibile)
terraform destroy -auto-approve
# Distrugge solo una risorsa specifica (con grande cautela)
terraform destroy -target=aws_subnet.public[0]
# In produzione, preferisci eliminare le risorse dal codice
# e fare terraform apply: Terraform le distruggerà correttamente
안티 패턴: 프로덕션에서 테라폼 파괴
절대 뛰지 마세요 terraform destroy 복구 계획 없이.
가장 좋은 방법은 HCL 코드에서 리소스를 제거하고 다음을 실행하는 것입니다. terraform apply:
동일한 결과를 얻을 수 있지만 먼저 검토할 수 있는 명시적인 계획이 있어야 합니다.
일부 조직에서는 IAM 정책 수준에서 삭제를 실행하는 기능을 차단합니다.
생산 환경에서.
Azure 공급자 구성
공급자 하늘빛 Azure 리소스를 관리합니다. AWS와 달리, Azure는 인증을 위해 서비스 주체 또는 관리 ID를 사용합니다.
# versions.tf aggiornato con provider Azure
terraform {
required_version = ">= 1.8.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.100"
}
}
}
# Configurazione provider Azure
provider "azurerm" {
features {
resource_group {
prevent_deletion_if_contains_resources = true
}
key_vault {
purge_soft_delete_on_destroy = false
recover_soft_deleted_key_vaults = true
}
}
# Autenticazione via variabili d'ambiente (consigliato)
# ARM_CLIENT_ID, ARM_CLIENT_SECRET, ARM_TENANT_ID, ARM_SUBSCRIPTION_ID
# oppure Azure CLI: az login
}
# Risorse Azure di base
resource "azurerm_resource_group" "main" {
name = "${local.name_prefix}-rg"
location = "West Europe"
tags = local.common_tags
}
resource "azurerm_virtual_network" "main" {
name = "${local.name_prefix}-vnet"
address_space = ["10.1.0.0/16"]
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
tags = local.common_tags
}
resource "azurerm_subnet" "public" {
name = "public-subnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.1.1.0/24"]
}
resource "azurerm_subnet" "private" {
name = "private-subnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.1.2.0/24"]
}
변수, 지역 및 데이터 소스
변수, 로컬 및 데이터 소스를 잘 사용하면 Terraform 구성이 구별됩니다. 임시 스크립트의 전문가. 기본 패턴은 다음과 같습니다.
# Tipi di variabili in HCL
# Stringa semplice
variable "app_name" {
type = string
default = "myapp"
}
# Numero con validazione
variable "min_instances" {
type = number
default = 1
validation {
condition = var.min_instances >= 1 && var.min_instances <= 10
error_message = "Il numero di istanze deve essere tra 1 e 10."
}
}
# Lista di stringhe
variable "allowed_cidr_blocks" {
type = list(string)
default = ["10.0.0.0/8"]
}
# Map di stringhe
variable "database_config" {
type = map(string)
default = {
engine = "postgres"
version = "15.4"
size = "db.t3.medium"
}
}
# Oggetto con schema tipizzato
variable "network_config" {
type = object({
vpc_cidr = string
subnet_count = number
enable_nat = bool
})
default = {
vpc_cidr = "10.0.0.0/16"
subnet_count = 2
enable_nat = false
}
}
# Locals: valori computati (non input dall'utente)
locals {
# Concatenazioni
full_name = "${var.environment}-${var.app_name}"
# Condizionale ternario
instance_type = var.environment == "prod" ? "t3.medium" : "t3.micro"
# Ciclo su lista (for expression)
subnet_cidrs = [
for i in range(var.network_config.subnet_count) :
cidrsubnet(var.network_config.vpc_cidr, 8, i)
]
# Map transformation
tag_map = {
for k, v in var.database_config :
"db_${k}" => v
}
}
# Data sources: recuperano informazioni da risorse esistenti
# non gestite da questo state
# AMI Amazon Linux 2023 piu recente
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# Account ID corrente (utile per ARN)
data "aws_caller_identity" "current" {}
# Uso nei resource:
# ami = data.aws_ami.amazon_linux.id
# account_id = data.aws_caller_identity.current.account_id
상태 파일: Terraform의 핵심
파일 terraform.tfstate Terraform의 "진실의 원천": 모든 자산을 매핑합니다.
HCL에서 클라우드의 실제 대응으로 정의됩니다. 작동 방식을 이해하는 것이 중요합니다.
가장 심각한 문제를 피하십시오.
// Struttura semplificata di terraform.tfstate
{
"version": 4,
"terraform_version": "1.9.0",
"serial": 42,
"lineage": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"outputs": {
"vpc_id": {
"value": "vpc-0123456789abcdef0",
"type": "string"
}
},
"resources": [
{
"mode": "managed",
"type": "aws_vpc",
"name": "main",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"id": "vpc-0123456789abcdef0",
"cidr_block": "10.0.0.0/16",
"enable_dns_hostnames": true,
...
}
}
]
}
]
}
상태 파일에 대한 황금률
- 수정하지 않음
terraform.tfstate수동으로 - 커밋하지 않음 Git 저장소에 명시하세요(다음에 추가하세요).
.gitignore) - 팀에서는 다음을 사용하세요. 항상 원격 백엔드 잠금 기능 있음(시리즈 03 참조)
- 상태는 그것을 포함할 수 있다 공개된 비밀 (RDS 비밀번호, 자격 증명): 민감한 데이터로 처리하세요.
- 위험한 작업을 하기 전에, 수동 백업 수행:
terraform state pull > backup.tfstate
국가검사명령
# Lista tutte le risorse gestite dallo state
terraform state list
# Mostra i dettagli di una risorsa specifica
terraform state show aws_vpc.main
# Rinomina una risorsa nello state (senza toccare l'infrastruttura)
terraform state mv aws_subnet.public aws_subnet.public_new
# Rimuove una risorsa dallo state (Terraform non la gestirà piu)
# La risorsa rimane nel cloud ma non è piu "owned" da Terraform
terraform state rm aws_subnet.private[0]
# Importa una risorsa esistente nello state
# (vedi articolo 03 per dettagli)
terraform import aws_vpc.main vpc-0123456789abcdef0
# Mostra l'output senza fare apply
terraform output vpc_id
terraform output -json # tutti gli output in formato JSON
권장 프로젝트 구조
실제 프로젝트의 경우 단일 디렉터리 구조는 금방 관리하기 어려워집니다. 프로덕션 환경에서 Terraform 인프라를 구성하기 위한 두 가지 일반적인 패턴은 다음과 같습니다.
# Pattern 1: Organizzazione per ambiente
infra/
├── modules/ # Moduli riusabili
│ ├── networking/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── compute/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── environments/
│ ├── dev/
│ │ ├── main.tf # Usa i moduli
│ │ ├── variables.tf
│ │ ├── terraform.tfvars # Valori specifici per dev
│ │ └── versions.tf
│ ├── staging/
│ │ └── ...
│ └── prod/
│ └── ...
└── .gitignore # Esclude .terraform/, *.tfstate
# Pattern 2: Terragrunt (wrapper per DRY)
infra/
├── terragrunt.hcl # Config globale
├── modules/
│ └── networking/
├── live/
│ ├── dev/
│ │ └── networking/
│ │ └── terragrunt.hcl
│ └── prod/
│ └── networking/
│ └── terragrunt.hcl
시작을 위한 모범 사례
이론을 살펴본 후 Terraform을 사용하는 사람들을 구별하는 경험 법칙은 다음과 같습니다. 첫날부터 기술적 부채를 생성하는 사람들의 말은 다음과 같습니다.
# 1. Formatta sempre prima di committare
terraform fmt -recursive
# 2. Valida la sintassi
terraform validate
# 3. Usa tflint per linting avanzato (trova deprecazioni, pattern errati)
tflint --init
tflint
# 4. Esegui checkov per security scanning
pip install checkov
checkov -d .
# 5. Pre-commit hooks per automatizzare tutto
# .pre-commit-config.yaml
# repos:
# - repo: https://github.com/antonbabenko/pre-commit-terraform
# hooks:
# - id: terraform_fmt
# - id: terraform_validate
# - id: terraform_tflint
# - id: terraform_checkov
Terraform용 .gitignore
# .gitignore per progetti Terraform
.terraform/
*.tfstate
*.tfstate.backup
*.tfstate.*.backup
.terraform.tfstate.lock.info
*.tfvars # Se contengono segreti (crea terraform.tfvars.example)
override.tf
override.tf.json
*_override.tf
*_override.tf.json
crash.log
.terraformrc
terraform.rc
전체 예: AWS의 웹 앱
실제 예인 보안 그룹이 있는 EC2 인스턴스로 모든 것을 통합해 보겠습니다. 로드 밸런서 및 RDS 데이터베이스가 올바르게 구성되어 있습니다.
# main.tf — infrastruttura web app completa
# Security Group per le istanze web
resource "aws_security_group" "web" {
name = "${local.name_prefix}-sg-web"
description = "Security group per istanze web"
vpc_id = aws_vpc.main.id
ingress {
description = "HTTP dal load balancer"
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = { Name = "${local.name_prefix}-sg-web" }
}
# Security Group per ALB
resource "aws_security_group" "alb" {
name = "${local.name_prefix}-sg-alb"
description = "Security group per Application Load Balancer"
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# Launch Template per le istanze EC2
resource "aws_launch_template" "web" {
name_prefix = "${local.name_prefix}-lt-"
image_id = data.aws_ami.amazon_linux.id
instance_type = local.instance_type
network_interfaces {
associate_public_ip_address = false
security_groups = [aws_security_group.web.id]
}
user_data = base64encode(<<-EOF
#!/bin/bash
dnf update -y
dnf install -y nginx
systemctl enable nginx
systemctl start nginx
echo "Deploy Terraform - ${var.environment}
" > /usr/share/nginx/html/index.html
EOF
)
tag_specifications {
resource_type = "instance"
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-web"
})
}
}
# Auto Scaling Group
resource "aws_autoscaling_group" "web" {
name = "${local.name_prefix}-asg"
vpc_zone_identifier = aws_subnet.private[*].id
target_group_arns = [aws_lb_target_group.web.arn]
health_check_type = "ELB"
min_size = var.environment == "prod" ? 2 : 1
max_size = var.environment == "prod" ? 6 : 2
desired_capacity = var.environment == "prod" ? 2 : 1
launch_template {
id = aws_launch_template.web.id
version = "$Latest"
}
tag {
key = "Name"
value = "${local.name_prefix}-web"
propagate_at_launch = true
}
}
# Application Load Balancer
resource "aws_lb" "main" {
name = "${local.name_prefix}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = aws_subnet.public[*].id
enable_deletion_protection = var.environment == "prod"
tags = local.common_tags
}
resource "aws_lb_target_group" "web" {
name = "${local.name_prefix}-tg-web"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.main.id
health_check {
enabled = true
healthy_threshold = 2
unhealthy_threshold = 3
timeout = 5
interval = 30
path = "/health"
}
}
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.main.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.web.arn
}
}
결론 및 다음 단계
이제 Terraform을 전문적으로 사용하기 위한 탄탄한 기반이 마련되었습니다. 구문을 알고 계셨습니다. HCL, 당신은 AWS 및 Azure 공급자를 구성하는 방법을 알고 있으며 계획-적용-폐기 주기와 규칙을 이해하고 있습니다. 상태 파일을 안전하게 관리하려면 필수적입니다.
Terraform을 통한 성장의 다음 자연스러운 단계는 코드 구성 방법을 배우는 것입니다. 안으로 재사용 가능한 모듈: 인프라가 200-300라인을 초과하는 경우 HCL의 경우 유지 관리를 위해 모듈화가 필수적입니다.
전체 시리즈: Terraform 및 IaC
- 제01조(본) — 처음부터 새로 만드는 Terraform: HCL, 공급자 및 계획-적용-파괴
- 제02조 — 재사용 가능한 Terraform 모듈 설계: 구조, I/O 및 레지스트리
- 제03조 — Terraform 상태: S3/GCS, 잠금 및 가져오기를 포함한 원격 백엔드
- 기사 04 — CI/CD의 Terraform: GitHub Actions, Atlantis 및 Pull Request Workflow
- 조항 05 — IaC 테스트: Terratest, Terraform 기본 테스트 및 계약 테스트
- 06조 — IaC 보안: Checkov, Trivy 및 OPA Policy-as-Code
- 기사 07 — Terraform 다중 클라우드: AWS + Azure + 공유 모듈이 있는 GCP
- 기사 08 — Terraform용 GitOps: Flux TF 컨트롤러, Spacelift 및 드리프트 감지
- 기사 09 — Terraform vs Pulumi vs OpenTofu: 2026년 최종 비교
- 기사 10 — Terraform 엔터프라이즈 패턴: 작업 공간, Sentinel 및 팀 확장
공식 리소스
- Terraform 공식 문서
- Terraform 레지스트리 — 공급자, 모듈 및 정책
- HashiCorp Learn — 대화형 튜토리얼







