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 작업을 생성할 수 있습니다.
{
"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": "public.ecr.aws/docker/library/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"
}
}
}
}
}
클러스터
다음 템플릿을 사용하여 빈 클러스터를 생성할 수 있습니다.
{
"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를 참조하세요.
{
"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"
}
}
}
서비스를 배포합니다.
다음 템플릿은 용량 공급자를 통해 실행할 AL2023 용량을 요청하는 서비스를 정의합니다. 컨테이너가 온라인 상태가 되면 AL2023 인스턴스에서 실행됩니다.
{
"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 사용 설명서의 보안 그룹 규칙을 참조하세요.
{
"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": "public.ecr.aws/docker/library/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에 대한 자세한 내용은 다음 리소스를 참조하세요.