Bài giảng: hiểu luồng trước khi chạy lệnh
Bài toán: Dùng input variable, validation, output, count, for expression và function để tránh copy-paste cấu hình giữa các môi trường.
terraform fmt
terraform init
terraform validate
terraform plan
terraform apply
terraform plan -destroy
terraform destroyInput variable: biến cấu hình, không phải secret store
Đặt phần thay đổi theo môi trường vào variables.tf:
variable "instance_count" {
type = number
description = "Số EC2 cần chạy"
default = 1
validation {
condition = var.instance_count >= 1 && var.instance_count <= 5
error_message = "instance_count phải từ 1 đến 5 trong lab này."
}
}
variable "instance_type" {
type = string
default = "t3.micro"
}
Gán giá trị bằng terraform.tfvars, file -var, hoặc biến môi trường TF_VAR_instance_type. Không đưa password và access key vào tfvars rồi commit; sensitive = true chỉ che output/log hiển thị, không mã hóa state.
# dev.tfvars
instance_count = 2
instance_type = "t3.micro"
terraform plan -var-file=dev.tfvars
Output: xuất thông tin cần dùng
output "instance_ids" {
description = "ID các EC2 được tạo"
value = aws_instance.app[*].id
}
Sau apply, terraform output instance_ids có thể được script khác đọc. Output nhạy cảm nên khai báo sensitive = true.
count, for và function
resource "aws_instance" "app" {
count = var.instance_count
ami = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
tags = {
Name = format("app-%02d", count.index + 1)
}
}
Với danh sách đã có, for tạo một map dễ dùng:
variable "team_names" {
type = list(string)
default = ["api", "worker", "frontend"]
}
locals {
team_tags = {
for name in var.team_names : name => upper(name)
}
}
count phù hợp khi các instance gần như giống nhau. Nếu mỗi phần tử có identity riêng và thứ tự có thể thay đổi, for_each thường an toàn hơn vì Terraform theo dõi theo key thay vì index.
Variable, local và output khác nhau thế nào?
- Variable là input từ người gọi/root module hoặc environment.
- Local là giá trị trung gian được tính bên trong module, ví dụ quy ước tên/tag.
- Output là contract trả thông tin ra ngoài module hoặc cho pipeline.
Đừng dùng variable cho mọi thứ. Ví dụ name_prefix có thể là input, còn map tag đầy đủ nên là local:
variable "name_prefix" { type = string }
variable "environment" { type = string }
locals {
common_tags = {
Project = var.name_prefix
ManagedBy = "terraform"
Environment = var.environment
}
}
Khi đổi từ count sang for_each, địa chỉ resource thay đổi (aws_instance.app[0] thành aws_instance.app["api"]). Hãy đọc phần replace trong plan và cân nhắc moved block để giữ resource hiện có, thay vì vô tình destroy/recreate.
Bài tập nhỏ
Hãy mở rộng ví dụ để nhận environment, thêm tag Environment, rồi tạo hai plan với dev.tfvars và prod.tfvars. So sánh plan trước khi apply. Mục tiêu không phải tạo thật nhiều EC2 mà là học cách một cấu hình dùng lại được.
Expected state và failure drills
Dùng resource test rẻ hoặc chỉ chạy plan. Với dev.tfvars, expected state là số lượng/key/tag đúng; với prod.tfvars, plan phải khác có chủ đích nhưng không lẫn environment, secret hoặc provider region. Output ID phải khớp resource address; output chứa credential/token phải sensitive = true và state vẫn được bảo vệ.
Thực hiện các drill:
- Truyền
instance_count = 0,6, sai type và thiếu bắt buộc; ghi validation/type error và xác nhận không có apply. - Đổi thứ tự list khi dùng
count, xem address/index churn; chuyển bản sao sangfor_eachvới key ổn định, đọc plan và viếtmovedblock nếu cần giữ resource. - Xóa một key khỏi map
for_each, kiểm tra resource address nào bị destroy; không approve nếu key bị xóa chỉ vì typo. - Đánh dấu output sensitive, chạy
terraform output/showvà kiểm tra giá trị không xuất hiện ở terminal/artifact công khai; nhớ sensitive không mã hóa state.
Quality gate
Pass khi người học giải thích variable/local/output boundary, validation/type behavior, count index risk và for_each key identity; tạo được hai plan reproducible, đọc replacement/destroy trước approval, dùng moved khi migration phù hợp và cleanup chỉ resource test sau plan -destroy. tfvars/output/plan không được chứa credential thật.