[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.
Để 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 trongterraform
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 filestate
nhưlocal
,remote
,s3
,azurerm
,…. Mặc định nơi lưu trữ filestate
làlocal
.
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à fileterraform.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
- S3 state locking (
-
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 blockbackend
, ở đây mình lấy tên làterraform-learning-triluong
. -
main.tf
thêmbackend
bock vàoterraform
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ằngterraform 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 ở bucketterraform-learning-triluong
(bucket
).
- Kiểm tra trong thư mục
.terraform
bạn sẽ thấy fileterraform.state
lưu lại cấu hình củabackend
.
- 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 blockbackend
, lúc này filemain.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: -
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: -
Sau khi apply xong thì file lock sẽ bị xoá và file state sẽ được tạo trên S3:
DynamoDB state locking
-
Tạo DynamoDB trên AWS với table name là
terraform-states
với partition key làLockID
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: -
Lúc này trên table DynamoDB sẽ có 1 record với
LockID
có định dạng{bucket}/{key}
: -
Sau khi chạy xong lệnh apply thì trên S3 file state cũng sẽ được tạo:
-
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:
Kết luận
- Terraform cung cấp block
backend
để định nghĩa lại vị trí lưu filestate
backend
có nhiều loạilocal
,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á, filestate
sẽ được tạo ra trên S3.
- Khi 1 lệnh apply được chạy, 1 file
All rights reserved