Bài 3. Tạo VPC Với Terraform: Xây Dựng Hạ Tầng Mạng Trên AWS

Tại Sao Cần Tạo VPC Với Terraform?

Tạo VPC với Terraform là một kỹ năng quan trọng để xây dựng hạ tầng mạng an toàn và hiệu quả trên AWS. Sau khi đã làm quen với Terraform qua bài 1 (cài đặt và viết mã cơ bản) và bài 2 (tạo máy chủ EC2), bạn có thể thấy Terraform giúp tự động hóa việc quản lý hạ tầng một cách dễ dàng.

Tuy nhiên, trong các dự án thực tế, bạn thường cần một hạ tầng mạng riêng biệt để triển khai ứng dụng, chẳng hạn như một VPC (Virtual Private Cloud) với các subnet, internet gateway, và route table. Việc tạo VPC bằng tay trên AWS Console có thể mất hàng giờ và dễ sai sót. Trong bài này, mình sẽ hướng dẫn bạn 5 bước để tạo VPC với Terraform, giúp bạn xây dựng hạ tầng mạng trên AWS một cách nhanh chóng và chính xác.

Tạo VPC 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 (như trong bài 2), 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-aws-vpc
      cd terraform-aws-vpc
    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"
      }
      
      # Tạo VPC
      resource "aws_vpc" "my_vpc" {
      cidr_block = "10.0.0.0/16"
      tags = {
       Name = "MyVPC"
      }
      }
      
      # Tạo subnet
      resource "aws_subnet" "my_subnet" {
      vpc_id     = aws_vpc.my_vpc.id
      cidr_block = "10.0.1.0/24"
      tags = {
       Name = "MySubnet"
      }
      }
      
      # Tạo Internet Gateway
      resource "aws_internet_gateway" "my_igw" {
      vpc_id = aws_vpc.my_vpc.id
      tags = {
       Name = "MyInternetGateway"
      }
      }
      
      # Tạo Route Table
      resource "aws_route_table" "my_route_table" {
      vpc_id = aws_vpc.my_vpc.id
      
      route {
       cidr_block = "0.0.0.0/0"
       gateway_id = aws_internet_gateway.my_igw.id
      }
      
      tags = {
       Name = "MyRouteTable"
      }
      }
      
      # Gắn Route Table với Subnet
      resource "aws_route_table_association" "my_route_table_association" {
      subnet_id      = aws_subnet.my_subnet.id
      route_table_id = aws_route_table.my_route_table.id
      }

      Giải thích:

      • aws_vpc: Tạo một VPC với CIDR block 10.0.0.0/16.
      • aws_subnet: Tạo một subnet trong VPC với CIDR block 10.0.1.0/24.
      • aws_internet_gateway: Tạo Internet Gateway và gắn vào VPC.
      • aws_route_table: Tạo Route Table với route mặc định trỏ đến Internet Gateway.
      • aws_route_table_association: Gắn Route Table với Subnet để subnet có thể truy cập internet.
  • Kết quả thực tế:

    • Sau khi chạy lệnh mkdircd, bạn đã ở trong thư mục terraform-aws-vpc. Kiểm tra bằng lệnh pwd:
      /Users/user/terraform-aws-vpc
    • Sau khi tạo và chỉnh sửa file main.tf, thư mục dự án sẽ có cấu trúc:
      terraform-aws-vpc/
      main.tf

      (Kiểm tra bằng lệnh ls, bạn sẽ thấy chỉ có 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à:

      terraform {
      required_providers {
       aws = {
         source = "hashicorp/aws"
         version = "5.0.0"
       }
      }
      }
      
      provider "aws" {
      region = "us-east-1"
      }
      
      resource "aws_vpc" "my_vpc" {
      cidr_block = "10.0.0.0/16"
      tags = {
       Name = "MyVPC"
      }
      }
      
      resource "aws_subnet" "my_subnet" {
      vpc_id     = aws_vpc.my_vpc.id
      cidr_block = "10.0.1.0/24"
      tags = {
       Name = "MySubnet"
      }
      }
      
      resource "aws_internet_gateway" "my_igw" {
      vpc_id = aws_vpc.my_vpc.id
      tags = {
       Name = "MyInternetGateway"
      }
      }
      
      resource "aws_route_table" "my_route_table" {
      vpc_id = aws_vpc.my_vpc.id
      
      route {
       cidr_block = "0.0.0.0/0"
       gateway_id = aws_internet_gateway.my_igw.id
      }
      
      tags = {
       Name = "MyRouteTable"
      }
      }
      
      resource "aws_route_table_association" "my_route_table_association" {
      subnet_id      = aws_subnet.my_subnet.id
      route_table_id = aws_route_table.my_route_table.id
      }

      (Nội dung file hiển thị đúng như mã đã viết).

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

  • Hành động:
    1. Trong thư mục terraform-aws-vpc, 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 VPC

  • Hành động:
    1. Chạy lệnh để xem trước các thay đổi:
      terraform plan
    2. Áp dụng mã để tạo VPC:
      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:

      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_internet_gateway.my_igw will be created
      + resource "aws_internet_gateway" "my_igw" {
       + id     = (known after apply)
       + vpc_id = (known after apply)
       + tags   = {
           + "Name" = "MyInternetGateway"
         }
       + tags_all = {
           + "Name" = "MyInternetGateway"
         }
      }
      
      # aws_route_table.my_route_table will be created
      + resource "aws_route_table" "my_route_table" {
       + id     = (known after apply)
       + vpc_id = (known after apply)
       + route  = [
           + {
               + cidr_block = "0.0.0.0/0"
               + gateway_id = (known after apply)
             }
         ]
       + tags   = {
           + "Name" = "MyRouteTable"
         }
       + tags_all = {
           + "Name" = "MyRouteTable"
         }
      }
      
      # aws_route_table_association.my_route_table_association will be created
      + resource "aws_route_table_association" "my_route_table_association" {
       + id             = (known after apply)
       + subnet_id      = (known after apply)
       + route_table_id = (known after apply)
      }
      
      # aws_subnet.my_subnet will be created
      + resource "aws_subnet" "my_subnet" {
       + id             = (known after apply)
       + vpc_id         = (known after apply)
       + cidr_block     = "10.0.1.0/24"
       + tags           = {
           + "Name" = "MySubnet"
         }
       + tags_all       = {
           + "Name" = "MySubnet"
         }
      }
      
      # aws_vpc.my_vpc will be created
      + resource "aws_vpc" "my_vpc" {
       + id             = (known after apply)
       + cidr_block     = "10.0.0.0/16"
       + tags           = {
           + "Name" = "MyVPC"
         }
       + tags_all       = {
           + "Name" = "MyVPC"
         }
      }
      
      Plan: 5 to add, 0 to change, 0 to destroy.

      (Kế hoạch cho thấy Terraform sẽ tạo 5 tài nguyên: VPC, subnet, internet gateway, route table, và route table association).

    • 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:
      
      # aws_internet_gateway.my_igw will be created
      + resource "aws_internet_gateway" "my_igw" {
       + id     = (known after apply)
       + vpc_id = (known after apply)
       + tags   = {
           + "Name" = "MyInternetGateway"
         }
       + tags_all = {
           + "Name" = "MyInternetGateway"
         }
      }
      
      # aws_route_table.my_route_table will be created
      + resource "aws_route_table" "my_route_table" {
       + id     = (known after apply)
       + vpc_id = (known after apply)
       + route  = [
           + {
               + cidr_block = "0.0.0.0/0"
               + gateway_id = (known after apply)
             }
         ]
       + tags   = {
           + "Name" = "MyRouteTable"
         }
       + tags_all = {
           + "Name" = "MyRouteTable"
         }
      }
      
      # aws_route_table_association.my_route_table_association will be created
      + resource "aws_route_table_association" "my_route_table_association" {
       + id             = (known after apply)
       + subnet_id      = (known after apply)
       + route_table_id = (known after apply)
      }
      
      # aws_subnet.my_subnet will be created
      + resource "aws_subnet" "my_subnet" {
       + id             = (known after apply)
       + vpc_id         = (known after apply)
       + cidr_block     = "10.0.1.0/24"
       + tags           = {
           + "Name" = "MySubnet"
         }
       + tags_all       = {
           + "Name" = "MySubnet"
         }
      }
      
      # aws_vpc.my_vpc will be created
      + resource "aws_vpc" "my_vpc" {
       + id             = (known after apply)
       + cidr_block     = "10.0.0.0/16"
       + tags           = {
           + "Name" = "MyVPC"
         }
       + tags_all       = {
           + "Name" = "MyVPC"
         }
      }
      
      Plan: 5 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_vpc.my_vpc: Creating...
      aws_vpc.my_vpc: Creation complete after 2s [id=vpc-0123456789abcdef0]
      aws_subnet.my_subnet: Creating...
      aws_internet_gateway.my_igw: Creating...
      aws_subnet.my_subnet: Creation complete after 1s [id=subnet-0123456789abcdef0]
      aws_internet_gateway.my_igw: Creation complete after 1s [id=igw-0123456789abcdef0]
      aws_route_table.my_route_table: Creating...
      aws_route_table.my_route_table: Creation complete after 1s [id=rtb-0123456789abcdef0]
      aws_route_table_association.my_route_table_association: Creating...
      aws_route_table_association.my_route_table_association: Creation complete after 1s [id=rtbassoc-0123456789abcdef0]
      
      Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

      (Dòng “Apply complete! Resources: 5 added, 0 changed, 0 destroyed” xác nhận VPC và các tài nguyên liên quan đã được tạo).

    • Kiểm tra trên AWS Console (VPC Dashboard), bạn sẽ thấy:
    • Một VPC mới với tag Name: MyVPC, CIDR 10.0.0.0/16.
    • Một subnet với tag Name: MySubnet, CIDR 10.0.1.0/24.
    • Một Internet Gateway với tag Name: MyInternetGateway.
    • Một Route Table với tag Name: MyRouteTable, có route 0.0.0.0/0 trỏ đến Internet Gateway.

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_internet_gateway.my_igw will be destroyed
      - resource "aws_internet_gateway" "my_igw" {
       - id     = "igw-0123456789abcdef0" -> null
       - vpc_id = "vpc-0123456789abcdef0" -> null
       - tags   = {
           - "Name" = "MyInternetGateway"
         } -> null
       - tags_all = {
           - "Name" = "MyInternetGateway"
         } -> null
      }
      
      # aws_route_table.my_route_table will be destroyed
      - resource "aws_route_table" "my_route_table" {
       - id     = "rtb-0123456789abcdef0" -> null
       - vpc_id = "vpc-0123456789abcdef0" -> null
       - route  = [
           - {
               - cidr_block = "0.0.0.0/0"
               - gateway_id = "igw-0123456789abcdef0"
             }
         ] -> null
       - tags   = {
           - "Name" = "MyRouteTable"
         } -> null
       - tags_all = {
           - "Name" = "MyRouteTable"
         } -> null
      }
      
      # aws_route_table_association.my_route_table_association will be destroyed
      - resource "aws_route_table_association" "my_route_table_association" {
       - id             = "rtbassoc-0123456789abcdef0" -> null
       - subnet_id      = "subnet-0123456789abcdef0" -> null
       - route_table_id = "rtb-0123456789abcdef0" -> null
      }
      
      # aws_subnet.my_subnet will be destroyed
      - resource "aws_subnet" "my_subnet" {
       - id             = "subnet-0123456789abcdef0" -> null
       - vpc_id         = "vpc-0123456789abcdef0" -> null
       - cidr_block     = "10.0.1.0/24" -> null
       - tags           = {
           - "Name" = "MySubnet"
         } -> null
       - tags_all       = {
           - "Name" = "MySubnet"
         } -> null
      }
      
      # aws_vpc.my_vpc will be destroyed
      - resource "aws_vpc" "my_vpc" {
       - id             = "vpc-0123456789abcdef0" -> null
       - cidr_block     = "10.0.0.0/16" -> null
       - tags           = {
           - "Name" = "MyVPC"
         } -> null
       - tags_all       = {
           - "Name" = "MyVPC"
         } -> null
      }
      
      Plan: 0 to add, 0 to change, 5 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_route_table_association.my_route_table_association: Destroying... [id=rtbassoc-0123456789abcdef0]
      aws_route_table_association.my_route_table_association: Destruction complete after 1s
      aws_route_table.my_route_table: Destroying... [id=rtb-0123456789abcdef0]
      aws_route_table.my_route_table: Destruction complete after 1s
      aws_internet_gateway.my_igw: Destroying... [id=igw-0123456789abcdef0]
      aws_internet_gateway.my_igw: Destruction complete after 1s
      aws_subnet.my_subnet: Destroying... [id=subnet-0123456789abcdef0]
      aws_subnet.my_subnet: Destruction complete after 1s
      aws_vpc.my_vpc: Destroying... [id=vpc-0123456789abcdef0]
      aws_vpc.my_vpc: Destruction complete after 2s
      
      Destroy complete! Resources: 5 destroyed.

      (Dòng “Destroy complete! Resources: 5 destroyed” xác nhận VPC và các tài nguyên liên quan đã bị xóa).

    • Kiểm tra lại trên AWS Console (VPC Dashboard), bạn sẽ thấy VPC MyVPC và các tài nguyên liên quan (subnet, internet gateway, route table) không còn tồn tại.

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

  • Bạn đã sử dụng Terraform để tạo một hạ tầng mạng hoàn chỉnh trên AWS, bao gồm VPC, subnet, internet gateway, route table, và route table association.
  • Bạn đã kiểm tra và xác nhận hạ tầng mạng hoạt động đúng trên AWS Console.
  • 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 tạo VPC với Terraform, một kỹ năng quan trọng để triển khai các ứng dụng thực tế.

Lưu Ý Quan Trọng

  • CIDR block: Đảm bảo CIDR block của VPC (10.0.0.0/16) và subnet (10.0.1.0/24) không trùng với các VPC hoặc mạng khác trong tài khoản AWS của bạn. Tham khảo tài liệu AWS để biết thêm chi tiết (AWS VPC Documentation).
  • Chi phí AWS: VPC và các tài nguyên liên quan trong bài này không phát sinh chi phí, nhưng nếu bạn triển khai thêm tài nguyên (VD: EC2, NAT Gateway), hãy kiểm tra chi phí trên AWS Pricing.
  • Bảo mật: Đảm bảo tài khoản AWS của bạn có quyền phù hợp (VD: quyền ec2:*, vpc:*) để tạo và xóa tài nguyên. Nếu gặp lỗi quyền, kiểm tra IAM policy.
  • Ôn lại kiến thức: Xem lại bài 1 Học Terraform Cơ Bản: 5 Bước Cài Đặt và Viết Mã Đầu Tiên và bài 2 Học Terraform Với AWS: 5 Bước Tạo Máy Chủ EC2 Đầu Tiên để nắm vững các khái niệm cơ bản.
Điều hướng chuỗi bài viết<< Bài 2. Học Terraform Với AWS: 5 Bước Tạo Máy Chủ EC2 Đầu Tiên
>> Bài 4. Quản Lý Tài Nguyên Với Terraform: Sử Dụng Variables Và Outputs
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