IaCInfrastructure as Codeterraformterragrunt

Khi nào Terraform không còn đủ? Giới thiệu Terragrunt

Terraform rất mạnh, nhưng khi số lượng môi trường và module tăng lên, việc quản lý dần trở nên khó khăn. Trong bài viết này, chúng ta sẽ tìm hiểu những giới hạn của Terraform và lý do Terragrunt ra đời.

22 thg 7, 20269 min readCập nhật 22 thg 7, 2026
Khi nào Terraform không còn đủ? Giới thiệu Terragrunt

Khi nào Terraform không còn đủ? Giới thiệu Terragrunt

Suốt series này, chúng ta đã tìm hiểu khá nhiều về Terraform.

Từ những khái niệm cơ bản như Infrastructure as Code, cách Terraform hoạt động, Terraform State, Plan & Apply cho đến Variables, Data Sources, Remote State và cách tổ chức repository production.

Nếu chỉ nhìn vào những gì Terraform cung cấp, có thể bạn sẽ nghĩ:

"Terraform đã đủ để xây dựng mọi hệ thống."

Thực tế...

Đúng nhưng chưa đủ.

Terraform là một công cụ cực kỳ mạnh để quản lý infrastructure.

Nhưng Terraform không được thiết kế để giải quyết tất cả các bài toán liên quan đến việc quản lý nhiều môi trường, nhiều account và hàng trăm module khác nhau.

Đó cũng là lý do gần như mọi công ty sử dụng Terraform ở quy mô lớn đều bổ sung thêm một lớp quản lý phía trên.

Một trong những công cụ phổ biến nhất chính là Terragrunt.


Terraform rất giỏi ở việc Provision Infrastructure

Terraform làm rất tốt nhiệm vụ của mình:

  • Quản lý Resource
  • Theo dõi State
  • Tính toán Dependency
  • Tạo Execution Plan
  • Apply thay đổi an toàn

Ví dụ:

code
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}
 
resource "aws_subnet" "public" {
  vpc_id = aws_vpc.main.id
}

Terraform hiểu rằng:

VPC
 ↓
Subnet

Terraform sẽ tự tạo đúng thứ tự.

Nếu thay đổi Subnet:

Plan
↓

Update Subnet

VPC giữ nguyên

Nếu Resource phụ thuộc lẫn nhau:

IAM Role
     ↓
EC2
     ↓
Load Balancer

Terraform cũng tự xây dựng Dependency Graph.

Đây là điểm mạnh nhất của Terraform.


Nhưng Production không chỉ có một môi trường

Khi mới bắt đầu học Terraform, hầu hết ví dụ đều giống như thế này:

terraform-project

main.tf
variables.tf
outputs.tf

Chỉ có một thư mục.

Một môi trường.

Một State.

Điều này hoàn toàn ổn để học.

Nhưng khi triển khai thực tế, mọi chuyện nhanh chóng thay đổi.

Ví dụ:

Production

AWS Account A
    ├── VPC
    ├── Network
    ├── EKS
    ├── RDS
    └── Monitoring

Staging

AWS Account B
    ├── VPC
    ├── Network
    ├── EKS
    ├── RDS
    └── Monitoring

Development

AWS Account C
    ├── VPC
    ├── Network
    ├── EKS
    ├── RDS
    └── Monitoring

Đột nhiên chúng ta không còn quản lý:

  • 1 môi trường

mà là:

  • 3 môi trường
  • nhiều AWS Account
  • nhiều Region
  • hàng chục Terraform Module

Sự lặp lại bắt đầu xuất hiện

Giả sử bạn đã viết xong một module VPC.

modules/
    vpc/

Bây giờ bạn cần dùng module này cho ba môi trường.

dev
staging
production

Thông thường bạn sẽ có:

live/

dev/
    vpc/

staging/
    vpc/

production/
    vpc/

Trong mỗi thư mục lại có một file gần giống nhau.

Ví dụ:

code
module "vpc" {
  source = "../../modules/vpc"
 
  cidr = "10.0.0.0/16"
 
  environment = "dev"
}

Staging:

code
module "vpc" {
  source = "../../modules/vpc"
 
  cidr = "10.1.0.0/16"
 
  environment = "staging"
}

Production:

code
module "vpc" {
  source = "../../modules/vpc"
 
  cidr = "10.2.0.0/16"
 
  environment = "production"
}

Thoạt nhìn thì không có vấn đề gì.

Nhưng khi số module tăng lên:

  • VPC
  • IAM
  • EKS
  • RDS
  • Redis
  • S3
  • CloudFront
  • Route53
  • Monitoring
  • Logging
  • WAF
  • Secrets

...

Mỗi môi trường đều phải lặp lại gần như toàn bộ cấu hình.


Không chỉ lặp code

Điều khó chịu hơn là những thông tin dùng chung.

Ví dụ:

Backend:

code
terraform {
  backend "s3" {
    bucket = "company-tfstate"
  }
}

Provider:

code
provider "aws" {
  region = "ap-southeast-1"
}

Common Tags:

code
tags = {
  Team = "Platform"
  Owner = "Infrastructure"
}

Remote State:

code
data "terraform_remote_state" ...

Provider Version:

code
terraform {
  required_providers {
    aws = {
      version = "~> 6.0"
    }
  }
}

Những đoạn cấu hình này gần như xuất hiện ở mọi module.

Nếu có 50 module và 4 môi trường, bạn có thể đang duy trì hàng trăm file Terraform gần giống nhau.

Đó là lúc việc bảo trì bắt đầu trở nên tốn kém.

Terraform không biết "Environment"

Một điều khá thú vị là Terraform không hề có khái niệm:

  • Development
  • Staging
  • Production

Terraform chỉ biết:

Working Directory

Ví dụ:

live/

dev/
    app/

staging/
    app/

production/
    app/

Đối với Terraform, ba thư mục trên hoàn toàn độc lập.

Terraform không hiểu rằng:

dev
↓

staging
↓

production

là ba phiên bản của cùng một hệ thống.

Terraform cũng không biết:

  • Environment nào thuộc cùng một project
  • Account nào thuộc Production
  • Region nào đang được sử dụng
  • Module nào nên dùng chung cấu hình

Mọi thứ đều do người dùng tự tổ chức.

Điều này mang lại sự linh hoạt rất lớn, nhưng cũng khiến việc quản lý trở nên khó khăn khi hệ thống ngày càng mở rộng.


Terraform cũng không quản lý Repository

Terraform chỉ đọc thư mục hiện tại.

Ví dụ:

terraform apply

Terraform sẽ đọc:

.
├── main.tf
├── variables.tf
└── outputs.tf

Nó không quan tâm:

company-iac/

projects/
platform/
network/
production/

hay

live/
modules/
shared/

được tổ chức như thế nào.

Terraform cũng không áp đặt:

  • cách đặt tên thư mục
  • cách chia module
  • cách quản lý environment
  • cách quản lý account
  • cách quản lý backend
  • cách chia repository

Điều đó có nghĩa là hai công ty đều dùng Terraform nhưng repository có thể hoàn toàn khác nhau.

Ví dụ:

Company A

production/
staging/
development/

Company B

aws/
azure/
gcp/

Company C

platform/
application/
security/
network/

Tất cả đều hợp lệ.

Terraform không hề kiểm tra điều này.


Khi hệ thống lớn dần

Hãy tưởng tượng một công ty có:

  • 4 AWS Account
  • 3 Region
  • 6 Environment
  • 80 Terraform Module

Nếu mỗi module đều có:

main.tf
providers.tf
backend.tf
versions.tf
variables.tf

thì tổng số file sẽ lên tới hàng trăm.

Điều đáng nói là phần lớn nội dung của chúng lại giống nhau.

Ví dụ:

Backend giống nhau.

code
terraform {
  backend "s3" {
    bucket = "company-state"
  }
}

Provider giống nhau.

code
provider "aws" {
  region = "ap-southeast-1"
}

Version giống nhau.

code
terraform {
  required_version = ">= 1.8"
}

Tags giống nhau.

code
tags = {
  ManagedBy = "Terraform"
}

Chỉ cần thay đổi một quy định nhỏ, chẳng hạn:

  • đổi bucket chứa State
  • nâng phiên bản Provider
  • thêm một Tag bắt buộc
  • thay đổi cấu hình Assume Role

bạn có thể phải cập nhật hàng chục hoặc hàng trăm thư mục.

Đây không phải là vấn đề của Terraform.

Đơn giản là Terraform chưa bao giờ được thiết kế để quản lý những quy ước ở cấp độ repository.


Những cách mọi người từng cố gắng giải quyết

Trước khi Terragrunt trở nên phổ biến, rất nhiều team đã tự xây dựng cách tổ chức riêng.

Ví dụ:

Dùng Symbolic Link.

backend.tf
↓

ln -s

Hoặc tạo script để copy file.

copy backend.tf

↓

100 folders

Một số team dùng Bash.

code
for dir in */ ; do
    cp backend.tf "$dir"
done

Một số khác dùng Makefile.

code
apply-all:

Hoặc tự viết wrapper bằng Python.

python deploy.py

Thậm chí có team xây dựng hẳn một công cụ nội bộ để quản lý Terraform.

Tất cả những cách làm này đều hướng tới cùng một mục tiêu:

Giảm việc lặp cấu hình và giúp repository dễ quản lý hơn.

Điều đó cho thấy nhu cầu này là có thật.

Và cũng chính từ những bài toán đó, Terragrunt được tạo ra.


Terragrunt không thay thế Terraform

Đây là điều rất nhiều người mới học thường hiểu nhầm.

Terragrunt không phải là phiên bản mới của Terraform.

Terragrunt cũng không tạo Resource.

Nó không gọi API của AWS.

Không quản lý State.

Không tính Dependency Graph.

Không thực hiện Provision Infrastructure.

Thực tế, quy trình vẫn là:

Terragrunt

↓

Terraform

↓

Cloud Provider

Hay nói cách khác:

Terragrunt chỉ đứng phía trước Terraform.

Nó giúp:

  • chuẩn bị cấu hình
  • tổ chức repository
  • giảm lặp code
  • truyền biến
  • quản lý nhiều module
  • quản lý nhiều environment

Cuối cùng, chính Terraform mới là công cụ thực hiện planapply.

Vì vậy, nếu chưa hiểu Terraform thì cũng sẽ rất khó sử dụng Terragrunt hiệu quả.

Terragrunt được sinh ra để bổ sung cho Terraform, chứ không phải để thay thế Terraform.

Terragrunt giải quyết điều gì?

Nếu phải mô tả Terragrunt bằng một câu ngắn gọn, mình sẽ nói:

Terragrunt là một lớp quản lý (wrapper) giúp Terraform dễ sử dụng hơn trong các dự án thực tế.

Nó không thay đổi cách Terraform hoạt động.

Nó chỉ giúp chúng ta giảm những công việc lặp đi lặp lại mà Terraform không xử lý.

Ví dụ:

Thay vì mỗi module đều phải khai báo Backend:

code
terraform {
  backend "s3" {
    bucket = "company-state"
    key    = "..."
    region = "ap-southeast-1"
  }
}

Terragrunt cho phép định nghĩa một lần và tái sử dụng ở nhiều nơi.

Tương tự với:

  • Provider
  • Common Variables
  • Common Tags
  • Remote State
  • Provider Version
  • Naming Convention

Điều này giúp repository gọn gàng hơn rất nhiều.


Những khả năng nổi bật của Terragrunt

Trong những bài tiếp theo của series, chúng ta sẽ đi sâu vào từng tính năng.

Ở thời điểm này, chỉ cần hình dung Terragrunt có thể hỗ trợ:

Giảm lặp cấu hình

Một cấu hình dùng chung có thể được chia sẻ cho toàn bộ repository.

Root Configuration
        │
        ├── Dev
        ├── Staging
        └── Production

Thay vì copy cùng một đoạn HCL vào hàng chục thư mục.


Quản lý nhiều Environment

Một repository có thể chứa:

live/

dev/

staging/

production/

Terragrunt giúp các môi trường này kế thừa cùng một cấu hình gốc nhưng vẫn dễ dàng ghi đè những giá trị cần thiết.


Quản lý nhiều Account và Region

Ví dụ:

AWS

Production
    ap-southeast-1
    us-east-1

Development
    ap-southeast-1

Terragrunt giúp việc tổ chức những cấu trúc như vậy trở nên rõ ràng hơn.


Chạy nhiều Module theo đúng thứ tự

Ví dụ:

Network
     ↓
Database
     ↓
EKS
     ↓
Applications

Terragrunt có thể hỗ trợ chạy các module theo đúng thứ tự phụ thuộc mà không cần bạn thực hiện thủ công từng thư mục.


Chuẩn hóa Repository

Một trong những lợi ích lớn nhất của Terragrunt là giúp toàn bộ team cùng làm việc theo một cấu trúc thống nhất.

Thay vì mỗi người tự nghĩ ra cách tổ chức repository riêng, cả team có thể sử dụng cùng một convention, giúp việc bảo trì và mở rộng về sau dễ dàng hơn.


Có phải dự án nào cũng cần Terragrunt?

Câu trả lời là:

Không.

Nếu dự án của bạn chỉ có:

  • một môi trường
  • vài resource
  • một hoặc hai module

thì Terraform thuần thường đã là lựa chọn đơn giản và hiệu quả.

Việc bổ sung thêm Terragrunt trong trường hợp này có thể khiến dự án phức tạp hơn mức cần thiết.

Ngược lại, khi hệ thống bắt đầu có:

  • nhiều environment
  • nhiều cloud account
  • nhiều region
  • nhiều team cùng phát triển
  • hàng chục hoặc hàng trăm module

thì việc quản lý chỉ bằng Terraform sẽ dần trở nên khó khăn.

Đó là lúc Terragrunt phát huy giá trị.

Điều quan trọng cần nhớ là:

Đừng sử dụng Terragrunt chỉ vì "mọi người đều dùng".

Hãy sử dụng nó khi những bài toán mà Terragrunt giải quyết thực sự xuất hiện trong dự án của bạn.


Tổng kết

Terraform là một công cụ tuyệt vời để quản lý hạ tầng.

Nhưng Terraform tập trung vào việc provision infrastructure, chứ không nhằm mục tiêu quản lý toàn bộ cấu trúc của một repository lớn.

Khi số lượng module, environment và cloud account tăng lên, việc lặp cấu hình và tổ chức repository sẽ trở thành một thách thức.

Terragrunt ra đời để giải quyết chính những bài toán đó bằng cách bổ sung một lớp quản lý phía trên Terraform, giúp giảm lặp, chuẩn hóa cấu trúc và đơn giản hóa việc vận hành các hệ thống Infrastructure as Code ở quy mô lớn.


Bài tiếp theo

Ở bài tiếp theo, chúng ta sẽ bắt đầu đi sâu vào Terragrunt với câu hỏi đầu tiên:

Terragrunt là gì và nó hoạt động như thế nào?

Chúng ta sẽ tìm hiểu kiến trúc của Terragrunt, cách nó hoạt động cùng Terraform, đồng thời xây dựng project Terragrunt đầu tiên để hiểu rõ vai trò của công cụ này trong một hệ thống Infrastructure as Code hiện đại.

Bình luận

0/2000

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