Bài 7. Terraform Workspaces: Quản Lý Nhiều Môi Trường Hiệu Quả Trên AWS

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:
    1. Đả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.
    2. 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).

Bước 2: Tạo Thư Mục Dự Án Và Viết Mã Terraform

  • Hành động:

    1. Tạo một thư mục mới cho dự án:
      mkdir terraform-workspaces-example
      cd terraform-workspaces-example
    2. 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
      }
    3. 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ụng terraform.workspace để xác định môi trường hiện tại (dev hoặc prod), từ đó điều chỉnh instance_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.
  • 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 file main.tfvariables.tf).

  • Đề 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ị file main.tf, với đoạn mã sử dụng terraform.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:
    1. Trong thư mục terraform-workspaces-example, khởi tạo dự án:
      terraform init
    2. Tạo workspace cho môi trường dev:
      terraform workspace new dev
    3. Tạo workspace cho môi trường prod:
      terraform workspace new prod
    4. Xem danh sách workspaces:
      terraform workspace list
  • 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 ở workspace prod).

Bước 4: Triển Khai Hạ Tầng Trong Các Workspaces

  • Hành động:
    1. Chuyển sang workspace dev:
      terraform workspace select dev
    2. 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.

    3. Chuyển sang workspace prod:
      terraform workspace select prod
    4. 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.

  • 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 workspace dev, 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 instance t2.micro với tag Name: 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 workspace prod, 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 instance t3.medium với tag Name: prod-EC2-1Name: prod-EC2-2).

    • Kiểm tra trên AWS Console (EC2 Dashboard):
    • Workspace dev: 1 instance với tag Name: dev-EC2-1, loại t2.micro.
    • Workspace prod: 2 instance với tag Name: prod-EC2-1Name: prod-EC2-2, loại t3.medium.

Bước 5: Xóa Tài Nguyên Để Dọn Dẹp

  • Hành động:
    1. 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.

    2. 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.

  • Kết quả thực tế:

    • Sau khi chạy terraform destroy trong workspace dev, 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 workspace prod, 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 devprod 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 cho dev và 2 instance t3.medium cho prod.
  • 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.tfstateterraform.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 trong dev nằm trong Free Tier, nhưng instance t3.medium trong prod có thể phát sinh chi phí (khoảng $0.0416/giờ mỗi instance). Luôn chạy terraform 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).
Điều hướng chuỗi bài viết<< 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 8. Terraform State: Quản Lý Trạng Thái Hạ Tầng Với S3 Và DynamoDB
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