TL;DR
Chạy terraform init trong thư mục làm việc trước khi chạy terraform plan hoặc terraform apply. Chỉ vậy thôi.
terraform init
terraform plan
Đã chạy init trong CI/CD rồi mà vẫn gặp lỗi này? Xem phần nguyên nhân sâu xa bên dưới.
Lỗi gặp phải
Error: Module not installed
This module is not yet installed. Run "terraform init" to install all modules required by this configuration.
Terraform báo lỗi này khi tìm thấy khối module trong các file .tf nhưng không thể xác định vị trí source đã tải về trong .terraform/modules/. Metadata của module chưa tồn tại — nên Terraform dừng lại trước khi thực hiện bất cứ điều gì.
Nguyên nhân gốc rễ
Giả sử bạn có một khối module như sau:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.1.2"
name = "my-vpc"
cidr = "10.0.0.0/16"
}
Trước khi Terraform có thể xử lý khối đó, nó cần source của module thực sự có trên đĩa. Lệnh terraform init đảm nhận việc tải về đó. Nó ghi vào hai nơi:
.terraform/modules/— các file module đã tải về.terraform/modules/modules.json— metadata từ registry
Không có thư mục .terraform/modules/? Terraform dừng ngay lập tức. Điều này xảy ra khi plan chạy trước init, hoặc khi ai đó đã xóa .terraform/ mà không khởi tạo lại.
Các nguyên nhân phổ biến nhất:
- Vừa clone repo mới —
.terraform/bị gitignore (đúng như vậy), nên không bao giờ được commit - Pipeline CI/CD mà bước
initbị bỏ qua hoặc thất bại âm thầm - Thêm khối
modulemới nhưng chưa chạy lạiinit - Ai đó chạy
rm -rf .terraform/để dọn dẹp và quên khởi tạo lại - Chuyển branch mà source hoặc version của module khác được khai báo
Cách khắc phục
Cách 1 — Sửa tiêu chuẩn (phát triển local)
# Điều hướng đến thư mục làm việc Terraform
cd path/to/your/terraform
# Khởi tạo — tải về modules và providers
terraform init
# Bây giờ plan sẽ hoạt động
terraform plan
Cách 2 — Thêm module mới vào config hiện có
Vừa thêm khối module mới vào workspace đã khởi tạo? Chạy lại init để tải source mới về:
terraform init -upgrade
Flag -upgrade không bắt buộc hoàn toàn (init thông thường vẫn hoạt động tốt), nhưng là thói quen tốt — nó cũng cập nhật providers lên phiên bản mới nhất được phép trong các ràng buộc bạn đã khai báo.
Cách 3 — Pipeline CI/CD
Trong GitHub Actions, GitLab CI hay tương tự, hãy giữ init và plan là các bước riêng biệt rõ ràng:
# Ví dụ GitHub Actions
- name: Terraform Init
run: terraform init
working-directory: ./infra
- name: Terraform Plan
run: terraform plan
working-directory: ./infra
Đang dùng remote backend (S3, GCS, Terraform Cloud)? Truyền cấu hình backend một cách tường minh — nếu không init có thể thất bại âm thầm do thiếu thông tin xác thực và pipeline vẫn tiếp tục chạy:
terraform init \
-backend-config="bucket=my-tf-state" \
-backend-config="key=prod/terraform.tfstate" \
-backend-config="region=us-east-1"
Cách 4 — Module từ đường dẫn local không tìm thấy
Module theo đường dẫn local hoạt động khác với module từ registry. Kiểm tra khai báo:
module "networking" {
source = "../modules/networking"
}
Đường dẫn đó phải tồn tại tương đối so với module đang gọi. Gõ sai đường dẫn sẽ khiến init thất bại — và init thất bại đồng nghĩa plan sẽ báo cùng lỗi này. Kiểm tra trước khi chạy lại:
# Xác nhận đường dẫn tồn tại
ls ../modules/networking
# Sau đó khởi tạo lại
terraform init
Cách 5 — Sai thư mục làm việc
Cái này thường gặp trong monorepo. Chạy init và plan từ các thư mục khác nhau chính là thủ phạm — mỗi thư mục cần có .terraform/ riêng của nó:
# Sai — init chạy trong /infra, plan chạy từ /
cd /infra && terraform init
cd / && terraform plan # ← thất bại, không có .terraform ở đây
# Đúng — cả hai lệnh trong cùng một thư mục
cd /infra
terraform init
terraform plan
Kiểm tra kết quả
Sau khi init hoàn tất, xác nhận các module đã được tải về đúng chỗ:
# Kiểm tra thư mục modules tồn tại và có nội dung
ls .terraform/modules/
# Sẽ hiển thị modules.json cùng một thư mục cho mỗi module
# Ví dụ output:
# modules.json vpc/
Chạy terraform plan. Lệnh này sẽ vượt qua giai đoạn tải module và in ra diff tài nguyên hoặc thông báo quen thuộc "No changes":
terraform plan
# Output thành công bắt đầu bằng:
# Terraform used the selected providers to generate the following execution plan...
Mẹo phòng tránh
- Giữ
.terraform/trong.gitignore— nó có trong template chính thức của Terraform, nhưng các repo cũ đôi khi bị thiếu. Đáng kiểm tra nhanh một cái. - Thêm một dòng vào README của repo: "Chạy
terraform initsau khi clone." Giúp mọi contributor mới tránh được lỗi này. - Trong CI/CD, coi
initvàplanlà các bước có tên riêng biệt. Khi có sự cố, bạn sẽ biết ngay bước nào thất bại. - Làm việc với các module lồng nhau phức tạp và file
.terraform.lock.hcllộn xộn? Dán nội dung lock file vào công cụ chuyển đổi YAML ↔ JSON của ToolCraft để nhanh chóng phát hiện các vấn đề cấu trúc — cú pháp key-value của HCL đủ gần để converter đánh dấu dấu ngoặc không khớp và các khối bị lỗi mà dễ bỏ sót khi đọc bằng mắt thường.
Tham chiếu nhanh
# Luôn chạy init trước
terraform init
# Chạy lại init sau khi thêm hoặc thay đổi modules
terraform init
# Cập nhật providers và modules lên phiên bản mới nhất được phép
terraform init -upgrade
# Kiểm tra modules đã được cài đặt
ls .terraform/modules/
cat .terraform/modules/modules.json

