IaCInfrastructure as Coderemote state backendterraform state

Terraform Remote State Backends — Nền tảng của mọi dự án Terraform Production

Tìm hiểu Terraform Remote State Backend, lý do vì sao Local State không phù hợp cho production và cách Remote Backend trở thành nền tảng cho mọi dự án Terraform chuyên nghiệp.

22 thg 7, 202611 min readCập nhật 22 thg 7, 2026
Terraform Remote State Backends — Nền tảng của mọi dự án Terraform Production

Terraform Remote State Backends — Nền tảng của mọi dự án Terraform Production

Ở bài trước, chúng ta đã tìm hiểu cách đưa những hạ tầng đang tồn tại vào Terraform bằng terraform import.

Sau khi import thành công, Terraform bắt đầu quản lý toàn bộ Infrastructure thông qua Terraform State.

Nhưng lúc này sẽ xuất hiện một câu hỏi quan trọng hơn rất nhiều.

Terraform State nên được lưu ở đâu?

Nếu chỉ làm việc một mình trên máy cá nhân, câu trả lời khá đơn giản.

terraform.tfstate

Nhưng khi project bắt đầu có:

  • nhiều developer
  • nhiều môi trường
  • CI/CD Pipeline
  • nhiều repository
  • nhiều team cùng quản lý Infrastructure

thì việc lưu State trên laptop gần như chắc chắn sẽ dẫn tới vấn đề.

Đó là lý do gần như mọi dự án Terraform production đều bắt đầu bằng Remote State Backend.


Terraform State quan trọng đến mức nào?

Ở bài 3 chúng ta đã biết Terraform luôn hoạt động theo quy trình:

Configuration
       ↓
Terraform State
       ↓
Refresh
       ↓
Execution Plan
       ↓
Apply

Terraform không đọc trực tiếp Infrastructure.

Terraform luôn đọc State trước.

State chứa toàn bộ thông tin Terraform cần để hiểu Infrastructure hiện tại.

Ví dụ:

code
resource "aws_s3_bucket" "assets" {
  bucket = "company-assets"
}

Sau lần Apply đầu tiên, State sẽ lưu những thông tin tương tự:

code
{
  "resources": [
    {
      "type": "aws_s3_bucket",
      "name": "assets",
      "instances": [
        {
          "attributes": {
            "id": "company-assets",
            "arn": "arn:aws:s3:::company-assets"
          }
        }
      ]
    }
  ]
}

Terraform không cần đi tìm bucket nào thuộc resource nào.

Nó chỉ cần đọc State.

Có thể nói:

Configuration là mong muốn của chúng ta.

State là trí nhớ của Terraform.

Nếu State sai, Terraform sẽ đưa ra Execution Plan sai.


Local Backend hoạt động như thế nào?

Nếu chúng ta không cấu hình gì cả, Terraform sẽ sử dụng Local Backend.

terraform init

Sau lần Apply đầu tiên, project sẽ có thêm:

terraform.tfstate

Ví dụ:

infra/

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

Khi chạy:

code
terraform apply

Terraform sẽ thực hiện:

Read local state
        ↓
Refresh infrastructure
        ↓
Execution Plan
        ↓
Apply
        ↓
Update local state

Toàn bộ State chỉ tồn tại trên máy đang chạy Terraform.

Điều này hoàn toàn ổn khi:

  • học Terraform
  • sandbox
  • demo
  • PoC
  • project cá nhân

Nhưng production thì hoàn toàn khác.


Điều gì xảy ra khi có nhiều người cùng làm?

Giả sử team có hai DevOps.

Alice
Bob

Cả hai cùng clone repository.

terraform-project/

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

State không được commit lên Git.

Sau khi chạy Terraform.

Alice sẽ có:

main.tf
terraform.tfstate

Bob cũng có:

main.tf
terraform.tfstate

Nhìn thì giống nhau.

Nhưng thực tế đây là hai file hoàn toàn độc lập.


Alice chạy:

code
terraform apply

Terraform tạo thêm một EC2.

AWS thay đổi.

State của Alice được cập nhật.

EC2

ID = i-0123456789

State của Bob vẫn chưa biết điều này.

Bob tiếp tục chạy:

code
terraform apply

Terraform sẽ đọc:

Configuration
+
State của Bob

Sau đó mới Refresh Infrastructure.

Lúc này Terraform phải cố gắng reconcile giữa:

  • Infrastructure thật
  • Configuration
  • State đã cũ

Nếu project lớn, việc tính toán này hoàn toàn có thể tạo ra Execution Plan không còn chính xác.

Thậm chí trong nhiều trường hợp Terraform sẽ nghĩ rằng một số Resource cần được tạo lại hoặc thay thế.

Không phải vì Terraform sai.

Mà vì State giữa các thành viên đã không còn giống nhau nữa.


Có nên commit terraform.tfstate lên Git?

Đây gần như là ý tưởng đầu tiên của mọi người khi gặp vấn đề này.

Nếu mọi người đều dùng chung State.

Vậy chỉ cần commit State lên Git.

Nghe khá hợp lý.

Ví dụ:

Alice vừa Apply.

terraform.tfstate

được cập nhật.

Alice commit:

code
git add terraform.tfstate
git commit
git push

Bob pull về.

Mọi thứ có vẻ ổn.

Nhưng thực tế đây là một trong những cách tệ nhất để quản lý Terraform State.


Git không phải Database

Git được thiết kế để quản lý Source Code.

Không phải để quản lý State.

Giả sử Alice và Bob cùng pull phiên bản mới nhất.

State hiện tại:

Version 25

Alice chạy:

code
terraform apply

Bob cũng chạy:

code
terraform apply

Hai người đều bắt đầu từ cùng một State.

Version 25

Alice Apply xong.

State trở thành:

Version 26

Bob vẫn đang chạy dựa trên Version 25.

Một lúc sau Bob cũng hoàn thành.

State của Bob ghi đè lên Version 26.

Version 25

├── Alice
│     ↓
│   Version 26
│
└── Bob
      ↓
    Version 26

Git chỉ phát hiện conflict khi commit.

Nhưng Infrastructure đã thay đổi từ trước đó.

Git hoàn toàn không thể ngăn hai tiến trình Terraform cùng sửa State.

Đây chính là vấn đề mà Remote Backend sẽ giải quyết bằng State Locking.


Terraform State còn chứa nhiều dữ liệu nhạy cảm

Rất nhiều người nghĩ State chỉ lưu Resource ID.

Thực tế không phải vậy.

State có thể chứa:

  • ARN
  • Internal IP
  • Database Endpoint
  • Resource ID
  • Outputs
  • Provider Metadata
  • Connection String
  • Username
  • Certificate
  • Password được generate
  • Access Token

Ví dụ:

code
resource "random_password" "database" {
  length  = 32
  special = true
}

Cho dù Output được đánh dấu là:

code
output "database_password" {
  value     = random_password.database.result
  sensitive = true
}

Terraform vẫn phải lưu giá trị thật vào State.

Nếu không lưu.

Terraform sẽ không thể biết Password hiện tại là gì.

Điều đó có nghĩa:

  • bất kỳ ai đọc được State đều có thể đọc Secret
  • commit lên Git sẽ lưu Secret vào History
  • việc xóa Secret khỏi Git sau này gần như không đơn giản

Đó cũng là lý do HashiCorp luôn khuyến nghị:

Không sử dụng Git để lưu Terraform State.


Production cần điều gì?

Một Production-grade Terraform project cần nhiều hơn một file JSON.

State cần phải:

  • có một nguồn dữ liệu duy nhất
  • nhiều người cùng truy cập được
  • tự động khóa khi Apply
  • có Versioning
  • có Backup
  • được mã hóa
  • có phân quyền
  • hoạt động tốt với CI/CD

Đó chính là mục tiêu của Terraform Remote State Backend.

Remote State Backend hoạt động như thế nào?

Ý tưởng của Remote State Backend thực ra khá đơn giản.

Thay vì lưu State trên máy của từng developer.

Terraform sẽ lưu State vào một nơi dùng chung.

              Terraform Apply

                     │
                     ▼

          Read Remote State
                     │
                     ▼
        Refresh Infrastructure
                     │
                     ▼
          Execution Plan
                     │
                     ▼
             Apply Changes
                     │
                     ▼
         Update Remote State

Developer không còn sở hữu State nữa.

State trở thành tài nguyên dùng chung của toàn bộ team.

Ví dụ:

             Alice
                │
                │
             Bob
                │
                │
            GitHub Actions
                │
                ▼
      Remote State Backend
                │
                ▼
         terraform.tfstate

Bất kỳ ai chạy Terraform cũng sẽ đọc cùng một State.

Điều này giúp mọi người luôn làm việc trên cùng một phiên bản Infrastructure.


Backend chỉ lưu State

Đây là một hiểu nhầm khá phổ biến.

Remote Backend không chạy Terraform.

Remote Backend cũng không tạo Infrastructure.

Nó chỉ chịu trách nhiệm lưu trữ Terraform State.

Terraform vẫn chạy trên:

  • máy developer
  • GitHub Actions
  • GitLab CI
  • Jenkins
  • Azure DevOps
  • hoặc bất kỳ Runner nào

Backend chỉ đóng vai trò giống như một "database" dành cho State.

Terraform CLI
      │
      ├── AWS API
      ├── Azure API
      ├── GCP API
      │
      ▼
Infrastructure

Terraform CLI
      │
      ▼
Remote Backend
      │
      ▼
Terraform State

Đây cũng là lý do nếu Backend gặp sự cố.

Infrastructure của bạn vẫn tồn tại.

Chỉ có Terraform không thể tiếp tục quản lý Infrastructure đó cho đến khi State được khôi phục.


State Locking là gì?

Đây là tính năng quan trọng nhất của Remote Backend.

Giả sử Alice đang chạy:

code
terraform apply

Terraform sẽ thực hiện:

Acquire Lock
       ↓
Read State
       ↓
Refresh
       ↓
Plan
       ↓
Apply
       ↓
Update State
       ↓
Release Lock

Trong toàn bộ quá trình này.

State bị khóa.

Nếu Bob cũng chạy:

code
terraform apply

Terraform sẽ nhận được thông báo tương tự:

Error acquiring the state lock

Bob phải đợi cho đến khi Alice hoàn thành.

Điều này đảm bảo rằng tại một thời điểm chỉ có một tiến trình được phép cập nhật State.


Vì sao State Locking quan trọng?

Giả sử không có Lock.

Alice và Bob cùng chạy:

code
terraform apply

Cả hai đều đọc:

State Version 100

Alice tạo thêm:

EC2 Instance

Bob tạo thêm:

Security Group

Alice ghi State mới.

Version 101

Bob cũng ghi State mới.

Version 101

State cuối cùng chỉ chứa thay đổi của người ghi sau cùng.

Một trong hai thay đổi sẽ biến mất khỏi State.

Infrastructure thật vẫn tồn tại.

Nhưng Terraform không còn biết chính xác Infrastructure đang ở trạng thái nào.

Đây được gọi là State Corruption.

Một khi State bị hỏng.

Việc khôi phục thường rất tốn thời gian.

Nhiều trường hợp phải Import lại toàn bộ Infrastructure.


Force Unlock có nên dùng không?

Đôi khi bạn sẽ gặp lỗi:

code
Error acquiring the state lock

Nguyên nhân có thể là:

  • tiến trình Terraform vẫn đang chạy
  • CI/CD bị hủy giữa chừng
  • mất kết nối mạng
  • runner bị crash

Terraform cung cấp:

code
terraform force-unlock LOCK_ID

Lệnh này xóa Lock thủ công.

Tuy nhiên.

Đây là lệnh chỉ nên dùng khi chắc chắn không còn tiến trình Terraform nào đang chạy.

Nếu force unlock trong khi một tiến trình khác vẫn đang Apply.

Bạn có thể khiến hai tiến trình cùng ghi State.

Kết quả cũng giống như không có State Locking.

Vì vậy.

Đừng xem force-unlock là cách sửa lỗi mặc định.

Hãy luôn kiểm tra xem tiến trình Terraform trước đó đã thực sự kết thúc hay chưa.


Versioning của Remote Backend

Một ưu điểm rất lớn của Remote Backend là State có thể được lưu theo nhiều phiên bản.

Ví dụ.

State hiện tại là:

Version 52

Sau khi Apply.

Backend tạo:

Version 53

Nếu phát hiện State mới bị lỗi.

Bạn vẫn có thể lấy lại Version trước đó.

Điều này đặc biệt hữu ích khi:

  • import sai Resource
  • move Resource nhầm
  • apply sai Workspace
  • xóa nhầm Resource khỏi State
  • migration Backend thất bại

Tất nhiên.

Khôi phục State luôn cần thực hiện cẩn thận.

Nhưng việc có Version History vẫn tốt hơn rất nhiều so với chỉ có một file trên laptop.


Các Remote Backend phổ biến

Terraform hỗ trợ rất nhiều Backend.

Trong thực tế, phổ biến nhất là:

BackendCloud
Amazon S3AWS
Azure Blob StorageAzure
Google Cloud StorageGoogle Cloud
HCP TerraformHashiCorp

Ngoài ra còn có:

  • Consul
  • PostgreSQL
  • Kubernetes
  • HTTP Backend
  • S3-compatible Storage (MinIO, Cloudflare R2...)

Tuy nhiên.

Khoảng 90% dự án production hiện nay sẽ sử dụng một trong bốn Backend đầu tiên.


Amazon S3 Backend

Đây là Backend phổ biến nhất.

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

Thông thường người ta sẽ kết hợp thêm:

  • S3 Versioning
  • Server-side Encryption
  • IAM Policy
  • DynamoDB (Terraform < 1.10)

hoặc S3 Native Locking trên các phiên bản Terraform mới.


Azure Blob Storage

Nếu làm việc trên Azure.

Thông thường Backend sẽ là Azure Blob Storage.

code
terraform {
  backend "azurerm" {
    resource_group_name  = "terraform"
    storage_account_name = "tfstateprod"
    container_name       = "state"
    key                  = "production.tfstate"
  }
}

Azure Blob hỗ trợ Locking thông qua Blob Lease.

Developer không cần cấu hình thêm.


Google Cloud Storage

Google Cloud cũng cung cấp Backend riêng.

code
terraform {
  backend "gcs" {
    bucket = "terraform-state-production"
    prefix = "network"
  }
}

GCS hỗ trợ Versioning rất tốt và được sử dụng khá phổ biến trong các dự án chạy trên Google Cloud.

HCP Terraform (Terraform Cloud)

Nếu bạn không muốn tự quản lý Backend.

HashiCorp cung cấp HCP Terraform (trước đây là Terraform Cloud).

Thay vì tự tạo S3, Azure Blob hay GCS.

Terraform sẽ lưu State trực tiếp trên nền tảng của HashiCorp.

Ví dụ:

code
terraform {
  cloud {
    organization = "my-company"
 
    workspaces {
      name = "production-network"
    }
  }
}

Ngoài việc lưu State, HCP Terraform còn hỗ trợ:

  • Remote Execution
  • Workspace Management
  • Variables Management
  • Policy as Code
  • Cost Estimation
  • Team Access Control
  • Audit Log
  • Run History

Nếu team đã sử dụng HCP Terraform thì gần như không cần tự xây dựng hạ tầng Backend nữa.


Chuyển từ Local State sang Remote Backend

Một điều khiến nhiều người lo lắng là:

Nếu project đang dùng Local State thì có phải tạo lại Infrastructure không?

Câu trả lời là không.

Terraform hỗ trợ migrate State rất dễ dàng.

Ví dụ:

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

Sau khi thêm Backend.

Chạy lại:

code
terraform init

Terraform sẽ phát hiện Backend đã thay đổi.

Backend configuration changed.

Do you want to copy the existing state to the new backend?

Chỉ cần xác nhận:

yes

Terraform sẽ:

Read Local State
        ↓
Upload State
        ↓
Configure Backend
        ↓
Switch to Remote Backend

Infrastructure hoàn toàn không bị ảnh hưởng.

Chỉ có vị trí lưu State được thay đổi.


Những lưu ý khi migrate

Quá trình migrate khá đơn giản.

Tuy nhiên vẫn có một vài nguyên tắc quan trọng.

Chỉ migrate khi không có ai đang Apply

Đừng migrate trong khi:

  • CI/CD đang chạy
  • một developer khác đang Apply
  • có nhiều Pull Request cùng deploy

Thời điểm tốt nhất là:

  • maintenance window
  • sau khi merge xong
  • hoặc trước khi team bắt đầu làm việc

Backup Local State

Trước khi migrate.

Hãy luôn tạo một bản sao.

Ví dụ:

code
cp terraform.tfstate terraform.tfstate.backup

Terraform vốn đã tạo file backup trong nhiều trường hợp.

Tuy nhiên việc tự tạo thêm một bản backup gần như không tốn chi phí nhưng có thể giúp bạn tránh rất nhiều rủi ro.


Không chỉnh sửa State bằng tay

State là dữ liệu nội bộ của Terraform.

Nếu mở file .tfstate bạn sẽ thấy đây chỉ là một file JSON.

Nhưng điều đó không có nghĩa chúng ta nên chỉnh sửa trực tiếp.

Ví dụ:

code
{
  "resources": [
    ...
  ]
}

Chỉ cần thay đổi sai một Resource Address hoặc Resource ID.

Terraform có thể:

  • tạo lại Resource
  • mất Mapping
  • không còn quản lý đúng Infrastructure

Nếu cần thao tác với State.

Hãy sử dụng các lệnh mà Terraform cung cấp.

Ví dụ:

code
terraform state list
code
terraform state mv
code
terraform state rm
code
terraform state show

Thay vì sửa JSON bằng tay.


Best Practices cho Remote State

Sau khi làm việc với Terraform trong nhiều dự án production.

Đây là những nguyên tắc gần như luôn được áp dụng.

Mỗi môi trường nên có State riêng

Đừng để:

dev
staging
production

dùng chung một State.

Thay vào đó.

dev.tfstate

staging.tfstate

production.tfstate

hoặc:

dev/network.tfstate

staging/network.tfstate

production/network.tfstate

Điều này giúp cô lập hoàn toàn từng môi trường.


Bật Versioning

Nếu Backend hỗ trợ Versioning.

Hãy luôn bật.

Ví dụ với Amazon S3.

Bucket Versioning
Enabled

Nếu State bị ghi sai.

Bạn vẫn có thể lấy lại phiên bản cũ.


Bật Encryption

Terraform State có thể chứa dữ liệu nhạy cảm.

Vì vậy Backend nên được mã hóa.

Ví dụ:

  • S3 Server-side Encryption
  • Azure Storage Encryption
  • Google Cloud Encryption

Đây gần như là yêu cầu bắt buộc đối với production.


Phân quyền truy cập

Không phải ai cũng cần quyền ghi State.

Ví dụ.

Developer chỉ cần:

Read
Plan

CI/CD mới là nơi thực hiện:

Apply

Việc giới hạn quyền sẽ giảm đáng kể nguy cơ thao tác nhầm trên production.


Không commit State lên Git

Đây là nguyên tắc quan trọng nhất.

Repository chỉ nên chứa:

  • Terraform Configuration
  • Modules
  • Variables
  • Documentation

Không nên chứa:

terraform.tfstate

terraform.tfstate.backup

Thông thường các file này sẽ được đưa vào:

code
*.tfstate
*.tfstate.*

Tổng kết

Terraform State chính là "bộ não" của Terraform.

Nếu Configuration mô tả Infrastructure mong muốn, thì State mô tả Infrastructure mà Terraform đang quản lý.

Khi làm việc một mình, Local State có thể là đủ.

Nhưng khi dự án bắt đầu có nhiều developer, CI/CD và nhiều môi trường, Remote State Backend gần như trở thành một thành phần bắt buộc.

Nó mang lại:

  • Single Source of Truth
  • State Locking
  • Versioning
  • Encryption
  • Team Collaboration
  • CI/CD Integration

Có thể nói:

Một dự án Terraform production gần như luôn bắt đầu bằng việc thiết lập Remote State Backend trước khi quản lý bất kỳ Infrastructure nào.


Ở bài tiếp theo, chúng ta sẽ không nói về thêm tính năng mới của Terraform nữa, mà sẽ nhìn lại những sai lầm phổ biến mà mình từng mắc phải khi sử dụng Terraform trong các dự án thực tế, từ quản lý State, cấu trúc project cho đến cách tổ chức Module và Workflow.

Bình luận

0/2000

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