Tình Huống Gặp Lỗi
Bạn chạy terraform plan — hoặc chỉ terraform validate — và Terraform dừng đột ngột với thông báo này:
Error: Duplicate provider "aws" configuration
A module may have only one "default" (non-aliased) provider configuration per provider type.
Không có gì được plan. Không có gì được apply. Config tưởng chừng ổn thì lại từ chối tải.
Lỗi này thường xảy ra trong một trong ba tình huống sau:
- Bạn copy-paste một provider block từ file khác vào module đã có sẵn một block rồi
- Bạn chia Terraform config ra nhiều file
.tfvà định nghĩa cùng một provider trong hai file - Bạn thêm cấu hình AWS region thứ hai mà không nhận ra rằng một provider block mặc định đã tồn tại trong
main.tf
Tại Sao Terraform Báo Lỗi Này
Terraform chỉ cho phép một provider block mặc định cho mỗi loại provider trong cùng một module. Provider mặc định là bất kỳ block provider nào không có argument alias. Khi Terraform tìm thấy hai block như vậy trong cùng một module — bất kể chúng nằm trong file .tf nào — nó không thể xác định block nào dùng làm mặc định, nên thay vì đoán mò, nó sẽ báo lỗi.
Đây là ví dụ tối giản để tái hiện lỗi:
# main.tf
provider "aws" {
region = "us-east-1"
}
# providers.tf — cùng module, khác file
provider "aws" {
region = "ap-southeast-1"
}
Terraform gộp tất cả file .tf trong một thư mục thành một module logic duy nhất. Cả hai block trên đều trở thành provider mặc định cho aws. Đó là nguyên nhân xung đột.
Cách Sửa Nhanh: Thêm Alias Cho Provider Thứ Hai
Nếu bạn thực sự cần hai cấu hình AWS khác nhau (hai region, hai tài khoản, hai bộ credentials), cách sửa là giữ một block làm mặc định và đặt alias cho block còn lại.
# providers.tf
provider "aws" {
region = "us-east-1" # provider mặc định — không có alias
}
provider "aws" {
alias = "ap"
region = "ap-southeast-1"
}
Bất kỳ resource nào cần cấu hình thứ hai thì tham chiếu tường minh qua argument provider:
resource "aws_s3_bucket" "asia_logs" {
provider = aws.ap
bucket = "my-asia-logs-bucket"
}
Các resource không có argument provider sẽ tự động dùng block mặc định (không có alias). Bạn chỉ cần chỉ định khi muốn dùng provider có alias.
Cách Sửa Triệt Để: Xóa Block Trùng Lặp
Nếu bạn chỉ cần một cấu hình AWS, cách sửa thực sự là xóa hoàn toàn block trùng lặp. Bắt đầu bằng cách tìm tất cả các chỗ xuất hiện:
grep -rn 'provider "aws"' .
Kết quả mẫu có thể trông như sau:
./main.tf:1:provider "aws" {
./providers.tf:1:provider "aws" {
Mở cả hai file, quyết định file nào có cấu hình đúng, rồi xóa file còn lại. Sau đó gộp tất cả vào một provider block duy nhất, có thẩm quyền — vị trí quy ước là providers.tf hoặc versions.tf:
# providers.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
profile = "my-profile"
}
Trường Hợp Đặc Biệt: Child Module
Nếu bạn đang gọi một child module và muốn nó dùng một cấu hình provider cụ thể, hãy truyền provider từ root module bằng một map providers. Child module không nên tự định nghĩa block provider "aws" {} của riêng nó — nó chỉ nên khai báo những gì nó cần.
# Root module — gọi child và truyền provider
module "networking" {
source = "./modules/networking"
providers = {
aws = aws.ap # truyền tường minh provider có alias
}
}
# modules/networking/versions.tf — chỉ khai báo yêu cầu, không dùng provider block đầy đủ
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
Thêm block provider "aws" { region = ... } bên trong child module sẽ tạo ra một provider mặc định thứ hai theo quan điểm của Terraform — cùng một lỗi, chỉ là khó phát hiện hơn vì nó nằm trong một thư mục con.
Các Bước Xác Minh
Chạy ba lệnh này theo thứ tự sau khi thực hiện thay đổi:
# 1. Kiểm tra cú pháp và cấu trúc cấu hình
terraform validate
# 2. Xem cây phụ thuộc provider
terraform providers
# 3. Xác nhận plan chạy sạch
terraform plan
terraform validate sẽ xuất ra:
Success! The configuration is valid.
terraform providers đặc biệt hữu ích để chẩn đoán provider đang được kéo vào từ đâu. Nó hiển thị toàn bộ cây phụ thuộc bao gồm cả child module, vì vậy nếu có provider trùng lặp ẩn trong một module lồng nhau, bạn sẽ thấy ở đây.
Mẹo Phòng Tránh
Thói quen hiệu quả nhất: giữ tất cả khai báo provider và version trong một file (providers.tf hoặc versions.tf), và không bao giờ đặt block provider ở bất kỳ chỗ nào khác. Khi cả team đều biết provider nằm trong một file duy nhất, việc vô tình tạo trùng lặp gần như không còn xảy ra.
Thêm bước validate vào CI pipeline để lỗi này được phát hiện trước khi ảnh hưởng đến máy của bất kỳ ai trong nhóm:
# .github/workflows/terraform.yml (trích đoạn)
- name: Validate Terraform
run: |
terraform init -backend=false
terraform validate
Khi làm việc với các cấu hình có file variable kết hợp định dạng YAML và JSON — điều phổ biến trong các dự án Terraform lớn — tôi thấy ToolCraft's YAML ↔ JSON Converter rất tiện để nhanh chóng kiểm tra cấu trúc của các file .tfvars hoặc file định nghĩa variable trước khi đưa vào Terraform. Công cụ này chạy hoàn toàn trên trình duyệt, không có dữ liệu nào được tải lên.

