Thursday, November 21, 2024

Ví dụ về module trong Terraform triển khai trên AWS

-

Tổng quan.

Nó chỉ ra cách triển khai mà không sử dụng phương thức sao chép các đoạn code trên các cụm máy chủ web trong các môi trường khác nhau bằng cách sử dụng modules. Ví dụ này sử dụng Terraform AWS Provider để tương tác với nhiều tài nguyên được hỗ trợ bởi AWS thông qua các API của nó và ví dụ này triển khai trên Terraform phiên bản 0.10.x.

Cấu hình các khóa truy cập AWS của bạn.

Vì lý do bảo mật, nên sử dụng người dùng IAM thay vì tài khoản gốc để truy cập vào AWS.

Cấu hình thông tin xác thực AWS để sử dụng bởi Terraform có thể được thực hiện theo nhiều cách khác nhau, nhưng đây là những cách tiếp cận được khuyến khích:

Cách 1: Cài đặt thông tin xác thực AWS trên hệ thống local của bạn, đối với Linux, macOS hoặc Unix:

~/.aws/credentials

Hoặc đối với Windows nằm tại.

C:\Users\USERNAME\.aws\credentials

File này nên chứa các dòng theo định dạng dưới, lưu ý hãy thay thế các giá trị thông tin xác thực AWS của bạn vào các giá trị <your_access_key_id> và <your_secret_access_key> trong file.

[default]
aws_access_key_id = <your_access_key_id>
aws_secret_access_key = <your_secret_access_key>

Cách 2: Đặt các biến môi trường AWS_ACCESS_KEY_ID và AWS_SECRET_ACCESS_KEY.

Để đặt các biến này trên Linux, macOS hoặc Unix, sử dụng lệnh export:

export AWS_ACCESS_KEY_ID=<your_access_key_id>
export AWS_SECRET_ACCESS_KEY=<your_secret_access_key>

Đối với windows hãy sử dụng set:

set AWS_ACCESS_KEY_ID=<your_access_key_id>
set AWS_SECRET_ACCESS_KEY=<your_secret_access_key>

Giới thiệu sơ về project Terraform này.

Đây là một ví dụ về cấu trúc file của Terraform trên AWS (Amazon Web Services). Thư mục chính có hai thư mục con là “global” và “stage”. Trong thư mục “global” có một ví dụ về cách sử dụng “Terraform Remote State” để quản lý trạng thái từ xa, cụ thể là lưu trữ trên S3. Thư mục “stage” chứa hai thư mục con là “services” và “data-stores”. Trong thư mục “services”, ví dụ cho việc triển khai một cụm máy chủ web bằng “Terraform Web Server Cluster”. Trong thư mục “data-stores”, có một ví dụ về cách triển khai máy chủ MySQL trên RDS bằng “Terraform MySQL on RDS”. Tổng quan về cấu trúc thư mục này cho phép người dùng tổ chức và quản lý các file Terraform của họ theo cách hợp lý và có thể mở rộng.

Và đây là cách bố trí các file của Terraform:

global
    └── s3/
        ├── main.tf
        └── (etc)

modules
    └── services/
        └── webserver-cluster/
            ├── main.tf
            └── (etc)

stage
    ├── services/
    │   └── webserver-cluster/
    │       ├── main.tf
    │       └── (etc)
    └── data-stores/
        └── mysql/
            ├── main.tf
            └── (etc)

prod
    ├── services/
    │   └── webserver-cluster/
    │       ├── main.tf
    │       └── (etc)
    └── data-stores/
        └── mysql/
            ├── main.tf
            └── (etc)

Tạo các thư mục cho dự án.

mkdir -p global/s3
mkdir -p /modules/services/webserver-cluster/
mkdir -p /prod/data-stores/mysql/
mkdir -p /prod/services/webserver-cluster/
mkdir -p /stage/data-stores/mysql/
mkdir -p /stage/services/webserver-cluster/

– /global/s3/main.tf

# Configure the AWS provider
provider "aws" {
  region = "eu-west-1"
}

# Create a S3 bucket
resource "aws_s3_bucket" "terraform_state" {
  bucket		  = "${var.bucket_name}"
  
  versioning {
    enabled = true
  }  
  
  lifecycle {
    prevent_destroy = true
  }
}

– /global/s3/outputs.tf

# Output variable: S3 bucket
output "s3_bucket_arn" {
  value = "${aws_s3_bucket.terraform_state.arn}"
}

– /global/s3/vars.tf

# Input variable: S3 bucket name
variable "bucket_name" {
  description = "The name of the S3 bucket. Must be globally unique."
  default = "terraform-state-my-bucket"
}

Đoạn code ở 3 file /global/s3/main.tf, /global/s3/outputs.tf và /global/s3/vars.tf ở trên là một file cấu hình Terraform để tạo một bucket S3 trên AWS. Cụ thể, nó bao gồm:

  • Khai báo aws là nhà cung cấp dịch vụ được sử dụng để triển khai tài nguyên.
  • Tạo một tài nguyên aws_s3_bucket để định nghĩa thông tin của bucket S3.
    • Bucket name được xác định bằng biến bucket_name được định nghĩa bên dưới, nơi mà giá trị mặc định là "terraform-state-my-bucket".
    • versioning được bật, cho phép phiên bản các đối tượng được lưu trữ trong bucket.
    • lifecycle được thiết lập để ngăn chặn việc xóa bucket một cách vô tình.
  • Tạo biến đầu vào bucket_name cho phép người dùng truyền vào tên của bucket S3 cần tạo.
  • Tạo biến đầu ra s3_bucket_arn để hiển thị Amazon Resource Name (ARN) của bucket S3 sau khi nó được tạo.

– /modules/services/webserver-cluster/main.tf

# Data source: query the list of availability zones
data "aws_availability_zones" "all" {}

# Data source: DB remote state
data "terraform_remote_state" "db" {
  backend = "s3"
  
  config {
	bucket = "${var.db_remote_state_bucket}"
	key    = "${var.db_remote_state_key}"
	region = "eu-west-1"
  }
}

# Data source: Template file
data "template_file" "user_data" {
  template = "${file("${path.module}/user-data.sh")}"
  
  vars {
    server_port = "${var.server_port}"
	db_address  = "${data.terraform_remote_state.db.address}"
	db_port     = "${data.terraform_remote_state.db.port}"
  }
}

# Create a Security Group for an EC2 instance
resource "aws_security_group" "instance" {
  name = "${var.cluster_name}-instance"
  
  lifecycle {
    create_before_destroy = true
  }
}

# Create a Security Group Rule
resource "aws_security_group_rule" "allow_server_http_inbound" {
  type = "ingress"
  security_group_id = "${aws_security_group.instance.id}"
  
  from_port	  = "${var.server_port}"
  to_port	  = "${var.server_port}"
  protocol	  = "tcp"
  cidr_blocks = ["0.0.0.0/0"]

}

# Create a Security Group for an ELB
resource "aws_security_group" "elb" {
  name = "${var.cluster_name}-elb"
}

# Create a Security Group Rule, inbound
resource "aws_security_group_rule" "allow_http_inbound" {
  type              = "ingress"
  security_group_id = "${aws_security_group.elb.id}"
  
  from_port	  = 80
  to_port	  = 80
  protocol	  = "tcp"
  cidr_blocks = ["0.0.0.0/0"]
}

# Create a Security Group Rule, outbound
resource "aws_security_group_rule" "allow_all_outbound" {
  type              = "egress"
  security_group_id = "${aws_security_group.elb.id}"
  
  from_port	  = 0
  to_port	  = 0
  protocol	  = "-1"
  cidr_blocks = ["0.0.0.0/0"]
}

# Create a Launch Configuration
resource "aws_launch_configuration" "example" {
  image_id		  = "ami-785db401"
  instance_type   = "${var.instance_type}"
  security_groups = ["${aws_security_group.instance.id}"]
  user_data       = "${data.template_file.user_data.rendered}"
  
  lifecycle {
    create_before_destroy = true
  }
}

# Create an Autoscaling Group
resource "aws_autoscaling_group" "example" {
  launch_configuration = "${aws_launch_configuration.example.id}"
  availability_zones   = ["${data.aws_availability_zones.all.names}"]
  load_balancers       = ["${aws_elb.example.name}"]
  health_check_type    = "ELB"
  
  min_size = "${var.min_size}"
  max_size = "${var.max_size}"
  
  tag {
    key                 = "Name"
    value               = "${var.cluster_name}"
    propagate_at_launch = true
  }
}

# Create an ELB
resource "aws_elb" "example" {
  name               = "${var.cluster_name}"
  availability_zones = ["${data.aws_availability_zones.all.names}"]
  security_groups    = ["${aws_security_group.elb.id}"]
  
  listener {
    lb_port           = 80
    lb_protocol       = "http"
    instance_port     = "${var.server_port}"
    instance_protocol = "http"
  }
  
  health_check {
    healthy_threshold   = 2
    unhealthy_threshold = 2
    timeout             = 3
    interval            = 30
    target              = "HTTP:${var.server_port}/"
  }
}

Đây là một file Terraform configuration, được sử dụng để tạo một môi trường infra đơn giản trên Amazon Web Services (AWS).

Phần đầu của file sử dụng data source để lấy danh sách các vùng khả dụng trong AWS và remote state từ một backend S3 được cấu hình trước để lấy địa chỉ IP của máy chủ cơ sở dữ liệu. Ngoài ra, cũng sử dụng data source để tải một file template, trong đó có định nghĩa các biến cho user data để truyền cho EC2 instance.

Sau đó, file định nghĩa các resource để tạo infra. Đầu tiên là một Security Group được tạo cho EC2 instance, có cho phép lưu lượng truy cập đến cổng được cấu hình.

Tiếp theo là một Security Group cho ELB, với một rule inbound cho phép lưu lượng truy cập đến cổng HTTP (port 80) và một rule outbound cho phép tất cả các lưu lượng truy cập ra ngoài.

Tiếp theo là một Launch Configuration để cấu hình EC2 instance, bao gồm định nghĩa image ID, instance type, và security group được cấu hình ở trên. Cũng bao gồm user data được truyền vào bằng cách sử dụng template file.

Sau đó, một Autoscaling Group được tạo để tự động mở rộng số lượng EC2 instance, sử dụng Launch Configuration được tạo trước đó. Availability zones được lấy từ data source và được cấu hình để kết nối với ELB đã tạo trước đó.

Cuối cùng, một ELB được tạo với các cấu hình cần thiết như các port và protocol để lắng nghe, health check, và các Security Group để quản lý lưu lượng truy cập.

Mục đích của file Terraform này là để tạo ra một môi trường infra đơn giản với một ELB và một số EC2 instance để chạy ứng dụng web.

– /modules/services/webserver-cluster/outputs.tf

# Output variable: DNS Name of ELB
output "elb_dns_name" {
  value = "${aws_elb.example.dns_name}"
}

# Output variable: Auto Scaling Group name
output "asg_name" {
  value = "${aws_autoscaling_group.example.name}"
}

# Output variable: ELB Security Group Id
output "elb_security_group_id" {
  value = "${aws_security_group.elb.id}"
}

Đoạn code này sử dụng Terraform để định nghĩa và quản lý các tài nguyên AWS bao gồm:

  • output variables để truy xuất thông tin của các tài nguyên được tạo ra trong mã Terraform và sử dụng chúng trong các mã hoặc tác vụ khác.

Cụ thể, đoạn code này bao gồm:

  • output “elb_dns_name”: định nghĩa biến output để lưu tên miền DNS của Elastic Load Balancer (ELB) được tạo bởi mã Terraform.
  • output “asg_name”: định nghĩa biến output để lưu tên của Auto Scaling Group (ASG) được tạo bởi mã Terraform.
  • output “elb_security_group_id”: định nghĩa biến output để lưu ID của Security Group được tạo cho ELB.

Các giá trị của các biến output này sẽ được hiển thị sau khi mã Terraform được thực thi.

– /modules/services/webserver-cluster/user-data.sh

#!/bin/bash

cat > index.html <<EOF
<h1>Hello, World</h1>
<p>DB address: ${db_address}</p>
<p>DB port: ${db_port}</p>
EOF

nohup busybox httpd -f -p "${server_port}" &

Đoạn code này là một script shell được sử dụng để khởi động web server BusyBox HTTPD. Script này sử dụng một biến môi trường db_addressdb_port để hiển thị địa chỉ và cổng của database được truy vấn bởi máy chủ web.

Cụ thể, đoạn mã này thực hiện các hành động sau:

  • Dùng lệnh cat để ghi nội dung vào file index.html trong script.
  • Nội dung này chứa một tiêu đề và hai đoạn văn bản. Hai đoạn văn bản này sử dụng giá trị của các biến db_addressdb_port được truyền vào từ terraform remote state.
  • Sử dụng lệnh nohup để chạy server BusyBox HTTPD với tùy chọn -f để thực thi tiến trình trong nền và tùy chọn -p để xác định cổng dịch vụ HTTP mà server sẽ lắng nghe.
  • Cuối cùng, script được đóng lại bằng dấu & để đảm bảo rằng quá trình thực thi của server BusyBox HTTPD sẽ tiếp tục chạy ngay cả khi session của shell kết thúc.

– /modules/services/webserver-cluster/vars.tf

# Input variable: server port
variable "server_port" {
  description = "The port the server will use for HTTP requests"
  default = "8080"
}

# Input variable: Cluster name
variable "cluster_name" {
  description = "The name to use for all the cluster resources"
}

# Input variable: DB remote state bucket name
variable "db_remote_state_bucket" {
  description = "The name of the S3 bucket for the database's remote state"
}

# Input variable: DB remote state bucket key
variable "db_remote_state_key" {
  description = "The path for database's remote state in S3"
}

# Input variable: Instance type
variable "instance_type" {
  description = "The type of EC2 Instances to run (e.g. t2.micro)"
}

# Input variable: Instance min size
variable "min_size" {
  description = "The minimum number of EC2 Instances in the ASG"
}

# Input variable: Instance max size
variable "max_size" {
  description = "The maximum number of EC2 Instances in the ASG"
}

Đây là một file mã hóa cấu hình Terraform, chứa các biến đầu vào (input variables) cho module. Các biến đầu vào này cung cấp thông tin cần thiết để Terraform có thể triển khai các tài nguyên AWS. Cụ thể:

  • Biến server_port: Đây là cổng mà máy chủ sẽ sử dụng để xử lý các yêu cầu HTTP. Giá trị mặc định là 8080.
  • Biến cluster_name: Tên này sẽ được sử dụng cho tất cả các tài nguyên trong cụm.
  • Biến db_remote_state_bucket: Tên của bucket S3 để lưu trữ trạng thái từ xa của cơ sở dữ liệu.
  • Biến db_remote_state_key: Đường dẫn cho trạng thái từ xa của cơ sở dữ liệu trong S3.
  • Biến instance_type: Loại instance EC2 để chạy (ví dụ: t2.micro).
  • Biến min_size: Số lượng instance tối thiểu trong Auto Scaling Group (ASG).
  • Biến max_size: Số lượng instance tối đa trong ASG.

– /prod/data-stores/mysql/backend.tf

# Define Terraform backend using a S3 bucket for storing the Terraform state
terraform {
  backend "s3" {
    bucket = "terraform-state-my-bucket"
    key    = "module-example/prod/data-stores/mysql/terraform.tfstate"
    region = "eu-west-1"
  }
}

Đoạn code này định nghĩa backend cho Terraform, nơi lưu trữ Terraform state (trạng thái của các tài nguyên được quản lý bởi Terraform). Backend ở đây được cấu hình sử dụng một bucket S3 của AWS.

Cụ thể, trong phần backend này, chúng ta định nghĩa rằng:

  • Backend sử dụng S3 với region là “eu-west-1”.
  • Tài nguyên lưu trữ trạng thái của Terraform sẽ được lưu trữ trong bucket “terraform-state-my-bucket” với đường dẫn “module-example/prod/data-stores/mysql/terraform.tfstate”. Trong đó “module-example/prod/data-stores/mysql” là tên của module và “terraform.tfstate” là tên mặc định của file lưu trữ trạng thái của Terraform.

Với việc định nghĩa backend này, chúng ta có thể đảm bảo rằng Terraform state sẽ được lưu trữ một cách an toàn, tránh mất mát dữ liệu trong quá trình triển khai hạ tầng.

– /prod/data-stores/mysql/main.tf

# Configure the AWS provider
provider "aws" {
  region = "eu-west-1"
}

# Create a DB instance
resource "aws_db_instance" "example" {
  engine              = "mysql"
  allocated_storage   = 10
  instance_class      = "db.t2.micro"
  name                = "example_database_prod"
  username            = "admin"
  password            = "${var.db_password}"
  skip_final_snapshot = true
}

Đoạn code trên là mã mô tả cấu hình để tạo một instance của cơ sở dữ liệu trên AWS, được định nghĩa bằng cấu trúc mã nguồn của Terraform. Nó bao gồm:

  • Khai báo “provider aws”: Đây là khai báo cấu hình cho nhà cung cấp AWS để Terraform có thể tạo và quản lý các tài nguyên trên AWS. Trong đoạn mã này, nó chỉ định khu vực eu-west-1.
  • Khai báo “resource aws_db_instance”: Đây là định nghĩa tài nguyên cụ thể, trong trường hợp này là một instance của cơ sở dữ liệu. Terraform sẽ sử dụng mã mô tả này để tạo một instance của cơ sở dữ liệu trên AWS.
    • engine: Loại cơ sở dữ liệu được sử dụng, trong trường hợp này là MySQL.
    • allocated_storage: Dung lượng đĩa được cấp phát cho instance.
    • instance_class: Kích thước của instance, trong trường hợp này là db.t2.micro.
    • name: Tên cho instance của cơ sở dữ liệu.
    • usernamepassword: Các thông tin đăng nhập cho instance của cơ sở dữ liệu.
    • skip_final_snapshot: Tùy chọn để bỏ qua chụp một snapshot cuối cùng trước khi xóa instance của cơ sở dữ liệu.

– /prod/data-stores/mysql/outputs.tf

# Output variable: DB instance address
output "address" {
  value = "${aws_db_instance.example.address}"
}

# Output variable: DB instance port
output "port" {
  value = "${aws_db_instance.example.port}"
}

Đoạn code trên định nghĩa hai biến đầu ra (output) của Terraform sau khi tạo DB instance trên AWS.

  • Biến đầu ra “address”: giá trị của biến này là địa chỉ IP của DB instance được tạo ra. Giá trị của biến được xác định bằng cách sử dụng giá trị trả về từ thuộc tính “address” của tài nguyên DB instance.
  • Biến đầu ra “port”: giá trị của biến này là số cổng (port) của DB instance được tạo ra. Giá trị của biến được xác định bằng cách sử dụng giá trị trả về từ thuộc tính “port” của tài nguyên DB instance.

Hai biến đầu ra này có thể được sử dụng trong Terraform hoặc bên ngoài nó, ví dụ như cho phép kết nối tới DB instance từ ứng dụng bên ngoài.

– /prod/data-stores/mysql/vars.tf

# Input variable: DB password
variable "db_password" {
  description = "The password for the database"
}

Đoạn code này khai báo một biến đầu vào trong Terraform với tên là db_password. Biến này sẽ được sử dụng để lưu trữ mật khẩu của cơ sở dữ liệu trong hệ thống. Khi thực thi các lệnh Terraform, giá trị của biến này có thể được nhập từ người dùng hoặc được khai báo mặc định nếu người dùng không cung cấp giá trị.

Với cú pháp của đoạn code, khi sử dụng các tài nguyên của AWS như cơ sở dữ liệu (RDS), thì người dùng phải cung cấp mật khẩu cho cơ sở dữ liệu đó. Do đó, biến đầu vào db_password sẽ được sử dụng để lưu trữ mật khẩu cơ sở dữ liệu, và giá trị này sẽ được truyền vào tài nguyên cơ sở dữ liệu AWS thông qua biến password của tài nguyên aws_db_instance.

– /prod/services/webserver-cluster/backend.tf

# Define Terraform backend using a S3 bucket for storing the Terraform state
terraform {
  backend "s3" {
    bucket = "terraform-state-my-bucket"
    key    = "module-example/prod/services/webserver-cluster/terraform.tfstate"
    region = "eu-west-1"
  }
}

Đoạn code này sử dụng để cấu hình backend của Terraform. Backend này được sử dụng để lưu trữ state của Terraform, chứa thông tin về tất cả các tài nguyên được quản lý bởi Terraform.

Trong đoạn mã này, chúng ta định nghĩa backend của Terraform là S3 bằng cách sử dụng khối backend và truyền giá trị s3 vào thuộc tính backend để chỉ định loại backend.

Sau đó, chúng ta chỉ định các thông số của backend như tên bucket (bucket), key cho state file (key) và khu vực (region) trong đó bucket này được lưu trữ. Cụ thể, state file sẽ được lưu trữ trong bucket có tên terraform-state-my-bucket, key là "module-example/prod/services/webserver-cluster/terraform.tfstate" và khu vực của bucket là eu-west-1. Khi Terraform chạy, nó sẽ tự động tìm kiếm state file trong bucket này để đồng bộ hóa với tài nguyên đang quản lý.

– /prod/services/webserver-cluster/main.tf

# Configure the AWS provider
provider "aws" {
  region = "eu-west-1"
}

# Use Module
module "webserver_cluster" {
  source = "../../../modules/services/webserver-cluster"
  
  cluster_name           = "werservers-prod"
  db_remote_state_bucket = "${var.db_remote_state_bucket}"
  db_remote_state_key    = "${var.db_remote_state_key}"

  instance_type = "t2.micro"
  min_size      = 2
  max_size      = 10
}

# Create an Autoscaling Schedule
resource "aws_autoscaling_schedule" "scale_out_during_business_hours" {
  scheduled_action_name = "scale-out-during-business-hours"
  min_size              = 2
  max_size              = 10
  desired_capacity      = 10
  recurrence            = "0 9 * * *"
  
  autoscaling_group_name = "${module.webserver_cluster.asg_name}"
}

# Create an Autoscaling Schedule
resource "aws_autoscaling_schedule" "scale_in_at_night" {
  scheduled_action_name = "scale-in-at-night"
  min_size              = 2
  max_size              = 10
  desired_capacity      = 2
  recurrence            = "0 17 * * *"

  autoscaling_group_name = "${module.webserver_cluster.asg_name}"
}

Đoạn code này sử dụng Terraform để tạo một nhóm Amazon Elastic Compute Cloud (EC2) instances được tự động điều chỉnh kích thước bằng cách sử dụng lịch trình tự động điều chỉnh tự động. Cụ thể, nó có các phần sau:

  1. Khai báo provider: định cấu hình terraform provider để tương tác với Amazon Web Services (AWS).
  2. Sử dụng một module: sử dụng module webserver-cluster được định nghĩa trong file ../../../modules/services/webserver-cluster để tạo một nhóm các EC2 instances. Module này định nghĩa một Auto Scaling Group (ASG) cùng với các resources khác như load balancer, security group, launch configuration, và database instance.
  3. Tạo một lịch trình tự động điều chỉnh để thay đổi kích thước nhóm instances. Cụ thể, code tạo ra hai resources aws_autoscaling_schedule, scale_out_during_business_hoursscale_in_at_night để mô tả việc điều chỉnh tự động kích thước nhóm instances của module webserver-cluster trong giờ làm việc và giờ nghỉ. Các thuộc tính của resource bao gồm:
  • scheduled_action_name: tên cho hành động tự động điều chỉnh lịch trình
  • min_size, max_size: số lượng instances tối thiểu và tối đa trong ASG
  • desired_capacity: số lượng instances mong muốn trong ASG khi kết thúc lịch trình
  • recurrence: biểu thức cron cho phép lịch trình tự động hoạt động vào các thời điểm cụ thể.
  • autoscaling_group_name: tên của ASG mà lịch trình tự động điều chỉnh sẽ được áp dụng.
  1. Các biến đầu vào (không được định nghĩa trong code này) sẽ được sử dụng để truyền các giá trị vào module và resources, giúp người dùng tùy chỉnh hành vi của cấu hình Terraform.

– /prod/services/webserver-cluster/outputs.tf

# Output variable: DNS Name of ELB
output "elb_dns_name" {
  value = "${module.webserver_cluster.elb_dns_name}"
}

Đoạn code này định nghĩa một biến đầu ra (output variable) để xuất ra tên miền DNS của Elastic Load Balancer (ELB).

Đầu ra này được lấy từ module “webserver_cluster” và giá trị của nó được định nghĩa là giá trị của thuộc tính “elb_dns_name” của module đó.

Khi chạy Terraform, đoạn code này sẽ xuất ra tên miền DNS của ELB để người dùng có thể sử dụng để truy cập vào các web server được phân phối tải.

– /prod/services/webserver-cluster/vars.tf

# Input variable: DB remote state bucket name
variable "db_remote_state_bucket" {
  description = "The name of the S3 bucket for the database's remote state"
  default     =  "terraform-state-my-bucket"
}

# Input variable: DB remote state bucket key
variable "db_remote_state_key" {
  description = "The path for database's remote state in S3"
  default     = "module-example/prod/data-stores/mysql/terraform.tfstate"
}

Đoạn code này định nghĩa 2 biến đầu vào (input variables) cho một module Terraform. Các biến này được sử dụng để chỉ định nơi lưu trữ trạng thái của database trong một bucket S3 khác.

  • Biến db_remote_state_bucket: Chỉ định tên của bucket S3 được sử dụng để lưu trữ trạng thái của database. Biến này có thể được ghi đè bằng giá trị khác khi gọi module.
  • Biến db_remote_state_key: Chỉ định đường dẫn (key) trong bucket S3 đến trạng thái của database. Giá trị mặc định của biến này là "module-example/prod/data-stores/mysql/terraform.tfstate".

– /stage/data-stores/mysql/backend.tf

# Define Terraform backend using a S3 bucket for storing the Terraform state
terraform {
  backend "s3" {
    bucket = "terraform-state-my-bucket"
    key    = "module-example/stage/data-stores/mysql/terraform.tfstate"
    region = "eu-west-1"
  }
}

Đoạn code này khai báo Terraform backend để sử dụng S3 bucket để lưu trữ trạng thái của Terraform.

Trong đó:

  • backend "s3" khai báo sử dụng backend là S3 bucket.
  • bucket là tên của bucket được sử dụng để lưu trữ trạng thái của Terraform.
  • key là đường dẫn cho file lưu trữ trạng thái Terraform. Trong trường hợp này, file sẽ được lưu trong module-example/stage/data-stores/mysql/terraform.tfstate.
  • region là khu vực của S3 bucket. Trong trường hợp này là eu-west-1.

Như vậy, khi thực hiện Terraform apply để triển khai hạ tầng AWS, Terraform sẽ sử dụng S3 bucket này để lưu trữ trạng thái của các tài nguyên được quản lý bởi Terraform. Việc sử dụng backend này giúp cho việc quản lý trạng thái của hạ tầng trở nên dễ dàng hơn khi có nhiều thành viên cùng làm việc trên một dự án.

– /stage/data-stores/mysql/main.tf

# Configure the AWS provider
provider "aws" {
  region = "eu-west-1"
}

# Create a DB instance
resource "aws_db_instance" "example" {
  engine              = "mysql"
  allocated_storage   = 10
  instance_class      = "db.t2.micro"
  name                = "example_database_stage"
  username            = "admin"
  password            = "${var.db_password}"
  skip_final_snapshot = true
}

Đoạn code này là một ví dụ về cách sử dụng Terraform để tạo một instance database MySQL trên AWS (Amazon Web Services).

  • Bắt đầu bằng cách cấu hình AWS provider với region được chỉ định là eu-west-1.
  • Tiếp theo, định nghĩa một resource aws_db_instance với tên là example. Trong resource này, chúng ta đang khai báo các thuộc tính như engine (MySQL), allocated_storage (10GB), instance_class (db.t2.micro), name (tên database), usernamepassword (được cung cấp thông qua biến var.db_password), và skip_final_snapshot (không tạo snapshot cuối cùng trước khi xóa DB instance).
  • Trong trường hợp này, biến var.db_password là một biến đầu vào để cung cấp mật khẩu cho database instance.

Tóm lại, đoạn mã này cho phép bạn tạo một database MySQL trên AWS bằng cách sử dụng Terraform.

– /stage/data-stores/mysql/outputs.tf

# Output variable: DB instance address
output "address" {
  value = "${aws_db_instance.example.address}"
}

# Output variable: DB instance port
output "port" {
  value = "${aws_db_instance.example.port}"
}

Đoạn code này định nghĩa 2 output variables để xuất ra địa chỉ và cổng của instance database đã tạo ra bởi Terraform. Output variables được sử dụng để truy cập vào các giá trị đã tạo bởi Terraform và sử dụng chúng trong các module và các lần chạy khác.

Đối với output “address”, giá trị được xuất ra là địa chỉ IP của instance database đã tạo.

Đối với output “port”, giá trị được xuất ra là cổng mà instance database đang lắng nghe để kết nối.

Để truy cập vào các giá trị này, ta có thể sử dụng lệnh terraform output để hiển thị các giá trị này trong cửa sổ terminal hoặc có thể sử dụng chúng trong các module khác của Terraform.

– /stage/data-stores/mysql/vars.tf

# Input variable: DB password
variable "db_password" {
  description = "The password for the database"
}

Đoạn code trên định nghĩa một biến đầu vào có tên db_password được sử dụng để lưu trữ mật khẩu cho cơ sở dữ liệu. Biến đầu vào này cho phép người dùng đưa ra giá trị mật khẩu để sử dụng trong các tài nguyên khác trong mã Terraform.

Nếu người dùng không đưa ra giá trị mặc định cho biến này, giá trị mặc định sẽ được sử dụng. Ở đây, không có giá trị mặc định nào được định nghĩa, do đó nếu người dùng không cung cấp giá trị cho biến db_password, Terraform sẽ yêu cầu người dùng nhập giá trị cho biến này khi thực thi mã.

– /stage/services/webserver-cluster/backend.tf

# Define Terraform backend using a S3 bucket for storing the Terraform state
terraform {
  backend "s3" {
    bucket = "terraform-state-my-bucket"
    key    = "module-example/stage/services/webserver-cluster/terraform.tfstate"
    region = "eu-west-1"
  }
}

Đoạn code này là cấu hình Terraform backend để lưu trữ state file trong một S3 bucket của AWS.

  • backend được sử dụng để cấu hình cách lưu trữ state file của Terraform.
  • s3 là loại backend được sử dụng trong đoạn code này.
  • bucket là tên của bucket S3 được sử dụng để lưu trữ state file của Terraform.
  • key là đường dẫn tới file state trong bucket.
  • region là khu vực của bucket S3.

Với đoạn code này, state file của module Terraform có đường dẫn là module-example/stage/services/webserver-cluster/terraform.tfstate sẽ được lưu trữ trong bucket có tên là terraform-state-my-bucket ở khu vực eu-west-1.

– /stage/services/webserver-cluster/main.tf

# Configure the AWS provider
provider "aws" {
  region = "eu-west-1"
}

# Use Module
module "webserver_cluster" {
  source = "../../../modules/services/webserver-cluster"
  
  cluster_name           = "werservers-stage"
  db_remote_state_bucket = "${var.db_remote_state_bucket}"
  db_remote_state_key    = "${var.db_remote_state_key}"
  
  instance_type = "t2.micro"
  min_size      = 2
  max_size      = 2
}

# Create a Security Group Rule
resource "aws_security_group_rule" "allow_testing_inbound" {
  type              = "ingress"
  security_group_id = "${module.webserver_cluster.elb_security_group_id}"

  from_port   = 12345
  to_port     = 12345
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]
}

Đoạn code này được sử dụng để cấu hình và triển khai các tài nguyên AWS bằng cách sử dụng Terraform.

  • provider "aws" xác định rằng Terraform sẽ sử dụng AWS làm nhà cung cấp dịch vụ đích để tạo các tài nguyên.
  • module "webserver_cluster" sử dụng module webserver-cluster đã được định nghĩa trước đó trong thư mục modules/services/webserver-cluster. Đoạn code này tạo một nhóm máy chủ web sử dụng các thông số như tên nhóm máy chủ, kích thước nhóm máy chủ, loại instance EC2 và nhiều thông số khác.
  • resource "aws_security_group_rule" "allow_testing_inbound" định nghĩa một quy tắc bảo mật cho phép kết nối đến port 12345 từ bất kỳ địa chỉ IP nào. Quy tắc bảo mật này được áp dụng cho nhóm bảo mật mà ELB sử dụng, được lấy từ output của module webserver_cluster.

Ngoài ra, đoạn code này cũng sử dụng các biến đầu vào (variable) để chứa các giá trị có thể được truyền vào các file Terraform để tạo các tài nguyên.

– /stage/services/webserver-cluster/outputs.tf

# Output variable: DNS Name of ELB
output "elb_dns_name" {
  value = "${module.webserver_cluster.elb_dns_name}"
}

Đoạn code này định nghĩa một biến đầu ra (output variable) với tên là elb_dns_name để trả về tên miền DNS của Application Load Balancer (ALB) được tạo ra bởi mô-đun webserver_cluster.

Cụ thể, biến đầu ra này sử dụng hàm nội suy (interpolation function) của Terraform là ${} để gán giá trị cho thuộc tính value. Giá trị này là thuộc tính elb_dns_name của mô-đun webserver_cluster.

Khi thực thi, Terraform sẽ đảm bảo rằng biến đầu ra này có sẵn trong file state, để có thể được sử dụng hoặc truy vấn bởi các module hoặc tài nguyên khác của Terraform.

– /stage/services/webserver-cluster/vars.tf

# Input variable: DB remote state bucket name
variable "db_remote_state_bucket" {
  description = "The name of the S3 bucket for the database's remote state"
  default     =  "terraform-state-my-bucket"
}

# Input variable: DB remote state bucket key
variable "db_remote_state_key" {
  description = "The path for database's remote state in S3"
  default     = "module-example/stage/data-stores/mysql/terraform.tfstate"
}

Đoạn code trên định nghĩa 2 biến đầu vào cho mô-đun, được sử dụng để định vị nơi lưu trữ trạng thái của cơ sở dữ liệu từ xa trong AWS S3 bucket.

  • Biến db_remote_state_bucket là tên của bucket AWS S3 để lưu trữ trạng thái từ xa của cơ sở dữ liệu. Nếu không được chỉ định giá trị cho biến này, giá trị mặc định là “terraform-state-my-bucket”.
  • Biến db_remote_state_key định nghĩa đường dẫn trong bucket S3 để lưu trữ trạng thái từ xa của cơ sở dữ liệu. Nếu không được chỉ định giá trị cho biến này, giá trị mặc định là “module-example/stage/data-stores/mysql/terraform.tfstate”.

Chi phí triển khai

Chi phí triển khai cụ thể cho phần này phụ thuộc vào nhiều yếu tố, bao gồm:

  • Loại instance được sử dụng cho các dịch vụ AWS (như EC2 instances, RDS databases, ELB load balancers…)
  • Thời gian chạy các instance và dịch vụ AWS
  • Kích thước và tần suất sử dụng S3 bucket cho Terraform backend
  • Số lần và số lượng tài nguyên (như instance, security group rule) được tạo ra trong quá trình triển khai

Nếu bạn chỉ triển khai và xoá liền, thì chi phí sẽ không lớn. Tuy nhiên, để tránh bị tính phí không cần thiết, bạn nên chắc chắn rằng các tài nguyên AWS và S3 bucket đã được xoá hoàn toàn sau khi bạn hoàn thành các bài kiểm tra của mình.

1 COMMENT

  1. Hello

    I hope this email finds you well. My name is Clyde, I am reaching out about an IT service company called Codero that I think may be able to help your business.

    Codero offers a variety of IT solutions such as website development, cybersecurity services, cloud solutions, and more.
    Their team of experts can help optimize your technology, protect your data, and allow you to focus on your core business.

    Many companies have been able to streamline operations, reduce costs, and gain a competitive advantage through partnering with Codero.
    They take a personalized approach to understand each client’s unique needs.

    I would highly recommend checking them out at https://rb.gy/pib5e to learn more about the types of services they provide.

    Get in touch with Codero’s team through the link below:
    https://rb.gy/pib5e
    Learn more on how Codero will be able to support your specific business goals and requirements.

    Let me know if you have any other questions.
    I hope you will consider Codero for your IT needs, and hope you’d return to testify after giving them a try?.

    Thank you for your time.

    Clyde Ryan

    Reply UNSUBSCRIBE if you wish to be unsubscribed from my list.

    Proxmox

    Proxmox | Wiki của Hoàng

    https://wiki.hoanghd.com/category/virtualization/proxmox/

    hoanghd.com

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories