Bỏ qua để đến nội dung

Hạ tầng Terraform

Terraform là một công cụ phần mềm mã nguồn mở cho infrastructure as code, cho phép bạn tạo, thay đổi và cải thiện hạ tầng một cách an toàn và dự đoán được.

Trình tạo hạ tầng Terraform tạo ra một dự án hạ tầng Terraform. Ứng dụng được tạo ra bao gồm các phương pháp bảo mật tốt nhất thông qua kiểm tra bảo mật Checkov.

Bạn có thể tạo một dự án Terraform mới theo hai cách:

Chạy generator này@aws/nx-plugin:terraform#project

pnpm nx g @aws/nx-plugin:terraform#project
Xây dựng lệnh của bạn5

Bắt buộc

Tùy chọn của generator5 tùy chọn
nameBắt buộcstring

Tên của dự án.

typeenumMặc định: application

Đây là terraform lib (các module có thể tái sử dụng) hay app (có thể triển khai).

applicationlibrary
directorystringMặc định: packages

Thư mục của dự án mới.

subDirectorystring

Thư mục con mà dự án được đặt trong đó. Mặc định đây là tên dự án.

preferInstallDependenciesbooleanMặc định: true

Có nên cài đặt các dependencies sau khi generator chạy xong hay không. Đặt thành false để hoãn việc cài đặt khi chạy nhiều generator liên tiếp (việc cài đặt vẫn sẽ chạy nếu cần thiết để các generator tiếp theo có thể tính toán Nx project graph); cài đặt một lần vào cuối.

Trình tạo tạo ra các cấu trúc tệp khác nhau tùy thuộc vào loại dự án:

type = application

Đối với các dự án application (--type=application), trình tạo tạo ra một ứng dụng Terraform hoàn chỉnh với quản lý trạng thái từ xa:

  • Thư mụcsrc
    • main.tf Tệp cấu hình Terraform chính
    • providers.tf Cấu hình Provider với S3 backend
    • variables.tf Định nghĩa biến đầu vào
    • outputs.tf Định nghĩa giá trị đầu ra
    • Thư mụcenv Tệp biến cụ thể cho môi trường
      • dev.tfvars Biến môi trường Development
  • Thư mụcbootstrap Cấu hình Bootstrap cho trạng thái từ xa
    • main.tf S3 bucket và policies cho lưu trữ state
    • providers.tf Cấu hình AWS provider
    • variables.tf Định nghĩa biến Bootstrap
  • Thư mụcscripts Node helpers chạy bởi các target nx bootstrap, bootstrap-destroyinit
    • aws-config.ts Phân giải account + region thông qua chuỗi thông tin xác thực AWS SDK
    • bootstrap.ts Pull/push bootstrap tfstate và chạy terraform apply
    • bootstrap-destroy.ts Làm trống state bucket và chạy terraform destroy
    • init.ts Chạy terraform init với cấu hình S3 backend
    • env.ts Trỏ terraform init đến shared provider cache
  • checkov.yml Cấu hình Checkov, bao gồm các kiểm tra cần bỏ qua
  • project.json Cấu hình dự án và build targets
type = library

Đối với các dự án library (--type=library), trình tạo tạo ra một cấu trúc đơn giản hơn cho các module Terraform có thể tái sử dụng:

  • Thư mụcsrc
    • main.tf Tệp module Terraform chính
  • checkov.yml Cấu hình Checkov, bao gồm các kiểm tra cần bỏ qua
  • project.json Cấu hình dự án và build targets

Bạn có thể bắt đầu viết hạ tầng Terraform của mình bên trong src/main.tf, ví dụ:

src/main.tf
locals {
account_id = data.aws_caller_identity.current.account_id
aws_region = data.aws_region.current.id
}
resource "null_resource" "print_info" {
# triggers = {
# always_run = timestamp()
# }
provisioner "local-exec" {
command = "echo 'AWS Region: ${local.aws_region}, AWS Account: ${local.account_id}, Environment: ${var.environment}'"
}
}
# Declare your infrastructure here
resource "aws_s3_bucket" "my_bucket" {
bucket = "my-unique-bucket-name"
}

Lưu ý rằng S3 bucket ở trên sẽ thất bại trong quá trình quét bảo mật Checkov, kiểm tra xem bucket có các cài đặt bảo mật thích hợp được bật hay không.

Nếu bạn muốn thực thi một module từ một dự án riêng biệt (lib), bạn có thể làm như sau:

module "lib_module" {
source = "../../path/to/my-lib/src"
}

Điều này sẽ tự động cập nhật đồ thị Nx để thêm phụ thuộc giữa ứng dụng sử dụng của bạn và lib của bạn.

Cấu hình các biến cụ thể cho môi trường trong các tệp src/env/*.tfvars.

Để thêm môi trường mới, tạo một tệp src/env/<environment>.tfvars mới với các biến cụ thể cho môi trường và thêm các mục mới cho apply, destroy, init, plan trong project.json cho cấu hình env mới. Ví dụ, giả sử chúng ta muốn thêm một env prod:

# Production environment variables
environment = "prod"
aws_region = "us-west-2"
type = application

Bootstrap Trạng thái Từ xa (Chỉ Dự án Application)

Phần tiêu đề “Bootstrap Trạng thái Từ xa (Chỉ Dự án Application)”

Trước khi triển khai hạ tầng của bạn, bạn sẽ cần bootstrap backend trạng thái từ xa. Điều này tạo ra một S3 bucket để lưu trữ các tệp trạng thái Terraform của bạn:

Terminal window
pnpm nx bootstrap tf-infra

Các target khả dụng phụ thuộc vào loại dự án của bạn:

Bạn có thể xác thực cấu hình Terraform của mình bằng cách sử dụng target validate:

Terminal window
pnpm nx validate tf-infra

Các dự án Terraform sử dụng terraform fmt để kiểm tra định dạng.

Để gọi linter kiểm tra dự án của bạn, bạn có thể chạy target lint.

Terminal window
pnpm nx lint tf-infra

Phần lớn các vấn đề linting hoặc định dạng có thể được sửa tự động bằng cách chạy với tham số --configuration=fix.

Terminal window
pnpm nx lint tf-infra --configuration=fix

Tương tự, nếu bạn muốn sửa tất cả các vấn đề lint trong tất cả các package trong workspace của mình, bạn có thể chạy:

Terminal window
pnpm nx run-many --target lint --all --configuration=fix

Để tránh các vấn đề linting làm chậm bạn trong quá trình phát triển (đặc biệt nếu bạn có các vấn đề không thể tự động sửa trong dự án của mình), bạn có thể chạy build với cấu hình skip-lint:

Terminal window
pnpm nx run-many --target build --configuration=skip-lint

Điều này bỏ qua hoàn toàn kiểm tra định dạng trong quá trình build.

Chạy kiểm tra bảo mật trên hạ tầng của bạn bằng cách sử dụng Checkov với target checkov:

Terminal window
pnpm nx checkov tf-infra

Bạn sẽ tìm thấy kết quả kiểm tra bảo mật của mình trong thư mục dist gốc, dưới dist/packages/<my-terraform-project>/checkov.

Checkov chạy như một phần của build.

Các kiểm tra được cấu hình trong checkov.yml của dự án. Thêm một check id vào skip-check để bỏ qua nó trên toàn bộ dự án:

checkov.yml
skip-check:
- CKV_AWS_115 # Concurrent execution limit
- CKV_AWS_116 # Dead Letter Queue

Để bỏ qua một kiểm tra cho một tài nguyên duy nhất, thêm một comment #checkov:skip=<id>:<reason> bên trong khối tài nguyên:

resource "aws_s3_bucket" "example" {
#checkov:skip=CKV_AWS_18:Access logging not required for this bucket
bucket = "example"
}

Target test chạy framework test gốc của Terraform trên bất kỳ tệp .tftest.hcl nào trong dự án của bạn:

Terminal window
pnpm nx test tf-infra

Một dự án không có tệp test sẽ thành công mà không làm gì, vì vậy bạn có thể thêm test khi cần. build chạy target này, vì vậy các test của bạn chạy như một phần của build bình thường.

Mỗi khối run đánh giá cấu hình của bạn. Sử dụng command = plan để kiểm tra những gì Terraform sẽ làm (điều này mở rộng toàn bộ đồ thị module, vì vậy nó bắt được các lỗi plan-time mà validate không thể), hoặc command = apply để tạo tài nguyên thực và khẳng định trên các output của chúng. Khai báo mock_provider có nghĩa là không có cuộc gọi API nào được thực hiện và không cần thông tin xác thực AWS, điều này giữ cho các test plan nhanh và an toàn để chạy trong CI:

src/main.tftest.hcl
mock_provider "aws" {
mock_data "aws_caller_identity" {
defaults = { account_id = "123456789012" }
}
mock_data "aws_region" {
defaults = { region = "us-east-1" }
}
}
variables {
aws_region = "us-east-1"
environment = "dev"
}
run "plan_is_valid" {
command = plan
assert {
condition = data.aws_caller_identity.current.account_id == "123456789012"
error_message = "Unexpected account id"
}
}

Đặt mọi biến mà cấu hình của bạn yêu cầu trong khối variables, nếu không run sẽ thất bại với “has a required variable … with no set value”.

Mọi target chạy terraform init đều tái sử dụng một provider cache dưới .terraform/plugin-cache trong workspace root của bạn, vì vậy các provider được tải xuống một lần thay vì mỗi lần chạy. Mỗi dự án có thư mục riêng ở đó: hai lần chạy terraform init cùng điền vào một cache có thể mỗi cái tính toán một hash khác nhau cho cùng một provider, sau đó terraform sẽ từ chối so với .terraform.lock.hcl của bạn. Xem tài liệu Terraform để biết thêm thông tin.

Đặt TF_PLUGIN_CACHE_DIR trong môi trường của bạn để trỏ script init được cung cấp đến một cache mà bạn tự quản lý — ví dụ như một volume được chia sẻ giữa các workspace. Lưu ý rằng target test đọc đường dẫn của nó từ project.json, vì vậy hãy thay đổi nó ở đó nữa.

type = application

Các target sau chỉ khả dụng cho các dự án loại application:

Trước khi áp dụng các thay đổi, bạn có thể xem Terraform sẽ làm gì bằng cách chạy target plan:

Terminal window
pnpm nx plan tf-infra

Điều này sẽ tạo một tệp plan trong dist/packages/<my-terraform-project>/terraform/dev.tfplan.

plan phụ thuộc vào assemble, vì vậy nó tạo ra các artifact mà các module của bạn tham chiếu, chẳng hạn như các bundle Lambda và metadata operations được tạo, mà không chạy các cổng lint, test và type-check.

Khởi tạo thư mục làm việc Terraform của bạn với target init:

Terminal window
pnpm nx run tf-infra:init

Sau khi lập kế hoạch, bạn có thể triển khai hạ tầng của mình lên AWS bằng cách sử dụng target apply:

Terminal window
pnpm nx apply tf-infra

Truy xuất các giá trị output từ cấu hình Terraform của bạn:

Terminal window
pnpm nx output tf-infra

Khi bạn cần phá bỏ hạ tầng của mình, sử dụng target destroy:

Terminal window
pnpm nx destroy tf-infra

Để dọn dẹp các tài nguyên bootstrap (S3 bucket cho lưu trữ state):

Terminal window
pnpm nx bootstrap-destroy tf-infra

Điều này làm trống state bucket trước khi hủy nó, và phân giải region từ chuỗi thông tin xác thực AWS SDK, vì vậy nó chạy tự động trong CI.

Để biết thêm thông tin về Terraform, vui lòng tham khảo Tài liệu TerraformTài liệu AWS Provider.