Terraform
← Tổng quan series

Workspace và file cấu hình Terraform

Tạo một project Terraform có version pinning, chạy plan/apply có kiểm soát và hiểu data source trong một cấu hình thực tế.

Instructor walkthrough

Bài giảng: hiểu luồng trước khi chạy lệnh

Bài toán: Tạo một project Terraform có version pinning, chạy plan/apply có kiểm soát và hiểu data source trong một cấu hình thực tế.

01Chuẩn bịkiểm tra account, region, provider và chi phí
02Đọc planđối chiếu resource address, diff và dependency
03Thực hànhapply mutation nhỏ trong sandbox, lưu evidence
04Khôi phụcre-run, failure drill, destroy hoặc rollback
Command reference · baseline
terraform fmt
terraform init
terraform validate
terraform plan
terraform apply
terraform plan -destroy
terraform destroy

Một workspace nhỏ nhưng đúng chuẩn

Một thư mục Terraform thường là một root module: nơi chứa các file .tf và là nơi ta chạy lệnh. Terraform đọc tất cả file .tf trong thư mục, vì vậy có thể tách versions.tf, provider.tf, main.tf, variables.tf để dễ đọc; không cần import giữa các file.

infra-dev/
├── versions.tf
├── provider.tf
├── main.tf
└── .gitignore

versions.tf nên khóa provider để máy local và CI không tự kéo phiên bản khác nhau:

terraform {
  required_version = ">= 1.9.0, < 2.0.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

Vòng đời một lần thay đổi

terraform init       # tải provider, khởi tạo backend
terraform fmt -check # CI kiểm tra format
terraform validate   # kiểm tra cú pháp và kiểu
terraform plan       # xem dự kiến thay đổi
terraform apply      # thực thi plan

plan không chỉ để “xem cho biết”. Hãy lưu plan trong CI để bước apply dùng đúng thứ đã review:

terraform plan -out=tfplan
terraform show -no-color tfplan
terraform apply tfplan

Không nên lưu tfplan vào artifact công khai vì nó có thể chứa dữ liệu nhạy cảm.

Ví dụ cấu hình có input và data source

variable "aws_region" {
  type    = string
  default = "ap-southeast-1"
}

provider "aws" {
  region = var.aws_region
}

data "aws_availability_zones" "available" {
  state = "available"
}

resource "aws_vpc" "main" {
  cidr_block           = "10.20.0.0/16"
  enable_dns_hostnames = true

  tags = { Name = "demo-vpc" }
}

data không tạo availability zone mới; nó truy vấn danh sách AWS đang có. Khi một resource tham chiếu aws_vpc.main.id, Terraform tự hiểu dependency và tạo VPC trước.

Những lỗi người mới hay gặp

  • Chạy Terraform ở sai thư mục nên không thấy file cấu hình.
  • Không commit .terraform.lock.hcl: file này nên commit để khóa checksum provider.
  • Hard-code AMI ID từ region khác. Hãy dùng data "aws_ami" hoặc biến theo môi trường.
  • Dùng apply -auto-approve ngay từ lần đầu, bỏ qua plan.

.gitignore tối thiểu:

.terraform/
*.tfstate
*.tfstate.*
tfplan
*.tfvars
!example.tfvars

Một plan tốt phải trả lời được ba câu hỏi

Trước khi approve, hãy chỉ ra được: resource nào sẽ đổi, vì sao nó đổi và tác động có thể là gì. Với thay đổi có nguy cơ recreate, dùng thêm:

terraform show -json tfplan > tfplan.json

File JSON phù hợp cho policy checker, nhưng không nên upload công khai. Trong code review, hãy yêu cầu người viết nêu rõ nếu plan có destroy, replace, thay đổi security group hoặc thay đổi database.

Nếu terraform init báo provider lock không khớp, không xóa .terraform.lock.hcl để chữa cháy. Kiểm tra Terraform version, architecture runner và chạy terraform providers lock theo quy trình của team.

Lab acceptance và failure drills

Tạo hai thư mục độc lập infra-devinfra-review để chứng minh Terraform làm việc theo root module hiện tại, không theo tên file. Expected state sau preflight là: fmt -check, init, validate pass; .terraform.lock.hcl được tạo và review; plan chỉ đọc đúng region/provider và không có thay đổi ngoài scope.

Thực hiện các drill sau trước khi apply:

  1. Chạy terraform ở thư mục cha hoặc thư mục rỗng, ghi lỗi “no configuration files” rồi quay lại root module đúng; không copy state sang thư mục khác để chữa.
  2. Đổi required_providers hoặc Terraform version trong một branch lab, chạy init và ghi lock/checksum/version mismatch; khôi phục bằng thay đổi có review, không xóa lock file tùy tiện.
  3. Tạo tfplan, xem human-readable và JSON output, kiểm tra plan không chứa destroy/replace ngoài ý muốn; xác nhận artifact không được public và apply dùng đúng plan đã review.

Sau khi apply resource lab, sửa một input có chủ ý, chạy plan, review dependency và chạy terraform plan -refresh-only nếu cần phân biệt drift với code change. Expected state cuối là plan no-op hoặc gap được giải thích, lock file ổn định và .gitignore không theo dõi state/credentials. Nếu backend remote được thêm ở bài sau, không coi local state copy là migration; cần backup và terraform init -migrate-state có approval.

Quality gate

Pass khi người học có thể giải thích root module/provider lock/backend boundary, tái chạy plan trên runner khác mà không tự đổi provider, phát hiện sai thư mục/lock/plan artifact và chứng minh apply/review/cleanup không làm lộ state. Các lệnh init, validate, plan không tạo phí; apply phụ thuộc resource cấu hình.