本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 CloudFormation 主控台建立 Amazon ECS 資源
搭配 使用 Amazon ECS 的一種方法是 CloudFormation 透過 AWS 管理主控台。使用此方法,您可以建立任務定義、叢集與服務等 Amazon ECS 元件的 CloudFormation 堆疊,並直接在主控台中部署它們。下列教學課程說明如何使用 CloudFormation 主控台來透過範本建立 Amazon ECS 資源。
先決條件
本教學課程假設已完成下列先決條件。
-
已完成「設定以使用 Amazon ECS。」中的步驟。
-
您的 IAM 使用者擁有 AmazonECS_FullAccess IAM 政策範例中指定的所需許可。
步驟 1:建立堆疊範本
使用下列步驟為 Amazon ECS 服務和其他相關資源建立 CloudFormation 堆疊範本。
-
使用所選的文字編輯器建立一個名為
ecs-tutorial-template.yaml的檔案。 -
在
ecs-tutorial-template.yaml檔案中,貼上下列範本並儲存變更。AWSTemplateFormatVersion: '2010-09-09' Description: '[AWSDocs] ECS: load-balanced-web-application' Parameters: VpcCidr: Type: String Default: '10.0.0.0/16' Description: CIDR block for the VPC ContainerImage: Type: String Default: 'public.ecr.aws/ecs-sample-image/amazon-ecs-sample:latest' Description: Container image to use in task definition PublicSubnet1Cidr: Type: String Default: '10.0.1.0/24' Description: CIDR block for public subnet 1 PublicSubnet2Cidr: Type: String Default: '10.0.2.0/24' Description: CIDR block for public subnet 2 PrivateSubnet1Cidr: Type: String Default: '10.0.3.0/24' Description: CIDR block for private subnet 1 PrivateSubnet2Cidr: Type: String Default: '10.0.4.0/24' Description: CIDR block for private subnet 2 ServiceName: Type: String Default: 'tutorial-app' Description: Name of the ECS service ContainerPort: Type: Number Default: 80 Description: Port on which the container listens DesiredCount: Type: Number Default: 2 Description: Desired number of tasks MinCapacity: Type: Number Default: 1 Description: Minimum number of tasks for auto scaling MaxCapacity: Type: Number Default: 10 Description: Maximum number of tasks for auto scaling Resources: # VPC and Networking VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCidr EnableDnsHostnames: true EnableDnsSupport: true Tags: - Key: Name Value: !Sub '${AWS::StackName}-vpc' # Internet Gateway InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: !Sub '${AWS::StackName}-igw' InternetGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref VPC # Public Subnets for ALB PublicSubnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [0, !GetAZs ''] CidrBlock: !Ref PublicSubnet1Cidr MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Sub '${AWS::StackName}-public-subnet-1' PublicSubnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [1, !GetAZs ''] CidrBlock: !Ref PublicSubnet2Cidr MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Sub '${AWS::StackName}-public-subnet-2' # Private Subnets for ECS Tasks PrivateSubnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [0, !GetAZs ''] CidrBlock: !Ref PrivateSubnet1Cidr Tags: - Key: Name Value: !Sub '${AWS::StackName}-private-subnet-1' PrivateSubnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [1, !GetAZs ''] CidrBlock: !Ref PrivateSubnet2Cidr Tags: - Key: Name Value: !Sub '${AWS::StackName}-private-subnet-2' # NAT Gateways for private subnet internet access NatGateway1EIP: Type: AWS::EC2::EIP DependsOn: InternetGatewayAttachment Properties: Domain: vpc Tags: - Key: Name Value: !Sub '${AWS::StackName}-nat-eip-1' NatGateway2EIP: Type: AWS::EC2::EIP DependsOn: InternetGatewayAttachment Properties: Domain: vpc Tags: - Key: Name Value: !Sub '${AWS::StackName}-nat-eip-2' NatGateway1: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt NatGateway1EIP.AllocationId SubnetId: !Ref PublicSubnet1 Tags: - Key: Name Value: !Sub '${AWS::StackName}-nat-1' NatGateway2: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt NatGateway2EIP.AllocationId SubnetId: !Ref PublicSubnet2 Tags: - Key: Name Value: !Sub '${AWS::StackName}-nat-2' # Route Tables PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub '${AWS::StackName}-public-routes' DefaultPublicRoute: Type: AWS::EC2::Route DependsOn: InternetGatewayAttachment Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway PublicSubnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PublicRouteTable SubnetId: !Ref PublicSubnet1 PublicSubnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PublicRouteTable SubnetId: !Ref PublicSubnet2 PrivateRouteTable1: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub '${AWS::StackName}-private-routes-1' DefaultPrivateRoute1: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable1 DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NatGateway1 PrivateSubnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTable1 SubnetId: !Ref PrivateSubnet1 PrivateRouteTable2: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub '${AWS::StackName}-private-routes-2' DefaultPrivateRoute2: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable2 DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NatGateway2 PrivateSubnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTable2 SubnetId: !Ref PrivateSubnet2 # Security Groups ALBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupName: !Sub '${AWS::StackName}-alb-sg' GroupDescription: Security group for Application Load Balancer VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 Description: Allow HTTP traffic from internet SecurityGroupEgress: - IpProtocol: -1 CidrIp: 0.0.0.0/0 Description: Allow all outbound traffic Tags: - Key: Name Value: !Sub '${AWS::StackName}-alb-sg' ECSSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupName: !Sub '${AWS::StackName}-ecs-sg' GroupDescription: Security group for ECS tasks VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: !Ref ContainerPort ToPort: !Ref ContainerPort SourceSecurityGroupId: !Ref ALBSecurityGroup Description: Allow traffic from ALB SecurityGroupEgress: - IpProtocol: -1 CidrIp: 0.0.0.0/0 Description: Allow all outbound traffic Tags: - Key: Name Value: !Sub '${AWS::StackName}-ecs-sg' # Application Load Balancer ApplicationLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: !Sub '${AWS::StackName}-alb' Scheme: internet-facing Type: application Subnets: - !Ref PublicSubnet1 - !Ref PublicSubnet2 SecurityGroups: - !Ref ALBSecurityGroup Tags: - Key: Name Value: !Sub '${AWS::StackName}-alb' ALBTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: Name: !Sub '${AWS::StackName}-tg' Port: !Ref ContainerPort Protocol: HTTP VpcId: !Ref VPC TargetType: ip HealthCheckIntervalSeconds: 30 HealthCheckPath: / HealthCheckProtocol: HTTP HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 2 UnhealthyThresholdCount: 5 Tags: - Key: Name Value: !Sub '${AWS::StackName}-tg' ALBListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref ALBTargetGroup LoadBalancerArn: !Ref ApplicationLoadBalancer Port: 80 Protocol: HTTP # ECS Cluster ECSCluster: Type: AWS::ECS::Cluster Properties: ClusterName: !Sub '${AWS::StackName}-cluster' CapacityProviders: - FARGATE - FARGATE_SPOT DefaultCapacityProviderStrategy: - CapacityProvider: FARGATE Weight: 1 - CapacityProvider: FARGATE_SPOT Weight: 4 ClusterSettings: - Name: containerInsights Value: enabled Tags: - Key: Name Value: !Sub '${AWS::StackName}-cluster' # IAM Roles ECSTaskExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub '${AWS::StackName}-task-execution-role' AssumeRolePolicyDocument: Version: '2012-10-17 ' Statement: - Effect: Allow Principal: Service: ecs-tasks.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy Tags: - Key: Name Value: !Sub '${AWS::StackName}-task-execution-role' ECSTaskRole: Type: AWS::IAM::Role Properties: RoleName: !Sub '${AWS::StackName}-task-role' AssumeRolePolicyDocument: Version: '2012-10-17 ' Statement: - Effect: Allow Principal: Service: ecs-tasks.amazonaws.com Action: sts:AssumeRole Tags: - Key: Name Value: !Sub '${AWS::StackName}-task-role' # CloudWatch Log Group LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/ecs/${AWS::StackName}' RetentionInDays: 7 # ECS Task Definition TaskDefinition: Type: AWS::ECS::TaskDefinition Properties: Family: !Sub '${AWS::StackName}-task' Cpu: '256' Memory: '512' NetworkMode: awsvpc RequiresCompatibilities: - FARGATE ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn TaskRoleArn: !GetAtt ECSTaskRole.Arn ContainerDefinitions: - Name: !Ref ServiceName Image: !Ref ContainerImage PortMappings: - ContainerPort: !Ref ContainerPort Protocol: tcp Essential: true LogConfiguration: LogDriver: awslogs Options: awslogs-group: !Ref LogGroup awslogs-region: !Ref AWS::Region awslogs-stream-prefix: ecs HealthCheck: Command: - CMD-SHELL - curl -f http://localhost/ || exit 1 Interval: 30 Timeout: 5 Retries: 3 StartPeriod: 60 Tags: - Key: Name Value: !Sub '${AWS::StackName}-task' # ECS Service ECSService: Type: AWS::ECS::Service DependsOn: ALBListener Properties: ServiceName: !Sub '${AWS::StackName}-service' Cluster: !Ref ECSCluster TaskDefinition: !Ref TaskDefinition DesiredCount: !Ref DesiredCount LaunchType: FARGATE PlatformVersion: LATEST NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: DISABLED SecurityGroups: - !Ref ECSSecurityGroup Subnets: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 LoadBalancers: - ContainerName: !Ref ServiceName ContainerPort: !Ref ContainerPort TargetGroupArn: !Ref ALBTargetGroup DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 50 DeploymentCircuitBreaker: Enable: true Rollback: true EnableExecuteCommand: true # For debugging Tags: - Key: Name Value: !Sub '${AWS::StackName}-service' # Auto Scaling Target ServiceScalingTarget: Type: AWS::ApplicationAutoScaling::ScalableTarget Properties: MaxCapacity: !Ref MaxCapacity MinCapacity: !Ref MinCapacity ResourceId: !Sub 'service/${ECSCluster}/${ECSService.Name}' RoleARN: !Sub 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService' ScalableDimension: ecs:service:DesiredCount ServiceNamespace: ecs # Auto Scaling Policy - CPU Utilization ServiceScalingPolicy: Type: AWS::ApplicationAutoScaling::ScalingPolicy Properties: PolicyName: !Sub '${AWS::StackName}-cpu-scaling-policy' PolicyType: TargetTrackingScaling ScalingTargetId: !Ref ServiceScalingTarget TargetTrackingScalingPolicyConfiguration: PredefinedMetricSpecification: PredefinedMetricType: ECSServiceAverageCPUUtilization TargetValue: 70.0 ScaleOutCooldown: 300 ScaleInCooldown: 300 Outputs: VPCId: Description: VPC ID Value: !Ref VPC Export: Name: !Sub '${AWS::StackName}-VPC-ID' LoadBalancerURL: Description: URL of the Application Load Balancer Value: !Sub 'http://${ApplicationLoadBalancer.DNSName}' Export: Name: !Sub '${AWS::StackName}-ALB-URL' ECSClusterName: Description: Name of the ECS Cluster Value: !Ref ECSCluster Export: Name: !Sub '${AWS::StackName}-ECS-Cluster' ECSServiceName: Description: Name of the ECS Service Value: !GetAtt ECSService.Name Export: Name: !Sub '${AWS::StackName}-ECS-Service' PrivateSubnet1: Description: Private Subnet 1 ID Value: !Ref PrivateSubnet1 Export: Name: !Sub '${AWS::StackName}-Private-Subnet-1' PrivateSubnet2: Description: Private Subnet 2 ID Value: !Ref PrivateSubnet2 Export: Name: !Sub '${AWS::StackName}-Private-Subnet-2'本教學課程中使用的範本會建立 Amazon ECS 服務,其中包含兩項在 Fargate 上執行的任務。每項任務都會執行範例 Amazon ECS 應用程式。範本也會建立一個 Application Load Balancer (用於分配應用程式流量),以及一個根據 CPU 使用率擴展應用程式的應用程式自動擴展政策。該範本還會建立部署應用程式所需的聯網資源、容器日誌的記錄資源,以及 Amazon ECS 任務執行 IAM 角色。如需任務執行角色的詳細資訊,請參閱「Amazon ECS 任務執行 IAM 角色」。如需有關自動擴展的詳細資訊,請參閱自動擴展 Amazon ECS 服務。
步驟 2:建立 Amazon ECS 資源的堆疊
為範本建立檔案之後,您可以依照下列步驟,使用 CloudFormation 主控台建立具有範本的堆疊。
如需有關如何使用 CloudFormation 主控台建立堆疊的資訊,請參閱AWS CloudFormation 《 使用者指南》中的在 CloudFormation 主控台上建立堆疊,並使用下表來決定要指定哪些選項。
| 選項 | Value |
|---|---|
|
先決條件 – 準備範本 |
選擇現有範本 |
| 指定範本 |
上傳範本檔案 |
| 選擇檔案 |
ecs-tutorial-template.yaml |
| Stack name (堆疊名稱) |
ecs-tutorial-stack |
| Parameters |
將所有參數值保留為預設值。 |
| 功能 |
選擇 我確認此範本可能會建立 IAM 資源,以確認 CloudFormation 建立 IAM 資源。 |
步驟 3:驗證
遵循下列步驟,使用提供的範本來驗證 Amazon ECS 資源是否已建立。
如需有關如何檢視堆疊資訊與資源的資訊,請參閱 AWS CloudFormation User Guide 中的 Viewing stack information from the CloudFormation console,並使用下表來決定要驗證的內容。
| 堆疊詳細資訊欄位 | 要尋找的內容 |
|---|---|
|
堆疊資訊 |
狀態為 CREATE_COMPLETE。 |
| Resources |
已建立的資源清單,其中包含指向服務主控台的連結。選擇 |
| 輸出 |
LoadBalancerURL。將 URL 貼到 Web 瀏覽器中,以檢視顯示範例 Amazon ECS 應用程式的網頁。 |
步驟 4:清除資源
若要清理資源並避免產生更多成本,請遵循 CloudFormation user guide 中 Delete a stack from the CloudFormation console 一節的步驟。