Thông báo lỗiBạn chạy terraform plan với mong đợi một quá trình triển khai suôn sẻ, nhưng HCL lại khiến mọi thứ dừng lại. Thay vì một bản kế hoạch, bạn nhận được một thông báo lỗi trực diện:
Error: Reference to undeclared resource
on main.tf line 42, in resource "aws_eip" "static_ip":
42: instance = aws_instance.web_server.id
A managed resource "aws_instance" "web_server" has not been declared in the root module.
Điều gì đã xảy ra?Terraform không chỉ đang gây khó dễ cho bạn. Công cụ phân tích tĩnh của nó hoạt động như một trình biên dịch nghiêm ngặt. Nếu nó không thể ánh xạ mọi tham chiếu đến một khối resource, data source, hoặc variable cụ thể trong giai đoạn khởi tạo, nó sẽ từ chối tiếp tục. Nó cần một bản đồ 1:1 cho hạ tầng của bạn trước khi mạo hiểm can thiệp vào môi trường đám mây thực tế.
Điều này thường xảy ra vì ba lý do:
- Lỗi đánh máy: Bạn đã đặt tên tài nguyên là
web_appnhưng lại gõweb_serverở dòng 42.- Cô lập Module: Bạn đã định nghĩa tài nguyên bên trong một module con, nhưng bạn lại cố gắng gọi nó trực tiếp từ filemain.tfgốc.- Tham chiếu "Ma": Bạn đã xóa hoặc vô hiệu hóa (comment) một khối tài nguyên nhưng lại quên mất một output hoặc biến local vẫn đang trỏ đến nó.## Cách khắc phục### 1. Tìm lỗi đánh máyCác định danh trong Terraform phân biệt chữ hoa chữ thường và rất khắt khe về dấu câu.web-servervàweb_serverlà hai đối tượng hoàn toàn khác nhau đối với trình phân tích. Hãy so sánh khối định nghĩa tài nguyên của bạn trực tiếp với dòng xảy ra lỗi. Sai lầm:
resource "aws_instance" "api_v1" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
}
output "server_id" {
value = aws_instance.api.id # Lỗi: "api" không khớp với "api_v1"
}
Cách sửa: Hãy làm cho chúng giống hệt nhau.
output "server_id" {
value = aws_instance.api_v1.id
}
2. Kết nối khoảng cách giữa các ModuleCác module trong Terraform giống như những chiếc hộp đen. Nếu bạn định nghĩa một tài nguyên bên trong ./modules/vpc, tài nguyên đó là riêng tư đối với module đó. Bạn không thể truy cập từ thư mục gốc và lấy ID theo kiểu module.vpc.aws_vpc.main.id.
Cách sửa: Sử dụng Output rõ ràng
Đầu tiên, hãy xuất (export) giá trị từ bên trong module con của bạn (ví dụ: ./modules/vpc/outputs.tf):
output "vpc_id" {
value = aws_vpc.main.id
}
Sau đó, trong cấu hình gốc, hãy tham chiếu đến output của module thay vì chính tài nguyên đó:
resource "aws_subnet" "public" {
vpc_id = module.network.vpc_id # Cách này hoạt động
}
3. Dọn dẹp Logic "Ma"Trong quá trình tái cấu trúc (refactoring), bạn rất dễ vô hiệu hóa một khối tài nguyên để tiết kiệm chi phí AWS nhưng lại quên rằng một giá trị local hoặc một bản đồ tags vẫn phụ thuộc vào nó. Nếu Terraform thấy một tham chiếu đến thứ gì đó hiện không hoạt động trong mã, nó sẽ báo lỗi.
Cách sửa: Sử dụng tìm kiếm toàn cục (Ctrl+Shift+F trong VS Code) cho tên tài nguyên cụ thể được đề cập trong lỗi. Xóa hoặc vô hiệu hóa bất kỳ tham chiếu còn sót lại nào trong outputs.tf hoặc locals.tf.
Các bước kiểm tra (Validation)Đừng chỉ chạy lại lệnh apply ngay lập tức. Hãy sử dụng hai công cụ này để xác minh logic của bạn:
- Validate: Chạy
terraform validate. Lệnh này thực hiện kiểm tra cục bộ cú pháp HCL và tính nhất quán nội bộ. Nó phát hiện các tài nguyên chưa được khai báo chỉ trong vài giây mà không cần kết nối với đám mây.- Plan: Chạyterraform plan. Nếu bước validate vượt qua, bản kế hoạch sẽ xác nhận rằng các tham chiếu của bạn hiện đã được giải quyết thành các giá trị thực tế.## Mẹo chuyên nghiệp để phòng tránh- Sử dụng công cụ IDE phù hợp: Sử dụng tiện ích mở rộng Terraform chính thức của HashiCorp cho VS Code. Nó cung cấp tính năng kiểm tra lỗi (linting) theo thời gian thực và sẽ gạch chân màu đỏ các tài nguyên chưa được khai báo khi bạn gõ.- Chuẩn hóa cách đặt tên: Hãy chọn một bên trong cuộc chiến "dấu gạch dưới vs dấu gạch nối" và trung thành với nó. Việc sử dụngsnake_casecho tất cả các tên tài nguyên giúp ngăn chặn 50% các lỗi này.- Giữ cho các Module gọn nhẹ: Nếu bạn thấy mình đang truyền tới 20 output giữa các module, có lẽ bạn cần xem xét lại ranh giới của các module để giữ các tài nguyên liên quan ở gần nhau hơn.

