Infrastructure as Code: Mastering Terraform
Infrastructure as Code: Mastering Terraform
In the modern cloud era, clicking through web consoles to provision servers, databases, and networks is an anti-pattern. Manual provisioning is slow, error-prone, and nearly impossible to replicate perfectly across environments. Enter Infrastructure as Code (IaC), and its undisputed king: Terraform.
Terraform by HashiCorp is an open-source tool that allows you to define both cloud and on-premise resources in human-readable configuration files that you can version, reuse, and share.
Part 1: The Core Philosophy of Terraform
Declarative vs. Imperative
Terraform is declarative. You don’t write scripts telling the system how to create resources (e.g., “create a VPC, then create a subnet, then launch an EC2 instance”). Instead, you describe the desired end state.
Terraform compares your desired state with the current actual state of the infrastructure and determines the exact steps needed to bridge the gap.
The Holy Trinity: Code, Plan, State
To understand Terraform, you must understand its three pillars:
- Code (.tf files): The blueprints written in HashiCorp Configuration Language (HCL).
- State (.tfstate): The database where Terraform records what infrastructure it has created. This is how Terraform knows what exists.
- Plan: The execution plan generated by comparing the Code and the State. It shows you exactly what will be added, changed, or destroyed before you apply it.
Part 2: Essential Terraform Workflow
Every Terraform interaction revolves around the core workflow:
1
2
3
4
5
6
7
8
9
10
11
12
# 1. Initialize the working directory and download provider plugins
terraform init
# 2. Format and validate your code
terraform fmt
terraform validate
# 3. See what changes will be made (Dry Run)
terraform plan
# 4. Execute the changes
terraform apply
Understanding Providers
Terraform doesn’t talk to AWS, Azure, or GCP natively. It uses Providers — plugins that translate HCL into API calls for the specific platform.
1
2
3
4
5
6
7
8
9
10
11
12
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-2"
}
Part 3: Engineering Best Practices
Writing Terraform is easy. Writing maintainable and scalable Terraform requires discipline.
1. State Management is Critical
Never store your terraform.tfstate file in local git repositories. The state file contains sensitive information (including database passwords in plain text) and requires locking to prevent concurrent modifications by multiple engineers.
Use a Remote Backend (e.g., AWS S3 + DynamoDB):
1
2
3
4
5
6
7
8
9
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "prod/infrastructure.tfstate"
region = "ap-northeast-2"
dynamodb_table = "terraform-state-locks"
encrypt = true
}
}
2. Don’t Repeat Yourself: Use Modules
Instead of copying and pasting VPC configurations, create reusable Modules. Think of modules as functions in programming.
1
2
3
4
5
6
7
8
9
10
11
12
13
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.0.0"
name = "production-vpc"
cidr = "10.0.0.0/16"
azs = ["ap-northeast-2a", "ap-northeast-2c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
}
3. Separate Environments Properly
Do not use the same state file for Staging and Production. If an apply fails or corrupts the state, it shouldn’t impact production.
Recommended Directory Structure:
1
2
3
4
5
6
7
8
9
10
11
12
environments/
├── staging/
│ ├── main.tf
│ ├── variables.tf
│ └── terraform.tfvars
└── production/
├── main.tf
├── variables.tf
└── terraform.tfvars
modules/
├── vpc/
└── eks/
4. Variables and Outputs
Hardcoding values is a red flag. Parameterize your configurations.
1
2
3
4
5
6
7
8
9
10
11
variable "instance_type" {
description = "EC2 instance type for worker nodes"
type = string
default = "t3.medium"
}
output "database_endpoint" {
description = "The connection endpoint for the RDS instance"
value = aws_db_instance.main.endpoint
sensitive = true # Masks the output in console logs
}
Conclusion
Terraform bridges the gap between infrastructure operations and software engineering. By treating infrastructure as version-controlled code, cloud engineers can implement CI/CD for infrastructure, conduct code reviews for architecture changes, and ensure disaster recovery is as simple as running terraform apply.
코드로서의 인프라: Terraform 마스터하기
현대 클라우드 시대에 웹 콘솔을 클릭하며 서버, 데이터베이스, 네트워크를 프로비저닝하는 것은 안티 패턴입니다. 수동 프로비저닝은 느리고, 오류가 발생하기 쉬우며, 여러 환경에서 완벽하게 동일하게 복제하는 것이 거의 불가능합니다. 이를 해결하기 위해 등장한 것이 코드로서의 인프라(IaC, Infrastructure as Code)이며, 그 분야의 절대적인 강자가 바로 Terraform(테라폼)입니다.
HashiCorp에서 만든 Terraform은 클라우드 및 온프레미스 리소스를 사람이 읽을 수 있는 설정 파일로 정의할 수 있게 해주는 오픈 소스 도구입니다. 이 파일들은 버전 관리가 가능하고, 재사용할 수 있으며, 팀원들과 공유할 수 있습니다.
Part 1: Terraform의 핵심 철학
선언적(Declarative) vs 절차적(Imperative)
Terraform은 선언적입니다. 시스템에 리소스를 어떻게 생성할지 지시하는 스크립트를 작성하지 않습니다 (예: “VPC를 만들고, 서브넷을 만들고, EC2를 띄워라”). 대신 원하는 최종 상태(Desired State)를 설명합니다.
Terraform은 여러분이 선언한 상태와 현재 인프라의 실제 상태를 비교하여, 그 차이를 메우기 위해 필요한 정확한 작업 단계를 스스로 결정합니다.
삼위일체: Code, Plan, State
Terraform을 제대로 이해하려면 다음 세 가지 핵심 기둥을 이해해야 합니다:
- Code (.tf 파일): HCL(HashiCorp Configuration Language)로 작성된 설계도입니다.
- State (.tfstate): Terraform이 자신이 생성한 인프라를 기록해두는 데이터베이스입니다. Terraform은 이 파일을 통해 현재 무엇이 존재하는지 파악합니다.
- Plan: Code와 State를 비교하여 생성된 실행 계획입니다. 실제 적용(Apply)하기 전에 무엇이 추가, 변경, 삭제될지 정확히 보여줍니다.
Part 2: 필수 Terraform 워크플로우
모든 Terraform 작업은 다음의 핵심 워크플로우를 중심으로 돌아갑니다:
1
2
3
4
5
6
7
8
9
10
11
12
# 1. 작업 디렉토리 초기화 및 Provider 플러그인 다운로드
terraform init
# 2. 코드 포맷팅 및 문법 검증
terraform fmt
terraform validate
# 3. 어떤 변경이 발생할지 확인 (Dry Run)
terraform plan
# 4. 변경 사항 실제 적용
terraform apply
Provider의 이해
Terraform은 AWS, Azure, GCP와 직접 통신하지 않습니다. 대신 Provider(프로바이더)라는 플러그인을 사용하여 HCL 코드를 특정 플랫폼의 API 호출로 번역합니다.
Part 3: 엔지니어링 모범 사례
Terraform 코드를 작성하는 것은 쉽습니다. 하지만 유지보수 가능하고 확장 가능한 Terraform을 작성하려면 원칙이 필요합니다.
1. State 관리는 매우 중요합니다
절대로 terraform.tfstate 파일을 로컬 Git 레포지토리에 저장하지 마세요. State 파일에는 평문 형태의 데이터베이스 비밀번호를 포함한 민감한 정보가 들어있으며, 여러 엔지니어가 동시에 수정하는 것을 막기 위해 Lock(잠금) 메커니즘이 필요합니다.
원격 백엔드 사용 (예: AWS S3 + DynamoDB): 안전한 State 저장 및 Lock 관리를 위해 S3와 DynamoDB를 조합하여 사용하는 것이 업계 표준입니다.
2. 반복을 피하세요 (DRY): Module 사용
VPC 설정을 매번 복사해서 붙여넣는 대신, 재사용 가능한 Module(모듈)을 만드세요. 프로그래밍에서의 함수(Function)라고 생각하면 됩니다. HashiCorp 공식 레지스트리에서 검증된 모듈을 가져다 쓸 수도 있습니다.
3. 환경의 완전한 분리
Staging(스테이징)과 Production(운영) 환경에서 같은 State 파일을 공유하지 마세요. Apply가 실패하거나 State 파일이 손상되었을 때 운영 환경에 영향을 미쳐서는 안 됩니다. 디렉토리 구조를 물리적으로 분리하여 환경별로 독립적인 State를 유지해야 합니다.
4. Variables와 Outputs의 활용
하드코딩은 피해야 합니다. 설정을 매개변수화(Parameterization)하세요. 민감한 출력값의 경우 sensitive = true 옵션을 사용하여 콘솔 로그에 평문으로 노출되는 것을 방지할 수 있습니다.
결론
Terraform은 인프라 운영과 소프트웨어 엔지니어링 사이의 격차를 해소합니다. 인프라를 버전 관리가 가능한 코드로 취급함으로써, 클라우드 엔지니어들은 인프라에 대한 CI/CD를 구현하고, 아키텍처 변경 사항에 대해 코드 리뷰를 진행하며, 단지 terraform apply를 실행하는 것만으로 재해 복구(DR)를 완수할 수 있게 되었습니다.