Amazon CloudFormation example templates for Amazon ECS
To provision and configure resources for Amazon ECS and related services, make sure that you're familiar with Amazon CloudFormation templates. For more information, see Amazon CloudFormation templates in the Amazon CloudFormation User Guide. Amazon CloudFormation templates are text files in the JSON or YAML format that describe the resources that you want to provision in your Amazon CloudFormation stacks. If you're unfamiliar with either the JSON or YAML format, or both, you can use Amazon Infrastructure Composer to get started using Amazon CloudFormation templates. For more information, see Create templates visually with Infrastructure Composer in the Amazon CloudFormation User Guide.
You can create Amazon ECS clusters, task definitions, and services using Amazon CloudFormation. The following topics include templates that demonstrate how to create resources with different configurations. You can create these resources with these templates by using the Amazon CloudFormation console or the Amazon CLI. For more information about how to create resources using the Amazon CloudFormation console, see the Amazon CloudFormation User Guide.
The following topics list example templates for Amazon ECS task definitions, clusters, and services.
Task definitions
A task definition is a blueprint for your application that describes the parameters and one or more containers that form your application. The following are example Amazon CloudFormation templates for Amazon ECS task definitions. For more information about Amazon ECS task definitions, see Amazon ECS task definitions.
Fargate Linux task definition
You can use the following template to create a sample Fargate Linux task.
- JSON
-
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "ECS Task Definition with parameterized values", "Parameters": { "ContainerImage": { "Type": "String", "Default": "public.ecr.aws/docker/library/httpd:2.4", "Description": "The container image to use for the task" }, "ContainerCpu": { "Type": "Number", "Default": 256, "Description": "The number of CPU units to reserve for the container", "AllowedValues": [256, 512, 1024, 2048, 4096] }, "ContainerMemory": { "Type": "Number", "Default": 512, "Description": "The amount of memory (in MiB) to reserve for the container", "AllowedValues": [512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192] }, "TaskFamily": { "Type": "String", "Default": "task-definition-cfn", "Description": "The name of the task definition family" }, "ContainerName": { "Type": "String", "Default": "sample-fargate-app", "Description": "The name of the container" }, "ContainerPort": { "Type": "Number", "Default": 80, "Description": "The port number on the container" }, "HostPort": { "Type": "Number", "Default": 80, "Description": "The port number on the host" }, "ExecutionRoleArn": { "Type": "String", "Default": "arn:aws:iam::aws_account_id:role/ecsTaskExecutionRole", "Description": "The ARN of the task execution role" }, "LogGroup": { "Type": "String", "Default": "/ecs/fargate-task-definition", "Description": "The CloudWatch log group for container logs" }, "NetworkMode": { "Type": "String", "Default": "awsvpc", "Description": "The Docker networking mode to use", "AllowedValues": ["awsvpc", "bridge", "host", "none"] }, "OperatingSystemFamily": { "Type": "String", "Default": "LINUX", "Description": "The operating system for the task", "AllowedValues": ["LINUX", "WINDOWS_SERVER_2019_FULL", "WINDOWS_SERVER_2019_CORE", "WINDOWS_SERVER_2022_FULL", "WINDOWS_SERVER_2022_CORE"] } }, "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 && -foreground\"" ], "EntryPoint": [ "sh", "-c" ], "Essential": true, "Image": {"Ref": "ContainerImage"}, "LogConfiguration": { "LogDriver": "awslogs", "Options": { "mode": "non-blocking", "max-buffer-size": "25m", "awslogs-create-group": "true", "awslogs-group": {"Ref": "LogGroup"}, "awslogs-region": {"Ref": "AWS::Region"}, "awslogs-stream-prefix": "ecs" } }, "Name": {"Ref": "ContainerName"}, "PortMappings": [ { "ContainerPort": {"Ref": "ContainerPort"}, "HostPort": {"Ref": "HostPort"}, "Protocol": "tcp" } ] } ], "Cpu": {"Ref": "ContainerCpu"}, "ExecutionRoleArn": {"Ref": "ExecutionRoleArn"}, "Family": {"Ref": "TaskFamily"}, "Memory": {"Ref": "ContainerMemory"}, "NetworkMode": {"Ref": "NetworkMode"}, "RequiresCompatibilities": [ "FARGATE" ], "RuntimePlatform": { "OperatingSystemFamily": {"Ref": "OperatingSystemFamily"} } } } }, "Outputs": { "TaskDefinitionArn": { "Description": "The ARN of the created task definition", "Value": {"Ref": "ECSTaskDefinition"} } } }
- YAML
-
AWSTemplateFormatVersion: 2010-09-09 Description: 'ECS Task Definition to deploy a sample app' Parameters: ContainerImage: Type: String Default: 'public.ecr.aws/docker/library/httpd:2.4' Description: The container image to use for the task ContainerCpu: Type: Number Default: 256 Description: The number of CPU units to reserve for the container AllowedValues: [256, 512, 1024, 2048, 4096] ContainerMemory: Type: Number Default: 512 Description: The amount of memory (in MiB) to reserve for the container AllowedValues: [512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192] TaskFamily: Type: String Default: 'task-definition-cfn' Description: The name of the task definition family ContainerName: Type: String Default: 'sample-fargate-app' Description: The name of the container ContainerPort: Type: Number Default: 80 Description: The port number on the container HostPort: Type: Number Default: 80 Description: The port number on the host ExecutionRoleArn: Type: String Default: 'arn:aws:iam::
111122223333
:role/ecsTaskExecutionRole' Description: The ARN of the task execution role LogGroup: Type: String Default: '/ecs/fargate-task-definition' Description: The CloudWatch log group for container logs NetworkMode: Type: String Default: 'awsvpc' Description: The Docker networking mode to use AllowedValues: ['awsvpc', 'bridge', 'host', 'none'] OperatingSystemFamily: Type: String Default: 'LINUX' Description: The operating system for the task AllowedValues: ['LINUX', 'WINDOWS_SERVER_2019_FULL', 'WINDOWS_SERVER_2019_CORE', 'WINDOWS_SERVER_2022_FULL', 'WINDOWS_SERVER_2022_CORE'] 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: !Ref ContainerImage LogConfiguration: LogDriver: awslogs Options: mode: non-blocking max-buffer-size: 25m awslogs-create-group: 'true' awslogs-group: !Ref LogGroup awslogs-region: !Ref AWS::Region awslogs-stream-prefix: ecs Name: !Ref ContainerName PortMappings: - ContainerPort: !Ref ContainerPort HostPort: !Ref HostPort Protocol: tcp Cpu: !Ref ContainerCpu ExecutionRoleArn: !Ref ExecutionRoleArn Family: !Ref TaskFamily Memory: !Ref ContainerMemory NetworkMode: !Ref NetworkMode RequiresCompatibilities: - FARGATE RuntimePlatform: OperatingSystemFamily: !Ref OperatingSystemFamily Outputs: TaskDefinitionArn: Description: The ARN of the created task definition Value: !Ref ECSTaskDefinition
Amazon EFS task definition
You can use the following template to create a task that uses an Amazon EFS file system that you created. For more information about using Amazon EFS volumes with Amazon ECS, see Use Amazon EFS volumes with Amazon ECS.
- JSON
-
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "Create a task definition for a web server with parameterized values.", "Parameters": { "ExecutionRoleArn": { "Type": "String", "Default": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole", "Description": "The ARN of the task execution role" }, "NetworkMode": { "Type": "String", "Default": "awsvpc", "Description": "The Docker networking mode to use", "AllowedValues": ["awsvpc", "bridge", "host", "none"] }, "TaskFamily": { "Type": "String", "Default": "my-ecs-task", "Description": "The name of the task definition family" }, "ContainerCpu": { "Type": "String", "Default": "256", "Description": "The number of CPU units to reserve for the container", "AllowedValues": ["256", "512", "1024", "2048", "4096"] }, "ContainerMemory": { "Type": "String", "Default": "512", "Description": "The amount of memory (in MiB) to reserve for the container", "AllowedValues": ["512", "1024", "2048", "3072", "4096", "5120", "6144", "7168", "8192"] }, "ContainerName": { "Type": "String", "Default": "nginx", "Description": "The name of the container" }, "ContainerImage": { "Type": "String", "Default": "public.ecr.aws/nginx/nginx:latest", "Description": "The container image to use for the task" }, "ContainerPort": { "Type": "Number", "Default": 80, "Description": "The port number on the container" }, "InitProcessEnabled": { "Type": "String", "Default": "true", "Description": "Whether to enable the init process inside the container", "AllowedValues": ["true", "false"] }, "EfsVolumeName": { "Type": "String", "Default": "efs-volume", "Description": "The name of the EFS volume" }, "EfsContainerPath": { "Type": "String", "Default": "/usr/share/nginx/html", "Description": "The path in the container where the EFS volume will be mounted" }, "LogGroup": { "Type": "String", "Default": "LogGroup", "Description": "The CloudWatch log group for container logs" }, "LogStreamPrefix": { "Type": "String", "Default": "efs-task", "Description": "The prefix for the log stream" }, "EfsFilesystemId": { "Type": "String", "Default": "fs-1234567890abcdef0", "Description": "The ID of the EFS filesystem" }, "EfsRootDirectory": { "Type": "String", "Default": "/", "Description": "The root directory in the EFS filesystem" }, "EfsTransitEncryption": { "Type": "String", "Default": "ENABLED", "Description": "Whether to enable transit encryption for EFS", "AllowedValues": ["ENABLED", "DISABLED"] } }, "Resources": { "ECSTaskDefinition": { "Type": "AWS::ECS::TaskDefinition", "Properties": { "ExecutionRoleArn": {"Ref": "ExecutionRoleArn"}, "NetworkMode": {"Ref": "NetworkMode"}, "RequiresCompatibilities": ["FARGATE"], "Family": {"Ref": "TaskFamily"}, "Cpu": {"Ref": "ContainerCpu"}, "Memory": {"Ref": "ContainerMemory"}, "ContainerDefinitions": [ { "Name": {"Ref": "ContainerName"}, "Image": {"Ref": "ContainerImage"}, "Essential": true, "PortMappings": [ { "ContainerPort": {"Ref": "ContainerPort"}, "Protocol": "tcp" } ], "LinuxParameters": { "InitProcessEnabled": {"Ref": "InitProcessEnabled"} }, "MountPoints": [ { "SourceVolume": {"Ref": "EfsVolumeName"}, "ContainerPath": {"Ref": "EfsContainerPath"} } ], "LogConfiguration": { "LogDriver": "awslogs", "Options": { "mode": "non-blocking", "max-buffer-size": "25m", "awslogs-group": {"Ref": "LogGroup"}, "awslogs-region": {"Ref": "AWS::Region"}, "awslogs-create-group": "true", "awslogs-stream-prefix": {"Ref": "LogStreamPrefix"} } } } ], "Volumes": [ { "Name": {"Ref": "EfsVolumeName"}, "EFSVolumeConfiguration": { "FilesystemId": {"Ref": "EfsFilesystemId"}, "RootDirectory": {"Ref": "EfsRootDirectory"}, "TransitEncryption": {"Ref": "EfsTransitEncryption"} } } ] } } }, "Outputs": { "TaskDefinitionArn": { "Description": "The ARN of the created task definition", "Value": {"Ref": "ECSTaskDefinition"} } } }
- YAML
-
AWSTemplateFormatVersion: 2010-09-09 Description: Create a task definition for a web server with parameterized values. Parameters: ExecutionRoleArn: Type: String Default: arn:aws:iam::123456789012:role/ecsTaskExecutionRole Description: The ARN of the task execution role NetworkMode: Type: String Default: awsvpc Description: The Docker networking mode to use AllowedValues: [awsvpc, bridge, host, none] TaskFamily: Type: String Default: my-ecs-task Description: The name of the task definition family ContainerCpu: Type: String Default: "256" Description: The number of CPU units to reserve for the container AllowedValues: ["256", "512", "1024", "2048", "4096"] ContainerMemory: Type: String Default: "512" Description: The amount of memory (in MiB) to reserve for the container AllowedValues: ["512", "1024", "2048", "3072", "4096", "5120", "6144", "7168", "8192"] ContainerName: Type: String Default: nginx Description: The name of the container ContainerImage: Type: String Default: public.ecr.aws/nginx/nginx:latest Description: The container image to use for the task ContainerPort: Type: Number Default: 80 Description: The port number on the container InitProcessEnabled: Type: String Default: "true" Description: Whether to enable the init process inside the container AllowedValues: ["true", "false"] EfsVolumeName: Type: String Default: efs-volume Description: The name of the EFS volume EfsContainerPath: Type: String Default: /usr/share/nginx/html Description: The path in the container where the EFS volume will be mounted LogGroup: Type: String Default: LogGroup Description: The CloudWatch log group for container logs LogStreamPrefix: Type: String Default: efs-task Description: The prefix for the log stream EfsFilesystemId: Type: String Default: fs-1234567890abcdef0 Description: The ID of the EFS filesystem EfsRootDirectory: Type: String Default: / Description: The root directory in the EFS filesystem EfsTransitEncryption: Type: String Default: ENABLED Description: Whether to enable transit encryption for EFS AllowedValues: [ENABLED, DISABLED] Resources: ECSTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: ExecutionRoleArn: !Ref ExecutionRoleArn NetworkMode: !Ref NetworkMode RequiresCompatibilities: - FARGATE Family: !Ref TaskFamily Cpu: !Ref ContainerCpu Memory: !Ref ContainerMemory ContainerDefinitions: - Name: !Ref ContainerName Image: !Ref ContainerImage Essential: true PortMappings: - ContainerPort: !Ref ContainerPort Protocol: tcp LinuxParameters: InitProcessEnabled: !Ref InitProcessEnabled MountPoints: - SourceVolume: !Ref EfsVolumeName ContainerPath: !Ref EfsContainerPath LogConfiguration: LogDriver: awslogs Options: mode: non-blocking max-buffer-size: 25m awslogs-group: !Ref LogGroup awslogs-region: !Ref AWS::Region awslogs-create-group: "true" awslogs-stream-prefix: !Ref LogStreamPrefix Volumes: - Name: !Ref EfsVolumeName EFSVolumeConfiguration: FilesystemId: !Ref EfsFilesystemId RootDirectory: !Ref EfsRootDirectory TransitEncryption: !Ref EfsTransitEncryption Outputs: TaskDefinitionArn: Description: The ARN of the created task definition Value: !Ref ECSTaskDefinition
Clusters
An Amazon ECS cluster is a logical grouping of tasks or services. You can use the following templates to create clusters with different configurations. For more information about Amazon ECS clusters, see Amazon ECS clusters.
Create an empty cluster with default settings
You can use the following template to create an empty cluster with default settings.
- 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
Create an empty cluster with managed storage encryption and enhanced Container Insights
You can use the following template to create a cluster with cluster-level managed storage and enhanced Container Insights enabled. Cluster-level encryption applies to Amazon ECS managed data volumes such as Amazon EBS volumes. For more information about Amazon EBS encryption, see Encrypt data stored in Amazon EBS volumes attached to Amazon ECS tasks. For more information about using Container Insights with enchanced observability, see Monitor Amazon ECS containers using Container Insights with enhanced observability.
- JSON
-
{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "Cluster": { "Type": "AWS::ECS::Cluster", "Properties": { "ClusterName": "EncryptedEnhancedCluster", "ClusterSettings": [ { "Name": "containerInsights", "Value": "enhanced" } ], "Configuration": { "ManagedStorageConfiguration": { "KmsKeyId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111" } } } } } }
- YAML
-
AWSTemplateFormatVersion: 2010-09-09 Resources: Cluster: Type: AWS::ECS::Cluster Properties: ClusterName: EncryptedEnhancedCluster ClusterSettings: - Name: containerInsights Value: enhanced Configuration: ManagedStorageConfiguration: KmsKeyId: a1b2c3d4-5678-90ab-cdef-EXAMPLE11111
Create a cluster with the AL2023 Amazon ECS-Optimized-AMI
You can use the following template to create a cluster that uses a capacity provider that launches AL2023 instances on Amazon EC2.
Important
For the latest AMI IDs, see Amazon ECS-optimized AMI in the Amazon Elastic Container Service Developer Guide.
- 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
Services
You can use an Amazon ECS service to run and maintain a specified number of instances of a task definition simultaneously in an Amazon ECS cluster. If one of your tasks fails or stops, the Amazon ECS service scheduler launches another instance of your task definition to replace it. This helps maintain your desired number of tasks in the service. The following templates can be used to deploy services. For more information about Amazon ECS services, see Amazon ECS services.
Deploy an application
The following template creates an Amazon ECS service that's named
cfn-service
that launches and maintains the task defined by the
task definition. The templates creates a cluster that's named
CFNCluster
. The cluster contains a Linux Fargate task
definition that sets up a web server. The template also creates the necessary networking and logging resources. The template also create an Amazon ECS task execution role. For more information about the task execution role, see Amazon ECS task execution IAM role.
- JSON
-
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "A template that deploys an application that is built on an Apache web server Docker image by creating an Amazon ECS cluster, task definition, and service. The template also creates networking and logging resources, and an Amazon ECS task execution role.", "Parameters": { "ClusterName": { "Type": "String", "Default": "CFNCluster", "Description": "Name of the ECS Cluster" }, "TaskFamily": { "Type": "String", "Default": "task-definition-cfn", "Description": "Family name for the Task Definition" }, "ServiceName": { "Type": "String", "Default": "cfn-service", "Description": "Name of the ECS Service" }, "ContainerImage": { "Type": "String", "Default": "public.ecr.aws/docker/library/httpd:2.4", "Description": "Container image to use for the task" }, "TaskCpu": { "Type": "Number", "Default": 256, "AllowedValues": [ 256, 512, 1024, 2048, 4096 ], "Description": "CPU units for the task" }, "TaskMemory": { "Type": "Number", "Default": 512, "AllowedValues": [ 512, 1024, 2048, 4096, 8192, 16384 ], "Description": "Memory (in MiB) for the task" }, "DesiredCount": { "Type": "Number", "Default": 1, "Description": "Desired number of tasks to run" }, "LogGroupName": { "Type": "String", "Default": "/ecs/fargate-task-definition", "Description": "CloudWatch Log Group name" }, "VpcCidr": { "Type": "String", "Default": "10.0.0.0/16", "Description": "CIDR block for the VPC" }, "PublicSubnet1Cidr": { "Type": "String", "Default": "10.0.0.0/24", "Description": "CIDR block for public subnet 1" }, "PublicSubnet2Cidr": { "Type": "String", "Default": "10.0.1.0/24", "Description": "CIDR block for public subnet 2" } }, "Resources": { "VPC": { "Type": "AWS::EC2::VPC", "Properties": { "CidrBlock": { "Ref": "VpcCidr" }, "EnableDnsSupport": true, "EnableDnsHostnames": true, "Tags": [ { "Key": "Name", "Value": { "Fn::Sub": "${AWS::StackName}-VPC" } } ] } }, "InternetGateway": { "Type": "AWS::EC2::InternetGateway", "Properties": { "Tags": [ { "Key": "Name", "Value": { "Fn::Sub": "${AWS::StackName}-IGW" } } ] } }, "InternetGatewayAttachment": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { "InternetGatewayId": { "Ref": "InternetGateway" }, "VpcId": { "Ref": "VPC" } } }, "PublicSubnet1": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "AvailabilityZone": { "Fn::Select": [ 0, { "Fn::GetAZs": "" } ] }, "CidrBlock": { "Ref": "PublicSubnet1Cidr" }, "MapPublicIpOnLaunch": true, "Tags": [ { "Key": "Name", "Value": { "Fn::Sub": "${AWS::StackName}-PublicSubnet1" } } ] } }, "PublicSubnet2": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "AvailabilityZone": { "Fn::Select": [ 1, { "Fn::GetAZs": "" } ] }, "CidrBlock": { "Ref": "PublicSubnet2Cidr" }, "MapPublicIpOnLaunch": true, "Tags": [ { "Key": "Name", "Value": { "Fn::Sub": "${AWS::StackName}-PublicSubnet2" } } ] } }, "PublicRouteTable": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": { "Fn::Sub": "${AWS::StackName}-PublicRouteTable" } } ] } }, "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" } } }, "ECSSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Security group for ECS tasks", "VpcId": { "Ref": "VPC" }, "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "tcp", "FromPort": 443, "ToPort": 443, "CidrIp": "0.0.0.0/0" } ] } }, "ECSTaskExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "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" ] } }, "TaskLogGroup": { "Type": "AWS::Logs::LogGroup", "DeletionPolicy": "Retain", "UpdateReplacePolicy": "Retain", "Properties": { "LogGroupName": { "Ref": "LogGroupName" }, "RetentionInDays": 30 } }, "ECSCluster": { "Type": "AWS::ECS::Cluster", "Properties": { "ClusterName": { "Ref": "ClusterName" } } }, "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": { "Ref": "ContainerImage" }, "LogConfiguration": { "LogDriver": "awslogs", "Options": { "mode": "non-blocking", "max-buffer-size": "25m", "awslogs-create-group": "true", "awslogs-group": { "Ref": "LogGroupName" }, "awslogs-region": { "Ref": "AWS::Region" }, "awslogs-stream-prefix": "ecs" } }, "Name": "sample-fargate-app", "PortMappings": [ { "ContainerPort": 80, "HostPort": 80, "Protocol": "tcp" } ] } ], "Cpu": { "Ref": "TaskCpu" }, "ExecutionRoleArn": { "Fn::GetAtt": [ "ECSTaskExecutionRole", "Arn" ] }, "Family": { "Ref": "TaskFamily" }, "Memory": { "Ref": "TaskMemory" }, "NetworkMode": "awsvpc", "RequiresCompatibilities": [ "FARGATE" ], "RuntimePlatform": { "OperatingSystemFamily": "LINUX" } } }, "ECSService": { "Type": "AWS::ECS::Service", "DependsOn": [ "PublicSubnet1RouteTableAssociation", "PublicSubnet2RouteTableAssociation" ], "Properties": { "ServiceName": { "Ref": "ServiceName" }, "Cluster": { "Ref": "ECSCluster" }, "DesiredCount": { "Ref": "DesiredCount" }, "LaunchType": "FARGATE", "NetworkConfiguration": { "AwsvpcConfiguration": { "AssignPublicIp": "ENABLED", "SecurityGroups": [ { "Ref": "ECSSecurityGroup" } ], "Subnets": [ { "Ref": "PublicSubnet1" }, { "Ref": "PublicSubnet2" } ] } }, "TaskDefinition": { "Ref": "ECSTaskDefinition" } } } }, "Outputs": { "ClusterName": { "Description": "The name of the ECS cluster", "Value": { "Ref": "ECSCluster" } }, "TaskDefinitionArn": { "Description": "The ARN of the task definition", "Value": { "Ref": "ECSTaskDefinition" } }, "ServiceName": { "Description": "The name of the ECS service", "Value": { "Ref": "ECSService" } }, "VpcId": { "Description": "The ID of the VPC", "Value": { "Ref": "VPC" } }, "PublicSubnet1": { "Description": "The ID of public subnet 1", "Value": { "Ref": "PublicSubnet1" } }, "PublicSubnet2": { "Description": "The ID of public subnet 2", "Value": { "Ref": "PublicSubnet2" } }, "SecurityGroup": { "Description": "The ID of the security group", "Value": { "Ref": "ECSSecurityGroup" } }, "ExecutionRoleArn": { "Description": "The ARN of the task execution role", "Value": { "Fn::GetAtt": [ "ECSTaskExecutionRole", "Arn" ] } } } }
- YAML
-
AWSTemplateFormatVersion: 2010-09-09 Description: A template that deploys an application that is built on an Apache web server Docker image by creating an Amazon ECS cluster, task definition, and service. The template also creates networking and logging resources, and an Amazon ECS task execution role. Parameters: ClusterName: Type: String Default: CFNCluster Description: Name of the ECS Cluster TaskFamily: Type: String Default: task-definition-cfn Description: Family name for the Task Definition ServiceName: Type: String Default: cfn-service Description: Name of the ECS Service ContainerImage: Type: String Default: public.ecr.aws/docker/library/httpd:2.4 Description: Container image to use for the task TaskCpu: Type: Number Default: 256 AllowedValues: [256, 512, 1024, 2048, 4096] Description: CPU units for the task TaskMemory: Type: Number Default: 512 AllowedValues: [512, 1024, 2048, 4096, 8192, 16384] Description: Memory (in MiB) for the task DesiredCount: Type: Number Default: 1 Description: Desired number of tasks to run LogGroupName: Type: String Default: /ecs/fargate-task-definition Description: CloudWatch Log Group name VpcCidr: Type: String Default: 10.0.0.0/16 Description: CIDR block for the VPC PublicSubnet1Cidr: Type: String Default: 10.0.0.0/24 Description: CIDR block for public subnet 1 PublicSubnet2Cidr: Type: String Default: 10.0.1.0/24 Description: CIDR block for public subnet 2 Resources: # VPC and Networking Resources VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref VpcCidr EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: !Sub ${AWS::StackName}-VPC 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 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}-PublicSubnet1 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}-PublicSubnet2 PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub ${AWS::StackName}-PublicRouteTable 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 # Security Group ECSSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Security group for ECS tasks VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 # IAM Roles ECSTaskExecutionRole: Type: AWS::IAM::Role Properties: 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 # CloudWatch Logs TaskLogGroup: Type: AWS::Logs::LogGroup DeletionPolicy: Retain UpdateReplacePolicy: Retain Properties: LogGroupName: !Ref LogGroupName RetentionInDays: 30 # ECS Resources ECSCluster: Type: AWS::ECS::Cluster Properties: ClusterName: !Ref ClusterName 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"s EntryPoint: - sh - '-c' Essential: true Image: !Ref ContainerImage LogConfiguration: LogDriver: awslogs Options: mode: non-blocking max-buffer-size: 25m awslogs-create-group: 'true' awslogs-group: !Ref LogGroupName awslogs-region: !Ref 'AWS::Region' awslogs-stream-prefix: ecs Name: sample-fargate-app PortMappings: - ContainerPort: 80 HostPort: 80 Protocol: tcp Cpu: !Ref TaskCpu ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn Family: !Ref TaskFamily Memory: !Ref TaskMemory NetworkMode: awsvpc RequiresCompatibilities: - FARGATE RuntimePlatform: OperatingSystemFamily: LINUX ECSService: Type: AWS::ECS::Service DependsOn: - PublicSubnet1RouteTableAssociation - PublicSubnet2RouteTableAssociation Properties: ServiceName: !Ref ServiceName Cluster: !Ref ECSCluster DesiredCount: !Ref DesiredCount LaunchType: FARGATE NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: ENABLED SecurityGroups: - !Ref ECSSecurityGroup Subnets: - !Ref PublicSubnet1 - !Ref PublicSubnet2 TaskDefinition: !Ref ECSTaskDefinition Outputs: ClusterName: Description: The name of the ECS cluster Value: !Ref ECSCluster TaskDefinitionArn: Description: The ARN of the task definition Value: !Ref ECSTaskDefinition ServiceName: Description: The name of the ECS service Value: !Ref ECSService VpcId: Description: The ID of the VPC Value: !Ref VPC PublicSubnet1: Description: The ID of public subnet 1 Value: !Ref PublicSubnet1 PublicSubnet2: Description: The ID of public subnet 2 Value: !Ref PublicSubnet2 SecurityGroup: Description: The ID of the security group Value: !Ref ECSSecurityGroup ExecutionRoleArn: Description: The ARN of the task execution role Value: !GetAtt ECSTaskExecutionRole.Arn
Deploy a service with ECS Exec enabled
You can use the following template to deploy a service with ECS Exec enabled. The service runs in a cluster with a KMS key for encrypting ECS Exec sessions and a log configuration for redirecting execute command session logs to an Amazon S3 bucket. For more information, see Monitor Amazon ECS containers with ECS Exec.
- JSON
-
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "ECS Cluster with Fargate Service and Task Definition and ECS Exec enabled.", "Parameters": { "ClusterName": { "Type": "String", "Default": "CFNCluster", "Description": "Name of the ECS Cluster" }, "S3BucketName": { "Type": "String", "Default": "amzn-s3-demo-bucket", "Description": "S3 bucket for ECS execute command logs" }, "KmsKeyId": { "Type": "String", "Default": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111", "Description": "KMS Key ID for ECS execute command encryption" }, "ContainerImage": { "Type": "String", "Default": "public.ecr.aws/docker/library/httpd:2.4", "Description": "Container image to use for the task" }, "ContainerCpu": { "Type": "Number", "Default": 256, "AllowedValues": [256, 512, 1024, 2048, 4096], "Description": "CPU units for the container (256 = 0.25 vCPU)" }, "ContainerMemory": { "Type": "Number", "Default": 512, "AllowedValues": [512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192], "Description": "Memory for the container (in MiB)" }, "DesiredCount": { "Type": "Number", "Default": 1, "Description": "Desired count of tasks in the service" }, "SecurityGroups": { "Type": "List<AWS::EC2::SecurityGroup::Id>", "Description": "Security Group IDs for the ECS Service" }, "Subnets": { "Type": "List<AWS::EC2::Subnet::Id>", "Description": "Subnet IDs for the ECS Service" }, "ServiceName": { "Type": "String", "Default": "cfn-service", "Description": "Name of the ECS service" }, "TaskFamily": { "Type": "String", "Default": "task-definition-cfn", "Description": "Family name for the task definition" }, "TaskExecutionRoleArn": { "Type": "String", "Description": "ARN of an existing IAM role for ECS task execution", "Default": "arn:aws:iam::
111122223333
:role/ecsTaskExecutionRole" }, "TaskRoleArn": { "Type": "String", "Description": "ARN of an existing IAM role for ECS tasks", "Default": "arn:aws:iam::111122223333
:role/execTaskRole" } }, "Resources": { "ECSCluster": { "Type": "AWS::ECS::Cluster", "Properties": { "ClusterName": {"Ref": "ClusterName"}, "Configuration": { "ExecuteCommandConfiguration": { "Logging": "OVERRIDE", "LogConfiguration": { "S3BucketName": {"Ref": "S3BucketName"} }, "KmsKeyId": {"Ref": "KmsKeyId"} } }, "Tags": [ { "Key": "Environment", "Value": {"Ref": "AWS::StackName"} } ] } }, "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": {"Ref": "ContainerImage"}, "LogConfiguration": { "LogDriver": "awslogs", "Options": { "mode": "non-blocking", "max-buffer-size": "25m", "awslogs-create-group": "true", "awslogs-group": {"Fn::Sub": "/ecs/${AWS::StackName}"}, "awslogs-region": {"Ref": "AWS::Region"}, "awslogs-stream-prefix": "ecs" } }, "Name": "sample-fargate-app", "PortMappings": [ { "ContainerPort": 80, "HostPort": 80, "Protocol": "tcp" } ] } ], "Cpu": {"Ref": "ContainerCpu"}, "ExecutionRoleArn": {"Ref": "TaskExecutionRoleArn"}, "TaskRoleArn": {"Ref": "TaskRoleArn"}, "Family": {"Ref": "TaskFamily"}, "Memory": {"Ref": "ContainerMemory"}, "NetworkMode": "awsvpc", "RequiresCompatibilities": [ "FARGATE" ], "RuntimePlatform": { "OperatingSystemFamily": "LINUX" }, "Tags": [ { "Key": "Name", "Value": {"Fn::Sub": "${AWS::StackName}-TaskDefinition"} } ] } }, "ECSService": { "Type": "AWS::ECS::Service", "Properties": { "ServiceName": {"Ref": "ServiceName"}, "Cluster": {"Ref": "ECSCluster"}, "DesiredCount": {"Ref": "DesiredCount"}, "EnableExecuteCommand": true, "LaunchType": "FARGATE", "NetworkConfiguration": { "AwsvpcConfiguration": { "AssignPublicIp": "ENABLED", "SecurityGroups": {"Ref": "SecurityGroups"}, "Subnets": {"Ref": "Subnets"} } }, "TaskDefinition": {"Ref": "ECSTaskDefinition"}, "Tags": [ { "Key": "Name", "Value": {"Fn::Sub": "${AWS::StackName}-Service"} } ] } } }, "Outputs": { "ClusterName": { "Description": "The name of the ECS cluster", "Value": {"Ref": "ECSCluster"} }, "ServiceName": { "Description": "The name of the ECS service", "Value": {"Ref": "ServiceName"} }, "TaskDefinitionArn": { "Description": "The ARN of the task definition", "Value": {"Ref": "ECSTaskDefinition"} }, "ClusterArn": { "Description": "The ARN of the ECS cluster", "Value": {"Fn::GetAtt": ["ECSCluster", "Arn"]} }, "StackName": { "Description": "The name of this stack", "Value": {"Ref": "AWS::StackName"} }, "StackId": { "Description": "The unique identifier for this stack", "Value": {"Ref": "AWS::StackId"} }, "Region": { "Description": "The AWS Region where the stack is deployed", "Value": {"Ref": "AWS::Region"} }, "AccountId": { "Description": "The AWS Account ID", "Value": {"Ref": "AWS::AccountId"} } } } - YAML
-
AWSTemplateFormatVersion: '2010-09-09' Description: ECS Cluster with Fargate Service and Task Definition and ECS Exec enabled. Parameters: ClusterName: Type: String Default: CFNCluster Description: Name of the ECS Cluster S3BucketName: Type: String Default: amzn-s3-demo-bucket Description: S3 bucket for ECS execute command logs KmsKeyId: Type: String Default: a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 Description: KMS Key ID for ECS execute command encryption ContainerImage: Type: String Default: public.ecr.aws/docker/library/httpd:2.4 Description: Container image to use for the task ContainerCpu: Type: Number Default: 256 AllowedValues: [256, 512, 1024, 2048, 4096] Description: CPU units for the container (256 = 0.25 vCPU) ContainerMemory: Type: Number Default: 512 AllowedValues: [512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192] Description: Memory for the container (in MiB) DesiredCount: Type: Number Default: 1 Description: Desired count of tasks in the service SecurityGroups: Type: List<AWS::EC2::SecurityGroup::Id> Description: Security Group IDs for the ECS Service Subnets: Type: List<AWS::EC2::Subnet::Id> Description: Subnet IDs for the ECS Service ServiceName: Type: String Default: cfn-service Description: Name of the ECS service TaskFamily: Type: String Default: task-definition-cfn Description: Family name for the task definition TaskExecutionRoleArn: Type: String Description: ARN of an existing IAM role for ECS task execution Default: 'arn:aws:iam::
111122223333
:role/ecsTaskExecutionRole' TaskRoleArn: Type: String Description: ARN of an existing IAM role for ECS tasks Default: 'arn:aws:iam::111122223333
:role/execTaskRole' Resources: ECSCluster: Type: AWS::ECS::Cluster Properties: ClusterName: !Ref ClusterName Configuration: ExecuteCommandConfiguration: Logging: OVERRIDE LogConfiguration: S3BucketName: !Ref S3BucketName KmsKeyId: !Ref KmsKeyId Tags: - Key: Environment Value: !Ref AWS::StackName 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: !Ref ContainerImage LogConfiguration: LogDriver: awslogs Options: mode: non-blocking max-buffer-size: 25m awslogs-create-group: 'true' awslogs-group: !Sub /ecs/${AWS::StackName} awslogs-region: !Ref AWS::Region awslogs-stream-prefix: ecs Name: sample-fargate-app PortMappings: - ContainerPort: 80 HostPort: 80 Protocol: tcp Cpu: !Ref ContainerCpu ExecutionRoleArn: !Ref TaskExecutionRoleArn TaskRoleArn: !Ref TaskRoleArn Family: !Ref TaskFamily Memory: !Ref ContainerMemory NetworkMode: awsvpc RequiresCompatibilities: - FARGATE RuntimePlatform: OperatingSystemFamily: LINUX Tags: - Key: Name Value: !Sub ${AWS::StackName}-TaskDefinition ECSService: Type: AWS::ECS::Service Properties: ServiceName: !Ref ServiceName Cluster: !Ref ECSCluster DesiredCount: !Ref DesiredCount EnableExecuteCommand: true LaunchType: FARGATE NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: ENABLED SecurityGroups: !Ref SecurityGroups Subnets: !Ref Subnets TaskDefinition: !Ref ECSTaskDefinition Tags: - Key: Name Value: !Sub ${AWS::StackName}-Service Outputs: ClusterName: Description: The name of the ECS cluster Value: !Ref ECSCluster ServiceName: Description: The name of the ECS service Value: !Ref ServiceName TaskDefinitionArn: Description: The ARN of the task definition Value: !Ref ECSTaskDefinition ClusterArn: Description: The ARN of the ECS cluster Value: !GetAtt ECSCluster.Arn StackName: Description: The name of this stack Value: !Ref AWS::StackName StackId: Description: The unique identifier for this stack Value: !Ref AWS::StackId Region: Description: The AWS Region where the stack is deployed Value: !Ref AWS::Region AccountId: Description: The AWS Account ID Value: !Ref AWS::AccountId
Deploy service that uses Amazon VPC Lattice
You can use the following template to get started with creating an Amazon ECS service with VPC Lattice. You may need to complete the following additional steps to set up VPC Lattice:
-
Update your security group's inbound rules for VPC Lattice to allow the inbound rule
vpc-lattice
prefix and to allow traffic on port 80. -
Associate VPC for the service to a VPC Lattice service network.
-
Configure a private or public hosted zone with Amazon Route 53.
-
Configure listeners and listener rules in a VPC Lattice service.
-
Verify health check configurations of the target group.
For more information about using VPC Lattice with Amazon ECS, see Use Amazon VPC Lattice to connect, observe, and secure your Amazon ECS services.
- JSON
-
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "The template used to create an ECS Service with VPC Lattice.", "Parameters": { "ECSClusterName": { "Type": "String", "Default": "vpc-lattice-cluster" }, "ECSServiceName": { "Type": "String", "Default": "vpc-lattice-service" }, "SecurityGroupIDs": { "Type": "List<AWS::EC2::SecurityGroup::Id>", "Description": "Security Group IDs for the ECS Service" }, "SubnetIDs": { "Type": "List<AWS::EC2::Subnet::Id>", "Description": "Subnet IDs for the ECS Service" }, "VpcID": { "Type": "AWS::EC2::VPC::Id", "Description": "VPC ID for the resources" }, "ContainerImage": { "Type": "String", "Default": "public.ecr.aws/docker/library/httpd:2.4", "Description": "Container image to use for the task" }, "TaskCpu": { "Type": "Number", "Default": 256, "AllowedValues": [256, 512, 1024, 2048, 4096], "Description": "CPU units for the task" }, "TaskMemory": { "Type": "Number", "Default": 512, "AllowedValues": [512, 1024, 2048, 4096, 8192, 16384], "Description": "Memory (in MiB) for the task" }, "LogGroupName": { "Type": "String", "Default": "/ecs/vpc-lattice-task", "Description": "CloudWatch Log Group name" }, "EnableContainerInsights": { "Type": "String", "Default": "enabled", "AllowedValues": ["enabled", "disabled"], "Description": "Enable or disable CloudWatch Container Insights for the cluster" } }, "Resources": { "ECSCluster": { "Type": "AWS::ECS::Cluster", "Properties": { "ClusterName": {"Ref": "ECSClusterName"}, "ClusterSettings": [ { "Name": "containerInsights", "Value": {"Ref": "EnableContainerInsights"} } ], "Tags": [ { "Key": "Name", "Value": {"Ref": "ECSClusterName"} } ] } }, "ECSTaskExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "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" ] } }, "TaskLogGroup": { "Type": "AWS::Logs::LogGroup", "DeletionPolicy": "Retain", "UpdateReplacePolicy": "Retain", "Properties": { "LogGroupName": {"Ref": "LogGroupName"}, "RetentionInDays": 30 } }, "VpcLatticeTaskDefinition": { "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": {"Ref": "ContainerImage"}, "LogConfiguration": { "LogDriver": "awslogs", "Options": { "mode": "non-blocking", "max-buffer-size": "25m", "awslogs-create-group": "true", "awslogs-group": {"Ref": "LogGroupName"}, "awslogs-region": {"Ref": "AWS::Region"}, "awslogs-stream-prefix": "ecs" } }, "Name": "vpc-lattice-container", "PortMappings": [ { "ContainerPort": 80, "HostPort": 80, "Protocol": "tcp", "Name": "vpc-lattice-port" } ] } ], "Cpu": {"Ref": "TaskCpu"}, "ExecutionRoleArn": {"Fn::GetAtt": ["ECSTaskExecutionRole", "Arn"]}, "Family": "vpc-lattice-task-definition", "Memory": {"Ref": "TaskMemory"}, "NetworkMode": "awsvpc", "RequiresCompatibilities": [ "FARGATE" ], "RuntimePlatform": { "OperatingSystemFamily": "LINUX" } } }, "ECSService": { "Type": "AWS::ECS::Service", "Properties": { "Cluster": {"Ref": "ECSCluster"}, "TaskDefinition": {"Ref": "VpcLatticeTaskDefinition"}, "LaunchType": "FARGATE", "ServiceName": {"Ref": "ECSServiceName"}, "SchedulingStrategy": "REPLICA", "DesiredCount": 2, "AvailabilityZoneRebalancing": "ENABLED", "NetworkConfiguration": { "AwsvpcConfiguration": { "AssignPublicIp": "ENABLED", "SecurityGroups": { "Ref": "SecurityGroupIDs" }, "Subnets": { "Ref": "SubnetIDs" } } }, "PlatformVersion": "LATEST", "VpcLatticeConfigurations": [ { "RoleArn": "arn:aws:iam::111122223333:role/ecsInfrastructureRole", "PortName": "vpc-lattice-port", "TargetGroupArn": { "Ref": "TargetGroup1" } } ], "DeploymentConfiguration": { "DeploymentCircuitBreaker": { "Enable": true, "Rollback": true }, "MaximumPercent": 200, "MinimumHealthyPercent": 100 }, "DeploymentController": { "Type": "ECS" }, "ServiceConnectConfiguration": { "Enabled": false }, "Tags": [], "EnableECSManagedTags": true } }, "TargetGroup1": { "Type": "AWS::VpcLattice::TargetGroup", "Properties": { "Type": "IP", "Name": "first-target-group", "Config": { "Port": 80, "Protocol": "HTTP", "VpcIdentifier": {"Ref": "VpcID"}, "HealthCheck": { "Enabled": true, "Path": "/" } }, "Tags": [ { "Key": "ecs-application-networking/ServiceName", "Value": {"Ref": "ECSServiceName"} }, { "Key": "ecs-application-networking/ClusterName", "Value": {"Ref": "ECSClusterName"} }, { "Key": "ecs-application-networking/TaskDefinition", "Value": {"Ref": "VpcLatticeTaskDefinition"} }, { "Key": "ecs-application-networking/VpcId", "Value": {"Ref": "VpcID"} } ] } } }, "Outputs": { "ClusterName": { "Description": "The cluster used to create the service.", "Value": { "Ref": "ECSCluster" } }, "ClusterArn": { "Description": "The ARN of the ECS cluster", "Value": { "Fn::GetAtt": ["ECSCluster", "Arn"] } }, "ECSService": { "Description": "The created service.", "Value": { "Ref": "ECSService" } }, "TaskDefinitionArn": { "Description": "The ARN of the task definition", "Value": { "Ref": "VpcLatticeTaskDefinition" } } } }
- YAML
-
AWSTemplateFormatVersion: '2010-09-09' Description: The template used to create an ECS Service with VPC Lattice. Parameters: ECSClusterName: Type: String Default: vpc-lattice-cluster ECSServiceName: Type: String Default: vpc-lattice-service SecurityGroupIDs: Type: List<AWS::EC2::SecurityGroup::Id> Description: Security Group IDs for the ECS Service SubnetIDs: Type: List<AWS::EC2::Subnet::Id> Description: Subnet IDs for the ECS Service VpcID: Type: AWS::EC2::VPC::Id Description: VPC ID for the resources ContainerImage: Type: String Default: public.ecr.aws/docker/library/httpd:2.4 Description: Container image to use for the task TaskCpu: Type: Number Default: 256 AllowedValues: [256, 512, 1024, 2048, 4096] Description: CPU units for the task TaskMemory: Type: Number Default: 512 AllowedValues: [512, 1024, 2048, 4096, 8192, 16384] Description: Memory (in MiB) for the task LogGroupName: Type: String Default: /ecs/vpc-lattice-task Description: CloudWatch Log Group name EnableContainerInsights: Type: String Default: 'enhanced' AllowedValues: ['enabled', 'disabled', 'enhanced'] Description: Enable or disable CloudWatch Container Insights for the cluster Resources: # ECS Cluster ECSCluster: Type: AWS::ECS::Cluster Properties: ClusterName: !Ref ECSClusterName ClusterSettings: - Name: containerInsights Value: !Ref EnableContainerInsights Tags: - Key: Name Value: !Ref ECSClusterName # IAM Roles ECSTaskExecutionRole: Type: AWS::IAM::Role Properties: 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 # CloudWatch Logs TaskLogGroup: Type: AWS::Logs::LogGroup DeletionPolicy: Retain UpdateReplacePolicy: Retain Properties: LogGroupName: !Ref LogGroupName RetentionInDays: 30 # Task Definition VpcLatticeTaskDefinition: 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: !Ref ContainerImage LogConfiguration: LogDriver: awslogs Options: mode: non-blocking max-buffer-size: 25m awslogs-create-group: 'true' awslogs-group: !Ref LogGroupName awslogs-region: !Ref 'AWS::Region' awslogs-stream-prefix: ecs Name: vpc-lattice-container PortMappings: - ContainerPort: 80 HostPort: 80 Protocol: tcp Name: vpc-lattice-port Cpu: !Ref TaskCpu ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn Family: vpc-lattice-task-definition Memory: !Ref TaskMemory NetworkMode: awsvpc RequiresCompatibilities: - FARGATE RuntimePlatform: OperatingSystemFamily: LINUX ECSService: Type: AWS::ECS::Service Properties: Cluster: !Ref ECSCluster TaskDefinition: !Ref VpcLatticeTaskDefinition LaunchType: FARGATE ServiceName: !Ref ECSServiceName SchedulingStrategy: REPLICA DesiredCount: 2 AvailabilityZoneRebalancing: ENABLED NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: ENABLED SecurityGroups: !Ref SecurityGroupIDs Subnets: !Ref SubnetIDs PlatformVersion: LATEST VpcLatticeConfigurations: - RoleArn: arn:aws:iam::111122223333:role/ecsInfrastructureRole PortName: vpc-lattice-port TargetGroupArn: !Ref TargetGroup1 DeploymentConfiguration: DeploymentCircuitBreaker: Enable: true Rollback: true MaximumPercent: 200 MinimumHealthyPercent: 100 DeploymentController: Type: ECS ServiceConnectConfiguration: Enabled: false Tags: [] EnableECSManagedTags: true TargetGroup1: Type: AWS::VpcLattice::TargetGroup Properties: Type: IP Name: first-target-group Config: Port: 80 Protocol: HTTP VpcIdentifier: !Ref VpcID HealthCheck: Enabled: true Path: / Tags: - Key: ecs-application-networking/ServiceName Value: !Ref ECSServiceName - Key: ecs-application-networking/ClusterName Value: !Ref ECSClusterName - Key: ecs-application-networking/TaskDefinition Value: !Ref VpcLatticeTaskDefinition - Key: ecs-application-networking/VpcId Value: !Ref VpcID Outputs: ClusterName: Description: The cluster used to create the service. Value: !Ref ECSCluster ClusterArn: Description: The ARN of the ECS cluster Value: !GetAtt ECSCluster.Arn ECSService: Description: The created service. Value: !Ref ECSService TaskDefinitionArn: Description: The ARN of the task definition Value: !Ref VpcLatticeTaskDefinition
Deploy service with a volume configuration
The following template includes a volume configuration in the service definition. Amazon ECS supports configuring the following data volumes by using a volume configuration at launch: Amazon EBS volumes. For more information about Amazon EBS volumes, see Use Amazon EBS volumes with Amazon ECS.
- JSON
-
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "The template used to create an ECS Service that includes a volume configuration. The configuration is used to create Amazon EBS volumes for attachment to the tasks. One volume is attached per task.", "Parameters": { "ECSClusterName": { "Type": "String", "Default": "volume-config-cluster", "Description": "Name of the ECS cluster" }, "SecurityGroupIDs": { "Type": "List<AWS::EC2::SecurityGroup::Id>", "Description": "Security Group IDs for the ECS Service" }, "SubnetIDs": { "Type": "List<AWS::EC2::Subnet::Id>", "Description": "Subnet IDs for the ECS Service" }, "InfrastructureRoleArn": { "Type": "String", "Description": "ARN of the IAM role that ECS will use to manage EBS volumes" }, "ContainerImage": { "Type": "String", "Default": "public.ecr.aws/nginx/nginx:latest", "Description": "Container image to use for the task" }, "TaskCpu": { "Type": "String", "Default": "2048", "Description": "CPU units for the task" }, "TaskMemory": { "Type": "String", "Default": "4096", "Description": "Memory (in MiB) for the task" }, "VolumeSize": { "Type": "String", "Default": "10", "Description": "Size of the EBS volume in GiB" }, "VolumeType": { "Type": "String", "Default": "gp3", "AllowedValues": ["gp2", "gp3", "io1", "io2", "st1", "sc1", "standard"], "Description": "EBS volume type" }, "VolumeIops": { "Type": "String", "Default": "3000", "Description": "IOPS for the EBS volume (required for io1, io2, and gp3)" }, "VolumeThroughput": { "Type": "String", "Default": "125", "Description": "Throughput for the EBS volume (only for gp3)" }, "FilesystemType": { "Type": "String", "Default": "xfs", "AllowedValues": ["xfs", "ext4"], "Description": "Filesystem type for the EBS volume" }, "EnableContainerInsights": { "Type": "String", "Default": "enhanced", "AllowedValues": ["enabled", "disabled", "enhanced"], "Description": "Enable or disable CloudWatch Container Insights for the cluster" } }, "Resources": { "ECSCluster": { "Type": "AWS::ECS::Cluster", "Properties": { "ClusterName": {"Ref": "ECSClusterName"}, "ClusterSettings": [ { "Name": "containerInsights", "Value": {"Ref": "EnableContainerInsights"} } ], "Tags": [ { "Key": "Name", "Value": {"Ref": "ECSClusterName"} } ] } }, "ECSTaskExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "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" ] } }, "EBSTaskDefinition": { "Type": "AWS::ECS::TaskDefinition", "Properties": { "Family": "ebs-task-attach-task-def", "ExecutionRoleArn": {"Fn::GetAtt": ["ECSTaskExecutionRole", "Arn"]}, "NetworkMode": "awsvpc", "RequiresCompatibilities": [ "EC2", "FARGATE" ], "Cpu": {"Ref": "TaskCpu"}, "Memory": {"Ref": "TaskMemory"}, "ContainerDefinitions": [ { "Name": "nginx", "Image": {"Ref": "ContainerImage"}, "Essential": true, "PortMappings": [ { "Name": "nginx-80-tcp", "ContainerPort": 80, "HostPort": 80, "Protocol": "tcp", "AppProtocol": "http" } ], "MountPoints": [ { "SourceVolume": "ebs-vol", "ContainerPath": "/foo-container-path", "ReadOnly": false } ] } ], "Volumes": [ { "Name": "ebs-vol", "ConfiguredAtLaunch": true } ] } }, "ECSService": { "Type": "AWS::ECS::Service", "Properties": { "Cluster": {"Ref": "ECSCluster"}, "TaskDefinition": {"Ref": "EBSTaskDefinition"}, "LaunchType": "FARGATE", "ServiceName": "ebs", "SchedulingStrategy": "REPLICA", "DesiredCount": 1, "NetworkConfiguration": { "AwsvpcConfiguration": { "AssignPublicIp": "ENABLED", "SecurityGroups": {"Ref": "SecurityGroupIDs"}, "Subnets": {"Ref": "SubnetIDs"} } }, "PlatformVersion": "LATEST", "DeploymentConfiguration": { "MaximumPercent": 200, "MinimumHealthyPercent": 100, "DeploymentCircuitBreaker": { "Enable": true, "Rollback": true } }, "DeploymentController": { "Type": "ECS" }, "Tags": [], "EnableECSManagedTags": true, "VolumeConfigurations": [ { "Name": "ebs-vol", "ManagedEBSVolume": { "RoleArn": {"Ref": "InfrastructureRoleArn"}, "VolumeType": {"Ref": "VolumeType"}, "Iops": {"Ref": "VolumeIops"}, "Throughput": {"Ref": "VolumeThroughput"}, "SizeInGiB": {"Ref": "VolumeSize"}, "FilesystemType": {"Ref": "FilesystemType"}, "TagSpecifications": [ { "ResourceType": "volume", "PropagateTags": "TASK_DEFINITION" } ] } } ] } } }, "Outputs": { "ClusterName": { "Description": "The cluster used to create the service.", "Value": {"Ref": "ECSCluster"} }, "ClusterArn": { "Description": "The ARN of the ECS cluster", "Value": {"Fn::GetAtt": ["ECSCluster", "Arn"]} }, "ECSService": { "Description": "The created service.", "Value": {"Ref": "ECSService"} }, "TaskDefinitionArn": { "Description": "The ARN of the task definition", "Value": {"Ref": "EBSTaskDefinition"} } } }
- YAML
-
AWSTemplateFormatVersion: 2010-09-09 Description: The template used to create an ECS Service that includes a volume configuration. The configuration is used to create Amazon EBS volumes for attachment to the tasks. One volume is attached per task. Parameters: ECSClusterName: Type: String Default: volume-config-cluster Description: Name of the ECS cluster SecurityGroupIDs: Type: List<AWS::EC2::SecurityGroup::Id> Description: Security Group IDs for the ECS Service SubnetIDs: Type: List<AWS::EC2::Subnet::Id> Description: Subnet IDs for the ECS Service InfrastructureRoleArn: Type: String Description: ARN of the IAM role that ECS will use to manage EBS volumes ContainerImage: Type: String Default: public.ecr.aws/nginx/nginx:latest Description: Container image to use for the task TaskCpu: Type: String Default: "2048" Description: CPU units for the task TaskMemory: Type: String Default: "4096" Description: Memory (in MiB) for the task VolumeSize: Type: String Default: "10" Description: Size of the EBS volume in GiB VolumeType: Type: String Default: gp3 AllowedValues: [gp2, gp3, io1, io2, st1, sc1, standard] Description: EBS volume type VolumeIops: Type: String Default: "3000" Description: IOPS for the EBS volume (required for io1, io2, and gp3) VolumeThroughput: Type: String Default: "125" Description: Throughput for the EBS volume (only for gp3) FilesystemType: Type: String Default: xfs AllowedValues: [xfs, ext4] Description: Filesystem type for the EBS volume EnableContainerInsights: Type: String Default: 'enhanced' AllowedValues: ['enabled', 'disabled', 'enhanced'] Description: Enable or disable CloudWatch Container Insights for the cluster Resources: # ECS Cluster ECSCluster: Type: AWS::ECS::Cluster Properties: ClusterName: !Ref ECSClusterName ClusterSettings: - Name: containerInsights Value: !Ref EnableContainerInsights Tags: - Key: Name Value: !Ref ECSClusterName # IAM Role for Task Execution ECSTaskExecutionRole: Type: AWS::IAM::Role Properties: 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 # Task Definition EBSTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: Family: ebs-task-attach-task-def ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn NetworkMode: awsvpc RequiresCompatibilities: - EC2 - FARGATE Cpu: !Ref TaskCpu Memory: !Ref TaskMemory ContainerDefinitions: - Name: nginx Image: !Ref ContainerImage Essential: true PortMappings: - Name: nginx-80-tcp ContainerPort: 80 HostPort: 80 Protocol: tcp AppProtocol: http MountPoints: - SourceVolume: ebs-vol ContainerPath: /foo-container-path ReadOnly: false Volumes: - Name: ebs-vol ConfiguredAtLaunch: true ECSService: Type: AWS::ECS::Service Properties: Cluster: !Ref ECSCluster TaskDefinition: !Ref EBSTaskDefinition LaunchType: FARGATE ServiceName: ebs SchedulingStrategy: REPLICA DesiredCount: 1 NetworkConfiguration: AwsvpcConfiguration: AssignPublicIp: ENABLED SecurityGroups: !Ref SecurityGroupIDs Subnets: !Ref SubnetIDs PlatformVersion: LATEST DeploymentConfiguration: MaximumPercent: 200 MinimumHealthyPercent: 100 DeploymentCircuitBreaker: Enable: true Rollback: true DeploymentController: Type: ECS Tags: [] EnableECSManagedTags: true VolumeConfigurations: - Name: ebs-vol ManagedEBSVolume: RoleArn: !Ref InfrastructureRoleArn VolumeType: !Ref VolumeType Iops: !Ref VolumeIops Throughput: !Ref VolumeThroughput SizeInGiB: !Ref VolumeSize FilesystemType: !Ref FilesystemType TagSpecifications: - ResourceType: volume PropagateTags: TASK_DEFINITION Outputs: ClusterName: Description: The cluster used to create the service. Value: !Ref ECSCluster ClusterArn: Description: The ARN of the ECS cluster Value: !GetAtt ECSCluster.Arn ECSService: Description: The created service. Value: !Ref ECSService TaskDefinitionArn: Description: The ARN of the task definition Value: !Ref EBSTaskDefinition
Deploy service with capacity providers
The following template defines a service that uses the capacity provider to request AL2023 capacity to run on. Containers will be launched onto the AL2023 instances as they come online.
- 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": { "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" } } }
- 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'
IAM roles for Amazon ECS
You can use Amazon CloudFormation templates to create IAM roles for use with Amazon ECS. For more information about IAM roles for Amazon ECS, see IAM roles for Amazon ECS.
Amazon ECS task execution role
The task execution role grants the Amazon ECS container and Fargate agents permission to make Amazon API calls on your behalf. The role is required depending on the requirements of your task. For more information, see Amazon ECS task execution IAM role.
The following template can be used to create a simple task execution role that
uses the AmazonECSTaskExecutionRolePolicy
managed policy.
- JSON
-
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "CloudFormation template for ECS Task Execution Role", "Resources": { "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:ecs:${AWS::Region}:${AWS::AccountId}:*" } }, "StringEquals": { "aws:SourceAccount": { "Ref": "AWS::AccountId" } } } } ] }, "Path": "/", "ManagedPolicyArns": [ "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" ] } } }, "Outputs": { "ECSTaskExecutionRoleARN": { "Description": "ARN of the ECS Task Execution Role", "Value": { "Fn::GetAtt": ["ECSTaskExecutionRole", "Arn"] }, "Export": { "Name": { "Fn::Sub": "${AWS::StackName}-ECSTaskExecutionRoleARN" } } }, "ECSTaskExecutionRoleName": { "Description": "Name of the ECS Task Execution Role", "Value": { "Ref": "ECSTaskExecutionRole" }, "Export": { "Name": { "Fn::Sub": "${AWS::StackName}-ECSTaskExecutionRoleName" } } } } }
- YAML
-
AWSTemplateFormatVersion: '2010-09-09' Description: 'CloudFormation template for ECS Task Execution Role' Resources: 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:ecs:${AWS::Region}:${AWS::AccountId}:* StringEquals: aws:SourceAccount: !Ref AWS::AccountId Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy Outputs: ECSTaskExecutionRoleARN: Description: ARN of the ECS Task Execution Role Value: !GetAtt ECSTaskExecutionRole.Arn Export: Name: !Sub "${AWS::StackName}-ECSTaskExecutionRoleARN" ECSTaskExecutionRoleName: Description: Name of the ECS Task Execution Role Value: !Ref ECSTaskExecutionRole Export: Name: !Sub "${AWS::StackName}-ECSTaskExecutionRoleName"