Terraform Trên AWS: Những Gợi Ý Giúp Tránh Lỗi Và Tiết Kiệm Thời Gian

Chẳng ai thực sự hiểu được Terraform trên AWS cho đến khi tự tay làm sập môi trường Production, dành hàng tiếng đồng hồ la hét vào cái file state, rồi thề thốt sẽ không bao giờ đụng vào terraform destroy nữa đâu.

Đây không phải là một bài viết Terraform 101 bình thường. Đây là những bài học được đúc kết từ chiến trường thực tế, trong những đêm mất ngủ vì lỗi hệ thống, những lần CI chạy lỗi banh xác, và những đoạn chat Slack mở đầu bằng câu AI vừa động vào cái route table vậy.

ecd08e52-b5e0-448e-9882-d86d2a41b31f

Dưới đây là cách để mọi người sống sót, thậm chí là thăng hoa khi dùng Terraform với AWS mà không phải hy sinh những cuối tuần hay đánh mất sự tỉnh táo của mình:

1. prevent_destroy: Phòng Tuyến Cuối Cùng Chống Lại Thảm Họa Xóa Nhầm

Chuyện gì đã xảy ra: Ai đó chạy terraform apply mà không để ý rằng cái plan sắp sửa xóa sổ con RDS của mình. Năm giây sau, database production bốc hơi.

Thêm ngay cái này vào:

lifecycle {
  prevent_destroy = true
}

Dùng nó cho những tài nguyên sau:

  • aws_db_instance
  • aws_s3_bucket
  • Bất kỳ tài nguyên nào mà việc xóa nó có thể khiến mọi người mất ăn mất ngủ cả ngày.

Nó không phải là bùa hộ mệnh bất khả xâm phạm đâu, nhưng nó sẽ khiến mọi người phải dừng lại và suy nghĩ thật kỹ trước khi biến Terraform thành cái máy ủi.

2. Gắn Tag Hết Mọi Thứ. Không Có Lý Do Nào Để Biện Minh.

Tại sao phải làm vậy: Hạ tầng mà không được gắn nhãn thì cũng giống như mấy món đồ ăn không tên trong tủ lạnh vậy đó: chẳng ai biết ai làm ra, nó dùng để làm gì, hay tại sao nó vẫn còn nằm chình ình ở đó.

Cứ để Terraform lo:

provider "aws" {
  region = "ap-south-1"

  default_tags {
    tags = {
      Owner       = "devops"
      Environment = "prod"
    }
  }
}

Sau này, khi bộ phận tài chính hỏi tại sao chi phí S3 tự nhiên đội lên, mấy cái tag của mọi người sẽ cứu mọi người một bàn thua trông thấy đó.

3. Bỏ Ngay Thói Quen Copy-Paste. Hãy Chia Module Ra Mà Dùng.

Chuyện có thật: Tôi từng thấy có đến bốn file main.tf trong cùng một repo, tất cả đều làm cùng một việc, mà cái nào cũng có lỗi vặt khác nhau.

Hãy tái cấu trúc thành các module:

Hãy giữ mỗi module tự chứa gọn gàng với các file main.tf, variables.tf, và outputs.tf riêng biệt.

Sau đó, cứ thế mà dùng lại thôi:

module "vpc" {
  source     = "./modules/vpc"
  cidr_block = "10.0.0.0/16"
}

Cứ nghĩ nó như mấy miếng xếp hình Lego ấy. Sửa một chỗ thôi là mọi thứ đều tốt lên.

4. Dùng depends_on Khi Terraform Cứ Tưởng Bở Là Mọi Thứ Đã Ổn

Cái gì lạ vậy: Mọi người triển khai một con Lambda kèm theo EventBridge. Cái rule thì được tạo ra trước, nhưng con Lambda thì chưa sẵn sàng, thế là chả có gì được kích hoạt cả.

Buộc nó phải chạy theo đúng thứ tự:

resource "aws_lambda_permission" "allow_eventbridge" {
  ...
  depends_on = [aws_lambda_function.my_lambda]
}

Đôi khi Terraform lạc quan quá mức. Cái này sẽ kéo nó về với thực tế.

5. Chuyển Sang Remote State. Nghiêm Túc Đó.

Thảm họa sắp ập đến: Hai đồng nghiệp cùng chạy Terraform cục bộ. Một người thực hiện thay đổi. Người kia vô tình đảo ngược lại thay đổi đó. Chúc mừng, giờ thì mọi người có hàng giờ để gỡ lỗi rồi đó.

Tập trung nó lại một chỗ:

backend "s3" {
  bucket         = "tfstate-prod"
  key            = "app/infrastructure.tfstate"
  region         = "us-east-1"
  dynamodb_table = "tfstate-lock"
}

Đây không chỉ là một cái best practice (thực hành tốt nhất) đâu. Nó còn là sự an tâm nữa đó.

6. Bắt Buộc terraform plan Trong Mọi PR

Tại sao: Thay đổi hạ tầng không bao giờ nên là một điều bất ngờ, đặc biệt là ở môi trường production.

Tự động hóa nó trong CI:

terraform init
terraform plan -out=tfplan

Tốt hơn nữa ư? Hãy thiết lập để nó tóm tắt cái plan đó vào thẳng PR luôn. Cái bản thân tương lai của mọi người (và những người duyệt code) sẽ phải cảm ơn mọi người đó.

7. Tham Số Hóa Mọi Thứ: Region, Profile, Environment

Khoảnh khắc đập mặt vào tường: Region bị hardcode thành us-east-1. Giờ mọi người muốn triển khai nó ở staging à? Khó đấy.

Sửa nó bằng cách dùng biến:

variable "aws_region" {
  default = "us-east-1"
}

Sau đó:

provider "aws" {
  region = var.aws_region
}

Viết một lần, dùng mọi nơi. Giống như cách viết code tốt vậy.

8. Thêm Tính Năng Nhận Biết Chi Phí Với Infracost

Cái bẫy: Một con EC2 instance bé tẹo nào đó lén lút chui vào PR của mọi người. Mọi người duyệt nó. Một tháng sau, cái hóa đơn đội lên bất ngờ.

Dùng Infracost:

  • Nó sẽ hiển thị chi phí dự kiến ngay trên mỗi PR.
  • Buộc các lập trình viên phải suy nghĩ thật kỹ trước khi tạo ra tài nguyên.
  • Cứu ngân sách của mọi người khỏi những khoản chi phí phát sinh âm thầm.

Cloud không đắt đâu, cho đến khi không ai để ý đó.

9. Xuất Những Gì Mọi Người Sẽ Cần Sau Này

Ai trong chúng ta cũng từng gặp phải: Triển khai thì ngon lành rồi. Nhưng giờ ai đó lại hỏi cái URL của API Gateway ở đâu. Cuối cùng, mọi người lại phải đào bới trong file state hoặc mò mẫm trên AWS Console.

Tiết kiệm thời gian cho chính mình:

output "lambda_url" {
  value = aws_lambda_function_url.my_lambda.function_url
}

Những cái output tốt giống như việc ghi log cẩn thận vậy đó. Cái bản thân tương lai của mọi người sẽ thầm cảm ơn cái bản thân quá khứ.

Final Thought

Terraform không tự gây lỗi đâu, là do con người mình làm lỗi đó. Nhưng nếu mọi người cài đặt sẵn những giá trị mặc định và các chốt chặn an toàn đúng đắn, mọi người sẽ bắt được lỗi trước khi chúng gây ra thảm họa.

Đây không phải là best practices thông thường. Đây là những chiến thuật đã được thử lửa trong thực tế, sẽ giúp mọi người nhanh nhẹn, bình tĩnh và không vượt ngân sách.

Article Thumbnail
Datadog Webinar: Modernize AWS Logs at Scale
Chia sẻ bài viết:
Theo dõi
Thông báo của
0 Góp ý
Được bỏ phiếu nhiều nhất
Mới nhất Cũ nhất
Phản hồi nội tuyến
Xem tất cả bình luận