Claude Code là một trong những agentic coding tool (công cụ lập trình bằng agent) tích hợp MCP mượt nhất hiện nay, hoạt động cả ở terminal (CLI) và bên trong VS Code qua extension. Khi kết hợp với Terraform MCP server, bạn có một trợ lý có thể đọc HCL, giải thích plan diff, và viết module Terraform tái sử dụng được — miễn là bạn setup đúng và biết cách prompt. Bài này hướng dẫn từng bước: cài đặt, cách để agent đọc plan an toàn, sinh module chuẩn, và phát hiện configuration drift (lệch cấu hình) giữa state và hạ tầng thật.
Cài Đặt Và Kết Nối Terraform MCP Vào Claude Code
Claude Code đọc MCP server config từ file .claude/settings.json (project-level) hoặc ~/.claude.json (user-level, áp dụng cho mọi project). Với công việc liên quan hạ tầng, nên khai báo ở project-level để tránh agent vô tình có quyền truy cập infra của project khác.
npm install -g terraform-mcp-server
go install github.com/hashicorp/terraform-mcp-server/cmd/terraform-mcp-server@latest
Thêm vào .claude/settings.json trong repo infra:
{
"mcpServers": {
"terraform": {
"command": "terraform-mcp-server",
"args": ["--workdir", "${workspaceFolder}/infra/prod"],
"env": {
"AWS_PROFILE": "terraform-agent-readonly"
}
}
}
}
Kiểm tra kết nối bằng lệnh:
claude mcp list
Nếu server hiện trạng thái connected, bạn có thể xác nhận bộ tool đã sẵn sàng bằng cách hỏi trực tiếp trong session: "Liệt kê các tool Terraform MCP hiện có." Claude Code sẽ trả về danh sách như terraform_init, terraform_plan, terraform_validate... Với VS Code, extension Claude Code đọc đúng cùng file settings này — không cần config riêng, chỉ cần mở workspace đúng thư mục có .claude/settings.json.
Mẹo: Đặt tên profile AWS rõ ràng như
terraform-agent-readonlyngay trongenvđể bất kỳ ai đọc lại config sau này biết ngay agent đang chạy dưới quyền hạn nào, không cần đi tra IAM console mới hiểu.
Để AI Đọc Và Giải Thích Plan Diff Trước Khi Bạn Apply
Quy trình review plan hiệu quả với Claude Code gồm ba bước: sinh plan, để agent tóm tắt có cấu trúc, và bạn tự verify điểm rủi ro nhất trước khi apply bằng tay (không phải agent).
Prompt ví dụ:
Chạy terraform plan cho module network trong thư mục hiện tại.
Tóm tắt theo 3 nhóm: resource sẽ create, sẽ update in-place,
và sẽ destroy/replace. Với nhóm destroy/replace, giải thích rõ
lý do (attribute nào force replacement) và đánh giá có khả năng
mất dữ liệu không.
Agent sẽ gọi terraform_plan, parse structured JSON, và trả lời dạng có cấu trúc, ví dụ:
- Create (2):
aws_subnet.private_c,aws_route_table_association.private_c - Update in-place (1):
aws_security_group.app— thêm 1 ingress rule cổng 8443 - Replace (1):
aws_instance.bastion— do thay đổiami, Terraform không hỗ trợ update AMI in-place nên phải destroy + create. Không mất dữ liệu vì instance này stateless, nhưng sẽ có downtime SSH trong lúc tạo lại.
Điểm mạnh của cách làm này so với đọc plan output thô: agent buộc phải phân loại rõ ràng, giúp bạn nhìn thấy ngay resource nguy hiểm (destroy/replace) mà không phải scroll qua hàng trăm dòng "no changes". Nhưng đừng dừng lại ở tóm tắt — luôn yêu cầu agent trích dẫn đúng dòng plan gốc cho phần replace, để bạn tự verify logic suy luận của nó có đúng không.
Mẹo: Thêm câu "trích dẫn nguyên văn đoạn plan gốc cho mỗi resource ở nhóm replace" vào cuối prompt. Việc này buộc agent show evidence thay vì chỉ diễn giải bằng lời — cách nhanh nhất để bắt lỗi khi agent hiểu sai plan.
Sinh Module Tái Sử Dụng Với Variables, Outputs Và Validation
Claude Code làm tốt việc sinh module Terraform theo convention chuẩn khi bạn cung cấp đủ ràng buộc trong prompt — không nên chỉ nói "viết module VPC" mà cần chỉ rõ input/output mong đợi và rule validation.
Viết module Terraform tên "vpc" với:
- Input: cidr_block (string), az_count (number, default 2, phải >= 1 và <= 6),
enable_nat_gateway (bool, default false)
- Output: vpc_id, private_subnet_ids (list), public_subnet_ids (list)
- Thêm validation block cho cidr_block: phải là CIDR hợp lệ dạng /16 đến /24
- Có description cho từng variable và output
Agent sẽ sinh ra cấu trúc chuẩn variables.tf, main.tf, outputs.tf, với validation block dạng:
variable "cidr_block" {
description = "CIDR block cho VPC, khuyến nghị /16 đến /24"
type = string
validation {
condition = can(cidrhost(var.cidr_block, 0)) && tonumber(split("/", var.cidr_block)[1]) >= 16 && tonumber(split("/", var.cidr_block)[1]) <= 24
error_message = "cidr_block phải là CIDR hợp lệ với prefix từ /16 đến /24."
}
}
Sau khi sinh, luôn chạy terraform_validate ngay (agent nên tự làm bước này, nhưng bạn nên double-check bằng cách hỏi "Chạy validate và cho tôi biết kết quả"). Với module publish ra ngoài team dùng chung, yêu cầu thêm agent viết README.md mô tả input/output theo format Terraform Registry — việc này giúp module dễ discover và dùng lại đúng, giảm tình trạng mỗi team tự viết lại VPC module riêng.
Mẹo: Luôn yêu cầu validation block ngay trong prompt đầu tiên, đừng để "thêm validation sau" — kinh nghiệm thực tế cho thấy agent (và cả con người) hay bỏ qua bước validation nếu nó không nằm trong yêu cầu ban đầu, dẫn đến module publish thiếu ràng buộc quan trọng.
Phát Hiện Drift Giữa State Và Hạ Tầng Thật
Drift (lệch cấu hình) xảy ra khi ai đó sửa resource trực tiếp qua console/CLI provider mà không qua Terraform — ví dụ một engineer tăng tay disk size của RDS instance qua AWS Console để fix gấp incident, nhưng quên cập nhật lại .tf file. Lần plan tiếp theo, Terraform sẽ đòi revert thay đổi đó vì nó không biết gì về sự thay đổi ngoài luồng.
Claude Code kết hợp Terraform MCP giúp việc phát hiện và xử lý drift nhanh hơn nhiều so với đọc log AWS CloudTrail bằng tay:
Chạy terraform plan -refresh-only, cho tôi biết resource nào
có drift so với config hiện tại, và với mỗi resource, cho biết
attribute nào lệch và giá trị thực tế trên cloud là gì.
Agent gọi terraform_plan với flag refresh-only, đọc kết quả, và trả lời dạng bảng: resource, attribute lệch, giá trị trong state cũ, giá trị thật hiện tại. Từ đây bạn có hai lựa chọn: cập nhật lại .tf để khớp với thực tế (nếu thay đổi đó là chủ ý, hợp lý), hoặc để Terraform revert lại đúng như thiết kế ban đầu (nếu thay đổi ngoài luồng đó là sai quy trình, cần sửa lại đúng chuẩn).
terraform plan -refresh-only -out=refresh.plan
terraform show -json refresh.plan | jq '.resource_drift'
Yêu cầu thực dụng: đừng để agent tự quyết định "cập nhật .tf để khớp thực tế" hay "revert" — đây là quyết định nghiệp vụ (business decision), luôn cần con người xác nhận based on lý do thay đổi ngoài luồng đó là gì.
Mẹo: Chạy
terraform plan -refresh-onlyđịnh kỳ (ví dụ cron job hàng ngày qua CI, có agent tóm tắt kết quả gửi vào Slack) thay vì chỉ chạy khi nghi ngờ có vấn đề — drift thường âm thầm tích lũy và chỉ lộ ra khi gây incident thật.
Bộ Quy Tắc Vàng Khi Dùng Claude Code Cho Terraform
Tổng kết lại các nguyên tắc nên áp dụng nhất quán khi làm việc với Terraform MCP trong Claude Code (cả CLI và VS Code):
- Luôn tách credentials read-only (dùng cho plan/validate) khỏi credentials có quyền apply.
- Luôn yêu cầu agent trích dẫn plan gốc khi tóm tắt, không tin tóm tắt suông.
- Đưa ràng buộc validation ngay từ prompt đầu khi sinh module mới, không để "thêm sau".
- Chạy refresh-only định kỳ để bắt drift sớm, xử lý trước khi nó gây incident.
- Ghi các quy tắc này vào
CLAUDE.mdtrong repo infra để mọi session mới đều tự động biết giới hạn của mình.
Mẹo: Nếu team có nhiều repo infra, tạo một file
CLAUDE.mdchuẩn chung (template) rồi symlink hoặc copy vào từng repo — tránh tình trạng mỗi repo có quy tắc agent khác nhau, dễ gây nhầm lẫn khi engineer chuyển qua chuyển lại giữa các project.