Vấn đề: Mọi thứ trông có vẻ đúng, nhưng vẫn lỗi
Bạn vừa hoàn thành một module Terraform phức tạp để triển khai một cụm 3 instance EC2. Bạn đang sử dụng hàm templatefile() để chèn các biến môi trường động vào một shell script. Trong IDE của bạn, mọi thứ trông rất hoàn hảo. File user_data.tpl nằm ngay trong thư mục templates đúng như dự kiến.
Bạn chạy terraform plan và gặp lỗi:
Error: Error in function call
Call to function "templatefile" failed: open ./templates/user_data.tpl: no such file or directory.
Thậm chí bạn có thể chạy ls ./templates/user_data.tpl từ terminal và thấy file hiện ra. Vậy tại sao Terraform lại từ chối nhận diện nó? Vấn đề không phải là file bị thiếu. Vấn đề là Terraform đang tìm kiếm sai chỗ.
Tại sao các đường dẫn của bạn bị lỗi
Terraform giải quyết các đường dẫn tương đối như ./templates/user_data.tpl dựa trên thư mục làm việc hiện tại (current working directory). Đây là thư mục nơi bạn thực thi lệnh terraform, chứ không phải thư mục chứa mã nguồn .tf của bạn.
Hãy tưởng tượng cấu trúc dự án của bạn như sau:
.
├── main.tf (Cấu hình gốc)
└── modules/
└── web_server/
├── main.tf (Mã nguồn module)
└── templates/
└── user_data.tpl
Nếu bạn gọi templatefile("./templates/user_data.tpl", {}) bên trong modules/web_server/main.tf, Terraform sẽ tìm kiếm file đó bắt đầu từ thư mục gốc. Vì file nằm sâu trong thư mục module, việc tìm kiếm sẽ thất bại. Sự thay đổi ngữ cảnh này là nguyên nhân số 1 gây ra lỗi đường dẫn trong các pipeline CI/CD như GitHub Actions hoặc Jenkins.
Các bước kiểm tra đầu tiên
Trước khi thay đổi mã nguồn, hãy loại trừ các lỗi đơn giản mà ngay cả những kỹ sư dày dạn kinh nghiệm cũng có thể mắc phải:
- Phân biệt chữ hoa chữ thường: Trên các CI runner chạy Linux,
Templates/vàtemplates/là hai thư mục khác nhau. - Phần mở rộng bị ẩn: Đảm bảo file của bạn không thực sự có tên là
user_data.tpl.txt. - Ngữ cảnh thực thi: Bạn có đang chạy Terraform từ một thư mục con bằng cờ
-chdirkhông? Điều này làm thay đổi nơi Terraform tìm kiếm các đường dẫn tương đối.
Giải pháp đáng tin cậy: Sử dụng path.module
Để mã nguồn của bạn có thể di động (portable), bạn cần yêu cầu Terraform tìm kiếm file tương đối với chính module đó. Terraform cung cấp một biến tích hợp sẵn gọi là path.module cho chính mục đích này. Biến này luôn trỏ đến đường dẫn hệ thống của thư mục chứa file .tf nơi nó được sử dụng.
Cập nhật block resource của bạn như sau:
# Cách tiếp cận đáng tin cậy
resource "aws_instance" "web" {
count = 3
# ...
user_data = templatefile("${path.module}/templates/user_data.tpl", {
admin_email = var.admin_email
server_id = count.index
})
}
Khi bạn sử dụng ${path.module}, Terraform sẽ tạo ra một đường dẫn tuyệt đối. Việc bạn chạy lệnh plan từ thư mục gốc, thư mục con hay từ một build agent từ xa sẽ không còn quan trọng nữa. Đường dẫn sẽ luôn chính xác.
Các biến đường dẫn hữu ích khác
path.root: Trỏ đến thư mục nơi bạn bắt đầu thực thi lệnh Terraform.path.cwd: Trỏ đến thư mục terminal hiện tại của bạn.
Đối với các lệnh gọi templatefile bên trong module, path.module hầu như luôn là công cụ phù hợp nhất.
Debug nhanh hơn với Terraform Console
Đừng đợi 60 giây để chạy một lệnh terraform plan đầy đủ chỉ để kiểm tra một đường dẫn. Bạn có thể xác minh logic của mình ngay lập tức bằng cách sử dụng terraform console. Đây là cách nhanh nhất để debug các vấn đề về đường dẫn mà không cần thực sự triển khai bất cứ thứ gì.
- Mở terminal tại thư mục gốc của dự án.
- Chạy lệnh
terraform console. - Kiểm tra đường dẫn tuyệt đối bằng cách nhập:
abspath("${path.module}/modules/web_server/templates/user_data.tpl") - Thử đọc trực tiếp nội dung file:
file("${path.module}/modules/web_server/templates/user_data.tpl")
Nếu hàm file() trả về nội dung script của bạn mà không có lỗi, đường dẫn của bạn đã được sửa xong. Nhấn Ctrl+C để thoát và tiếp tục triển khai.
Tổng kết
Lỗi "no such file or directory" hiếm khi là do thiếu file. Nó hầu như luôn là do sự hiểu nhầm về cách Terraform xử lý ngữ cảnh thực thi. Bằng cách loại bỏ các đường dẫn tương đối được viết cứng (hardcoded) và sử dụng ${path.module}, bạn sẽ giúp mã nguồn hạ tầng của mình trở nên linh hoạt, dễ di động và dễ debug hơn nhiều.

