Bài 5. Tự Động Hóa Triển Khai Với Terraform: Tạo Load Balancer Và Auto Scaling Group

Tại Sao Cần Tự Động Hóa Triển Khai Với Terraform?

Tự động hóa triển khai với Terraform là bước quan trọng để xây dựng hạ tầng có khả năng mở rộng và chịu tải cao, đặc biệt trong các ứng dụng thực tế. 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), và sử dụng variables/outputs (bài 4).

Tuy nhiên, khi triển khai một ứng dụng web, bạn cần đảm bảo ứng dụng có thể xử lý lưu lượng truy cập tăng đột biến và duy trì tính sẵn sàng cao. Điều này đòi hỏi một Load Balancer để phân phối lưu lượng và một Auto Scaling Group để tự động tăng/giảm số lượng máy chủ dựa trên nhu cầu. Trong bài này, mình sẽ hướng dẫn bạn 5 bước để tự động hóa triển khai với Terraform, tạo một hạ tầng hoàn chỉnh trên AWS với Load Balancer và Auto Scaling Group.

Tự Động Hóa Triển Khai Với Terraform: 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-load-balancer-autoscaling
      cd terraform-load-balancer-autoscaling
    2. Tạo file main.tf:
      touch main.tf
    3. 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 = "us-east-1"
      }
      
      # Sử dụng VPC và subnet từ bài 3 (giả định đã có sẵn, hoặc bạn có thể tạo lại)
      data "aws_vpc" "my_vpc" {
      filter {
       name   = "tag:Name"
       values = ["MyVPC"]
      }
      }
      
      data "aws_subnet" "my_subnet" {
      filter {
       name   = "tag:Name"
       values = ["MySubnet"]
      }
      }
      
      # Tạo Security Group cho EC2 và Load Balancer
      resource "aws_security_group" "web_sg" {
      vpc_id = data.aws_vpc.my_vpc.id
      
      ingress {
       from_port   = 80
       to_port     = 80
       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 = "WebSecurityGroup"
      }
      }
      
      # Tạo Launch Template cho Auto Scaling Group
      resource "aws_launch_template" "web_template" {
      name_prefix   = "web-template-"
      image_id      = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 in us-east-1
      instance_type = "t2.micro"
      
      network_interfaces {
       associate_public_ip_address = true
       security_groups             = [aws_security_group.web_sg.id]
      }
      
      user_data = base64encode(<<-EOF
      #!/bin/bash
      yum update -y
      yum install -y httpd
      systemctl start httpd
      systemctl enable httpd
      echo "
      <h1>Hello from Terraform Auto Scaling Group!</h1>" > /var/www/html/index.html
      EOF
      )
      
      tags = {
       Name = "WebInstance"
      }
      }
      
      # Tạo Auto Scaling Group
      resource "aws_autoscaling_group" "web_asg" {
      desired_capacity = 2
      min_size         = 1
      max_size         = 3
      vpc_zone_identifier = [data.aws_subnet.my_subnet.id]
      
      launch_template {
       id      = aws_launch_template.web_template.id
       version = "$Latest"
      }
      
      tag {
       key                 = "Name"
       value               = "WebASGInstance"
       propagate_at_launch = true
      }
      }
      
      # Tạo Application Load Balancer
      resource "aws_lb" "web_lb" {
      name               = "web-lb"
      internal           = false
      load_balancer_type = "application"
      security_groups    = [aws_security_group.web_sg.id]
      subnets            = [data.aws_subnet.my_subnet.id]
      
      tags = {
       Name = "WebLoadBalancer"
      }
      }
      
      # Tạo Target Group cho Load Balancer
      resource "aws_lb_target_group" "web_tg" {
      name     = "web-tg"
      port     = 80
      protocol = "HTTP"
      vpc_id   = data.aws_vpc.my_vpc.id
      
      health_check {
       path                = "/"
       protocol            = "HTTP"
       matcher             = "200"
       interval            = 30
       timeout             = 5
       healthy_threshold   = 2
       unhealthy_threshold = 2
      }
      }
      
      # Tạo Listener cho Load Balancer
      resource "aws_lb_listener" "web_listener" {
      load_balancer_arn = aws_lb.web_lb.arn
      port              = 80
      protocol          = "HTTP"
      
      default_action {
       type             = "forward"
       target_group_arn = aws_lb_target_group.web_tg.arn
      }
      }
      
      # Gắn Auto Scaling Group với Target Group
      resource "aws_autoscaling_attachment" "asg_attachment" {
      autoscaling_group_name = aws_autoscaling_group.web_asg.name
      lb_target_group_arn    = aws_lb_target_group.web_tg.arn
      }
      
      # Output DNS của Load Balancer
      output "load_balancer_dns" {
      description = "DNS name of the Load Balancer"
      value       = aws_lb.web_lb.dns_name
      }

      Giải thích:

      • data "aws_vpc"data "aws_subnet": Sử dụng VPC và subnet đã tạo từ bài 3 (giả định đã có sẵn).
      • aws_security_group: Tạo Security Group cho phép truy cập HTTP (port 80) và tất cả outbound traffic.
      • aws_launch_template: Tạo Launch Template với user data để cài đặt web server (Apache) trên EC2.
      • aws_autoscaling_group: Tạo Auto Scaling Group với 2 instance ban đầu, có thể mở rộng từ 1 đến 3 instance.
      • aws_lb, aws_lb_target_group, aws_lb_listener: Tạo Application Load Balancer, Target Group, và Listener để phân phối lưu lượng.
      • aws_autoscaling_attachment: Gắn Auto Scaling Group với Target Group để Load Balancer phân phối lưu lượng đến các instance.
      • output: Xuất DNS của Load Balancer để truy cập ứng dụng.
  • Kết quả thực tế:
    • Sau khi chạy lệnh mkdircd, bạn đã ở trong thư mục terraform-load-balancer-autoscaling. Kiểm tra bằng lệnh pwd:
      /Users/user/terraform-load-balancer-autoscaling
    • Sau khi tạo và chỉnh sửa file main.tf, thư mục dự án sẽ có cấu trúc:
      terraform-load-balancer-autoscaling/
      main.tf

      (Kiểm tra bằng lệnh ls, bạn sẽ thấy file main.tf trong thư mục).

    • Kiểm tra nội dung file main.tf bằng lệnh:
      cat main.tf

      Output sẽ là mã Terraform như đã viết ở trên (được định dạng rõ ràng).

Bước 3: Khởi Tạo Dự Án Terraform

  • Hành động:
    1. Trong thư mục terraform-load-balancer-autoscaling, chạy lệnh:
      terraform init
  • Kết quả thực tế:

    • Terminal sẽ hiển thị quá trình khởi tạo:

      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!
      
      You may now begin working with Terraform. Try running "terraform plan" to see
      any changes that are required for your infrastructure. All Terraform commands
      should now work.
      
      If you ever set or change modules or backend configuration for Terraform,
      rerun this command to reinitialize your working directory. If you forget, other
      commands will detect it and remind you to do so if necessary.

      (Dòng “Terraform has been successfully initialized!” xác nhận quá trình khởi tạo thành công).

    • Thư mục dự án sẽ có thêm các file và thư mục mới. Kiểm tra bằng lệnh ls:
      .terraform  .terraform.lock.hcl  main.tf

      (Thư mục .terraform chứa provider đã tải về, và file .terraform.lock.hcl lưu thông tin phiên bản provider).

Bước 4: Xem Trước Và Áp Dụng Mã Terraform Để Tạo Hạ Tầng

  • Hành động:
    1. Chạy lệnh để xem trước các thay đổi:
      terraform plan
    2. Áp dụng mã để tạo hạ tầng:
      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 plan, terminal sẽ hiển thị kế hoạch thực thi (được rút gọn để dễ đọc):

      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_autoscaling_group.web_asg will be created
      + resource "aws_autoscaling_group" "web_asg" {
       + desired_capacity = 2
       + min_size         = 1
       + max_size         = 3
       + vpc_zone_identifier = [(known after apply)]
      }
      
      # aws_launch_template.web_template will be created
      + resource "aws_launch_template" "web_template" {
       + name_prefix   = "web-template-"
       + image_id      = "ami-0c55b159cbfafe1f0"
       + instance_type = "t2.micro"
      }
      
      # aws_lb.web_lb will be created
      + resource "aws_lb" "web_lb" {
       + name               = "web-lb"
       + internal           = false
       + load_balancer_type = "application"
      }
      
      # aws_lb_target_group.web_tg will be created
      + resource "aws_lb_target_group" "web_tg" {
       + name     = "web-tg"
       + port     = 80
       + protocol = "HTTP"
      }
      
      # aws_security_group.web_sg will be created
      + resource "aws_security_group" "web_sg" {
       + name   = (known after apply)
       + vpc_id = (known after apply)
      }
      
      Plan: 7 to add, 0 to change, 0 to destroy.

      (Kế hoạch cho thấy Terraform sẽ tạo 7 tài nguyên: Security Group, Launch Template, Auto Scaling Group, Load Balancer, Target Group, Listener, và Auto Scaling Attachment).

    • Sau khi chạy terraform apply và gõ yes, terminal sẽ hiển thị quá trình áp dụng:

      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:
      
      # (Tương tự như terraform plan ở trên)
      
      Plan: 7 to add, 0 to change, 0 to destroy.
      
      Do you want to perform these actions?
      Terraform will perform the actions described above.
      Only 'yes' will be accepted to approve.
      
      Enter a value: yes
      
      aws_security_group.web_sg: Creating...
      aws_security_group.web_sg: Creation complete after 2s [id=sg-0123456789abcdef0]
      aws_launch_template.web_template: Creating...
      aws_launch_template.web_template: Creation complete after 1s [id=lt-0123456789abcdef0]
      aws_autoscaling_group.web_asg: Creating...
      aws_lb.web_lb: Creating...
      aws_lb_target_group.web_tg: Creating...
      aws_lb_target_group.web_tg: Creation complete after 1s [id=arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/web-tg/abcdef1234567890]
      aws_lb.web_lb: Creation complete after 10s [id=arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/web-lb/abcdef1234567890]
      aws_lb_listener.web_listener: Creating...
      aws_lb_listener.web_listener: Creation complete after 1s [id=arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/web-lb/abcdef1234567890/1234567890abcdef]
      aws_autoscaling_attachment.asg_attachment: Creating...
      aws_autoscaling_group.web_asg: Still creating... [10s elapsed]
      aws_autoscaling_group.web_asg: Creation complete after 15s [id=web-asg]
      aws_autoscaling_attachment.asg_attachment: Creation complete after 1s
      
      Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
      
      Outputs:
      
      load_balancer_dns = "web-lb-1234567890.us-east-1.elb.amazonaws.com"

      (Dòng “Apply complete! Resources: 7 added, 0 changed, 0 destroyed” xác nhận hạ tầng đã được tạo. Output hiển thị DNS của Load Balancer).

    • Kiểm tra trên AWS Console:
    • EC2 Dashboard: Bạn sẽ thấy 2 instance (do desired_capacity = 2) với tag Name: WebASGInstance, trạng thái Running.
    • Load Balancer Dashboard: Một Application Load Balancer với tên web-lb, trạng thái Active.
    • Truy cập DNS của Load Balancer (web-lb-1234567890.us-east-1.elb.amazonaws.com) trên trình duyệt, bạn sẽ thấy trang web hiển thị: `

      Hello from Terraform Auto Scaling Group!

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

  • Hành động:
    1. Chạy lệnh để xóa tài nguyên:
      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 và gõ yes, terminal sẽ hiển thị quá trình xóa:

      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_autoscaling_group.web_asg will be destroyed
      - resource "aws_autoscaling_group" "web_asg" {
       - desired_capacity = 2 -> null
       - min_size         = 1 -> null
       - max_size         = 3 -> null
      }
      
      # aws_launch_template.web_template will be destroyed
      - resource "aws_launch_template" "web_template" {
       - name_prefix   = "web-template-" -> null
       - image_id      = "ami-0c55b159cbfafe1f0" -> null
       - instance_type = "t2.micro" -> null
      }
      
      # aws_lb.web_lb will be destroyed
      - resource "aws_lb" "web_lb" {
       - name               = "web-lb" -> null
       - internal           = false -> null
       - load_balancer_type = "application" -> null
      }
      
      # aws_lb_target_group.web_tg will be destroyed
      - resource "aws_lb_target_group" "web_tg" {
       - name     = "web-tg" -> null
       - port     = 80 -> null
       - protocol = "HTTP" -> null
      }
      
      # aws_security_group.web_sg will be destroyed
      - resource "aws_security_group" "web_sg" {
       - name   = "WebSecurityGroup" -> null
       - vpc_id = "vpc-0123456789abcdef0" -> null
      }
      
      Plan: 0 to add, 0 to change, 7 to destroy.
      
      Do you really want to destroy all resources?
      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_autoscaling_attachment.asg_attachment: Destroying...
      aws_autoscaling_attachment.asg_attachment: Destruction complete after 1s
      aws_autoscaling_group.web_asg: Destroying... [id=web-asg]
      aws_autoscaling_group.web_asg: Still destroying... [10s elapsed]
      aws_autoscaling_group.web_asg: Destruction complete after 15s
      aws_lb_listener.web_listener: Destroying... [id=arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/web-lb/abcdef1234567890/1234567890abcdef]
      aws_lb_listener.web_listener: Destruction complete after 1s
      aws_lb.web_lb: Destroying... [id=arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/web-lb/abcdef1234567890]
      aws_lb.web_lb: Still destroying... [10s elapsed]
      aws_lb.web_lb: Destruction complete after 15s
      aws_lb_target_group.web_tg: Destroying... [id=arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/web-tg/abcdef1234567890]
      aws_lb_target_group.web_tg: Destruction complete after 1s
      aws_launch_template.web_template: Destroying... [id=lt-0123456789abcdef0]
      aws_launch_template.web_template: Destruction complete after 1s
      aws_security_group.web_sg: Destroying... [id=sg-0123456789abcdef0]
      aws_security_group.web_sg: Destruction complete after 2s
      
      Destroy complete! Resources: 7 destroyed.

      (Dòng “Destroy complete! Resources: 7 destroyed” xác nhận hạ tầng đã bị xóa).

    • Kiểm tra lại trên AWS Console:
    • EC2 Dashboard: Các instance của Auto Scaling Group không còn tồn tại.
    • Load Balancer Dashboard: Load Balancer web-lb không còn tồn tại.

Kết Quả Đạt Được

  • Bạn đã tự động hóa triển khai với Terraform, tạo một hạ tầng hoàn chỉnh trên AWS bao gồm Load Balancer, Auto Scaling Group, và các instance chạy web server.
  • Bạn đã truy cập DNS của Load Balancer và xác nhận ứng dụng web hoạt động đúng.
  • Bạn đã xóa tài nguyên để dọn dẹp, tránh phát sinh chi phí không cần thiết.
  • Bạn đã làm quen với cách sử dụng Terraform để triển khai hạ tầng có khả năng mở rộng và chịu tải cao.

Lưu Ý Quan Trọng

  • Chi phí AWS: Load Balancer và Auto Scaling Group có thể phát sinh chi phí (khoảng $0.0225/giờ cho ALB và $0.10/giờ cho mỗi instance t2.micro ngoài Free Tier). Luôn chạy terraform destroy sau khi thử nghiệm.
  • Tối ưu Auto Scaling: Trong ví dụ này, Auto Scaling Group chưa có scaling policy. Bạn có thể thêm policy dựa trên CPU usage hoặc request count (xem tài liệu AWS Auto Scaling).
  • Bảo mật: Security Group trong bài cho phép truy cập từ 0.0.0.0/0 (toàn thế giới). Trong môi trường production, hãy giới hạn CIDR block hoặc sử dụng VPN.
  • Tài liệu tham khảo: Xem thêm về Load Balancer và Auto Scaling trong tài liệu chính thức của AWS (AWS Load Balancing) và (AWS Auto Scaling).
Điều hướng chuỗi bài viết<< Bài 4. Quản Lý Tài Nguyên Với Terraform: Sử Dụng Variables Và Outputs
>> Bài 6. Sử Dụng Terraform Modules: Tái Sử Dụng Mã Để Quản Lý Hạ Tầng Hiệu Quả
Article Thumbnail
Article Thumbnail
Datadog Webinar: Modernize AWS Logs at Scale

Bài viết khác

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