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ế.
terraform fmt
terraform init
terraform validate
terraform plan
terraform apply
terraform plan -destroy
terraform destroyMộ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-approvengay 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-dev và infra-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:
- 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. - Đổi
required_providershoặc Terraform version trong một branch lab, chạyinitvà 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. - 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.