IaCInfrastructure as Codeterraformterraform methods

Những tính năng Terraform mình dùng mỗi ngày (for_each, count, dynamic, locals, depends_on, lifecycle, ...)

Khám phá những tính năng Terraform được sử dụng nhiều nhất trong thực tế như for_each, count, locals, dynamic blocks, depends_on và lifecycle để viết Infrastructure as Code gọn gàng, dễ bảo trì và mở rộng.

22 thg 7, 20266 min readCập nhật 22 thg 7, 2026
Những tính năng Terraform mình dùng mỗi ngày (for_each, count, dynamic, locals, depends_on, lifecycle, ...)

Những tính năng Terraform mình dùng mỗi ngày

Ở những bài trước, chúng ta đã biết:

  • Terraform hoạt động như thế nào
  • Terraform State là gì
  • Variables và Outputs
  • Modules
  • Data Sources

Đến đây, bạn hoàn toàn có thể viết được một project Terraform cơ bản.

Nhưng nếu nhìn vào các project production trên GitHub hoặc trong doanh nghiệp, bạn sẽ thấy rất nhiều syntax như:

code
for_each = ...
 
count = ...
 
locals {
...
}
 
dynamic "ingress" {
...
}
 
lifecycle {
...
}
 
depends_on = [...]

Người mới thường có cảm giác:

Terraform sao nhiều keyword quá.

Thực tế thì không phải.

Terraform có rất ít syntax.

Chỉ là có khoảng 6–7 tính năng gần như xuất hiện ở mọi project.

Nếu hiểu chúng, bạn sẽ đọc được phần lớn code Terraform ngoài đời thực.


Terraform không phải là ngôn ngữ lập trình

Đây là điều rất quan trọng.

Terraform không phải Java.

Không phải Go.

Không phải Python.

Terraform không có:

  • class
  • function
  • loop truyền thống
  • if/else đầy đủ

Terraform chỉ là một ngôn ngữ khai báo (Declarative Language).

Bạn chỉ mô tả:

"Infrastructure cuối cùng phải như thế này."

Terraform sẽ tự tính toán cách tạo ra nó.

Vì vậy những thứ như:

  • for_each
  • count
  • dynamic

không phải loop theo nghĩa truyền thống.

Chúng chỉ giúp Terraform tạo ra nhiều resource từ cùng một template.


Tổng quan những tính năng dùng nhiều nhất

Trong thực tế, mình gần như dùng đi dùng lại đúng những tính năng này.

FeatureMục đích
localsTạo biến trung gian
for_eachTạo nhiều resource từ map hoặc set
countTạo nhiều resource theo số lượng
dynamicSinh nested block
depends_onKhai báo dependency thủ công
lifecycleĐiều khiển cách Terraform cập nhật resource

Nếu biết sử dụng tốt 6 tính năng này thì bạn đã đọc được khoảng 80–90% code Terraform production.


locals — Biến trung gian

Giả sử project có nhiều nơi cùng dùng một prefix.

Không nên viết lặp lại:

code
resource "aws_s3_bucket" "logs" {
  bucket = "company-dev-logs"
}
 
resource "aws_s3_bucket" "backup" {
  bucket = "company-dev-backup"
}

Thay vào đó:

code
locals {
  prefix = "company-dev"
}
 
resource "aws_s3_bucket" "logs" {
  bucket = "${local.prefix}-logs"
}
 
resource "aws_s3_bucket" "backup" {
  bucket = "${local.prefix}-backup"
}

Mọi nơi chỉ cần dùng:

code
local.prefix

locals không phải variable

Đây là điều nhiều người nhầm.

Variable:

code
variable "environment" {}

được truyền từ bên ngoài.

Ví dụ:

terraform apply \
-var="environment=dev"

Trong khi đó:

code
locals {
    prefix = "company-${var.environment}"
}

là giá trị được Terraform tính toán bên trong.

Nói đơn giản:

  • Variable là input
  • Local là kết quả xử lý từ input

count — Tạo nhiều resource theo số lượng

Ví dụ muốn tạo ba EC2 giống hệt nhau.

code
resource "aws_instance" "web" {
    count = 3
 
    instance_type = "t3.micro"
}

Terraform sẽ tạo:

web[0]

web[1]

web[2]

Có thể truy cập bằng:

code
aws_instance.web[0]

count phù hợp khi nào?

Count phù hợp nếu:

  • mọi resource giống nhau
  • chỉ khác index

Ví dụ:

  • nhiều VM giống nhau
  • nhiều disk giống nhau

Nhược điểm của count

Giả sử:

count = 3

Terraform tạo:

0

1

2

Sau đó sửa thành:

count = 2

Terraform sẽ xóa:

2

Nhưng nếu thay đổi thứ tự dữ liệu đầu vào, index có thể thay đổi và Terraform sẽ hiểu nhầm là resource cũ bị xóa, resource mới được tạo.

Đây là lý do nhiều project hiện nay ưu tiên for_each hơn count.


for_each — Cách phổ biến nhất để tạo nhiều resource

Ví dụ:

code
locals {
    buckets = {
        logs = "company-logs"
        backup = "company-backup"
        assets = "company-assets"
    }
}

Sau đó:

code
resource "aws_s3_bucket" "bucket" {
    for_each = local.buckets
 
    bucket = each.value
}

Terraform sẽ tạo:

bucket["logs"]

bucket["backup"]

bucket["assets"]

each.key và each.value

Ví dụ:

code
locals {
    buckets = {
        logs = "company-logs"
    }
}

thì:

code
each.key

là:

logs

Còn:

code
each.value

là:

company-logs

Vì sao for_each tốt hơn count?

Giả sử có:

logs

backup

assets

Sau này thêm:

media

Terraform sẽ chỉ tạo:

media

Những resource còn lại giữ nguyên.

Không có chuyện index bị đổi.

Đây là lý do hầu hết project production đều ưu tiên dùng for_each.


dynamic block — Sinh nested block

Một số resource có nested block.

Ví dụ:

code
resource "aws_security_group" "web" {
 
    ingress {
        ...
    }
 
    ingress {
        ...
    }
 
    ingress {
        ...
    }
}

Nếu có hàng chục rule thì sẽ rất dài.

Terraform cho phép:

code
dynamic "ingress" {
 
}

Ví dụ:

code
dynamic "ingress" {
    for_each = var.ingress_rules
 
    content {
        from_port = ingress.value.port
        to_port = ingress.value.port
        protocol = "tcp"
        cidr_blocks = ingress.value.cidr
    }
}

Terraform sẽ tự sinh ra nhiều block:

ingress {}

ingress {}

ingress {}

thay vì phải viết tay.


depends_on — Dependency thủ công

Thông thường Terraform tự biết dependency.

Ví dụ:

code
resource "aws_instance" "web" {
    subnet_id = aws_subnet.private.id
}

Terraform hiểu:

Subnet

↓

EC2

Không cần viết gì thêm.


Khi nào cần depends_on?

Đôi khi dependency không thể suy ra.

Ví dụ:

code
depends_on = [
    aws_iam_role.example
]

Terraform sẽ luôn tạo IAM Role trước.

Hoặc:

CloudFront

↓

Route53

dù hai resource không tham chiếu trực tiếp.


Không nên lạm dụng depends_on

Nhiều người mới học Terraform có thói quen:

depends_on

ở mọi resource.

Điều này làm graph của Terraform trở nên phức tạp hơn cần thiết.

Hãy để Terraform tự suy luận trước.

Chỉ dùng depends_on khi thật sự cần.


lifecycle — Điều khiển hành vi của Terraform

Đây là một trong những tính năng rất mạnh.

Ví dụ:

code
lifecycle {
 
}

bên trong có nhiều tùy chọn.


create_before_destroy

Mặc định:

Destroy

↓

Create

Điều này có thể gây downtime.

Có thể đổi thành:

code
lifecycle {
    create_before_destroy = true
}

Terraform sẽ:

Create

↓

Destroy

Đây là lựa chọn rất hữu ích khi thay thế:

  • Load Balancer
  • Launch Template
  • ASG
  • DNS

prevent_destroy

Ví dụ:

code
lifecycle {
    prevent_destroy = true
}

Nếu ai đó chạy:

terraform destroy

Terraform sẽ báo lỗi thay vì xóa resource.

Rất hữu ích cho:

  • Production Database
  • KMS Key
  • S3 Bucket chứa dữ liệu
  • DNS Zone

ignore_changes

Ví dụ:

code
lifecycle {
    ignore_changes = [
        tags
    ]
}

Terraform sẽ bỏ qua việc so sánh trường tags.

Điều này thường dùng khi:

  • tags được hệ thống khác cập nhật
  • Azure Policy tự thêm tag
  • AWS Organizations tự thêm metadata

Nếu không ignore, mỗi lần terraform plan đều xuất hiện thay đổi không mong muốn.


Những tính năng mình dùng nhiều nhất

Nếu nhìn vào các project Terraform mình đang sử dụng hằng ngày, mức độ xuất hiện sẽ gần như sau:

FeatureTần suất
locals⭐⭐⭐⭐⭐
for_each⭐⭐⭐⭐⭐
lifecycle⭐⭐⭐⭐
data sources⭐⭐⭐⭐
dynamic⭐⭐⭐
depends_on⭐⭐
count⭐⭐

Đặc biệt:

  • locals
  • for_each

gần như xuất hiện trong mọi module.


Tổng kết

Terraform không có quá nhiều cú pháp.

Trong phần lớn dự án thực tế, bạn sẽ làm việc lặp đi lặp lại với một nhóm tính năng quen thuộc:

  • locals để giảm lặp code
  • for_each để tạo nhiều resource ổn định
  • count cho các trường hợp đơn giản
  • dynamic để sinh nested block
  • depends_on khi Terraform không thể tự suy luận dependency
  • lifecycle để kiểm soát cách resource được tạo, cập nhật hoặc xóa

Hiểu rõ những tính năng này sẽ giúp bạn đọc được hầu hết các Terraform Module trên GitHub cũng như code trong các dự án production.

Ở bài tiếp theo, chúng ta sẽ chuyển sang một chủ đề quan trọng hơn:

Làm thế nào để tổ chức một project Terraform theo đúng cấu trúc khi số lượng resource ngày càng lớn? Chúng ta sẽ cùng tìm hiểu cách chia module, phân tách thư mục và xây dựng một kiến trúc Terraform dễ mở rộng và bảo trì..

Bình luận

0/2000

Đang tải bình luận…