Giao diện
Thực hành: State Management
🎯 Mục tiêu
🎯 Sau bài thực hành này, bạn sẽ:
- Cấu hình remote backend (S3 + DynamoDB) cho state storage
- Thực hiện state migration từ local sang remote
- Import resource tồn tại vào Terraform state
Mô tả bài tập
Team của bạn đang dùng local state — mỗi người có bản state riêng, gây conflict và corruption. Bạn cần migrate sang remote backend để team cộng tác an toàn, đồng thời import một số resource đã tạo thủ công vào Terraform quản lý.
Yêu cầu
Bài 1: Tạo Remote Backend Infrastructure
Trước khi dùng remote backend, cần tạo S3 bucket và DynamoDB table:
hcl
# backend-setup/main.tf
# Chỉ chạy 1 lần để bootstrap backend infrastructure
provider "aws" {
region = "ap-southeast-1"
}
resource "aws_s3_bucket" "terraform_state" {
bucket = "my-team-terraform-state"
# TODO: Bật versioning để recovery
# TODO: Bật server-side encryption
}
resource "aws_s3_bucket_versioning" "enabled" {
# TODO: Enable versioning
}
resource "aws_s3_bucket_server_side_encryption_configuration" "default" {
# TODO: AES256 encryption
}
resource "aws_s3_bucket_public_access_block" "public_access" {
# TODO: Block ALL public access
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-state-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}Bài 2: Migrate Local → Remote State
Sau khi backend infrastructure sẵn sàng, cấu hình project để dùng remote backend:
hcl
# main.tf — Thêm backend configuration
terraform {
backend "s3" {
bucket = "my-team-terraform-state"
key = "dev/infrastructure/terraform.tfstate"
region = "ap-southeast-1"
dynamodb_table = "terraform-state-locks"
encrypt = true
}
}Quy trình migration:
bash
# 1. Thêm backend config vào main.tf
# 2. Chạy init để migrate
terraform init -migrate-state
# 3. Xác nhận state đã chuyển
terraform state list
# 4. Xóa local state file (đã có trên remote)
# Terraform tự xử lý, nhưng verify trước khi xóa .terraform/Câu hỏi: State key nên theo convention nào? Tại sao dùng dev/infrastructure/ prefix?
Bài 3: Import Existing Resource
Đồng nghiệp đã tạo thủ công 1 S3 bucket qua console. Import vào Terraform:
hcl
# Step 1: Viết HCL resource block TRƯỚC
resource "aws_s3_bucket" "legacy_data" {
bucket = "legacy-data-bucket-12345"
tags = {
Name = "Legacy Data"
ManagedBy = "terraform"
}
}
# Step 2: Import
# TODO: Viết lệnh terraform importSau import, chạy terraform plan để kiểm tra drift:
bash
# Nếu plan hiển thị changes, cần cập nhật HCL cho khớp với actual state
terraform plan
# Mục tiêu: "No changes. Your infrastructure matches the configuration."Gợi ý
💡 Xem gợi ý
- Bài 1: S3 versioning cho phép recovery state file bị corrupt. DynamoDB cung cấp locking. Public access block là bắt buộc
- Bài 2:
terraform init -migrate-statetự động copy local state lên remote. Luôn backup state trước khi migrate - Bài 2: State key convention:
<env>/<component>/terraform.tfstate— phân tách theo environment và component - Bài 3: Syntax:
terraform import aws_s3_bucket.legacy_data legacy-data-bucket-12345. Sau import, chạy plan để phát hiện config drift - Lưu ý:
terraform importchỉ import state, KHÔNG generate HCL code (Terraform 1.5+ có import block)
Lời giải
✅ Xem lời giải
Bài 1: Backend Setup hoàn chỉnh
hcl
provider "aws" {
region = "ap-southeast-1"
}
resource "aws_s3_bucket" "terraform_state" {
bucket = "my-team-terraform-state"
tags = { Name = "Terraform State" }
}
resource "aws_s3_bucket_versioning" "enabled" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "default" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
}
}
}
resource "aws_s3_bucket_public_access_block" "public_access" {
bucket = aws_s3_bucket.terraform_state.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-state-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
tags = { Name = "Terraform Lock Table" }
}Bài 3: Import commands
bash
# Import existing bucket
terraform import aws_s3_bucket.legacy_data legacy-data-bucket-12345
# Check for drift
terraform plan
# Nếu có drift, cập nhật HCL cho khớp
# Terraform 1.5+ import block (khai báo trong HCL):
import {
to = aws_s3_bucket.legacy_data
id = "legacy-data-bucket-12345"
}