Danh sách bài viết trong series Hành Trình Làm Chủ Terraform
- Bài 1. Học Terraform Cơ Bản: Terraform Là Gì? Cài Đặt Và Viết Mã Đầu Tiên
- Bài 2. Học Terraform Với AWS: 5 Bước Tạo Máy Chủ EC2 Đầu Tiên
- Bài 3. Tạo VPC Với Terraform: Xây Dựng Hạ Tầng Mạng Trên AWS
- Bài 4. Quản Lý Tài Nguyên Với Terraform: Sử Dụng Variables Và Outputs
- Bài 5. Tự Động Hóa Triển Khai Với Terraform: Tạo Load Balancer Và Auto Scaling Group
- Bài 6. Sử Dụng Terraform Modules: Tái Sử Dụng Mã Để Quản Lý Hạ Tầng Hiệu Quả
- Bài 7. Terraform Workspaces: Quản Lý Nhiều Môi Trường Hiệu Quả Trên AWS
- Bài 8. Terraform State: Quản Lý Trạng Thái Hạ Tầng Với S3 Và DynamoDB
- Bài 9. Terraform Provisioners: Tự Động Hóa Cấu Hình Web Server Trên EC2
- Bài 10. Terraform CI/CD: Tự Động Triển Khai Hạ Tầng Với GitHub Actions
Tại Sao Cần Sử Dụng Terraform Workspaces?
Terraform workspaces là một công cụ mạnh mẽ để quản lý nhiều môi trường (như dev, staging, prod) trong cùng một mã nguồn Terraform, giúp bạn triển khai hạ tầng một cách hiệu quả và tránh lặp lại mã. Trong các bài trước, chúng ta đã làm quen với Terraform cơ bản (bài 1), tạo máy chủ EC2 (bài 2), xây dựng hạ tầng mạng VPC (bài 3), sử dụng variables/outputs (bài 4), tự động hóa triển khai với Load Balancer và Auto Scaling Group (bài 5), và sử dụng Terraform modules (bài 6).
Tuy nhiên, khi làm việc với nhiều môi trường, việc tạo các thư mục riêng hoặc sao chép mã cho từng môi trường (dev, staging, prod) có thể gây khó khăn trong việc bảo trì và dễ dẫn đến sai sót. Terraform workspaces cho phép bạn duy trì một bộ mã duy nhất nhưng triển khai hạ tầng khác nhau cho từng môi trường bằng cách quản lý trạng thái (state) riêng biệt. Trong bài này, mình sẽ hướng dẫn bạn 5 bước để sử dụng Terraform workspaces, triển khai EC2 trong các môi trường dev và prod trên AWS.
Terraform Workspaces: Hướng Dẫn Từng Bước
Bước 1: Chuẩn Bị Môi Trường Và Cấu Hình AWS CLI
- Hành động:
- Đảm bảo bạn đã cài đặt Terraform 1.11.2 và AWS CLI. Nếu chưa, tham khảo bài 1 và bài 2 để cài đặt.
- Kiểm tra cấu hình AWS CLI:
aws configure
Đảm bảo bạn đã nhập đúng Access Key, Secret Key, và vùng (VD:
us-east-1
).
- Kết quả thực tế:
- Nếu AWS CLI đã được cấu hình từ trước, bạn có thể kiểm tra bằng lệnh:
aws sts get-caller-identity
Output sẽ là:
{ "UserId": "AIDAXYZ1234567890", "Account": "123456789012", "Arn": "arn:aws:iam::123456789012:user/your-user-name" }
(Output xác nhận AWS CLI đã được cấu hình đúng và có thể kết nối với tài khoản AWS của bạn).
- Nếu AWS CLI đã được cấu hình từ trước, bạn có thể kiểm tra bằng lệnh:
Bước 2: Tạo Thư Mục Dự Án Và Viết Mã Terraform
-
Hành động:
- Tạo một thư mục mới cho dự án:
mkdir terraform-workspaces-example cd terraform-workspaces-example
-
Tạo file
variables.tf
để khai báo variables:touch variables.tf
Mở file
variables.tf
trong VS Code và dán nội dung sau:variable "region" { description = "AWS region to deploy resources" type = string default = "us-east-1" } variable "ami" { description = "AMI ID for the EC2 instance" type = string default = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 in us-east-1 }
-
Tạo file
main.tf
để viết mã Terraform:touch main.tf
Mở file
main.tf
trong VS Code và dán nội dung sau:terraform { required_providers { aws = { source = "hashicorp/aws" version = "5.0.0" } } } provider "aws" { region = var.region } # Định nghĩa thông số dựa trên workspace locals { instance_type = terraform.workspace == "prod" ? "t3.medium" : "t2.micro" instance_count = terraform.workspace == "prod" ? 2 : 1 environment = terraform.workspace } # Tạo Security Group cho EC2 resource "aws_security_group" "workspace_sg" { name_prefix = "${local.environment}-sg-" ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "${local.environment}-SG" } } # Tạo EC2 resource "aws_instance" "workspace_ec2" { count = local.instance_count ami = var.ami instance_type = local.instance_type vpc_security_group_ids = [aws_security_group.workspace_sg.id] tags = { Name = "${local.environment}-EC2-${count.index + 1}" } } # Output public IP của EC2 output "ec2_public_ips" { description = "Public IPs of the EC2 instances" value = aws_instance.workspace_ec2[*].public_ip }
Giải thích:
locals
: Sử dụngterraform.workspace
để xác định môi trường hiện tại (dev
hoặcprod
), từ đó điều chỉnhinstance_type
(t2.micro
cho dev,t3.medium
cho prod) vàinstance_count
(1 cho dev, 2 cho prod).aws_security_group
: Tạo Security Group với tên và tag động dựa trên workspace.aws_instance
: Tạo EC2 với số lượng và loại instance tùy thuộc vào workspace.output
: Xuất public IP của các EC2 để kiểm tra sau khi triển khai.
- Tạo một thư mục mới cho dự án:
- Kết quả thực tế:
- Sau khi tạo các file, cấu trúc thư mục sẽ là:
terraform-workspaces-example/ ├── main.tf └── variables.tf
(Kiểm tra bằng lệnh
ls
, bạn sẽ thấy hai filemain.tf
vàvariables.tf
).
- Sau khi tạo các file, cấu trúc thư mục sẽ là:
- Đề xuất hình ảnh minh họa:
Đề xuất chèn hình ảnh chụp giao diện VS Code hiển thị filemain.tf
, với đoạn mã sử dụngterraform.workspace
được highlight. Văn bản thay thế (alt text): “Terraform workspaces – Viết mã Terraform sử dụng workspaces để quản lý môi trường”.
Bước 3: Tạo Và Quản Lý Workspaces
- Hành động:
- Trong thư mục
terraform-workspaces-example
, khởi tạo dự án:terraform init
- Tạo workspace cho môi trường
dev
:terraform workspace new dev
- Tạo workspace cho môi trường
prod
:terraform workspace new prod
- Xem danh sách workspaces:
terraform workspace list
- Trong thư mục
-
Kết quả thực tế:
-
Sau khi chạy
terraform init
, terminal sẽ hiển thị:Initializing the backend... Initializing provider plugins... - Finding hashicorp/aws versions matching "5.0.0"... - Installing hashicorp/aws v5.0.0... - Installed hashicorp/aws v5.0.0 (signed by HashiCorp) Terraform has been successfully initialized!
(Dòng “Terraform has been successfully initialized!” xác nhận quá trình khởi tạo thành công).
-
Sau khi chạy
terraform workspace new dev
, terminal sẽ hiển thị:Created and switched to workspace "dev"! You're now on a new, empty workspace. Workspaces isolate their state, so if you run "terraform plan" Terraform will not see any existing state for this configuration.
- Sau khi chạy
terraform workspace new prod
, terminal sẽ hiển thị:Created and switched to workspace "prod"!
- Sau khi chạy
terraform workspace list
, terminal sẽ hiển thị:default dev * prod
(Dấu
*
cho biết bạn đang ở workspaceprod
).
-
Bước 4: Triển Khai Hạ Tầng Trong Các Workspaces
- Hành động:
- Chuyển sang workspace
dev
:terraform workspace select dev
- Triển khai hạ tầng trong workspace
dev
:terraform apply
Khi được hỏi “Do you want to perform these actions?”, gõ
yes
và nhấn Enter. - Chuyển sang workspace
prod
:terraform workspace select prod
- Triển khai hạ tầng trong workspace
prod
:terraform apply
Khi được hỏi “Do you want to perform these actions?”, gõ
yes
và nhấn Enter.
- Chuyển sang workspace
-
Kết quả thực tế:
- Sau khi chạy
terraform workspace select dev
, terminal sẽ hiển thị:Switched to workspace "dev".
-
Sau khi chạy
terraform apply
trong workspacedev
, terminal sẽ hiển thị:Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_instance.workspace_ec2[0] will be created + resource "aws_instance" "workspace_ec2" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" + tags = { + "Name" = "dev-EC2-1" } } # aws_security_group.workspace_sg will be created + resource "aws_security_group" "workspace_sg" { + name_prefix = "dev-sg-" + tags = { + "Name" = "dev-SG" } } Plan: 2 to add, 0 to change, 0 to destroy. Do you want to perform these actions in workspace "dev"? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes aws_security_group.workspace_sg: Creating... aws_security_group.workspace_sg: Creation complete after 2s [id=sg-0123456789abcdef0] aws_instance.workspace_ec2[0]: Creating... aws_instance.workspace_ec2[0]: Still creating... [10s elapsed] aws_instance.workspace_ec2[0]: Creation complete after 15s [id=i-0123456789abcdef0] Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: ec2_public_ips = [ "54.123.45.67", ]
(Workspace
dev
tạo 1 instancet2.micro
với tagName: dev-EC2-1
). - Sau khi chạy
terraform workspace select prod
, terminal sẽ hiển thị:Switched to workspace "prod".
-
Sau khi chạy
terraform apply
trong workspaceprod
, terminal sẽ hiển thị:Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_instance.workspace_ec2[0] will be created + resource "aws_instance" "workspace_ec2" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t3.medium" + tags = { + "Name" = "prod-EC2-1" } } # aws_instance.workspace_ec2[1] will be created + resource "aws_instance" "workspace_ec2" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t3.medium" + tags = { + "Name" = "prod-EC2-2" } } # aws_security_group.workspace_sg will be created + resource "aws_security_group" "workspace_sg" { + name_prefix = "prod-sg-" + tags = { + "Name" = "prod-SG" } } Plan: 3 to add, 0 to change, 0 to destroy. Do you want to perform these actions in workspace "prod"? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes aws_security_group.workspace_sg: Creating... aws_security_group.workspace_sg: Creation complete after 2s [id=sg-0987654321fedcba0] aws_instance.workspace_ec2[0]: Creating... aws_instance.workspace_ec2[1]: Creating... aws_instance.workspace_ec2[0]: Still creating... [10s elapsed] aws_instance.workspace_ec2[1]: Still creating... [10s elapsed] aws_instance.workspace_ec2[0]: Creation complete after 15s [id=i-0987654321fedcba0] aws_instance.workspace_ec2[1]: Creation complete after 15s [id=i-0987654321fedcba1] Apply complete! Resources: 3 added, 0 changed, 0 destroyed. Outputs: ec2_public_ips = [ "54.123.45.68", "54.123.45.69", ]
(Workspace
prod
tạo 2 instancet3.medium
với tagName: prod-EC2-1
vàName: prod-EC2-2
). - Kiểm tra trên AWS Console (EC2 Dashboard):
- Workspace
dev
: 1 instance với tagName: dev-EC2-1
, loạit2.micro
. - Workspace
prod
: 2 instance với tagName: prod-EC2-1
vàName: prod-EC2-2
, loạit3.medium
.
- Sau khi chạy
Bước 5: Xóa Tài Nguyên Để Dọn Dẹp
- Hành động:
- Chuyển sang workspace
dev
và xóa tài nguyên:terraform workspace select dev terraform destroy
Khi được hỏi “Do you really want to destroy all resources?”, gõ
yes
và nhấn Enter. - Chuyển sang workspace
prod
và xóa tài nguyên:terraform workspace select prod terraform destroy
Khi được hỏi “Do you really want to destroy all resources?”, gõ
yes
và nhấn Enter.
- Chuyển sang workspace
-
Kết quả thực tế:
-
Sau khi chạy
terraform destroy
trong workspacedev
, terminal sẽ hiển thị:Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # aws_instance.workspace_ec2[0] will be destroyed - resource "aws_instance" "workspace_ec2" { - ami = "ami-0c55b159cbfafe1f0" -> null - instance_type = "t2.micro" -> null - id = "i-0123456789abcdef0" -> null } # aws_security_group.workspace_sg will be destroyed - resource "aws_security_group" "workspace_sg" { - name_prefix = "dev-sg-" -> null - id = "sg-0123456789abcdef0" -> null } Plan: 0 to add, 0 to change, 2 to destroy. Do you really want to destroy all resources in workspace "dev"? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes aws_instance.workspace_ec2[0]: Destroying... [id=i-0123456789abcdef0] aws_instance.workspace_ec2[0]: Still destroying... [10s elapsed] aws_instance.workspace_ec2[0]: Destruction complete after 15s aws_security_group.workspace_sg: Destroying... [id=sg-0123456789abcdef0] aws_security_group.workspace_sg: Destruction complete after 2s Destroy complete! Resources: 2 destroyed.
-
Sau khi chạy
terraform destroy
trong workspaceprod
, terminal sẽ hiển thị:Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # aws_instance.workspace_ec2[0] will be destroyed - resource "aws_instance" "workspace_ec2" { - ami = "ami-0c55b159cbfafe1f0" -> null - instance_type = "t3.medium" -> null - id = "i-0987654321fedcba0" -> null } # aws_instance.workspace_ec2[1] will be destroyed - resource "aws_instance" "workspace_ec2" { - ami = "ami-0c55b159cbfafe1f0" -> null - instance_type = "t3.medium" -> null - id = "i-0987654321fedcba1" -> null } # aws_security_group.workspace_sg will be destroyed - resource "aws_security_group" "workspace_sg" { - name_prefix = "prod-sg-" -> null - id = "sg-0987654321fedcba0" -> null } Plan: 0 to add, 0 to change, 3 to destroy. Do you really want to destroy all resources in workspace "prod"? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes aws_instance.workspace_ec2[0]: Destroying... [id=i-0987654321fedcba0] aws_instance.workspace_ec2[1]: Destroying... [id=i-0987654321fedcba1] aws_instance.workspace_ec2[0]: Still destroying... [10s elapsed] aws_instance.workspace_ec2[1]: Still destroying... [10s elapsed] aws_instance.workspace_ec2[0]: Destruction complete after 15s aws_instance.workspace_ec2[1]: Destruction complete after 15s aws_security_group.workspace_sg: Destroying... [id=sg-0987654321fedcba0] aws_security_group.workspace_sg: Destruction complete after 2s Destroy complete! Resources: 3 destroyed.
- Kiểm tra lại trên AWS Console, tất cả instance và Security Group trong cả hai môi trường
dev
vàprod
không còn tồn tại.
-
Kết Quả Đạt Được
- Bạn đã học cách sử dụng Terraform workspaces để quản lý nhiều môi trường (dev và prod) trong cùng một mã nguồn.
- Bạn đã triển khai hạ tầng khác nhau cho từng môi trường: 1 instance
t2.micro
chodev
và 2 instancet3.medium
choprod
. - Bạn đã kiểm tra và xác nhận hạ tầng hoạt động đúng trên AWS Console.
- Bạn đã xóa tài nguyên trong cả hai workspaces để dọn dẹp, tránh phát sinh chi phí không cần thiết.
Lưu Ý Quan Trọng
- Quản lý state: Mỗi workspace có file state riêng (VD:
terraform.tfstate.d/dev/terraform.tfstate
vàterraform.tfstate.d/prod/terraform.tfstate
). Đảm bảo không xóa hoặc sửa các file state này. - Chi phí AWS: Instance
t2.micro
trongdev
nằm trong Free Tier, nhưng instancet3.medium
trongprod
có thể phát sinh chi phí (khoảng $0.0416/giờ mỗi instance). Luôn chạyterraform destroy
sau khi thử nghiệm. - Bảo mật: Security Group trong bài cho phép SSH (port 22) từ
0.0.0.0/0
. Trong môi trường production, hãy giới hạn CIDR block hoặc sử dụng bastion host. - Tài liệu tham khảo: Xem thêm về Terraform workspaces trong tài liệu chính thức (Terraform Workspaces).