+2

AWS CloudFormation Hands-on 03: Khởi tạo Virtual Private Cloud

Overview

Trong phần này, mình sẽ chia sẻ các bước để tạo AWS Virtual Private Cloud với CloudFormation Template file.

Trước đó, hãy làm rõ một số khái niệm trước:

  • Virtual Private Cloud: một network ảo riêng biệt cho phép bạn dễ dàng khởi tạo và quản trị tài nguyên AWS trên đó. Mỗi VPC sẽ có tập IP address riêng.
  • Subnet: là một tập IP adresss con của VPC. Subnet có hai loại: private subnet và public subnet
  • Internet Gateway: cổng kết nối public subnet với Internet
  • NAT Gateway: cổng kết nối private subnet với Internet, thường được đặt ở public subnet
  • Route table: bảng gồm các bản ghi dạng <destination> <target> quy định cách thức điều hướng các request trong hệ thống. Ví dụ bản ghi 10.169.0.0/8 igw-id sẽ điều hướng tất cả các request có đích là IP thuộc tập 10.169.0.0/8 tới Internet Gateway có id igw-id.
  • Router: thành phần trực tiếp thực hiện việc điều hướng request, dựa vào route table.

Chúng ta sẽ khởi tạo VPC với thiết kế gồm các thành phần như sau:

CloudFormation_design_vpc.png Cụ thể, VPC sẽ gồm:

  • 4 subnet: 2 subnet (1 private, 1 public) tại Available Zone A, 2 subnet (1 private, 1 public) tại Available Zone B
  • 1 InternetGateway
  • 2 NAT Gateway
  • 3 Route table: 1 public route table và 2 private route table

Hands-on

Bước 1: Khởi tạo template file

Khởi tạo file template.yml với bản mô tả đơn giản

## =================== DESCRIPTION =================== #
Description: >-
  AWS CloudFormation sample template. 
  Create a custom VPC with a pair of public and private subnets spread across two AZs

Bổ sung các tham số

## =================== PARAMETERS =================== #
Parameters:
  paramVpcCIDR:
    Description: Enter the IP range (CIDR notation) for VPC
    Type: String
    Default: 10.192.0.0/16
  paramPublicSubnet1CIDR:
    Description: Enter the IP range (CIDR notation)  for the public subnet in AZ A
    Type: String
    Default: 10.192.10.0/24
  paramPublicSubnet2CIDR:
    Description: Enter the IP range (CIDR notation)  for the public subnet in AZ B
    Type: String
    Default: 10.192.11.0/24
  paramPrivateSubnet1CIDR:
    Description: Enter the IP range (CIDR notation)  for the private subnet in AZ A
    Type: String
    Default: 10.192.20.0/24
  paramPrivateSubnet2CIDR:
    Description: Enter the IP range (CIDR notation)  for the private subnet in AZ B
    Type: String
    Default: 10.192.21.0/24
  paramUniqueName:
    Description: Give a unique name for "CloudFormationLab" tag value
    Type: String
    Default: CodeFormation Practise

Các tham số này tương ứng với dải IP (dạng CIDR notation) cho VPC và 4 subnet. Ngoài ra, thêm một tham số paramUniqueName để đánh tag cho các resources.

Tiếp theo, ta khởi tạo các resources.

Bổ sung resource VPC

Resources:
  # Create a VPC
  myVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref paramVpcCIDR
      EnableDnsSupport: true # let instances in the VPC get DNS hostnames
      EnableDnsHostnames: true # allow DNS resolution
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

Internet Gateway

  myInternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

NAT Gateway

  myVPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref myVPC
      InternetGatewayId: !Ref myInternetGateway

Public Route Table với bản ghi route 0.0.0.0/0 myInternetGateway nhằm điều hướng tất cả request tới Internet Gateway đã thêm phía trên.

  # Create a public route table for the VPC (will be public once it is associated with the Internet Gateway)
  myPublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref myVPC
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

  # Associate the public route table with the Internet Gateway
  myPublicRoute:
    Type: AWS::EC2::Route
    DependsOn: myVPCGatewayAttachment
    Properties:
      RouteTableId: !Ref myPublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref myInternetGateway

Khởi tạo 2 public subnet

  # Create a public subnet in AZ 1 (will be public once it is associated with public route table)
  myPublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref myVPC
      AvailabilityZone: !Select [ 0, !GetAZs '' ] # AZ 1
      CidrBlock: !Ref paramPublicSubnet1CIDR
      MapPublicIpOnLaunch: true # allow instances launched in this subnet receive a public IPv4 address
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

  # Create a public subnet in AZ 2 (will be public once it is associated with public route table)
  myPublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref myVPC
      AvailabilityZone: !Select [ 1, !GetAZs  '' ] # AZ 2
      CidrBlock: !Ref paramPublicSubnet2CIDR
      MapPublicIpOnLaunch: true # allow instances launched in this subnet receive a public IPv4 address
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

Liên kết hai public subnet vừa tạo với public route table

  # Associate the public route table with the public subnet in AZ 1
  myPublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref myPublicRouteTable
      SubnetId: !Ref myPublicSubnet1
  
  # Associate the public route table with the public subnet in AZ 2
  myPublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref myPublicRouteTable
      SubnetId: !Ref myPublicSubnet2

Khởi tạo 2 NAT Gateway, mỗi NAT Gateway sẽ cần được gán Elastic IP nằm trong public subnet

# Specify an Elastic IP (EIP) address for a NAT Gateway in AZ 1
myEIPforNatGateway1:
    Type: AWS::EC2::EIP
    DependsOn: myVPCGatewayAttachment
    Properties:
      Domain: vpc # if the region supports EC2-Classic, the default is "standard", otherwise - "vpc"
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

  # Specify an Elastic IP (EIP) address for a NAT Gateway in AZ 2
  myEIPforNatGateway2:
    Type: AWS::EC2::EIP
    DependsOn: myVPCGatewayAttachment
    Properties:
      Domain: vpc # if the region supports EC2-Classic, the default is "standard", otherwise - "vpc"
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

  # Create a NAT Gateway in the public subnet for AZ 1
  myNatGateway1:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt myEIPforNatGateway1.AllocationId
      SubnetId: !Ref myPublicSubnet1
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

   # Create a NAT Gateway in the public subnet for AZ 2
  myNatGateway2:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt myEIPforNatGateway2.AllocationId
      SubnetId: !Ref myPublicSubnet2
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

Tạo 2 route table nhằm điều hướng tất cả request tới 2 NAT Gateway tương ứng

# Create a private route table for AZ 1
  myPrivateRouteTable1:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref myVPC
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

  # Create a private route table for AZ 2
  myPrivateRouteTable2:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref myVPC
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

  # Associate the private route table with the Nat Gateway in AZ 1
  myPrivateRouteForAz1:
    Type: AWS::EC2::Route
    DependsOn: myVPCGatewayAttachment
    Properties:
      RouteTableId: !Ref myPrivateRouteTable1
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref myNatGateway1 

  #  Associate the private route table with the Nat Gateway in AZ 2
  myPrivateRouteForAz2:
    Type: AWS::EC2::Route
    DependsOn: myVPCGatewayAttachment
    Properties:
      RouteTableId: !Ref myPrivateRouteTable2
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref myNatGateway2

Bước cuối cùng, bổ sung 2 private subnet và liên kết chúng với 2 route table

  # Create a private subnet in AZ 1
  myPrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref myVPC
      AvailabilityZone: !Select [ 0, !GetAZs '' ] # AZ 1
      CidrBlock: !Ref paramPrivateSubnet1CIDR
      MapPublicIpOnLaunch: false # private subnet doesn't need public IP
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

  # Create a private subnet in AZ 2
  myPrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref myVPC
      AvailabilityZone: !Select [ 1, !GetAZs  '' ] # AZ 2
      CidrBlock: !Ref paramPrivateSubnet2CIDR
      MapPublicIpOnLaunch: false # private subnet doesn't need public IP
      Tags:
      - Key: MasteringCF
        Value:  !Ref paramUniqueName

  # Associate the private route table with the private subnet in AZ 1
  myPrivateSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref myPrivateRouteTable1
      SubnetId: !Ref myPrivateSubnet1
  
  #  Associate the private route table with the private subnet in AZ 2
  myPrivateSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref myPrivateRouteTable2
      SubnetId: !Ref myPrivateSubnet2

Vậy là hoàn tất, bạn có thể tham khảo file template hoàn chỉnh tại đây.

Chi tiết về cú pháp sử dụng trong Template file, bạn có thể tham khảo tại "Sơ lược về CloudFormation".

Bước 2: Khởi tạo stack từ template file

Chạy lệnh sau để khởi tạo stack trên AWS

aws cloudformation create-stack \
  --stack-name custom-vpc \
  --template-body file://template.yml

Truy cập website AWS, mục CloudFormation để kiểm tra trạng thái của stack vừa tạo.

Tham khảo các phần Resources được tạo: image.png

Kiểm tra mục Parameter của stack trong tab "Parameters" image.png

Bước 3: Cập nhật stack

Trong phần này, ta sẽ tạo changeset để cập nhật dải IP của một subnet

Sử dụng lệnh sau để tạo changeset

aws cloudformation create-change-set --change-set-name update-private-subnet-id\
  --stack-name custom-vpc \
  --use-previous-template \
  --parameters ParameterKey=paramPrivateSubnet2CIDR,ParameterValue="10.192.41.0/24"

Mục tiêu ở đây là cập nhật giá trị của tham số paramPrivateSubnet2CIDR - dải IP của private subnet 2 với giá trị: 10.192.41.0/24

Truy cập website AWS, click chọn changeset vừa tạo để view các resources sẽ cập nhật nếu execute changeset: image.png

Ở đây, nếu ta apply changeset sẽ có hai đối tượng được cập nhật là: myPrivateSubnet2 và myPrivateSubnet2RouteTableAssociation (đối tượng liên kết subnet với route table)

Để apply changeset, chạy lệnh

aws cloudformation execute-change-set \
    --change-set-name update-private-subnet-id \
    --stack-name custom-vpc

Theo dõi stack được cập nhật trên website. Parameter sau khi được cập nhật: image.png

Vậy là xong, bạn đã thực hiện hầu hết các thao tác cơ bản khi làm việc với AWS CloudFormation.

Bước 4: Delete stack

Last but not least, đừng quên xóa stack để tránh bị tính phí ngoài ý muốn.

aws cloudformation delete-stack --stack-name custom-vpc

Kết luận

Trong bài viết này, mình đã chia sẻ chi tiết các bước để triển khai Virtual Private Cloud sử dụng CloudFormation template. Hi vọng bài viết này có ích cho bạn. Trân trọng!

Link tham khảo

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-guide.html

https://dev.to/tiamatt/hands-on-aws-cloudformation-part-4-create-vpc-with-private-and-public-subnets-85d


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí