Khi quy mô dự án mở rộng với nhiều kỹ sư DevOps và các pipeline CI/CD cùng tham gia quản trị hạ tầng, mô hình Local State (local backend) trở thành "quả bom nổ chậm". Hai kỹ sư cùng chạy terraform apply một lúc có thể ghi đè state lẫn nhau (Race Condition), làm hỏng serial, và khiến dữ liệu hạ tầng bị mất đồng bộ hoàn toàn.
Để giải quyết triệt để bài toán làm việc nhóm và bảo vệ tính toàn vẹn của hệ thống, AWS S3 Backend kết hợp DynamoDB State Locking là tiêu chuẩn công nghiệp bắt buộc. Trong bài viết này, chúng ta sẽ phân tích kiến trúc hoạt động, cấu hình chuẩn Enterprise với mã hóa SSE-KMS, giải mã cơ chế Mutex Lock của DynamoDB, và hướng dẫn quy trình Di trú State (Backend Migration) an toàn 100%.
1. Kiến Trúc Tổng Thể S3 Backend & DynamoDB State Locking
Mô hình Remote Backend phân tách rõ ràng giữa nơi lưu trữ dữ liệu (Storage Layer - S3) và cơ chế phân xử khóa đồng thời (Locking Layer - DynamoDB):
1.1. Vai Trò Của Từng Thành Phần
- AWS S3 Bucket: Kho lưu trữ bền vững đạt độ tin cậy 99.999999999% (11 số 9), hỗ trợ Server-Side Encryption (SSE-KMS / SSE-S3) bảo vệ plaintext secrets, và S3 Versioning cho phép khôi phục bất kỳ bản snapshot nào trong quá khứ khi xảy ra sự cố.
- AWS DynamoDB Table: Hoạt động như một trọng tài khóa phân tán (Distributed Mutex Lock). DynamoDB sử dụng cơ chế điều kiện ghi (Conditional Writes) để đảm bảo chỉ duy nhất một tiến trình ghi được bản ghi khóa tại một thời điểm.
2. Giải Mã Bản Ghi Khóa (Lock Info) Trong DynamoDB
Khi Terraform chiếm giữ khóa, nó ghi một item vào DynamoDB với Partition Key bắt buộc là LockID = "<bucket-name>/<state-key>-md5". Nội dung trường Info chứa chi tiết siêu dữ liệu của tiến trình:
{
"ID": "b3e9447d-8153-4811-9a7e-cb9192451390",
"Operation": "OperationTypeApply",
"Info": "",
"Who": "kiennt@devops-workstation.local",
"Version": "1.7.5",
"Created": "2026-09-06T04:45:12.128456Z",
"Path": "ntk-prod-tfstate/vpc/production.tfstate"
}
Quy ước Schema DynamoDB: Bảng DynamoDB dùng cho State Lock bắt buộc phải đặt tên Partition Key là LockID với kiểu dữ liệu String (S). Mã nguồn Terraform Core S3 Backend đã được hardcode để truy vấn chính xác tên này. Nếu bạn đặt tên là id, LockId, hoặc lock_id, Terraform sẽ báo lỗi schema mismatch và không thể acquire lock.
3. Cấu Hình S3 Backend Chuẩn Enterprise
Dưới đây là kiến trúc cấu hình chuẩn production đáp ứng các tiêu chuẩn bảo mật khắt khe nhất (CIS AWS Benchmark & SOC2):
# File: bootstrap/backend-storage.tf (Tạo hạ tầng lưu trữ S3 + DynamoDB)
resource "aws_s3_bucket" "terraform_state" {
bucket = "ntk-enterprise-terraform-state-prod"
force_destroy = false # Ngăn chặn việc xóa nhầm bucket chứa state
lifecycle {
prevent_destroy = true
}
}
# 1. Bắt buộc bật Versioning để có khả năng Rollback
resource "aws_s3_bucket_versioning" "state_versioning" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
# 2. Bắt buộc mã hóa tại chỗ bằng KMS
resource "aws_s3_bucket_server_side_encryption_configuration" "state_encryption" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
# 3. Chặn hoàn toàn Public Access
resource "aws_s3_bucket_public_access_block" "state_public_block" {
bucket = aws_s3_bucket.terraform_state.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# 4. DynamoDB Lock Table chuẩn HashiCorp
resource "aws_dynamodb_table" "terraform_locks" {
name = "ntk-terraform-lock-table"
billing_mode = "PAY_PER_REQUEST" # Tiết kiệm chi phí tối đa
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
4. Kỹ Thuật Partial Configuration (-backend-config)
Khối terraform { backend "s3" {} } không cho phép sử dụng biến var.* hoặc local.*. Nếu hardcode tên bucket và môi trường trực tiếp trong code, bạn sẽ vi phạm nguyên tắc DRY (Don't Repeat Yourself) và không thể tái sử dụng mã cho Dev/Staging/Prod.
Giải pháp chuẩn: Khai báo block backend rỗng và truyền tham số động lúc chạy init:
# File: backend.tf (Giữ khung rỗng trong mã nguồn Git)
terraform {
backend "s3" {}
}
Tạo các tệp cấu hình độc lập cho từng môi trường:
# File: env/prod/backend-prod.tfvars
bucket = "ntk-enterprise-terraform-state-prod"
key = "prod/vpc-network.tfstate"
region = "ap-southeast-1"
dynamodb_table = "ntk-terraform-lock-table"
encrypt = true
Khởi tạo môi trường linh hoạt qua CLI hoặc CI/CD:
# Khởi tạo cho Production
terraform init -backend-config="env/prod/backend-prod.tfvars"
# Khởi tạo cho Staging
terraform init -reconfigure -backend-config="env/staging/backend-staging.tfvars"
5. Quy Trình Di Trú State An Toàn (Backend Migration)
Khi chuyển đổi một dự án từ Local State lên S3 Remote Backend, hoặc chuyển đổi giữa hai Backend khác nhau, kỹ sư cần phân biệt rõ ràng giữa -migrate-state và -reconfigure:
Cạm bẫy chí mạng: Tuyệt đối không dùng -reconfigure khi bạn muốn chuyển dữ liệu từ Local lên S3. Lệnh -reconfigure sẽ trỏ tới S3 nhưng để lại file State trống rỗng. Khi chạy terraform plan sau đó, Terraform sẽ tưởng toàn bộ hạ tầng chưa tồn tại và đề xuất tạo mới đè lên hạ tầng thực tế!
6. Xử Lý Sự Cố Deadlock Với terraform force-unlock
Trong môi trường CI/CD, nếu một runner container bị sập nguồn (OOMKilled) hoặc mất mạng đột ngột giữa lúc apply, Terraform sẽ không kịp gửi API xóa bản ghi khóa trên DynamoDB. Các pipeline tiếp theo sẽ bị kẹt với thông báo:
Error: Error acquiring the state lock
Lock Info:
ID: b3e9447d-8153-4811-9a7e-cb9192451390
Path: ntk-prod-tfstate/vpc/production.tfstate
Operation: OperationTypeApply
Who: gitlab-runner-01@ip-10-0-12-88
Quy Trình Cứu Hộ An Toàn 4 Bước:
- Kiểm tra Dashboard CI/CD: Đảm bảo 100% job runner cũ đã bị terminate hoàn toàn, không còn tiến trình nào đang ghi ngầm vào hạ tầng.
- Kiểm tra CloudTrail: Xác minh không có API call nào liên quan đến tài nguyên diễn ra trong 15 phút qua.
- Sao lưu State: Tải snapshot state hiện tại trên S3 về máy an toàn bằng AWS CLI.
- Mở khóa cưỡng chế:
bash terraform force-unlock b3e9447d-8153-4811-9a7e-cb9192451390
Mẹo CI/CD: Luôn thêm tham số -lock-timeout=300s vào các lệnh terraform plan và terraform apply trong pipeline. Tham số này hướng dẫn Terraform kiên nhẫn thử lại trong 5 phút thay vì báo lỗi đỏ ngay tức khắc khi gặp tranh chấp khóa ngắn hạn.
7. Tổng Kết & Lộ Trình Tiếp Theo
Việc thiết lập Remote State trên S3 kết hợp DynamoDB State Locking là bước chuyển mình quan trọng từ việc sử dụng Terraform nghiệp dư sang vận hành IaC cấp độ Enterprise. Hệ thống này đảm bảo:
- Tính toàn vẹn: Không còn nỗi lo Race Condition hay ghi đè state giữa các thành viên.
- Bảo mật: Plaintext secrets được mã hóa tại chỗ và cách ly quyền truy cập qua IAM Policy.
- Khả năng phục hồi: S3 Versioning cho phép rollback nhanh chóng khi xảy ra thảm họa.
Trong bài viết tiếp theo, chúng ta sẽ bước vào thế giới "Phẫu thuật State Chuyên Sâu" với các lệnh terraform state mv, rm, show, list và kỹ thuật Import tài nguyên Legacy vào mã nguồn quản trị.
Bài viết thuộc Series đào tạo Terraform Thực Chiến độc quyền trên ShowTech.vn.