Ba trạng thái có thể khác nhau
Terraform không chỉ so code với state. Provider refresh state từ infrastructure thật rồi mới lập plan. Vì thế lỗi có thể đến từ:
- Resource tồn tại thật nhưng không có trong state.
- State còn ghi resource nhưng nó đã bị xóa ngoài cloud.
- Resource tồn tại, nhưng thuộc tính/tag/config bị sửa ngoài Terraform.
Quan sát trước, sửa sau
terraform state list
terraform state show aws_instance.app
terraform plan
Muốn cập nhật state theo remote mà chưa sửa infrastructure:
terraform plan -refresh-only
terraform apply -refresh-only
Hãy review output như một thay đổi production. Refresh-only không “sửa drift”; nó làm Terraform ghi nhận hiện trạng mới vào state, sau đó plan bình thường có thể đề xuất đưa code về trạng thái mong muốn.
Import resource có sẵn
Nếu một bucket đã được tạo tay, viết resource block trước rồi dùng import block:
resource "aws_s3_bucket" "existing" {
bucket = "company-existing-assets"
}
import {
to = aws_s3_bucket.existing
id = "company-existing-assets"
}
terraform plan
Sau khi import, plan có thể còn nhiều thay đổi vì code chưa mô tả hết cấu hình thật. Thêm dần các thuộc tính cần quản lý và xác nhận từng lần. Không import một resource production vào code sơ sài rồi apply ngay.
Resource đã bị xóa ngoài cloud
Nếu state vẫn có resource nhưng provider báo không tìm thấy, Terraform thường đề xuất tạo lại. Kiểm tra xem việc tạo lại có ảnh hưởng dữ liệu hay dependency không. Với resource đã chuyển quyền quản lý sang hệ thống khác, có thể dùng terraform state rm để bỏ khỏi state, nhưng lệnh này không xóa resource ngoài cloud và phải có approval:
terraform state rm aws_s3_bucket.legacy
Quy trình recovery
- Khóa thay đổi đồng thời.
- Backup/kiểm tra version state.
- Đọc audit log để biết thay đổi ngoài Terraform.
- Chọn import, sửa code, refresh-only hoặc state rm.
- Chạy plan và review dependency/destroy.
- Apply một thay đổi nhỏ, rồi kiểm tra lại plan.
Khi nào dùng moved block?
Nếu chỉ đổi địa chỉ trong code, ví dụ đưa resource vào module, không nên để Terraform hiểu đó là xóa và tạo lại:
moved {
from = aws_s3_bucket.assets
to = module.storage.aws_s3_bucket.this
}
Chạy plan để xác nhận Terraform ghi nhận move, không có destroy/create. Giữ moved block đủ lâu cho mọi branch/workspace đã nâng cấp; sau đó có thể dọn theo chính sách của team. Đây là cách an toàn hơn so với sửa state thủ công.
Bài tập recovery không phá dữ liệu
Tạo một bucket test, import vào state, thêm một tag ngoài Console, chạy plan để thấy drift, rồi cập nhật code cho khớp. Cuối cùng chạy terraform plan -refresh-only và xác nhận no-op. Không thực hành state rm, import hoặc refresh trên production nếu chưa có backup và người thứ hai review.
Xem bài nguồn về Terraform state và infrastructure thật. Với state production, không sửa JSON thủ công nếu chưa có quy trình recovery được phê duyệt.