TLDR: Terraform lưu trữ thông tin tài nguyên trong tệp trạng thái (terraform.tfstate). Tệp này ánh xạ cấu hình của bạn tới cơ sở hạ tầng thực. Không bao giờ chỉnh sửa nó bằng tay. Sử dụng các lệnh terraform state để kiểm tra và sửa đổi trạng thái một cách an toàn. Giữ trạng thái an toàn - nó thường chứa dữ liệu nhạy cảm.

Tệp trạng thái của Terraform là thứ giúp nó hoạt động. Hiểu trạng thái là rất quan trọng vì các sự cố với trạng thái gây ra hầu hết các sự cố Terraform mà bạn sẽ gặp phải.

Trạng thái là gì?

Khi Terraform tạo một tài nguyên, nó sẽ ghi lại thông tin về tài nguyên đó trong tệp JSON có tên terraform.tfstate:

{
  "version": 4,
  "terraform_version": "1.6.5",
  "resources": [
    {
      "mode": "managed",
      "type": "aws_instance",
      "name": "web",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "attributes": {
            "id": "i-0123456789abcdef",
            "ami": "ami-0c55b159cbfafe1f0",
            "instance_type": "t3.micro",
            "public_ip": "54.123.45.67",
            "private_ip": "10.0.1.25"
          }
        }
      ]
    }
  ]
}

trạng thái này nói với Terraform:

  • Những tài nguyên nào nó quản lý
  • Các thuộc tính hiện tại của những tài nguyên đó
  • Sự phụ thuộc giữa các nguồn lực
  • Cấu hình nhà cung cấp được sử dụng

Không có trạng thái, Terraform không biết nó đã tạo ra cơ sở hạ tầng gì.

Tại sao trạng thái lại quan trọng

trạng thái phục vụ một số mục đích:

Ánh xạ cấu hình vào thực tế

Các tệp .tf của bạn mô tả những gì bạn muốn. trạng thái ghi lại những gì thực sự tồn tại. Terraform so sánh chúng để xác định những gì cần thay đổi.

Configuration (.tf)          State File             Real Infrastructure
┌────────────────┐          ┌────────────┐         ┌──────────────┐
│ resource       │          │ {          │         │  EC2 Instance│
│ "aws_instance" │  ══════> │   id:      │  ═════> │  i-abc123   │
│ "web" {        │  mapping │   "i-abc123│  tracks │  t3.micro   │
│   type = "t3   │          │   type:    │         │  10.0.1.5   │
│   .micro"      │          │   "t3.micro│         │             │
│ }              │          │ }          │         │             │
└────────────────┘          └────────────┘         └──────────────┘

Hiệu suất

Đối với cơ sở hạ tầng lớn, việc truy vấn mọi tài nguyên từ API nhà cung cấp sẽ chậm. trạng thái lưu trữ thông tin tài nguyên cục bộ.

Theo dõi siêu dữ liệu

trạng thái lưu trữ siêu dữ liệu như các phần phụ thuộc tài nguyên không hiển thị trong API của nhà cung cấp.

Phối hợp nhóm

Với trạng thái từ xa, các thành viên trong nhóm có thể xem cơ sở hạ tầng nào tồn tại và tránh xung đột.

Kiểm tra trạng thái

Xem trạng thái hiện tại của bạn với terraform show:

terraform show

Điều này hiển thị tất cả các tài nguyên và thuộc tính hiện tại của chúng:

# aws_instance.web:
resource "aws_instance" "web" {
    ami                    = "ami-0c55b159cbfafe1f0"
    instance_type          = "t3.micro"
    id                     = "i-0123456789abcdef"
    public_ip              = "54.123.45.67"
    private_ip             = "10.0.1.25"
    availability_zone      = "us-east-1a"
    # ... more attributes ...
}

Liệt kê tất cả các tài nguyên trong trạng thái:

terraform state list

Đầu ra:

aws_vpc.main
aws_subnet.public
aws_instance.web
aws_security_group.web

Hiển thị chi tiết về một tài nguyên cụ thể:

terraform state show aws_instance.web

Điều này hữu ích cho việc tìm kiếm các giá trị thuộc tính bạn cần tham khảo.

Hoạt động trạng thái

Terraform cung cấp các lệnh để thao tác trạng thái an toàn. Không bao giờ chỉnh sửa trực tiếp terraform.tfstate.

Di chuyển tài nguyên

Đổi tên tài nguyên trong cấu hình của bạn mà không hủy và tạo lại nó:

# You renamed this in your .tf file:
# resource "aws_instance" "web" { ... }
# to:
# resource "aws_instance" "web_server" { ... }

# Update state to match
terraform state mv aws_instance.web aws_instance.web_server

Bây giờ Terraform biết phiên bản hiện tại tương ứng với tên mới.

Di chuyển tài nguyên giữa các module:

terraform state mv aws_instance.web module.web_servers.aws_instance.web

Xóa tài nguyên khỏi trạng thái

Xóa tài nguyên khỏi trạng thái mà không hủy tài nguyên:

terraform state rm aws_instance.web

Phiên bản tiếp tục chạy nhưng Terraform không còn theo dõi nó nữa. Điều này rất hữu ích khi:

  • Di chuyển tài nguyên sang cấu hình Terraform khác
  • Xóa nội dung nào đó khỏi quản lý Terraform
  • Sửa lỗi trạng thái bị hỏng

Sau khi xóa, nếu bạn chạy terraform plan, Terraform sẽ muốn tạo lại tài nguyên (nó không thấy tài nguyên đó trong trạng thái). Xóa tài nguyên khỏi cấu hình của bạn hoặc nhập lại.

Nhập tài nguyên hiện có

Thêm cơ sở hạ tầng hiện có vào quản lý Terraform. Tạo cấu hình tài nguyên trước:

resource "aws_instance" "existing_server" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"

  # Other required properties
}

Nhập phiên bản hiện có:

terraform import aws_instance.existing_server i-0123456789abcdef

Terraform thêm phiên bản này vào trạng thái. Chạy terraform plan để xem cấu hình của bạn có khớp với tài nguyên thực hay không. Điều chỉnh tệp .tf của bạn cho đến khi plan không hiển thị thay đổi nào.

Nhập khẩu là tẻ nhạt đối với các tài nguyên phức tạp. Các công cụ như terraformer có thể tạo cả lệnh cấu hình và lệnh nhập từ cơ sở hạ tầng hiện có.

Thay thế tài nguyên

Buộc tái tạo tài nguyên:

terraform apply -replace="aws_instance.web"

Điều này phá hủy và tạo lại tài nguyên ngay cả khi không cần thay đổi. Hữu ích khi:

  • Tài nguyên đang ở trạng thái trạng thái không hợp lệ
  • Bạn cần kiểm tra quá trình giải trí
  • Áp dụng các thay đổi cấu hình mà Terraform không phát hiện được

Khóa trạng thái

Khi nhiều người làm việc trên cùng một cơ sở hạ tầng, khóa trạng thái sẽ ngăn ngừa xung đột. Nếu bạn chạy terraform apply trong khi một đồng đội chạy nó, bạn có thể đồng thời sửa đổi cơ sở hạ tầng, làm hỏng trạng thái.

Khóa trạng thái khiến Terraform có được khóa trước bất kỳ thao tác nào có thể ghi trạng thái. Nếu người khác giữ khóa, Terraform sẽ đợi hoặc thất bại.

Đối với trạng thái cục bộ (một người), không cần khóa. Đối với trạng thái backend từ xa, hầu hết đều hỗ trợ khóa:

Developer A               State Lock              Developer B
    │                         │                       │
    │  terraform apply        │                       │
    ├────────────────────────>│                       │
    │  Lock acquired          │                       │
    │<────────────────────────┤                       │
    │  Making changes...      │                       │
    │                         │  terraform apply      │
    │                         │<──────────────────────┤
    │                         │  Lock held by A       │
    │                         ├──────────────────────>│
    │                         │  Waiting...           │
    │  Complete, release lock │                       │
    ├────────────────────────>│                       │
    │                         │  Lock acquired        │
    │                         ├──────────────────────>│
    │                         │  Making changes...    │

Nếu Terraform gặp sự cố trong khi thao tác, khóa có thể không mở được. Buộc mở khóa nó:

terraform force-unlock LOCK_ID

Nhận LOCK_ID từ thông báo lỗi. Chỉ làm điều này nếu bạn chắc chắn không có ai khác đang chạy Terraform.

Vị trí lưu trữ trạng thái

Theo mặc định, Terraform lưu trữ trạng thái trong tệp cục bộ terraform.tfstate. Điều này phù hợp cho việc học tập cá nhân nhưng có vấn đề:

Security: Các tệp trạng thái chứa dữ liệu nhạy cảm (mật khẩu, khóa riêng). Bộ nhớ cục bộ khiến chúng dễ dàng vô tình tạo ra commit.

Collaboration: Các thành viên trong nhóm cần có quyền truy cập vào cùng một trạng thái. Truyền các tập tin xung quanh không có quy mô.

Reliability: Nếu máy tính xách tay của bạn chết, bạn sẽ mất trạng thái. Phục hồi là đau đớn.

Đối với các đội, hãy sử dụng backend từ xa (được đề cập ở phần sau). Hiện tại, hãy biết rằng trạng thái có thể được lưu trữ:

  • Cục bộ (mặc định)
  • Trong S3 có DynamoDB để khóa (AWS)
  • Trong bộ lưu trữ Azure Blob (Azure)
  • Trong Google Cloud Storage (GCP)
  • Trong đám mây Terraform
  • Trong backend khác (Lãnh sự, etcd, PostgreSQL)

Sao lưu trạng thái

Terraform tự động sao lưu trạng thái trước khi sửa đổi nó. Khi bạn chạy apply hoặc destroy, Terraform sẽ tạo terraform.tfstate.backup chứa trạng thái trước đó.

Nếu có sự cố xảy ra, bạn có thể khôi phục:

# Terraform made a bad change and current state is broken
cp terraform.tfstate.backup terraform.tfstate

Luôn giữ bản sao lưu khi làm việc với trạng thái. Đối với backend từ xa, nhiều phiên bản trạng thái tự động, cung cấp cho bạn lịch sử của tất cả các thay đổi.

Dữ liệu nhạy cảm trong trạng thái

Tệp trạng thái chứa mọi thứ về tài nguyên của bạn. Điều này bao gồm:

  • Mật khẩu và khóa API
  • Khóa riêng
  • Chuỗi kết nối cơ sở dữ liệu
  • Mọi cấu hình nhạy cảm

Không bao giờ commit trạng thái để kiểm soát phiên bản. Sử dụng .gitignore:

# .gitignore
.terraform/
*.tfstate
*.tfstate.backup
*.tfstate.lock.info

Đối với trạng thái từ xa, hãy sử dụng backend hỗ trợ mã hóa:

  • S3 với mã hóa phía máy chủ
  • Lưu trữ Azure Blob với mã hóa
  • Terraform Cloud (được mã hóa theo mặc định)
  • Google Cloud Storage có mã hóa

Đánh dấu các đầu ra nhạy cảm để chúng không xuất hiện trong nhật ký:

output "database_password" {
  value     = aws_db_instance.main.password
  sensitive = true
}

Các vấn đề và giải pháp phổ biến của trạng thái

Trạng thái không đồng bộ

Ai đó đã sửa đổi cơ sở hạ tầng bên ngoài Terraform (thông qua bảng điều khiển hoặc CLI). trạng thái không phù hợp với thực tế.

Solution: Làm mới trạng thái để đồng bộ với thực tế hiện tại:

terraform refresh

Hoặc sử dụng cách tiếp cận mới hơn:

terraform apply -refresh-only

Điều này cập nhật trạng thái mà không thực hiện thay đổi. Xem lại những gì đã thay đổi, sau đó sửa cấu hình của bạn cho phù hợp.

Tài nguyên trùng lặp

Terraform cố gắng tạo tài nguyên đã tồn tại.

Solution: Nhập tài nguyên hiện có:

terraform import resource_type.name resource_id

Tham nhũng trạng thái

Tệp trạng thái bị hỏng hoặc JSON không hợp lệ.

Solution: Khôi phục từ bản sao lưu:

cp terraform.tfstate.backup terraform.tfstate

Nếu không có bản sao lưu nào, hãy tạo lại trạng thái theo cách thủ công bằng cách nhập tài nguyên hoặc bắt đầu mới (rủi ro).

Đã xóa trạng thái

Bạn vô tình xóa terraform.tfstate.

Solution: Nếu bạn có bản sao lưu, hãy khôi phục chúng. Mặt khác:

  1. Tạo lại trạng thái theo cách thủ công bằng cách nhập từng tài nguyên
  2. Hoặc phá hủy toàn bộ cơ sở hạ tầng và tạo lại bằng terraform apply
  3. Đối với backend từ xa, khôi phục từ lịch sử phiên bản

Đây là lý do tại sao backend từ xa có phiên bản lại quan trọng.

Ví dụ thực tế: Quy trình làm việc trạng thái

Đây là một kịch bản thực tế:

# Create initial infrastructure
terraform init
terraform plan
terraform apply

# Check what you created
terraform state list

# See details about the web server
terraform state show aws_instance.web

# Rename the resource in your .tf file from "web" to "web_server"
# Update state to match
terraform state mv aws_instance.web aws_instance.web_server

# Verify the plan shows no changes
terraform plan

# Someone manually changed the instance type through AWS console
# Detect the drift
terraform plan

# See what changed
terraform refresh

# Fix the drift by reapplying
terraform apply

# Remove the instance from management but keep it running
terraform state rm aws_instance.web_server

# Later, bring it back under management
terraform import aws_instance.web_server i-0123456789abcdef

Hiểu sự phụ thuộc của trạng thái

trạng thái theo dõi các phụ thuộc tài nguyên để Terraform biết thứ tự tạo và phá hủy mọi thứ. Chạy terraform graph để hình dung:

terraform graph | dot -Tpng > graph.png

Điều này tạo ra sự trình bày trực quan về các phụ thuộc cơ sở hạ tầng của bạn. Bạn cần cài đặt graphviz (brew install graphviz trên macOS).

Phiên bản trạng thái

Terraform trạng thái có số phiên bản. Khi bạn nâng cấp Terraform, việc chạy bất kỳ lệnh nào cũng có thể nâng cấp trạng thái lên phiên bản mới:

Upgrading state from version 3 to version 4...

Các phiên bản Terraform cũ hơn không thể đọc các định dạng trạng thái mới hơn. Điều này có nghĩa là:

  • Phối hợp nâng cấp phiên bản Terraform trong nhóm của bạn
  • Ghim các phiên bản Terraform trong cấu hình của bạn
  • Thử nghiệm nâng cấp trong quá trình phát triển trước tiên

Ghim phiên bản Terraform:

terraform {
  required_version = "~> 1.6.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

quản lý trạng thái là một trong những khía cạnh phức tạp nhất của Terraform. Hiểu trạng thái, biết cách kiểm tra nó và cảm thấy thoải mái với các lệnh trạng thái sẽ giúp bạn tránh được nhiều vấn đề. Tiếp theo, chúng ta sẽ xem xét các biến số và kết quả đầu ra - cách tạo cấu hình linh hoạt và hiển thị thông tin hữu ích.