Nếu bạn đang theo series HashiCorp Certified: Terraform Associate, đến bài này mình sẽ giải thích một khái niệm quan trọng mà ai học Terraform cũng cần nắm: Data Source. Hiểu được Data Source là bạn đã biết cách viết cấu hình linh hoạt hơn, không còn phụ thuộc vào giá trị hard-code nữa.
Xem thêm:
13-Terraform Provisioners – remote-exec và local-exec
03-Terraform Provider là gì? Tại sao bắt buộc phải có Provider
1. Resource và Data Source khác nhau chỗ nào?
Trước giờ bạn hay dùng resource để tạo mới tài nguyên trên AWS, ví dụ tạo EC2, VPC, S3 bucket. Nhưng không phải lúc nào cũng cần tạo mới — đôi khi bạn chỉ cần lấy thông tin của thứ đã tồn tại.
Đó là lúc dùng data.
resource |
data |
|
|---|---|---|
| Mục đích | Tạo tài nguyên mới | Lấy thông tin tài nguyên đã tồn tại |
| Terraform quản lý? | Có (create/update/delete) | Không, chỉ đọc |
| Lifecycle | Đầy đủ | Read-only |
2. Data Source là gì?
Data Source cho phép bạn truy xuất thông tin động từ Cloud Provider — những thông tin không nằm trong cấu hình Terraform hiện tại của bạn.
Một số ví dụ thực tế:
- Lấy danh sách Availability Zones của một region
- Lấy AMI mới nhất từ Amazon
- Lấy VPC đang tồn tại trong tài khoản AWS
- Lấy Security Group đã tạo trước đó
- Lấy IP ranges của các dịch vụ AWS
Terraform thực hiện điều này bằng cách gọi API của Cloud Provider (AWS API, Azure API, GCP API…) trong bước plan hoặc apply.
3. Tại sao không hard-code cho nhanh?
Giả sử bạn viết thế này:
availability_zone = "ap-southeast-1a"
Trông ổn, nhưng có một số vấn đề thực tế:
- AZ đó unavailable thì sao? AWS đôi khi tắt AZ để bảo trì
- Deploy sang region khác thì tên AZ sẽ khác hoàn toàn
- AMI ID thay đổi theo region — bạn không thể dùng chung một AMI ID cho mọi nơi
- AMI cũ bị deprecated — bạn phải update tay mỗi lần có bản mới
Dùng Data Source giải quyết hết các vấn đề trên. Terraform sẽ tự hỏi AWS lúc chạy, lấy giá trị đúng tại thời điểm đó.
4. Cú pháp Data Source
Cấu trúc chung:
data "<PROVIDER>_<TYPE>" "<NAME>" {
# filter tùy chọn
}
Ví dụ lấy danh sách Availability Zones:
data "aws_availability_zones" "available" {}
Không cần filter gì thêm. Terraform sẽ tự gọi API và trả về danh sách AZ trong region bạn đang cấu hình.
5. Ví dụ thực tế: Lấy AMI mới nhất
Đây là use case phổ biến nhất khi làm việc với EC2:
data "aws_ami" "latest_amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm*"]
}
}
Giải thích từng phần:
most_recent = true— nếu có nhiều AMI khớp với filter, lấy cái mới nhấtowners = ["amazon"]— chỉ lấy AMI được publish bởi Amazon, tránh lấy nhầm AMI lạfilter— lọc theo tên, ở đây lấy các AMI tên bắt đầu bằngamzn2-ami-hvm
Sau khi định nghĩa xong, dùng nó trong resource:
resource "aws_instance" "web" {
ami = data.aws_ami.latest_amazon_linux.id
instance_type = "t3.micro"
}
Lúc này ami không còn là một chuỗi ID cứng nữa. Mỗi lần chạy Terraform, nó sẽ tự lấy AMI mới nhất phù hợp.
6. Ví dụ thực tế: Deploy EC2 vào nhiều AZ
Trong AWS, một region như ap-southeast-1 có nhiều Availability Zone:
ap-southeast-1aap-southeast-1bap-southeast-1c
Để tạo 2 EC2 ở 2 AZ khác nhau mà không hard-code tên AZ:
provider "aws" {
region = "ap-southeast-1"
}
data "aws_availability_zones" "available" {}
resource "aws_instance" "app" {
count = 2
ami = data.aws_ami.latest_amazon_linux.id
instance_type = "t3.micro"
availability_zone = data.aws_availability_zones.available.names[count.index]
}
Kết quả:
- Instance
app[0]→ap-southeast-1a - Instance
app[1]→ap-southeast-1b
Nếu bạn đổi region sang us-east-1, code vẫn chạy đúng vì Terraform tự lấy AZ của region đó.
Tóm lại
Bài này bạn đã nắm được:
datadùng để đọc thông tin,resourcedùng để tạo mới- Data Source gọi API của Cloud Provider để lấy dữ liệu động
- Không nên hard-code AMI ID hay tên AZ — dùng Data Source để cấu hình
- Cú pháp
data.<TYPE>.<NAME>.<ATTRIBUTE>để tham chiếu trong resource khác