Terraform Từ Cơ Bản Đến Thực Chiến
Học Terraform từ con số không tới khi dựng được hạ tầng AWS đa môi trường qua CI/CD. Series đi qua HCL, provider và resource, state và remote state với S3, biến và biểu thức, modules, đa môi trường, lifecycle, kiểm thử và pipeline — khép lại bằng một dự án capstone hoàn chỉnh. Mọi lệnh chạy thật trên AWS, code lưu tại github.com/nghiadaulau/terraform-series. Bám docs chính thức HashiCorp, Terraform 1.15 và AWS provider v6.
Infrastructure as Code, Terraform Là Gì, và Làm Quen CLI
Bài mở đầu series: vì sao quản lý hạ tầng bằng tay sớm muộn cũng vỡ, Infrastructure as Code giải quyết điều gì, Terraform đứng ở đâu trong bức tranh đó. Mổ kiến trúc core và provider, cài Terraform 1.15, và đi một vòng các lệnh CLI chính.
Provider, Resource Đầu Tiên, và Vòng Đời init plan apply destroy
Dựng resource AWS thật đầu tiên: khai báo provider và pin phiên bản, tạo một bucket S3, rồi đi trọn vòng init → plan → apply → destroy. Mỗi lệnh làm gì bên trong, vì sao plan ghi 'known after apply', state lưu cái gì, và vì sao chạy apply lần hai không tạo thêm gì.
HCL Từ Trong Ra Ngoài: Block, Kiểu Dữ Liệu, Biểu Thức
Mổ xẻ ngôn ngữ HCL cho ra ngọn ngành: cấu trúc một block gồm gì, các kiểu dữ liệu string/number/bool/list/map/null, biểu thức và hàm, cách nội suy chuỗi. Dùng terraform console để thử trực tiếp, và xem block terraform{} còn khai báo được những gì.
State: Terraform Lưu Gì, Vì Sao Cần, và Drift
Đào vào file state: vì sao Terraform cần nó thay vì hỏi thẳng AWS mỗi lần, nó lưu chính xác cái gì, và cơ chế refresh so ba chiều giữa cấu hình, state và thực tế. Tự tay tạo drift bằng AWS CLI rồi xem Terraform phát hiện ra sao, khác nhau giữa plan thường và plan -refresh-only.
Đồ Thị Phụ Thuộc: Implicit, depends_on, và -target
Terraform tự suy ra thứ tự tạo và xóa resource từ một đồ thị phụ thuộc. Bài này mổ chính đồ thị đó: phụ thuộc ngầm sinh ra từ tham chiếu, xem trực tiếp bằng lệnh graph, vì sao destroy đảo ngược thứ tự, khi nào cần depends_on, và vì sao -target chỉ là lối thoát hiểm.
Remote State Trên S3 Với use_lockfile
State nằm trên máy cá nhân không chia sẻ được, không an toàn, và hai người chạy cùng lúc sẽ ghi đè nhau. Bài này chuyển state lên S3: bootstrap một bucket có versioning và mã hóa, cấu hình backend, và bật khóa state bằng use_lockfile — cách hiện hành thay cho DynamoDB đã lỗi thời. Có demo xung đột lock thật.
Thao Tác State: import Block, state mv, state rm
Làm việc với state hằng ngày: đưa hạ tầng có sẵn vào quản lý bằng import block và tự sinh cấu hình với -generate-config-out, đổi tên resource trong state bằng state mv, và gỡ resource khỏi quản lý mà không xóa nó bằng state rm. Tất cả chạy thật trên một bucket dựng tay từ trước.
Secrets: sensitive, ephemeral, và Write-Only Arguments
State lưu secret ở dạng plaintext — bài này xử lý đúng vấn đề đó. sensitive chỉ che output chứ vẫn ghi vào state; ephemeral resources và write-only arguments (Terraform 1.10/1.11) mới thực sự giữ secret khỏi state. Demo thật: cùng một mật khẩu, cách cũ lọt vào state còn write-only thì không.
Variable, Output, Locals và Kiểm Tra Giá Trị Sớm
Tham số hóa cấu hình để cùng một code chạy cho nhiều môi trường: variable nhận đầu vào, output trả kết quả, locals đặt tên cho biểu thức dẫn xuất. Quan trọng hơn là bắt lỗi sớm — validation chặn input sai ngay ở plan, precondition và postcondition kiểm giả định quanh mỗi resource.
Data Source, Hàm, Biểu Thức for và Dynamic Block
Đọc thông tin có sẵn trên AWS bằng data source (AMI mới nhất, vùng khả dụng, tài khoản hiện tại), biến đổi và lọc dữ liệu bằng biểu thức for, rồi sinh các block lồng lặp lại bằng dynamic block. Một security group với rule ingress sinh tự động từ danh sách cổng làm ví dụ xuyên suốt.
count và for_each: Cạm Bẫy Chỉ Số, Conditional, templatefile
Hai cách tạo nhiều resource: count theo chỉ số và for_each theo khóa. Bài này chỉ ra cạm bẫy thực tế khi dùng count với một danh sách — bỏ một phần tử giữa làm dịch chỉ số và xóa-tạo lại nhầm hàng loạt — bằng demo thật, rồi cho thấy for_each tránh được. Kèm tạo resource có điều kiện và templatefile.
Viết Module Đầu Tiên
Module đóng gói một nhóm resource sau một giao diện input/output sạch, để dùng lại nhiều nơi mà không chép code. Bài này viết một module 'secure-bucket' gói bucket S3 cùng versioning, mã hóa và chặn public thành một khái niệm, rồi gọi nó hai lần từ root với đầu vào khác nhau.