AWS CloudFormation을 사용하여 Amazon ECS 리소스 생성 - Amazon Elastic Container Service

AWS CloudFormation을 사용하여 Amazon ECS 리소스 생성

Amazon ECS는 모델을 생성하고 사용자가 정의한 템플릿이 포함된 AWS 리소스 설정하는 데 사용할 수 있는 서비스인 AWS CloudFormation과 통합됩니다. 이렇게 하면 리소스 및 인프라를 생성하고 관리하는 데 소요되는 시간을 줄일 수 있습니다. AWS CloudFormation을 사용하여 특정 Amazon ECS 클러스터와 같이 원하는 모든 AWS 리소스를 설명하는 템플릿을 만들 수 있습니다. 그런 다음 AWS CloudFormation은 해당 리소스를 프로비저닝하고 구성합니다.

AWS CloudFormation을 사용할 때 템플릿을 재사용하여 Amazon ECS 리소스를 일관되고 반복적으로 설정할 수 있습니다. 리소스를 한 번 설명한 후 여러 AWS 계정 및 AWS 리전 간에 동일한 리소스를 다시 프로비저닝할 수 있습니다.

AWS CloudFormation 템플릿

Amazon ECS 및 관련 서비스에 대한 리소스를 프로비저닝하고 구성하려면 AWS CloudFormation 템플릿에 대해 잘 알고 있어야 합니다. AWS CloudFormation 템플릿은 AWS CloudFormation 스택에서 프로비저닝할 리소스를 설명하는 JSON 또는 YAML 형식의 텍스트 파일입니다. JSON 또는 YAML에 익숙하지 않은 경우 AWS CloudFormation Designer를 사용하여 AWS CloudFormation 템플릿을 시작할 수 있습니다. 자세한 내용은 AWS CloudFormation 사용 설명서에서 AWS CloudFormation Designer이란 무엇입니까?를 참조하세요.

Amazon ECS는 AWS CloudFormation에서 클러스터, 태스크 정의, 서비스 및 작업 세트 만들기를 지원합니다. 다음 예제에서는 AWS CLI를 사용하여 이러한 템플릿을 포함한 리소스를 생성하는 방법을 보여줍니다. 또한 AWS CloudFormation 콘솔을 사용하여 이러한 리소스를 만들 수 있습니다. AWS CloudFormation 콘솔을 사용하여 리소스를 생성하는 방법에 대한 자세한 내용은 AWS CloudFormation 사용 설명서를 참조하세요.

템플릿 예제

별도의 스택을 사용하여 Amazon ECS 리소스 생성

다음 예제에서는 각 리소스에 대해 별도의 스택을 사용하여 Amazon ECS 리소스를 생성하는 방법을 보여줍니다.

태스크 정의

다음 템플릿을 사용하여 Fargate Linux 작업을 생성할 수 있습니다.

JSON
{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "ECSTaskDefinition": { "Type": "AWS::ECS::TaskDefinition", "Properties": { "ContainerDefinitions": [ { "Command": [ "/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' > /usr/local/apache2/htdocs/index.html && httpd-foreground\"" ], "EntryPoint": [ "sh", "-c" ], "Essential": true, "Image": "httpd:2.4", "LogConfiguration": { "LogDriver": "awslogs", "Options": { "awslogs-group": "/ecs/fargate-task-definition", "awslogs-region": "us-east-1", "awslogs-stream-prefix": "ecs" } }, "Name": "sample-fargate-app", "PortMappings": [ { "ContainerPort": 80, "HostPort": 80, "Protocol": "tcp" } ] } ], "Cpu": 256, "ExecutionRoleArn": "arn:aws:iam::aws_account_id:role/ecsTaskExecutionRole", "Family": "task-definition-cfn", "Memory": 512, "NetworkMode": "awsvpc", "RequiresCompatibilities": [ "FARGATE" ], "RuntimePlatform": { "OperatingSystemFamily": "LINUX" } } } } }
YAML
AWSTemplateFormatVersion: 2010-09-09 Resources: ECSTaskDefinition: Type: 'AWS::ECS::TaskDefinition' Properties: ContainerDefinitions: - Command: - >- /bin/sh -c "echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' > /usr/local/apache2/htdocs/index.html && httpd-foreground" EntryPoint: - sh - '-c' Essential: true Image: 'httpd:2.4' LogConfiguration: LogDriver: awslogs Options: awslogs-group: /ecs/fargate-task-definition awslogs-region: us-east-1 awslogs-stream-prefix: ecs Name: sample-fargate-app PortMappings: - ContainerPort: 80 HostPort: 80 Protocol: tcp Cpu: 256 ExecutionRoleArn: 'arn:aws:iam::aws_account_id:role/ecsTaskExecutionRole' Family: task-definition-cfn Memory: 512 NetworkMode: awsvpc RequiresCompatibilities: - FARGATE RuntimePlatform: OperatingSystemFamily: LINUX

클러스터

다음 템플릿을 사용하여 빈 클러스터를 생성할 수 있습니다.

JSON
{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "ECSCluster": { "Type": "AWS::ECS::Cluster", "Properties": { "ClusterName": "MyEmptyCluster" } } } }
YAML
AWSTemplateFormatVersion: 2010-09-09 Resources: ECSCluster: Type: 'AWS::ECS::Cluster' Properties: ClusterName: MyEmptyCluster

AL2023 Amazon ECS-Optimized-AMI를 사용하여 클러스터 생성

Amazon EC2에서 AL2023 인스턴스를 실행하는 용량 공급자를 사용하는 클러스터를 정의합니다.

중요

최신 AMI ID는 Amazon Elastic Container Service 개발자 안내서Amazon ECS 최적화 AMI를 참조하세요.

JSON
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "EC2 ECS cluster that starts out empty, with no EC2 instances yet. An ECS capacity provider automatically launches more EC2 instances as required on the fly when you request ECS to launch services or standalone tasks.", "Parameters": { "InstanceType": { "Type": "String", "Description": "EC2 instance type", "Default": "t2.medium", "AllowedValues": [ "t1.micro", "t2.2xlarge", "t2.large", "t2.medium", "t2.micro", "t2.nano", "t2.small", "t2.xlarge", "t3.2xlarge", "t3.large", "t3.medium", "t3.micro", "t3.nano", "t3.small", "t3.xlarge" ] }, "DesiredCapacity": { "Type": "Number", "Default": "0", "Description": "Number of EC2 instances to launch in your ECS cluster." }, "MaxSize": { "Type": "Number", "Default": "100", "Description": "Maximum number of EC2 instances that can be launched in your ECS cluster." }, "ECSAMI": { "Description": "The Amazon Machine Image ID used for the cluster", "Type": "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>", "Default": "/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id" }, "VpcId": { "Type": "AWS::EC2::VPC::Id", "Description": "VPC ID where the ECS cluster is launched", "Default": "vpc-1234567890abcdef0" }, "SubnetIds": { "Type": "List<AWS::EC2::Subnet::Id>", "Description": "List of subnet IDs where the EC2 instances will be launched", "Default": "subnet-021345abcdef67890" } }, "Resources": { "ECSCluster": { "Type": "AWS::ECS::Cluster", "Properties": { "ClusterSettings": [ { "Name": "containerInsights", "Value": "enabled" } ] } }, "ECSAutoScalingGroup": { "Type": "AWS::AutoScaling::AutoScalingGroup", "DependsOn": [ "ECSCluster", "EC2Role" ], "Properties": { "VPCZoneIdentifier": { "Ref": "SubnetIds" }, "LaunchTemplate": { "LaunchTemplateId": { "Ref": "ContainerInstances" }, "Version": { "Fn::GetAtt": [ "ContainerInstances", "LatestVersionNumber" ] } }, "MinSize": 0, "MaxSize": { "Ref": "MaxSize" }, "DesiredCapacity": { "Ref": "DesiredCapacity" }, "NewInstancesProtectedFromScaleIn": true }, "UpdatePolicy": { "AutoScalingReplacingUpdate": { "WillReplace": "true" } } }, "ContainerInstances": { "Type": "AWS::EC2::LaunchTemplate", "Properties": { "LaunchTemplateName": "asg-launch-template-2", "LaunchTemplateData": { "ImageId": { "Ref": "ECSAMI" }, "InstanceType": { "Ref": "InstanceType" }, "IamInstanceProfile": { "Name": { "Ref": "EC2InstanceProfile" } }, "SecurityGroupIds": [ { "Ref": "ContainerHostSecurityGroup" } ], "UserData": { "Fn::Base64": { "Fn::Sub": "#!/bin/bash -xe\n echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config\n yum install -y aws-cfn-bootstrap\n /opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource ContainerInstances --configsets full_install --region ${AWS::Region} &\n" } }, "MetadataOptions": { "HttpEndpoint": "enabled", "HttpTokens": "required" } } } }, "EC2InstanceProfile": { "Type": "AWS::IAM::InstanceProfile", "Properties": { "Path": "/", "Roles": [ { "Ref": "EC2Role" } ] } }, "CapacityProvider": { "Type": "AWS::ECS::CapacityProvider", "Properties": { "AutoScalingGroupProvider": { "AutoScalingGroupArn": { "Ref": "ECSAutoScalingGroup" }, "ManagedScaling": { "InstanceWarmupPeriod": 60, "MinimumScalingStepSize": 1, "MaximumScalingStepSize": 100, "Status": "ENABLED", "TargetCapacity": 100 }, "ManagedTerminationProtection": "ENABLED" } } }, "CapacityProviderAssociation": { "Type": "AWS::ECS::ClusterCapacityProviderAssociations", "Properties": { "CapacityProviders": [ { "Ref": "CapacityProvider" } ], "Cluster": { "Ref": "ECSCluster" }, "DefaultCapacityProviderStrategy": [ { "Base": 0, "CapacityProvider": { "Ref": "CapacityProvider" }, "Weight": 1 } ] } }, "ContainerHostSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Access to the EC2 hosts that run containers", "VpcId": { "Ref": "VpcId" } } }, "EC2Role": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "ec2.amazonaws.com" ] }, "Action": [ "sts:AssumeRole" ] } ] }, "Path": "/", "ManagedPolicyArns": [ "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role", "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" ] } }, "ECSTaskExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "ecs-tasks.amazonaws.com" ] }, "Action": [ "sts:AssumeRole" ], "Condition": { "ArnLike": { "aws:SourceArn": { "Fn::Sub": "arn:${AWS::Partition}:ecs:${AWS::Region}:${AWS::AccountId}:*" } }, "StringEquals": { "aws:SourceAccount": { "Fn::Sub": "${AWS::AccountId}" } } } } ] }, "Path": "/", "ManagedPolicyArns": [ "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" ] } } }, "Outputs": { "ClusterName": { "Description": "The ECS cluster into which to launch resources", "Value": "ECSCluster" }, "ECSTaskExecutionRole": { "Description": "The role used to start up a task", "Value": "ECSTaskExecutionRole" }, "CapacityProvider": { "Description": "The cluster capacity provider that the service should use to request capacity when it wants to start up a task", "Value": "CapacityProvider" } } }
YAML
AWSTemplateFormatVersion: '2010-09-09' Description: EC2 ECS cluster that starts out empty, with no EC2 instances yet. An ECS capacity provider automatically launches more EC2 instances as required on the fly when you request ECS to launch services or standalone tasks. Parameters: InstanceType: Type: String Description: EC2 instance type Default: t2.medium AllowedValues: - t1.micro - t2.2xlarge - t2.large - t2.medium - t2.micro - t2.nano - t2.small - t2.xlarge - t3.2xlarge - t3.large - t3.medium - t3.micro - t3.nano - t3.small - t3.xlarge DesiredCapacity: Type: Number Default: '0' Description: Number of EC2 instances to launch in your ECS cluster. MaxSize: Type: Number Default: '100' Description: Maximum number of EC2 instances that can be launched in your ECS cluster. ECSAMI: Description: The Amazon Machine Image ID used for the cluster Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id> Default: /aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id VpcId: Type: AWS::EC2::VPC::Id Description: VPC ID where the ECS cluster is launched Default: vpc-1234567890abcdef0 SubnetIds: Type: List<AWS::EC2::Subnet::Id> Description: List of subnet IDs where the EC2 instances will be launched Default: subnet-021345abcdef67890 Resources: ECSCluster: Type: AWS::ECS::Cluster Properties: ClusterSettings: - Name: containerInsights Value: enabled ECSAutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup DependsOn: - ECSCluster - EC2Role Properties: VPCZoneIdentifier: !Ref SubnetIds LaunchTemplate: LaunchTemplateId: !Ref ContainerInstances Version: !GetAtt ContainerInstances.LatestVersionNumber MinSize: 0 MaxSize: !Ref MaxSize DesiredCapacity: !Ref DesiredCapacity NewInstancesProtectedFromScaleIn: true UpdatePolicy: AutoScalingReplacingUpdate: WillReplace: 'true' ContainerInstances: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateName: asg-launch-template-2 LaunchTemplateData: ImageId: !Ref ECSAMI InstanceType: !Ref InstanceType IamInstanceProfile: Name: !Ref EC2InstanceProfile SecurityGroupIds: - !Ref ContainerHostSecurityGroup UserData: !Base64 Fn::Sub: | #!/bin/bash -xe echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config yum install -y aws-cfn-bootstrap /opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource ContainerInstances --configsets full_install --region ${AWS::Region} & MetadataOptions: HttpEndpoint: enabled HttpTokens: required EC2InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: / Roles: - !Ref EC2Role CapacityProvider: Type: AWS::ECS::CapacityProvider Properties: AutoScalingGroupProvider: AutoScalingGroupArn: !Ref ECSAutoScalingGroup ManagedScaling: InstanceWarmupPeriod: 60 MinimumScalingStepSize: 1 MaximumScalingStepSize: 100 Status: ENABLED TargetCapacity: 100 ManagedTerminationProtection: ENABLED CapacityProviderAssociation: Type: AWS::ECS::ClusterCapacityProviderAssociations Properties: CapacityProviders: - !Ref CapacityProvider Cluster: !Ref ECSCluster DefaultCapacityProviderStrategy: - Base: 0 CapacityProvider: !Ref CapacityProvider Weight: 1 ContainerHostSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Access to the EC2 hosts that run containers VpcId: !Ref VpcId EC2Role: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore ECSTaskExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: - ecs-tasks.amazonaws.com Action: - sts:AssumeRole Condition: ArnLike: aws:SourceArn: !Sub arn:${AWS::Partition}:ecs:${AWS::Region}:${AWS::AccountId}:* StringEquals: aws:SourceAccount: !Sub ${AWS::AccountId} Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy Outputs: ClusterName: Description: The ECS cluster into which to launch resources Value: ECSCluster ECSTaskExecutionRole: Description: The role used to start up a task Value: ECSTaskExecutionRole CapacityProvider: Description: The cluster capacity provider that the service should use to request capacity when it wants to start up a task Value: CapacityProvider

서비스를 배포합니다.

다음 템플릿은 용량 공급자를 통해 실행할 AL2023 용량을 요청하는 서비스를 정의합니다. 컨테이너가 온라인 상태가 되면 AL2023 인스턴스에서 실행됩니다.

JSON
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "An example service that deploys in AWS VPC networking mode on EC2 capacity. Service uses a capacity provider to request EC2 instances to run on. Service runs with networking in private subnets, but still accessible to the internet via a load balancer hosted in public subnets.", "Parameters": { "VpcId": { "Type": "String", "Description": "The VPC that the service is running inside of" }, "PublicSubnetIds": { "Type": "List<AWS::EC2::Subnet::Id>", "Description": "List of public subnet ID's to put the load balancer in" }, "PrivateSubnetIds": { "Type": "List<AWS::EC2::Subnet::Id>", "Description": "List of private subnet ID's that the AWS VPC tasks are in" }, "ClusterName": { "Type": "String", "Description": "The name of the ECS cluster into which to launch capacity." }, "ECSTaskExecutionRole": { "Type": "String", "Description": "The role used to start up an ECS task" }, "CapacityProvider": { "Type": "String", "Description": "The cluster capacity provider that the service should use to request capacity when it wants to start up a task" }, "ServiceName": { "Type": "String", "Default": "web", "Description": "A name for the service" }, "ImageUrl": { "Type": "String", "Default": "public.ecr.aws/docker/library/nginx:latest", "Description": "The url of a docker image that contains the application process that will handle the traffic for this service" }, "ContainerCpu": { "Type": "Number", "Default": 256, "Description": "How much CPU to give the container. 1024 is 1 CPU" }, "ContainerMemory": { "Type": "Number", "Default": 512, "Description": "How much memory in megabytes to give the container" }, "ContainerPort": { "Type": "Number", "Default": 80, "Description": "What port that the application expects traffic on" }, "DesiredCount": { "Type": "Number", "Default": 2, "Description": "How many copies of the service task to run" } }, "Resources": { "TaskDefinition": { "Type": "AWS::ECS::TaskDefinition", "Properties": { "Family": "ServiceName", "Cpu": "ContainerCpu", "Memory": "ContainerMemory", "NetworkMode": "awsvpc", "RequiresCompatibilities": [ "EC2" ], "ExecutionRoleArn": "ECSTaskExecutionRole", "ContainerDefinitions": [ { "Name": "ServiceName", "Cpu": "ContainerCpu", "Memory": "ContainerMemory", "Image": "ImageUrl", "PortMappings": [ { "ContainerPort": "ContainerPort", "HostPort": "ContainerPort" } ], "LogConfiguration": { "LogDriver": "awslogs", "Options": { "mode": "non-blocking", "max-buffer-size": "25m", "awslogs-group": "LogGroup", "awslogs-region": "AWS::Region", "awslogs-stream-prefix": "ServiceName" } } } ] } }, "Service": { "Type": "AWS::ECS::Service", "DependsOn": "PublicLoadBalancerListener", "Properties": { "ServiceName": "ServiceName", "Cluster": "ClusterName", "PlacementStrategies": [ { "Field": "attribute:ecs.availability-zone", "Type": "spread" }, { "Field": "cpu", "Type": "binpack" } ], "CapacityProviderStrategy": [ { "Base": 0, "CapacityProvider": "CapacityProvider", "Weight": 1 } ], "NetworkConfiguration": { "AwsvpcConfiguration": { "SecurityGroups": [ "ServiceSecurityGroup" ], "Subnets": "PrivateSubnetIds" } }, "DeploymentConfiguration": { "MaximumPercent": 200, "MinimumHealthyPercent": 75 }, "DesiredCount": "DesiredCount", "TaskDefinition": "TaskDefinition", "LoadBalancers": [ { "ContainerName": "ServiceName", "ContainerPort": "ContainerPort", "TargetGroupArn": "ServiceTargetGroup" } ] } }, "ServiceSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Security group for service", "VpcId": "VpcId" } }, "ServiceTargetGroup": { "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", "Properties": { "HealthCheckIntervalSeconds": 6, "HealthCheckPath": "/", "HealthCheckProtocol": "HTTP", "HealthCheckTimeoutSeconds": 5, "HealthyThresholdCount": 2, "TargetType": "ip", "Port": "ContainerPort", "Protocol": "HTTP", "UnhealthyThresholdCount": 10, "VpcId": "VpcId", "TargetGroupAttributes": [ { "Key": "deregistration_delay.timeout_seconds", "Value": 0 } ] } }, "PublicLoadBalancerSG": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Access to the public facing load balancer", "VpcId": "VpcId", "SecurityGroupIngress": [ { "CidrIp": "0.0.0.0/0", "IpProtocol": -1 } ] } }, "PublicLoadBalancer": { "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", "Properties": { "Scheme": "internet-facing", "LoadBalancerAttributes": [ { "Key": "idle_timeout.timeout_seconds", "Value": "30" } ], "Subnets": "PublicSubnetIds", "SecurityGroups": [ "PublicLoadBalancerSG" ] } }, "PublicLoadBalancerListener": { "Type": "AWS::ElasticLoadBalancingV2::Listener", "Properties": { "DefaultActions": [ { "Type": "forward", "ForwardConfig": { "TargetGroups": [ { "TargetGroupArn": "ServiceTargetGroup", "Weight": 100 } ] } } ], "LoadBalancerArn": "PublicLoadBalancer", "Port": 80, "Protocol": "HTTP" } }, "ServiceIngressfromLoadBalancer": { "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { "Description": "Ingress from the public ALB", "GroupId": "ServiceSecurityGroup", "IpProtocol": -1, "SourceSecurityGroupId": "PublicLoadBalancerSG" } }, "LogGroup": { "Type": "AWS::Logs::LogGroup" } } }
YAML
AWSTemplateFormatVersion: '2010-09-09' Description: >- An example service that deploys in AWS VPC networking mode on EC2 capacity. Service uses a capacity provider to request EC2 instances to run on. Service runs with networking in private subnets, but still accessible to the internet via a load balancer hosted in public subnets. Parameters: VpcId: Type: String Description: The VPC that the service is running inside of PublicSubnetIds: Type: 'List<AWS::EC2::Subnet::Id>' Description: List of public subnet ID's to put the load balancer in PrivateSubnetIds: Type: 'List<AWS::EC2::Subnet::Id>' Description: List of private subnet ID's that the AWS VPC tasks are in ClusterName: Type: String Description: The name of the ECS cluster into which to launch capacity. ECSTaskExecutionRole: Type: String Description: The role used to start up an ECS task CapacityProvider: Type: String Description: >- The cluster capacity provider that the service should use to request capacity when it wants to start up a task ServiceName: Type: String Default: web Description: A name for the service ImageUrl: Type: String Default: 'public.ecr.aws/docker/library/nginx:latest' Description: >- The url of a docker image that contains the application process that will handle the traffic for this service ContainerCpu: Type: Number Default: 256 Description: How much CPU to give the container. 1024 is 1 CPU ContainerMemory: Type: Number Default: 512 Description: How much memory in megabytes to give the container ContainerPort: Type: Number Default: 80 Description: What port that the application expects traffic on DesiredCount: Type: Number Default: 2 Description: How many copies of the service task to run Resources: TaskDefinition: Type: 'AWS::ECS::TaskDefinition' Properties: Family: !Ref ServiceName Cpu: !Ref ContainerCpu Memory: !Ref ContainerMemory NetworkMode: awsvpc RequiresCompatibilities: - EC2 ExecutionRoleArn: !Ref ECSTaskExecutionRole ContainerDefinitions: - Name: !Ref ServiceName Cpu: !Ref ContainerCpu Memory: !Ref ContainerMemory Image: !Ref ImageUrl PortMappings: - ContainerPort: !Ref ContainerPort HostPort: !Ref ContainerPort LogConfiguration: LogDriver: awslogs Options: mode: non-blocking max-buffer-size: 25m awslogs-group: !Ref LogGroup awslogs-region: !Ref AWS::Region awslogs-stream-prefix: !Ref ServiceName Service: Type: AWS::ECS::Service DependsOn: PublicLoadBalancerListener Properties: ServiceName: !Ref ServiceName Cluster: !Ref ClusterName PlacementStrategies: - Field: 'attribute:ecs.availability-zone' Type: spread - Field: cpu Type: binpack CapacityProviderStrategy: - Base: 0 CapacityProvider: !Ref CapacityProvider Weight: 1 NetworkConfiguration: AwsvpcConfiguration: SecurityGroups: - !Ref ServiceSecurityGroup Subnets: !Ref PrivateSubnetIds DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 75 DesiredCount: !Ref DesiredCount TaskDefinition: !Ref TaskDefinition LoadBalancers: - ContainerName: !Ref ServiceName ContainerPort: !Ref ContainerPort TargetGroupArn: !Ref ServiceTargetGroup ServiceSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Security group for service VpcId: !Ref VpcId ServiceTargetGroup: Type: 'AWS::ElasticLoadBalancingV2::TargetGroup' Properties: HealthCheckIntervalSeconds: 6 HealthCheckPath: / HealthCheckProtocol: HTTP HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 2 TargetType: ip Port: !Ref ContainerPort Protocol: HTTP UnhealthyThresholdCount: 10 VpcId: !Ref VpcId TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: 0 PublicLoadBalancerSG: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Access to the public facing load balancer VpcId: !Ref VpcId SecurityGroupIngress: - CidrIp: 0.0.0.0/0 IpProtocol: -1 PublicLoadBalancer: Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer' Properties: Scheme: internet-facing LoadBalancerAttributes: - Key: idle_timeout.timeout_seconds Value: '30' Subnets: !Ref PublicSubnetIds SecurityGroups: - !Ref PublicLoadBalancerSG PublicLoadBalancerListener: Type: 'AWS::ElasticLoadBalancingV2::Listener' Properties: DefaultActions: - Type: forward ForwardConfig: TargetGroups: - TargetGroupArn: !Ref ServiceTargetGroup Weight: 100 LoadBalancerArn: !Ref PublicLoadBalancer Port: 80 Protocol: HTTP ServiceIngressfromLoadBalancer: Type: 'AWS::EC2::SecurityGroupIngress' Properties: Description: Ingress from the public ALB GroupId: !Ref ServiceSecurityGroup IpProtocol: -1 SourceSecurityGroupId: !Ref PublicLoadBalancerSG LogGroup: Type: 'AWS::Logs::LogGroup'

하나의 스택에 여러 Amazon ECS 리소스 생성

다음 예제 템플릿을 사용하여 하나의 스택에 여러 Amazon ECS 리소스를 생성할 수 있습니다. 템플릿은 CFNCluster로 이름이 지정된 Amazon ECS 클러스터를 생성합니다. 클러스터에는 웹 서버를 설정하는 Linux Fargate 작업 정의가 포함되어 있습니다. 템플릿은 또한 작업 정의에서 정의한 작업을 시작하고 유지 관리하는 cfn-service로 이름이 지정된 서비스를 생성합니다. 이 템플릿을 사용하기 전에 서비스 NetworkConfiguration의 서브넷 및 보안 그룹 ID가 모두 동일한 VPC 속하고 보안 그룹에 필요한 규칙이 지정되어 있는지 확인합니다. 보안 그룹 규칙에 대한 자세한 내용은 Amazon VPC 사용 설명서의 보안 그룹 규칙을 참조하세요.

JSON
{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "ECSCluster": { "Type": "AWS::ECS::Cluster", "Properties": { "ClusterName": "CFNCluster" } }, "ECSTaskDefinition": { "Type": "AWS::ECS::TaskDefinition", "Properties": { "ContainerDefinitions": [ { "Command": [ "/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' > /usr/local/apache2/htdocs/index.html && httpd-foreground\"" ], "EntryPoint": [ "sh", "-c" ], "Essential": true, "Image": "httpd:2.4", "LogConfiguration": { "LogDriver": "awslogs", "Options": { "awslogs-group": "/ecs/fargate-task-definition", "awslogs-region": "us-east-1", "awslogs-stream-prefix": "ecs" } }, "Name": "sample-fargate-app", "PortMappings": [ { "ContainerPort": 80, "HostPort": 80, "Protocol": "tcp" } ] } ], "Cpu": 256, "ExecutionRoleArn": "arn:aws:iam::aws_account_id::role/ecsTaskExecutionRole", "Family": "task-definition-cfn", "Memory": 512, "NetworkMode": "awsvpc", "RequiresCompatibilities": [ "FARGATE" ], "RuntimePlatform": { "OperatingSystemFamily": "LINUX" } } }, "ECSService": { "Type": "AWS::ECS::Service", "Properties": { "ServiceName": "cfn-service", "Cluster": { "Ref": "ECSCluster" }, "DesiredCount": 1, "LaunchType": "FARGATE", "NetworkConfiguration": { "AwsvpcConfiguration": { "AssignPublicIp": "ENABLED", "SecurityGroups": [ "sg-abcdef01234567890" ], "Subnets": [ "subnet-abcdef01234567890" ] } }, "TaskDefinition": { "Ref": "ECSTaskDefinition" } } } } }
YAML
AWSTemplateFormatVersion: 2010-09-09 Resources: ECSCluster: Type: 'AWS::ECS::Cluster' Properties: ClusterName: CFNCluster ECSTaskDefinition: Type: 'AWS::ECS::TaskDefinition' Properties: ContainerDefinitions: - Command: - >- /bin/sh -c "echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' > /usr/local/apache2/htdocs/index.html && httpd-foreground" EntryPoint: - sh - '-c' Essential: true Image: 'httpd:2.4' LogConfiguration: LogDriver: awslogs Options: awslogs-group: /ecs/fargate-task-definition awslogs-region: us-east-1 awslogs-stream-prefix: ecs Name: sample-fargate-app PortMappings: - ContainerPort: 80 HostPort: 80 Protocol: tcp Cpu: 256 ExecutionRoleArn: 'arn:aws:iam::aws_account_id:role/ecsTaskExecutionRole' Family: task-definition-cfn Memory: 512 NetworkMode: awsvpc RequiresCompatibilities: - FARGATE RuntimePlatform: OperatingSystemFamily: LINUX ECSService: Type: 'AWS::ECS::Service' Properties: ServiceName: cfn-service Cluster: !Ref ECSCluster DesiredCount: 1 LaunchType: FARGATE NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: ENABLED SecurityGroups: - sg-abcdef01234567890 Subnets: - subnet-abcdef01234567890 TaskDefinition: !Ref ECSTaskDefinition

AWS CLI를 사용하여 템플릿에서 리소스 생성

다음 명령은 ecs-template-body.json로 이름이 지정된 템플릿 본문 파일을 사용하여 ecs-stack로 이름이 지정된 스택을 생성합니다. 템플릿 본문 파일이 JSON 또는 YAML 형식인지 확인합니다. 파일의 위치는 --template-body 파라미터에서 지정됩니다. 이 경우 템플릿 본문 파일은 현재 디렉터리에 위치합니다.

aws cloudformation create-stack \ --stack-name ecs-stack \ --template-body file://ecs-template-body.json

리소스가 올바르게 생성되었는지 확인하려면 Amazon ECS 콘솔을 확인하거나 다음 명령을 사용하십시오.

  • 다음 명령은 모든 작업 정의를 나열합니다.

    aws ecs list-task-definitions
  • 다음 명령은 모든 클러스터를 나열합니다.

    aws ecs list-clusters
  • 다음 명령은 클러스터 CFNCluster에 정의된 모든 서비스를 나열합니다. CFNCluster를 서비스를 생성할 클러스터의 이름으로 바꿉니다.

    aws ecs list-services \ --cluster CFNCluster

AWS CloudFormation에 대해 자세히 알아보기

AWS CloudFormation에 대한 자세한 내용은 다음 리소스를 참조하세요.