0

[Terraform] Tìm hiểu về Terraform backend


Vấn đề

Terraform quản lý cơ sở hạ tầng dựa vào state, được lưu thành file mặc định là terraform.tfstate . Sẽ không có vấn đề nếu ta làm việc 1 mình, nhưng nếu có nhiều người cùng tham gia xây dựng, quản lý cơ sở hạ tầng thì sẽ dẫn đến xung đột.

image.png

Để giải quyết vấn đề này thì Terraform cung cấp backend block để cấu hình vị trí để lưu state .

Khai báo trong file config

  • backend block sẽ được đặt ở đầu trong terraform block:

    terraform {
      backend "remote" {
        organization = "learning-journey"
    
        workspaces {
          name = "demo01"
        }
      }
    }
    
  • Terraform cung cấp nhiều loại backend , tức nhiều nơi để lưu file state như local , remote, s3 , azurerm ,…. Mặc định nơi lưu trữ file statelocal .

Các loại backend

Như đã đề cập ở trên Terraform cung cấp nhiều loại backend, nhưng trong bài viết này mình xin đề cập đến 2 loại là local và s3 .

local

  • local backend sẽ lưu trữ state trên máy của người dùng.

  • Khai báo

    terraform {
      backend "local" {
        path = "relative/path/to/terraform.tfstate"
      }
    }
    
    • path: định nghĩa nơi lưu trữ file state, mặc định là file terraform.tfstate ở root module
  • Loại backend này sẽ phù hợp khi triền khai cơ sở hạ tầng 1 mình, nhưng khi có nhiều người thì sẽ dẫn đến xung đột. Vì vậy, ta cần lưu file state ở chung một nơi để tránh xung đột, và loại backend tiếp theo sẽ giải quyết được vấn đề trên.

s3

  • Với loại backend này, file state sẽ được lưu ở S3, ngoài ra để đảm bảo tính nhất quán có 2 cách để lock state:

    • S3 state locking (use_lockfile), chỉ có ở phiên bản terraform 1.10 trở lên.
    • DynamoDB (dynamodb_table), Partition key là LockID với kiểu dữ liệu là string
  • Tạo S3 bucket và DynamoDB trên AWS.

  • Định nghĩa:

    terraform {
      backend "s3" {
        bucket = "mybucket"
        key    = "your-state.tfstate"
        region = "us-east-1"
        profile= "Your_Profile"
        dynamodb_table= "states_tb"
      }
    }
    
    
  • Nếu dùng profile để truy xuất vào S3, profile này đã có permission để access vào S3 thì ta không cần set permission cho S3 nữa. Nếu chưa thì ta phải set permission trên S3 cho phép đọc ghi S3 object:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": "s3:ListBucket",
          "Resource": "arn:aws:s3:::mybucket"
        },
        {
          "Effect": "Allow",
          "Action": ["s3:GetObject", "s3:PutObject"],
          "Resource": [
            "arn:aws:s3:::mybucket/path/to/my/key",
            "arn:aws:s3:::mybucket/path/to/my/key.tflock"
          ]
        }
      ]
    }
    
    
  • Nếu sử dung DynamoDB để lock state, ta cũng phải set permission cho DynamoDB trên AWS (trường hợp profile chưa set permission cho DynamoDB):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "dynamodb:DescribeTable",
            "dynamodb:GetItem",
            "dynamodb:PutItem",
            "dynamodb:DeleteItem"
          ],
          "Resource": "arn:aws:dynamodb:*:*:table/mytable"
        }
      ]
    }
    
    

Practices

Lưu state trên S3

  • Mình sẽ dựa vào bài Lab 01 để cấu hình s3 backend.

  • Tạo S3 bucket trên AWS, tên do trùng với field bucket trong block backend, ở đây mình lấy tên là terraform-learning-triluong .

  • main.tf thêm backend bock vào terraform block:

    terraform {
      backend "s3" {
        bucket  = "terraform-learning-triluong"
        key     = "terraform.state"
        region  = "us-east-1"
        profile = "saa"
      }
    
      ...
    }
    
  • Khởi tạo lại workspace:

    terraform init
    
    Initializing the backend...
    
    Successfully configured the backend "s3"! Terraform will automatically
    use this backend unless the backend configuration changes.
    Initializing modules...
    Initializing provider plugins...
    - Reusing previous version of hashicorp/aws from the dependency lock file
    - Using previously-installed hashicorp/aws v4.67.0
    
    Terraform has been successfully initialized!
    ...
    
  • Sau đó lần lượt thực hiện các lệnh terraform plan để kiểm tra sự thay đổi, sau đó triển khai cơ sở hạ tầng bằng terraform apply .

  • Sau khi chạy xong, vào S3 bucket để kiểm tra, lúc này ta sẽ thấy file terraform.state (key) được lưu ở bucket terraform-learning-triluong (bucket).

image.png

  • Kiểm tra trong thư mục .terraform bạn sẽ thấy file terraform.state lưu lại cấu hình của backend .

image.png

  • Vậy là ta đã cấu hình cho việc lưu file state lên S3 thành công.

Lock state

S3 state locking

  • Để enable s3 state locking ta thêm thông số use_lockfile (chỉ có ở phiên bản Terraform 1.10) vào block backend, lúc này file main.tf như sau:

    terraform {
      backend "s3" {
        bucket       = "terraform-learning-triluong"
        key          = "terraform.state"
        region       = "us-east-1"
        profile      = "saa"
        use_lockfile = true
      }
    
      ...
    }
    ...
    
  • Chỉnh sửa lại value của resource, ở đây mình chọn chỉ sửa lại cidr block subnet, sau đó chạy terraform apply đồng thời, ta sẽ thấy lỗi hiện ra ở console: image.png

  • Trên S3 bucket sẽ xuất hiện 1 file lock, có định dạng {key}.tflock , file này được dùng để lock state lại tránh xung đột khi nhiều người cùng apply:

    image.png

  • Sau khi apply xong thì file lock sẽ bị xoá và file state sẽ được tạo trên S3:

    image.png

DynamoDB state locking

  • Tạo DynamoDB trên AWS với table name là terraform-states với partition keyLockID kiểu dữ liệu là string .

  • Cấu hình backend DynamoDB trong file main.tf .

    terraform {
      backend "s3" {
        bucket         = "terraform-learning-triluong"
        key            = "terraform.state"
        region         = "us-east-1"
        profile        = "saa"
        dynamodb_table = "terraform-states"
      }
      
      ...
    }
    
  • Sau khi DynamoDB đã được tạo xong, ta chỉnh sửa lại value của resource, sau đó chạy terraform apply đồng thời, ta sẽ thấy có lỗi hiện ra ở console:

    image.png

  • Lúc này trên table DynamoDB sẽ có 1 record với LockID có định dạng {bucket}/{key} :

    image.png

  • Sau khi chạy xong lệnh apply thì trên S3 file state cũng sẽ được tạo:

    image.png

  • Lúc này trên DynamoDB, file lock cũng được xoá, nhưng có 1 file {bucket}/{key}-md5 được tạo ra:

    image.png

Kết luận

  • Terraform cung cấp block backend để định nghĩa lại vị trí lưu file state
  • backend có nhiều loại local , remote , s3 ,…
  • Loại s3 có hỗ trợ state locking bằng s3 native (chỉ có ở phiên bản terraform 1.10 trở lên) hoặc DynamoDB:
    • Khi 1 lệnh apply được chạy, 1 file *.lock sẽ được tạo ra ở S3 hoặc DynamoDB tuỳ vào cấu hình state locking.
    • Khi lệnh apply được hoàn thành file *.lock sẽ được xoá, file state sẽ được tạo ra trên S3.

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí