本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 建立具有私有子網路和 NAT 閘道的 VPC AWS CLI
本教學課程示範如何使用 建立可用於生產環境中伺服器的 VPC AWS CLI。為了改善彈性,您將使用 Auto Scaling 群組和 Application Load Balancer,在兩個可用區域中部署伺服器。為了提高安全性,您將在私有子網路中部署伺服器。伺服器會透過負載平衡器接收請求,並且可以使用 NAT 閘道連線至網際網路。若要改善彈性,您將在每個可用區域中部署 NAT 閘道。
下圖提供本教學課程中包含的資源概觀。VPC 具有兩個可用區域中的公有子網路和私有子網路。每個公有子網路都包含一個 NAT 閘道和一個負載平衡器節點。在私有子網路中執行的伺服器會使用 Auto Scaling 群組啟動和終止,並從負載平衡器接收流量。伺服器可以使用 NAT 閘道連線至網際網路。伺服器可以使用閘道 VPC 端點連線至 Amazon S3。

先決條件
開始本教學課程之前,您需要:
-
安裝 AWS CLI 和設定的 具有建立 VPC 資源、EC2 執行個體、負載平衡器和 Auto Scaling 群組的許可。如需安裝 的詳細資訊 AWS CLI,請參閱安裝或更新最新版本的 AWS CLI。
-
VPC 概念的基本知識,包括子網路、路由表和網際網路閘道。
-
已安裝
jq
命令列 JSON 處理器。這用於剖析 AWS CLI 命令的輸出。如需安裝 jq 的詳細資訊,請參閱下載 jq。 -
您建立的資源有足夠的服務配額,包括:
-
至少 2 個可用的彈性 IP 地址
-
至少 2 個 NAT 閘道
-
至少 1 個 VPC
-
至少 4 個子網路
-
至少 1 個 Application Load Balancer
預估成本:在本教學課程中建立的資源會在 AWS 您的帳戶中產生費用:NAT 閘道:每小時約 0.045 USD,加上資料處理費用 彈性 IP 地址:與執行中的執行個體相關聯時免費,與 EC2 執行個體無關時每小時約 0.005 USD:依執行個體類型而異 (本教學課程中使用的 t3.micro) Application Load Balancer:每小時約 0.0225 USD,加上資料處理費用
建立 VPC 和子網路
首先,您將建立 CIDR 區塊為 10.0.0.0/16 的 VPC,最多可提供 65,536 個私有 IP 地址。
# Create a VPC with CIDR block 10.0.0.0/16 aws ec2 create-vpc --cidr-block 10.0.0.0/16 --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=ProductionVPC}]'
此命令會傳回類似以下的輸出:
{ "Vpc": { "CidrBlock": "10.0.0.0/16", "DhcpOptionsId": "dopt-abcd1234", "State": "pending", "VpcId": "vpc-abcd1234", "OwnerId": "123456789012", "InstanceTenancy": "default", "Ipv6CidrBlockAssociationSet": [], "CidrBlockAssociationSet": [ { "AssociationId": "vpc-cidr-assoc-abcd1234", "CidrBlock": "10.0.0.0/16", "CidrBlockState": { "State": "associated" } } ], "IsDefault": false, "Tags": [ { "Key": "Name", "Value": "ProductionVPC" } ] } }
請注意輸出的 VPC ID (例如 vpc-abcd1234
)。您將在後續命令中使用此 ID。
接下來,您將識別您區域中的兩個可用區域,以建立彈性架構。
# Get available Availability Zones aws ec2 describe-availability-zones --query 'AvailabilityZones[0:2].ZoneName' --output text
此命令會傳回類似以下的輸出:
us-east-1a us-east-1b
現在,請建立四個子網路:負載平衡器和 NAT 閘道的兩個公有子網路,以及應用程式伺服器的兩個私有子網路。vpc-abcd1234
將 取代為您實際的 VPC ID,將 us-east-1a
和 us-east-1b
取代為您實際的可用區域。
# Create public subnet in first AZ aws ec2 create-subnet \ --vpc-id vpc-abcd1234 \ --cidr-block 10.0.0.0/24 \ --availability-zone us-east-1a \ --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=PublicSubnet1}]' # Create private subnet in first AZ aws ec2 create-subnet \ --vpc-id vpc-abcd1234 \ --cidr-block 10.0.1.0/24 \ --availability-zone us-east-1a \ --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=PrivateSubnet1}]' # Create public subnet in second AZ aws ec2 create-subnet \ --vpc-id vpc-abcd1234 \ --cidr-block 10.0.2.0/24 \ --availability-zone us-east-1b \ --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=PublicSubnet2}]' # Create private subnet in second AZ aws ec2 create-subnet \ --vpc-id vpc-abcd1234 \ --cidr-block 10.0.3.0/24 \ --availability-zone us-east-1b \ --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=PrivateSubnet2}]'
每個命令都會傳回包含子網路 ID 的輸出。請注意,這些 IDs可用於後續命令:
-
公有子網路 1:
subnet-abcd1234
-
私有子網路 1:
subnet-abcd5678
-
公有子網路 2:
subnet-efgh1234
-
私有子網路 2:
subnet-efgh5678
建立和設定網際網路連線
在本節中,您將建立網際網路閘道,以允許 VPC 與網際網路之間的通訊,並將其連接至 VPC。
# Create an Internet Gateway aws ec2 create-internet-gateway --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=ProductionIGW}]'
命令會傳回包含網際網路閘道 ID 的輸出。請記下此 ID (例如 igw-abcd1234
)。
將網際網路閘道連接至您的 VPC。igw-abcd1234
將 取代為您實際的網際網路閘道 ID,將 vpc-abcd1234
取代為您實際的 VPC ID。
# Attach the Internet Gateway to the VPC aws ec2 attach-internet-gateway --internet-gateway-id igw-abcd1234 --vpc-id vpc-abcd1234
接著,為您的公有和私有子網路建立路由表。將 取代vpc-abcd1234
為您實際的 VPC ID。
# Create a route table for public subnets aws ec2 create-route-table --vpc-id vpc-abcd1234 --tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=PublicRouteTable}]' # Create route table for private subnet in first AZ aws ec2 create-route-table --vpc-id vpc-abcd1234 --tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=PrivateRouteTable1}]' # Create route table for private subnet in second AZ aws ec2 create-route-table --vpc-id vpc-abcd1234 --tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=PrivateRouteTable2}]'
每個命令都會傳回包含路由表 ID 的輸出。請注意這些 IDs:
-
公有路由表:
rtb-abcd1234
-
私有路由表 1:
rtb-efgh1234
-
私有路由表 2:
rtb-ijkl1234
在公有路由表中將路由新增至網際網路閘道,以啟用網際網路存取。rtb-abcd1234
將 取代為您實際的公有路由表 ID,並將 igw-abcd1234
取代為您實際的網際網路閘道 ID。
# Add a route to the Internet Gateway aws ec2 create-route --route-table-id rtb-abcd1234 --destination-cidr-block 0.0.0.0/0 --gateway-id igw-abcd1234
將子網路與其個別路由表建立關聯。使用實際 IDs取代路由表 IDs 和子網路 IDs。
# Associate public subnets with the public route table aws ec2 associate-route-table --route-table-id rtb-abcd1234 --subnet-id subnet-abcd1234 aws ec2 associate-route-table --route-table-id rtb-abcd1234 --subnet-id subnet-efgh1234 # Associate private subnets with their respective route tables aws ec2 associate-route-table --route-table-id rtb-efgh1234 --subnet-id subnet-abcd5678 aws ec2 associate-route-table --route-table-id rtb-ijkl1234 --subnet-id subnet-efgh5678
建立 NAT 閘道
NAT 閘道允許私有子網路中的執行個體連線至網際網路或其他 AWS 服務,但可防止網際網路啟動與這些執行個體的連線。首先,為您的 NAT 閘道配置彈性 IP 地址。
# Allocate Elastic IP for NAT Gateway in first AZ aws ec2 allocate-address --domain vpc --tag-specifications 'ResourceType=elastic-ip,Tags=[{Key=Name,Value=NAT1-EIP}]' # Allocate Elastic IP for NAT Gateway in second AZ aws ec2 allocate-address --domain vpc --tag-specifications 'ResourceType=elastic-ip,Tags=[{Key=Name,Value=NAT2-EIP}]'
每個命令都會傳回包含配置 ID 的輸出。請注意這些 IDs:
-
EIP 1 配置 ID:
eipalloc-abcd1234
-
EIP 2 配置 ID:
eipalloc-efgh1234
在每個公有子網路中建立 NAT 閘道。將子網路 IDs和配置 IDs 取代為您實際IDs。
# Create NAT Gateway in public subnet of first AZ aws ec2 create-nat-gateway \ --subnet-id subnet-abcd1234 \ --allocation-id eipalloc-abcd1234 \ --tag-specifications 'ResourceType=natgateway,Tags=[{Key=Name,Value=NAT-Gateway1}]' # Create NAT Gateway in public subnet of second AZ aws ec2 create-nat-gateway \ --subnet-id subnet-efgh1234 \ --allocation-id eipalloc-efgh1234 \ --tag-specifications 'ResourceType=natgateway,Tags=[{Key=Name,Value=NAT-Gateway2}]'
每個命令都會傳回包含 NAT Gateway ID 的輸出。請注意這些 IDs:
-
NAT 閘道 1:
nat-abcd1234
-
NAT 閘道 2:
nat-efgh1234
NAT Gateways 需要幾分鐘的時間來佈建。等待它們可用再繼續。將 NAT Gateway IDs取代為您實際IDs。
# Wait for NAT Gateways to be available aws ec2 wait nat-gateway-available --nat-gateway-ids nat-abcd1234 aws ec2 wait nat-gateway-available --nat-gateway-ids nat-efgh1234
將路由新增至私有路由表中的 NAT 閘道,以啟用私有子網路中執行個體的網際網路存取。將路由表 IDs和 NAT Gateway IDs 取代為您的實際 IDs。
# Add route to NAT Gateway 1 in private route table 1 aws ec2 create-route \ --route-table-id rtb-efgh1234 \ --destination-cidr-block 0.0.0.0/0 \ --nat-gateway-id nat-abcd1234 # Add route to NAT Gateway 2 in private route table 2 aws ec2 create-route \ --route-table-id rtb-ijkl1234 \ --destination-cidr-block 0.0.0.0/0 \ --nat-gateway-id nat-efgh1234
為 Amazon S3 建立 VPC 端點
Amazon S3 的 VPC 端點可讓私有子網路中的執行個體存取 S3,而無需經過 NAT Gateway,從而降低資料傳輸成本並提供更好的網路效能。vpc-abcd1234
將 取代為您實際的 VPC ID,將路由表 IDs 取代為您實際IDs。
# Get the prefix list ID for S3 in your region S3_PREFIX_LIST_ID=$(aws ec2 describe-prefix-lists --filters "Name=prefix-list-name,Values=com.amazonaws.$(aws configure get region).s3" --query 'PrefixLists[0].PrefixListId' --output text) # Create the VPC endpoint for S3 aws ec2 create-vpc-endpoint \ --vpc-id vpc-abcd1234 \ --service-name com.amazonaws.$(aws configure get region).s3 \ --route-table-ids rtb-efgh1234 rtb-ijkl1234 \ --tag-specifications 'ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=S3-Endpoint}]'
命令會傳回包含 VPC 端點 ID 的輸出。請注意此 ID (例如 vpce-abcd1234
)。
設定安全群組
安全群組可做為執行個體的虛擬防火牆,以控制傳入和傳出流量。為負載平衡器建立安全群組,允許來自任何地方的傳入 HTTP 流量。將 取代vpc-abcd1234
為您實際的 VPC ID。
# Create security group for the load balancer aws ec2 create-security-group \ --group-name LoadBalancerSG \ --description "Security group for the load balancer" \ --vpc-id vpc-abcd1234 \ --tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=LoadBalancerSG}]'
命令會傳回包含安全群組 ID 的輸出。請注意此 ID (例如 sg-abcd1234
)。
允許傳入 HTTP 流量到負載平衡器。將 取代sg-abcd1234
為您實際的負載平衡器安全群組 ID。
# Allow inbound HTTP traffic from anywhere aws ec2 authorize-security-group-ingress \ --group-id sg-abcd1234 \ --protocol tcp \ --port 80 \ --cidr 0.0.0.0/0
為應用程式伺服器建立安全群組,只允許來自負載平衡器的傳入流量。將 取代vpc-abcd1234
為您實際的 VPC ID。
# Create security group for the application servers aws ec2 create-security-group \ --group-name AppServerSG \ --description "Security group for the application servers" \ --vpc-id vpc-abcd1234 \ --tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=AppServerSG}]'
命令會傳回包含安全群組 ID 的輸出。請注意此 ID (例如 sg-efgh1234
)。
允許從負載平衡器安全群組到應用程式伺服器的傳入 HTTP 流量。sg-efgh1234
將 取代為您實際的應用程式伺服器安全群組 ID,並將 sg-abcd1234
取代為您實際的負載平衡器安全群組 ID。
# Allow inbound HTTP traffic from the load balancer security group aws ec2 authorize-security-group-ingress \ --group-id sg-efgh1234 \ --protocol tcp \ --port 80 \ --source-group sg-abcd1234
建立 EC2 執行個體的啟動範本
啟動範本包含啟動執行個體的組態資訊,例如 AMI ID、執行個體類型和安全群組。首先,建立將在執行個體啟動時執行的使用者資料指令碼。
cat > user-data.sh << 'EOF' #!/bin/bash yum update -y yum install -y httpd systemctl start httpd systemctl enable httpd echo "<h1>Hello from $(hostname -f) in $(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)</h1>" > /var/www/html/index.html EOF
在 base64 中編碼使用者資料指令碼。
USER_DATA=$(base64 -w 0 user-data.sh)
取得最新的 Amazon Linux 2 AMI ID。
# Get the latest Amazon Linux 2 AMI ID aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-*-x86_64-gp2" "Name=state,Values=available" --query 'sort_by(Images, &CreationDate)[-1].ImageId' --output text
使用 AMI ID、執行個體類型、安全群組和使用者資料建立啟動範本。將 取代sg-efgh1234
為您實際的應用程式伺服器安全群組 ID 和 $AMI_ID
,並將 $USER_DATA
取代為從先前命令取得的值。
# Create a launch template aws ec2 create-launch-template \ --launch-template-name AppServerTemplate \ --version-description "Initial version" \ --tag-specifications 'ResourceType=launch-template,Tags=[{Key=Name,Value=AppServerTemplate}]' \ --launch-template-data '{ "NetworkInterfaces": [{ "DeviceIndex": 0, "Groups": ["sg-efgh1234"], "DeleteOnTermination": true }], "ImageId": "ami-abcd1234", "InstanceType": "t3.micro", "UserData": "IyEvYmluL2Jhc2gKeXVtIHVwZGF0ZSAteQp5dW0gaW5zdGFsbCAteSBodHRwZApzeXN0ZW1jdGwgc3RhcnQgaHR0cGQKc3lzdGVtY3RsIGVuYWJsZSBodHRwZAplY2hvICI8aDE+SGVsbG8gZnJvbSAkKGhvc3RuYW1lIC1mKSBpbiAkKGN1cmwgLXMgaHR0cDovLzE2OS4yNTQuMTY5LjI1NC9sYXRlc3QvbWV0YS1kYXRhL3BsYWNlbWVudC9hdmFpbGFiaWxpdHktem9uZSk8L2gxPiIgPiAvdmFyL3d3dy9odG1sL2luZGV4Lmh0bWw=", "TagSpecifications": [{ "ResourceType": "instance", "Tags": [{ "Key": "Name", "Value": "AppServer" }] }] }'
建立負載平衡器和目標群組
目標群組會使用您指定的通訊協定和連接埠,將請求路由到已註冊的目標,例如 EC2 執行個體。為您的應用程式伺服器建立目標群組。將 取代vpc-abcd1234
為您實際的 VPC ID。
# Create a target group aws elbv2 create-target-group \ --name AppTargetGroup \ --protocol HTTP \ --port 80 \ --vpc-id vpc-abcd1234 \ --target-type instance \ --health-check-protocol HTTP \ --health-check-path / \ --health-check-port traffic-port
命令會傳回包含目標群組 ARN 的輸出。請注意此 ARN (例如 arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/AppTargetGroup/abcd1234
)。
在公有子網路中建立 Application Load Balancer。將子網路 IDs和安全群組 ID 取代為您實際IDs。
# Create a load balancer aws elbv2 create-load-balancer \ --name AppLoadBalancer \ --subnets subnet-abcd1234 subnet-efgh1234 \ --security-groups sg-abcd1234 \ --tags Key=Name,Value=AppLoadBalancer
命令會傳回包含負載平衡器 ARN 的輸出。請注意此 ARN (例如 arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/AppLoadBalancer/abcd1234
)。
等待負載平衡器處於作用中狀態再繼續。arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/AppLoadBalancer/abcd1234
將 取代為您實際的負載平衡器 ARN。
# Wait for load balancer to be active aws elbv2 wait load-balancer-available \ --load-balancer-arns arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/AppLoadBalancer/abcd1234
為將 HTTP 流量轉送至目標群組的負載平衡器建立接聽程式。將負載平衡器 ARN 和目標群組 ARN 取代為您實際ARNs。
# Create a listener aws elbv2 create-listener \ --load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/AppLoadBalancer/abcd1234 \ --protocol HTTP \ --port 80 \ --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/AppTargetGroup/abcd1234
建立 Auto Scaling 群組
Auto Scaling 群組包含一群 EC2 執行個體,該群就自動擴展和管理目的而言被視為一個邏輯分組。建立使用啟動範本的 Auto Scaling 群組,並將執行個體放置在私有子網路中。將子網路 IDs和目標群組 ARN 取代為您的實際 IDs和 ARN。
# Create an Auto Scaling group aws autoscaling create-auto-scaling-group \ --auto-scaling-group-name AppAutoScalingGroup \ --launch-template LaunchTemplateName=AppServerTemplate,Version='$Latest' \ --min-size 2 \ --max-size 4 \ --desired-capacity 2 \ --vpc-zone-identifier "subnet-abcd5678,subnet-efgh5678" \ --target-group-arns arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/AppTargetGroup/abcd1234 \ --health-check-type ELB \ --health-check-grace-period 300 \ --tags Key=Name,Value=AppServer,PropagateAtLaunch=true
測試組態
Auto Scaling 群組啟動執行個體並通過運作狀態檢查後,您就可以測試負載平衡器。取得負載平衡器的 DNS 名稱。將負載平衡器 ARN 取代為您實際的 ARN。
# Get the DNS name of the load balancer aws elbv2 describe-load-balancers \ --load-balancer-arns arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/AppLoadBalancer/abcd1234 \ --query 'LoadBalancers[0].DNSName' \ --output text)
使用 curl 以負載平衡器名稱測試應用程式。
curl http://LoadBalancerName
如果您多次重新整理頁面,應該會看到不同可用區域中不同執行個體的回應。
清除資源
完成本教學課程後,您應該刪除所有資源,以避免產生費用。將所有 IDs 取代為您的實際資源 IDs。
# Delete the Auto Scaling group aws autoscaling delete-auto-scaling-group \ --auto-scaling-group-name AppAutoScalingGroup \ --force-delete # Wait for the Auto Scaling group to be deleted sleep 60 # Delete the load balancer aws elbv2 delete-load-balancer \ --load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/AppLoadBalancer/abcd1234 # Wait for the load balancer to be deleted sleep 30 # Delete the target group aws elbv2 delete-target-group \ --target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/AppTargetGroup/abcd1234 # Delete the launch template aws ec2 delete-launch-template \ --launch-template-name AppServerTemplate # Delete the NAT Gateways aws ec2 delete-nat-gateway --nat-gateway-id nat-abcd1234 aws ec2 delete-nat-gateway --nat-gateway-id nat-efgh1234 # Wait for the NAT Gateways to be deleted sleep 90 # Release the Elastic IPs aws ec2 release-address --allocation-id eipalloc-abcd1234 aws ec2 release-address --allocation-id eipalloc-efgh1234 # Delete the VPC endpoint aws ec2 delete-vpc-endpoints --vpc-endpoint-ids vpce-abcd1234 # Wait for security group dependencies to clear sleep 30 # Delete the security groups aws ec2 delete-security-group --group-id sg-efgh1234 aws ec2 delete-security-group --group-id sg-abcd1234 # Detach the Internet Gateway aws ec2 detach-internet-gateway --internet-gateway-id igw-abcd1234 --vpc-id vpc-abcd1234 # Delete the Internet Gateway aws ec2 delete-internet-gateway --internet-gateway-id igw-abcd1234 # Delete the route tables aws ec2 delete-route-table --route-table-id rtb-efgh1234 aws ec2 delete-route-table --route-table-id rtb-ijkl1234 aws ec2 delete-route-table --route-table-id rtb-abcd1234 # Delete the subnets aws ec2 delete-subnet --subnet-id subnet-abcd1234 aws ec2 delete-subnet --subnet-id subnet-efgh1234 aws ec2 delete-subnet --subnet-id subnet-abcd5678 aws ec2 delete-subnet --subnet-id subnet-efgh5678 # Delete the VPC aws ec2 delete-vpc --vpc-id vpc-abcd1234
後續步驟
現在您已使用私有子網路和 NAT 閘道建立 VPC,您可能想要探索這些相關主題: