Các mẫu thiết kế trong Terraform - Phần 1

Được tạo bởi Lê Thanh Thương trong terraform 18/07/2023
Chia sẻ

Chào anh chị em gần xa, cũng đã rất lâu rồi tôi không có dịp viết bài về kỹ thuật, nhân dịp xây dựng lại website dạy học CuliOps, ngoài việc muốn chia sẽ những kinh nghiệm của mình, tôi cũng muốn bài viết sẽ là công cụ để quảng bá CuliOps đến anh chị em. Và vì cũng rất lâu rồi tôi mới viết bài, nên nếu có gì sai sót mong các anh chị em bỏ qua và góp ý để cho chất lượng các bài tiếp theo sẽ tốt hơn.

Một số yêu cầu trước khi bắt đầu

Bài viết sẽ tập trung vào việc làm thế nào để thiết kế và cấu trúc cho một dự án mà hạ tầng được quản lý bằng IaC(Infrastructure as Code), cụ thể ở đây là Terraform. Tại sao lại là Terraform mà không phải các IaC tools khác. Tôi nghĩ về phương diện các ngôn ngữ khai báo trong việc quản lý hạ tầng, Terraform cho tôi cảm giác có thể lập trình nhiều hơn so với CloudFormation(AWS). Điều này có nghĩa, tôi có thể viết code, test code, build CI/CD giống như 1 ngôn ngữ bình thường ở một mức độ vừa đủ.

Nhiều anh chị đọc đến đây sẽ thắc mắc, nếu thích lập trình để quản lý hạ tầng sao không dùng Pulumi hay các CDKs, cơ bản vì nó đòi hỏi kỹ năng lập trình quá nhiều, bạn sẽ tốn thời gian và nhân lực hơn để xây dựng và bảo trì các thành phần hạ tầng cho một dự án. Tôi nghĩ CDK sẽ tốt cho các công ty mà ở đó có team chuyên xây dựng và phát triển các công cụ dành riêng cho nội bộ(Internal Developer Platform - IDP), nói chung là các công ty thừa tiền, nhân lực, hoặc đang muốn chuyển đổi và chuẩn hoá quy trình nội bộ bằng các giải pháp công nghệ.

Do đó, trong bài viết này một yêu cầu cơ bản đó là bạn đang hoặc đã sử dụng Terraform một thời gian, bạn đang chuẩn bị ứng dụng Terraform vào trong hạ tầng của mình. Hoặc dành cho các bạn đã từng sử dụng các CaC(Configuration as Code) như Ansible, và nay muốn tìm hiểu Terraform.

Một số trường hợp thực tế mà bạn sẽ gặp phải

  • Một trường hợp phổ biến mà tôi nghĩ các bạn hay gặp đó là dịch vụ sẽ cần triển khai trên nhiều môi trường khác nhau, như: staging, production,…
  • Trường hợp một dự án cần triển khai hạ tầng trên nhiều quốc gia khác nhau, tôi may mắn được làm việc trong một vài công ty kinh doanh trong miền E-commerce/Payment, các sản phẩm hầu như sẽ được kinh doanh trên nhiều quốc gia khác nhau, nên hạ tầng cần được triển khai và quản lý một cách độc lập.
  • Cũng có trường hợp, một dịch vụ nào đó có thể sử dụng chung hạ tầng triển khai cho tất cả quốc gia, mà không cần thiết phải tách riêng.
  • Một trường hợp thực tế khác bạn sẽ gặp phải, nếu công ty bạn đang làm đòi hỏi khả năng sẵn sàng cao cho người dùng, thì việc triển khai DR(Disaster Recovery) là điều bắt buộc. Nói cho dễ hiểu, nếu hạ tầng của bạn đang được xây dựng tại Singapore, với DR setup, bạn có thể bê nguyên hoặc 1 phần hạ tầng sang một quốc gia khác, chẳng hạn Tokyo.

Mục đích cho việc cấu trúc và thiết kế Terraform code

  • Mục đích cuối cùng cho việc này, đó là làm thế nào chúng ta có thể sử dụng lại Terraform code, tránh lặp lại Terraform code nhiều nhất có thể.
  • Làm cho Terraform code được rõ ràng, sạch sẽ, và được xếp sắp, quan trọng hơn hết, giúp cho các thành viên khác trong team thực sự dễ hiểu và sử dụng.
  • Terraform code là dễ dàng bảo trì và mở rộng, giảm thiểu thời gian triển khai cho các dự án và dịch vụ tương tự trong tương lai.
  • Một vài Public Clouds sẽ có hạn chế số lượng tài nguyên được tạo ra. Do đó, một mục đích khác, các tài nguyên và thành phần của hạ tầng được tạo ra mà không bị trùng lặp khi được triển khai ở nhiều nơi.

Terraform Patterns

  • Module

Tôi nghĩ 1 pattern đang được sử dụng phổ biến hiện này, chính là thiết kế terraform code thành các module khác nhau. Mỗi module là nơi tập hợp các terraform code, để triển khai một thành phần cơ bản, hoặc có thể là kết hợp nhiều thành phần với nhau. Mục đích, có khả năng sử dụng lại terraform code. Tuy nhiên, việc tạo ra 1 module để có thể dễ dàng sử dụng và khả năng mở rộng cho module cũng là một vấn đề cần chú ý. Rất tiếc, trong phạm vi bài viết này tôi không thể đi sâu vào chi tiết làm thế nào để viết một module đủ tốt, mà hẹn các anh chị ở một bài viết khác.

module "database" {
source = "../modules/rds"

name = "culiops-${local.env}-${local.country_code}"
}

  • Chia sẽ dữ liệu trạng thái - State data sharing

Như các bạn đã biết, mỗi Terraform workspace sẽ cần chỉ định nơi để chứa dữ liệu trạng thái, để Terraform có thể theo dõi tài nguyên nào đang có sự thay đổi.

Và ở trên, như tôi có chia sẽ một số trường hợp thực tế, trong một vài trường hợp khi bạn cần truy cập dữ liệu hạ tầng giữa các terraform workspaces. Ví dụ như, khi triển khai hạ tầng trên một quốc gia hay một môi trường, tôi cần truy cập các tài nguyên đang được chia sẽ và dùng chung, lúc này tôi sẽ sử dụng một terraform resource có tên terraform_remote_state.

data "terraform_remote_state" "vpc" {
backend = "remote"

config = {
organization = "hashicorp"
workspaces = {
name = "vpc-prod"
}
}
}

# Terraform >= 0.12
resource "aws_instance" "foo" {
# ...
subnet_id = data.terraform_remote_state.vpc.outputs.subnet_id
}
  • Mỗi dịch vụ nên sử dụng một role với các quyền vừa đủ để triển khai các tài nguyên

Nếu anh chị đã từng sử dụng AWS public cloud, chắc sẽ không còn xa lạ với khái niệm về IAM Role và Assume Role. Assume một role là một hoạt động cho phép một đối tượng trong AWS IAM sử dụng một tập hợp thông tin đăng nhập bảo mật tạm thời của role đó để truy cập tài nguyên AWS. Tôi không chắc GCP hay Azure có những khái niệm tương tự hay không, nếu có hỗ trợ, tôi khuyên các bạn nên sử dụng.

Một vấn đề tôi nghĩ trong một số ít anh chị, có thể sẽ có thói quen dùng một tài khoản người dùng có quyền administrator hoặc root account để triển khai tài nguyên hạ tầng cho tất cả các dịch vụ. Việc này có thể giúp các bạn tiết kiệm thời gian để triển khai vì các bạn sẽ không cần phải suy nghĩ về vấn đề cần quyền hạn gì để truy cập tài nguyên.

Tuy nhiên, nó cũng có một vấn đề, đó là khi một ai đó từ developer team từ dịch vụ này cần truy cập tài nguyên hạ tầng, mà không thể truy cập tài nguyên của dịch vụ khác. Khi các bạn thiết kế mỗi một dịch vụ sẽ sử dụng một assume role khác nhau, đồng nghĩa việc truy cập và thao tác tài nguyên trên dịch vụ này sẽ không ảnh hưởng đến dịch vụ khác. Và lúc này, bạn chỉ cần cho phép developer team của dịch vụ nào assume role đến role của dịch vụ đó.

Hoặc, nếu bạn đang sử dụng Atlantis hoặc Terraform Cloud cho team collaboration , việc thiết lập này có thể giới hạn các quyền cần thiết và tối thiểu để uỷ quyền cho Atlantis/Terraform Cloud truy cập và thay đổi tài nguyên hạ tầng của anh chị.

provider "aws" {
region = "us-east-2"

assume_role {
role_arn = ""
}
}

Tổng kết phần 1

Trên là một số mẫu thiết kế tôi đúc kết được trong quá trình triển khai hạ tầng bằng Terraform, nếu anh chị biết thêm mẫu thiết kế nào hoặc bất kỳ góp ý nào thì hãy comment hoặc đóng góp ý kiến để tôi có thể cập nhật cho bài viết trở nên phong phú và chất lượng.

Tôi có sử dụng vài từ tiếng Anh trong bài viết, vì thực sự tôi không biết phải dịch sao cho sát nghĩa, nên tôi nghĩ cứ giữ tiếng Anh có khi anh chị lại dễ hiểu hơn.

Tôi dự định sẽ viết tất cả trong một bài, nhưng có vẽ nó khá dài đối với anh chị, nên tôi xin phép tổng kết bài 1 tại đây. Bài 2 tôi sẽ tập trung đưa ra 1 trường hợp thực tế và cách tôi áp dụng các thiết kế ở trên cho một dự án mà tôi đã thực hiện. Tôi cũng sẽ trình bày cách tôi tổ chức và sắp xếp các Terraform workplaces như thế nào.

Bình luận (0)

Chia sẻ

Chia sẻ bài viết này với người khác

Chương trình khuyến mãi

Chương trình khuyến mãi

Nhân dịp mở website CuliOps, giảm giá 50% tất cả các khóa học từ ngày 01/07/2023 đến 30/08/2023