← Tổng quan series

Dùng S3 làm standard backend

Tạo bucket backend đúng cách, bật versioning và locking, sau đó migrate một project từ local state sang S3.

Kiến trúc bootstrap

Có một vòng lặp nhỏ: muốn lưu state vào S3 thì bucket phải tồn tại, nhưng không nên để bucket tự quản lý state của chính nó. Vì vậy tạo backend infrastructure bằng một thư mục/bootstrap riêng hoặc provision một lần bằng quy trình được kiểm soát.

resource "aws_s3_bucket" "terraform_state" {
  bucket = "company-terraform-state-12345"
}

resource "aws_s3_bucket_versioning" "terraform_state" {
  bucket = aws_s3_bucket.terraform_state.id
  versioning_configuration { status = "Enabled" }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
  bucket = aws_s3_bucket.terraform_state.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

Trong môi trường yêu cầu kiểm soát khóa, dùng KMS key thay vì SSE-S3 và giới hạn IAM chỉ cho bucket/prefix cần thiết.

Khai báo backend

Với Terraform hiện đại, S3 backend hỗ trợ native lock file:

terraform {
  backend "s3" {
    bucket       = "company-terraform-state-12345"
    key          = "app/dev/terraform.tfstate"
    region       = "ap-southeast-1"
    use_lockfile = true
    encrypt      = true
  }
}

key phải khác cho từng account/môi trường. Không dùng cùng một key cho dev và production.

terraform init
# Nếu project đang có local state:
terraform init -migrate-state
terraform plan

Nếu tổ chức còn dùng cơ chế lock cũ, có thể gặp yêu cầu DynamoDB; hãy theo version Terraform/provider đang được phê duyệt thay vì copy một cấu hình cũ không kiểm tra.

IAM tối thiểu

Runner cần quyền đọc/ghi đúng object state và lock file, cộng với quyền tạo resource ứng dụng. Tách role bootstrap và role workload; đừng cấp AdministratorAccess chỉ vì chạy thử nhanh rồi quên hạ quyền.

Ví dụ tư duy phân quyền theo prefix:

company-terraform-state/
├── networking/dev/terraform.tfstate
├── payments/dev/terraform.tfstate
└── payments/prod/terraform.tfstate

Role của project payments-dev chỉ cần đọc/ghi prefix payments/dev/*; role production có approval và policy riêng. Đừng đặt state của toàn bộ công ty vào một key duy nhất, cũng đừng cho mọi developer quyền xóa bucket backend.

Kiểm tra backend trước khi giao cho team

terraform state pull > /tmp/app-state.json
terraform workspace show
terraform plan

Xóa file export sau khi kiểm tra vì nó là bản sao plaintext của state. Thử hai terminal chạy plan/apply cạnh nhau để xác nhận lock hoạt động; không dùng -lock=false để vượt qua lỗi lock trừ khi đang thực hiện recovery có runbook.

Checklist vận hành

  • Bucket bật block public access.
  • Versioning và encryption đã bật.
  • State key tách theo project/account/environment.
  • Có lock và không tắt lock để “cho chạy được”.
  • Có cách khôi phục version cũ khi state hỏng.

Xem bài nguồn S3 backend để đối chiếu cấu trúc triển khai mẫu.