Khắc phục lỗi 'Error acquiring the state lock' trong Terraform

intermediate🏗️ Terraform2026-03-16| Linux, macOS, Windows với Terraform CLI, trạng thái từ xa (ví dụ: backend AWS S3 và DynamoDB)

Error Message

Error acquiring the state lock
#terraform#state#lock#dynamodb

TL;DR: Khắc phục nhanh

Khi bạn gặp thông báo "Error acquiring the state lock", điều này thường có nghĩa là một hoạt động Terraform khác đang diễn ra, hoặc một hoạt động trước đó đã gặp sự cố và để lại khóa lỗi thời. Để giải quyết nhanh trong trường hợp khẩn cấp, đặc biệt nếu bạn chắc chắn không có hoạt động hợp lệ nào khác đang chạy, bạn thường có thể force-unlock trạng thái. Lấy ID khóa từ thông báo lỗi và chạy:

terraform force-unlock <LOCK_ID>

Hãy cực kỳ thận trọng khi sử dụng force-unlock, vì việc sử dụng không đúng cách có thể dẫn đến hỏng trạng thái nếu một tiến trình khác thực sự đang giữ khóa.

Nguyên nhân gốc rễ chi tiết

Terraform sử dụng khóa trạng thái để ngăn các hoạt động đồng thời làm hỏng tệp trạng thái của bạn. Khi bạn chạy terraform plan, apply hoặc destroy, Terraform cố gắng giành quyền khóa trạng thái. Cơ chế này đảm bảo rằng chỉ một người hoặc một tiến trình có thể sửa đổi cơ sở hạ tầng tại bất kỳ thời điểm nào. Với các backend từ xa như AWS S3, một dịch vụ riêng biệt, thường là DynamoDB, được sử dụng để quản lý các khóa này.

Thông báo "Error acquiring the state lock" xuất hiện vì một số lý do:

  • Chạy đồng thời: Ai đó khác (hoặc một pipeline tự động khác) đang chạy lệnh Terraform trên cùng một tệp trạng thái cùng lúc.
  • Hoạt động bị lỗi: Một lệnh Terraform trước đó đã thất bại giữa chừng do sự cố, gián đoạn mạng hoặc chấm dứt thủ công (ví dụ: Ctrl+C). Khóa không được giải phóng một cách sạch sẽ.
  • Sự cố mạng: Terraform không thể giao tiếp với cơ chế khóa (ví dụ: DynamoDB) để giành quyền hoặc xác minh khóa.
  • Sự cố quyền: Người dùng hoặc vai trò IAM thực thi Terraform thiếu các quyền cần thiết để tương tác với bảng khóa DynamoDB hoặc S3 state bucket.

Về cơ bản, Terraform đang thực hiện nhiệm vụ của mình bằng cách từ chối tiếp tục, bảo vệ trạng thái cơ sở hạ tầng của bạn khỏi hư hại tiềm ẩn. Nhiệm vụ của chúng ta là tìm hiểu tại sao nó cho rằng mình không thể có được khóa đó.

Các phương pháp khắc phục

Phương pháp 1: Sử dụng terraform force-unlock (Cẩn thận!)

Đây thường là cách nhanh nhất để giải quyết khóa lỗi thời, nhưng nó tiềm ẩn rủi ro. Chỉ sử dụng phương pháp này nếu bạn hoàn toàn chắc chắn không có hoạt động Terraform hợp lệ nào khác đang hoạt động.

  • Xác định ID khóa: Thông báo lỗi thường chứa ID khóa. Nó trông giống như một UUID (ví dụ: 0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d).

Lỗi: Đang truy xuất khóa trạng thái

Thông báo lỗi: Không thể lấy khóa: Đã xảy ra lỗi (ConditionalCheckFailedException) khi gọi thao tác PutItem: Yêu cầu có điều kiện đã thất bại Thông tin khóa: ID: a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d Đường dẫn: some-s3-bucket/path/to/terraform.tfstate Thao tác: OperationTypeApply Ai: user@hostname Phiên bản: 1.0.0 Đã tạo: 2023-10-27 08:00:00 +0000 UTC Thông tin:

Terraform giành quyền khóa trạng thái để bảo vệ trạng thái khỏi bị cập nhật đồng thời bởi nhiều bản sao làm việc. Nếu bạn cho rằng khóa này bị lỗi, bạn có thể sử dụng lệnh "terraform force-unlock" để giải phóng nó.

  
  - 
    **Chạy `terraform force-unlock`:**

    ```bash
terraform force-unlock a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d

Terraform sẽ yêu cầu xác nhận. Gõ yes để tiếp tục.

Phương pháp 2: Kiểm tra các tiến trình Terraform đang hoạt động

Trước khi force-unlock, nên đảm bảo không có tiến trình Terraform nào khác đang chạy, đặc biệt là trong môi trường tự động hoặc nếu các thành viên khác trong nhóm có thể đang làm việc.

  • Tại cục bộ: Kiểm tra các tiến trình đang chạy trên máy của bạn. Trên Linux/macOS:

ps aux | grep terraform


Tìm kiếm bất kỳ tiến trình `terraform apply` hoặc `terraform plan` nào còn sót lại. Chấm dứt chúng nếu tìm thấy bằng cách sử dụng `kill <PID>`.

  
  - 
    **CI/CD Pipelines:** Nếu lỗi này xuất phát từ một job CI/CD, hãy kiểm tra nhật ký và trạng thái pipeline. Có thể có một job bị kẹt cần được hủy hoặc khởi động lại thủ công.

  

### Phương pháp 3: Xác minh bảng khóa DynamoDB (cho backend AWS S3)
Nếu bạn đang sử dụng AWS S3 cho trạng thái từ xa, Terraform sử dụng bảng DynamoDB để khóa. Kiểm tra bảng này có thể tiết lộ điều gì đang giữ khóa.

  - 
    **Truy cập DynamoDB:** Truy cập Bảng điều khiển quản lý AWS (AWS Management Console), điều hướng đến DynamoDB và tìm bảng Terraform sử dụng để khóa (thường có tên `terraform-lock` hoặc tương tự, được cấu hình trong backend của bạn). Xem các mục trong bảng.

    Ngoài ra, sử dụng AWS CLI:

    ```bash
aws dynamodb scan --table-name your-terraform-lock-table --query 'Items[*].LockID.S'

Thao tác này sẽ liệt kê các ID khóa đang hoạt động. So sánh chúng với ID trong thông báo lỗi của bạn.

  • Xóa mục khóa lỗi thời thủ công (Cực kỳ thận trọng!): Nếu bạn tìm thấy một mục khóa trong DynamoDB tương ứng với thông báo lỗi của mình và bạn hoàn toàn chắc chắn nó đã lỗi thời (nghĩa là không có hoạt động Terraform thực tế nào đang hoạt động), bạn có thể xóa nó trực tiếp từ bảng điều khiển DynamoDB hoặc sử dụng AWS CLI. Đây về cơ bản là những gì terraform force-unlock thực hiện.

aws dynamodb delete-item
--table-name your-terraform-lock-table
--key '{"LockID": {"S": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d"}}'


Chỉ xóa nếu bạn hiểu đầy đủ các hàm ý. Xóa một khóa đang hoạt động có thể dẫn đến hỏng dữ liệu.

  

### Phương pháp 4: Khả năng kết nối mạng và quyền IAM
Một vấn đề cơ bản hơn có thể đang ngăn Terraform kiểm tra khóa.

  - 
    **Kiểm tra khả năng kết nối mạng:** Đảm bảo máy chạy Terraform có quyền truy cập mạng đến các điểm cuối AWS S3 và DynamoDB. Điều này liên quan đến việc kiểm tra nhóm bảo mật, NACL, điểm cuối VPC hoặc cài đặt proxy.

  
  - 
    **Xác minh quyền IAM:** Thực thể IAM (người dùng hoặc vai trò) thực thi Terraform cần các quyền cụ thể cho S3 bucket (`s3:GetObject`, `s3:PutObject`, `s3:DeleteObject`, `s3:ListBucket`) và bảng khóa DynamoDB (`dynamodb:GetItem`, `dynamodb:PutItem`, `dynamodb:DeleteItem`, `dynamodb:DescribeTable`). Thiếu quyền ở đây sẽ chặn khóa và mở khóa trạng thái.

    ```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::your-terraform-state-bucket",
                "arn:aws:s3:::your-terraform-state-bucket/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:DeleteItem",
                "dynamodb:DescribeTable"
            ],
            "Resource": "arn:aws:dynamodb:<REGION>:<ACCOUNT_ID>:table/your-terraform-lock-table"
        }
    ]
}

Kiểm tra các chính sách đính kèm và đảm bảo chúng cấp quyền truy cập cần thiết. Sử dụng aws sts get-caller-identity để xác nhận thực thể IAM nào Terraform đang sử dụng.

Các bước xác minh

Sau khi cố gắng khắc phục, điều quan trọng là phải xác minh rằng vấn đề khóa đã được giải quyết và Terraform có thể hoạt động bình thường.

  • Chạy terraform plan: Thực thi một plan đơn giản. Nếu khóa được giải phóng hoặc giành quyền thành công, lệnh này sẽ chạy mà không gặp lỗi khóa.

terraform plan

  
  - 
    **Chạy `terraform apply -auto-approve -refresh=false` (nếu an toàn):** Để kiểm tra kỹ hơn trong môi trường phi sản xuất hoặc nếu plan của bạn thực sự là một no-op, bạn có thể thử apply nhanh. Cờ `-refresh=false` có thể tăng tốc độ này nếu bạn chỉ muốn kiểm tra cơ chế khóa, không phải làm mới trạng thái.

    ```bash
terraform apply -auto-approve -refresh=false
  • Giám sát DynamoDB: Nếu bạn đang theo dõi bảng DynamoDB, bạn sẽ thấy mục khóa xuất hiện khi plan hoặc apply bắt đầu và biến mất khi thao tác hoàn tất thành công.

Đọc thêm

Related Error Notes