UNPKG

aws-cdk-lib

Version:

Version 2 of the AWS Cloud Development Kit library

1,153 lines (997 loc) 34.9 kB
# CDK Construct library for higher-level ECS Constructs This library provides higher-level Amazon ECS constructs which follow common architectural patterns. It contains: * Application Load Balanced Services * Network Load Balanced Services * Queue Processing Services * Scheduled Tasks (cron jobs) * Additional Examples ## Application Load Balanced Services To define an Amazon ECS service that is behind an application load balancer, instantiate one of the following: * `ApplicationLoadBalancedEc2Service` ```ts declare const cluster: ecs.Cluster; const loadBalancedEcsService = new ecsPatterns.ApplicationLoadBalancedEc2Service(this, 'Service', { cluster, memoryLimitMiB: 1024, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('test'), environment: { TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value", }, command: ['command'], entryPoint: ['entry', 'point'], }, desiredCount: 2, }); ``` * `ApplicationLoadBalancedFargateService` ```ts declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), command: ['command'], entryPoint: ['entry', 'point'], }, }); loadBalancedFargateService.targetGroup.configureHealthCheck({ path: "/custom-health-path", }); ``` Instead of providing a cluster you can specify a VPC and CDK will create a new ECS cluster. If you deploy multiple services CDK will only create one cluster per VPC. You can omit `cluster` and `vpc` to let CDK create a new VPC with two AZs and create a cluster inside this VPC. You can customize the health check for your target group; otherwise it defaults to `HTTP` over port `80` hitting path `/`. You can customize the health check configuration of the container via the [`healthCheck`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.HealthCheck.html) property; otherwise it defaults to the health check configuration from the container. Fargate services will use the `LATEST` platform version by default, but you can override by providing a value for the `platformVersion` property in the constructor. Fargate services use the default VPC Security Group unless one or more are provided using the `securityGroups` property in the constructor. By setting `redirectHTTP` to true, CDK will automatically create a listener on port 80 that redirects HTTP traffic to the HTTPS port. If you specify the option `recordType` you can decide if you want the construct to use CNAME or Route53-Aliases as record sets. If you need to encrypt the traffic between the load balancer and the ECS tasks, you can set the `targetProtocol` to `HTTPS`. Additionally, if more than one application target group are needed, instantiate one of the following: * `ApplicationMultipleTargetGroupsEc2Service` ```ts // One application load balancer with one listener and two target groups. declare const cluster: ecs.Cluster; const loadBalancedEc2Service = new ecsPatterns.ApplicationMultipleTargetGroupsEc2Service(this, 'Service', { cluster, memoryLimitMiB: 256, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, targetGroups: [ { containerPort: 80, }, { containerPort: 90, pathPattern: 'a/b/c', priority: 10, }, ], }); ``` * `ApplicationMultipleTargetGroupsFargateService` ```ts // One application load balancer with one listener and two target groups. declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.ApplicationMultipleTargetGroupsFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, targetGroups: [ { containerPort: 80, }, { containerPort: 90, pathPattern: 'a/b/c', priority: 10, }, ], }); ``` ## Network Load Balanced Services To define an Amazon ECS service that is behind a network load balancer, instantiate one of the following: * `NetworkLoadBalancedEc2Service` ```ts declare const cluster: ecs.Cluster; const loadBalancedEcsService = new ecsPatterns.NetworkLoadBalancedEc2Service(this, 'Service', { cluster, memoryLimitMiB: 1024, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('test'), environment: { TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value", }, }, desiredCount: 2, }); ``` * `NetworkLoadBalancedFargateService` ```ts declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.NetworkLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, }); ``` The CDK will create a new Amazon ECS cluster if you specify a VPC and omit `cluster`. If you deploy multiple services the CDK will only create one cluster per VPC. If `cluster` and `vpc` are omitted, the CDK creates a new VPC with subnets in two Availability Zones and a cluster within this VPC. If you specify the option `recordType` you can decide if you want the construct to use CNAME or Route53-Aliases as record sets. Additionally, if more than one network target group is needed, instantiate one of the following: * NetworkMultipleTargetGroupsEc2Service ```ts // Two network load balancers, each with their own listener and target group. declare const cluster: ecs.Cluster; const loadBalancedEc2Service = new ecsPatterns.NetworkMultipleTargetGroupsEc2Service(this, 'Service', { cluster, memoryLimitMiB: 256, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, loadBalancers: [ { name: 'lb1', listeners: [ { name: 'listener1', }, ], }, { name: 'lb2', listeners: [ { name: 'listener2', }, ], }, ], targetGroups: [ { containerPort: 80, listener: 'listener1', }, { containerPort: 90, listener: 'listener2', }, ], }); ``` * NetworkMultipleTargetGroupsFargateService ```ts // Two network load balancers, each with their own listener and target group. declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.NetworkMultipleTargetGroupsFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, loadBalancers: [ { name: 'lb1', listeners: [ { name: 'listener1', }, ], }, { name: 'lb2', listeners: [ { name: 'listener2', }, ], }, ], targetGroups: [ { containerPort: 80, listener: 'listener1', }, { containerPort: 90, listener: 'listener2', }, ], }); ``` ## Queue Processing Services To define a service that creates a queue and reads from that queue, instantiate one of the following: * `QueueProcessingEc2Service` ```ts declare const cluster: ecs.Cluster; const queueProcessingEc2Service = new ecsPatterns.QueueProcessingEc2Service(this, 'Service', { cluster, memoryLimitMiB: 1024, image: ecs.ContainerImage.fromRegistry('test'), command: ["-c", "4", "amazon.com"], enableLogging: false, desiredTaskCount: 2, environment: { TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value", }, maxScalingCapacity: 5, containerName: 'test', }); ``` * `QueueProcessingFargateService` ```ts declare const cluster: ecs.Cluster; const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), command: ["-c", "4", "amazon.com"], enableLogging: false, desiredTaskCount: 2, environment: { TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value", }, maxScalingCapacity: 5, containerName: 'test', }); ``` when queue not provided by user, CDK will create a primary queue and a dead letter queue with default redrive policy and attach permission to the task to be able to access the primary queue. NOTE: `QueueProcessingFargateService` adds a CPU Based scaling strategy by default. You can turn this off by setting `disableCpuBasedScaling: true`. ```ts declare const cluster: ecs.Cluster; const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), command: ["-c", "4", "amazon.com"], enableLogging: false, desiredTaskCount: 2, environment: { TEST_ENVIRONMENT_VARIABLE1: "test environment variable 1 value", TEST_ENVIRONMENT_VARIABLE2: "test environment variable 2 value", }, maxScalingCapacity: 5, containerName: 'test', disableCpuBasedScaling: true, }); ``` To specify a custom target CPU utilization percentage for the scaling strategy use the `cpuTargetUtilizationPercent` property: ```ts declare const cluster: ecs.Cluster; const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), command: ["-c", "4", "amazon.com"], enableLogging: false, desiredTaskCount: 2, environment: {}, maxScalingCapacity: 5, containerName: 'test', cpuTargetUtilizationPercent: 90, }); ``` ## Scheduled Tasks To define a task that runs periodically, there are 2 options: * `ScheduledEc2Task` ```ts // Instantiate an Amazon EC2 Task to run at a scheduled interval declare const cluster: ecs.Cluster; const ecsScheduledTask = new ecsPatterns.ScheduledEc2Task(this, 'ScheduledTask', { cluster, scheduledEc2TaskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), memoryLimitMiB: 256, environment: { name: 'TRIGGER', value: 'CloudWatch Events' }, }, schedule: appscaling.Schedule.expression('rate(1 minute)'), enabled: true, ruleName: 'sample-scheduled-task-rule', }); ``` * `ScheduledFargateTask` ```ts declare const cluster: ecs.Cluster; const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'ScheduledFargateTask', { cluster, scheduledFargateTaskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), memoryLimitMiB: 512, }, schedule: appscaling.Schedule.expression('rate(1 minute)'), platformVersion: ecs.FargatePlatformVersion.LATEST, }); ``` ## Additional Examples In addition to using the constructs, users can also add logic to customize these constructs: ### Configure HTTPS on an ApplicationLoadBalancedFargateService ```ts import { HostedZone } from 'aws-cdk-lib/aws-route53'; import { Certificate } from 'aws-cdk-lib/aws-certificatemanager'; import { SslPolicy } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; const domainZone = HostedZone.fromLookup(this, 'Zone', { domainName: 'example.com' }); const certificate = Certificate.fromCertificateArn(this, 'Cert', 'arn:aws:acm:us-east-1:123456:certificate/abcdefg'); declare const vpc: ec2.Vpc; declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { vpc, cluster, certificate, sslPolicy: SslPolicy.RECOMMENDED, domainName: 'api.example.com', domainZone, redirectHTTP: true, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, }); ``` ### Set capacityProviderStrategies for ApplicationLoadBalancedFargateService ```ts declare const cluster: ecs.Cluster; cluster.enableFargateCapacityProviders(); const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, capacityProviderStrategies: [ { capacityProvider: 'FARGATE_SPOT', weight: 2, base: 0, }, { capacityProvider: 'FARGATE', weight: 1, base: 1, }, ], }); ``` ### Add Schedule-Based Auto-Scaling to an ApplicationLoadBalancedFargateService ```ts declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, }); const scalableTarget = loadBalancedFargateService.service.autoScaleTaskCount({ minCapacity: 5, maxCapacity: 20, }); scalableTarget.scaleOnSchedule('DaytimeScaleDown', { schedule: appscaling.Schedule.cron({ hour: '8', minute: '0'}), minCapacity: 1, }); scalableTarget.scaleOnSchedule('EveningRushScaleUp', { schedule: appscaling.Schedule.cron({ hour: '20', minute: '0'}), minCapacity: 10, }); ``` ### Add Metric-Based Auto-Scaling to an ApplicationLoadBalancedFargateService ```ts declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, }); const scalableTarget = loadBalancedFargateService.service.autoScaleTaskCount({ minCapacity: 1, maxCapacity: 20, }); scalableTarget.scaleOnCpuUtilization('CpuScaling', { targetUtilizationPercent: 50, }); scalableTarget.scaleOnMemoryUtilization('MemoryScaling', { targetUtilizationPercent: 50, }); ``` ### Change the default Deployment Controller ```ts declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, deploymentController: { type: ecs.DeploymentControllerType.CODE_DEPLOY, }, }); ``` ### Deployment circuit breaker and rollback Amazon ECS [deployment circuit breaker](https://aws.amazon.com/tw/blogs/containers/announcing-amazon-ecs-deployment-circuit-breaker/) automatically rolls back unhealthy service deployments without the need for manual intervention. Use `circuitBreaker` to enable deployment circuit breaker and optionally enable `rollback` for automatic rollback. See [Using the deployment circuit breaker](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-type-ecs.html) for more details. ```ts declare const cluster: ecs.Cluster; const service = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, circuitBreaker: { rollback: true }, }); ``` ### Set deployment configuration on QueueProcessingService ```ts declare const cluster: ecs.Cluster; const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), command: ["-c", "4", "amazon.com"], enableLogging: false, desiredTaskCount: 2, environment: {}, maxScalingCapacity: 5, maxHealthyPercent: 200, minHealthyPercent: 66, }); ``` ### Set taskSubnets and securityGroups for QueueProcessingFargateService ```ts declare const vpc: ec2.Vpc; declare const securityGroup: ec2.SecurityGroup; const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { vpc, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), securityGroups: [securityGroup], taskSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, }); ``` ### Define tasks with public IPs for QueueProcessingFargateService ```ts declare const vpc: ec2.Vpc; const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { vpc, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), assignPublicIp: true, }); ``` ### Define tasks with custom queue parameters for QueueProcessingFargateService ```ts declare const vpc: ec2.Vpc; const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { vpc, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), maxReceiveCount: 42, retentionPeriod: Duration.days(7), visibilityTimeout: Duration.minutes(5), }); ``` ### Set cooldown for QueueProcessingFargateService The cooldown period is the amount of time to wait for a previous scaling activity to take effect. To specify something other than the default cooldown period of 300 seconds, use the `cooldown` parameter: ```ts declare const vpc: ec2.Vpc; const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { vpc, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), assignPublicIp: true, cooldown: Duration.seconds(500), }); ``` ### Set capacityProviderStrategies for QueueProcessingFargateService ```ts declare const cluster: ecs.Cluster; cluster.enableFargateCapacityProviders(); const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), capacityProviderStrategies: [ { capacityProvider: 'FARGATE_SPOT', weight: 2, }, { capacityProvider: 'FARGATE', weight: 1, }, ], }); ``` ### Set a custom container-level Healthcheck for QueueProcessingFargateService ```ts declare const vpc: ec2.Vpc; declare const securityGroup: ec2.SecurityGroup; const queueProcessingFargateService = new ecsPatterns.QueueProcessingFargateService(this, 'Service', { vpc, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), healthCheck: { command: [ "CMD-SHELL", "curl -f http://localhost/ || exit 1" ], // the properties below are optional interval: Duration.minutes(30), retries: 123, startPeriod: Duration.minutes(30), timeout: Duration.minutes(30), }, }); ``` ### Set capacityProviderStrategies for QueueProcessingEc2Service ```ts import * as autoscaling from 'aws-cdk-lib/aws-autoscaling'; const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 1 }); const cluster = new ecs.Cluster(this, 'EcsCluster', { vpc }); const autoScalingGroup = new autoscaling.AutoScalingGroup(this, 'asg', { vpc, instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), machineImage: ecs.EcsOptimizedImage.amazonLinux2(), }); const capacityProvider = new ecs.AsgCapacityProvider(this, 'provider', { autoScalingGroup, }); cluster.addAsgCapacityProvider(capacityProvider); const queueProcessingEc2Service = new ecsPatterns.QueueProcessingEc2Service(this, 'Service', { cluster, memoryLimitMiB: 512, image: ecs.ContainerImage.fromRegistry('test'), capacityProviderStrategies: [ { capacityProvider: capacityProvider.capacityProviderName, }, ], }); ``` ### Select specific vpc subnets for ApplicationLoadBalancedFargateService ```ts declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, taskSubnets: { subnets: [ec2.Subnet.fromSubnetId(this, 'subnet', 'VpcISOLATEDSubnet1Subnet80F07FA0')], }, }); ``` ### Select idleTimeout for ApplicationLoadBalancedFargateService ```ts declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, idleTimeout: Duration.seconds(120), }); ``` ### Select idleTimeout for ApplicationMultipleTargetGroupsFargateService ```ts import { Certificate } from 'aws-cdk-lib/aws-certificatemanager'; import { InstanceType } from 'aws-cdk-lib/aws-ec2'; import { Cluster, ContainerImage } from 'aws-cdk-lib/aws-ecs'; import { ApplicationProtocol, SslPolicy } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { PublicHostedZone } from 'aws-cdk-lib/aws-route53'; const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 1 }); const loadBalancedFargateService = new ecsPatterns.ApplicationMultipleTargetGroupsFargateService(this, 'myService', { cluster: new ecs.Cluster(this, 'EcsCluster', { vpc }), memoryLimitMiB: 256, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), }, enableExecuteCommand: true, loadBalancers: [ { name: 'lb', idleTimeout: Duration.seconds(400), domainName: 'api.example.com', domainZone: new PublicHostedZone(this, 'HostedZone', { zoneName: 'example.com' }), listeners: [ { name: 'listener', protocol: ApplicationProtocol.HTTPS, certificate: Certificate.fromCertificateArn(this, 'Cert', 'helloworld'), sslPolicy: SslPolicy.TLS12_EXT, }, ], }, { name: 'lb2', idleTimeout: Duration.seconds(120), domainName: 'frontend.com', domainZone: new PublicHostedZone(this, 'HostedZone', { zoneName: 'frontend.com' }), listeners: [ { name: 'listener2', protocol: ApplicationProtocol.HTTPS, certificate: Certificate.fromCertificateArn(this, 'Cert2', 'helloworld'), sslPolicy: SslPolicy.TLS12_EXT, }, ], }, ], targetGroups: [ { containerPort: 80, listener: 'listener', }, { containerPort: 90, pathPattern: 'a/b/c', priority: 10, listener: 'listener', }, { containerPort: 443, listener: 'listener2', }, { containerPort: 80, pathPattern: 'a/b/c', priority: 10, listener: 'listener2', }, ], }); ``` ### Set health checks for ApplicationMultipleTargetGroupsFargateService ```ts import { Certificate } from 'aws-cdk-lib/aws-certificatemanager'; import { InstanceType } from 'aws-cdk-lib/aws-ec2'; import { Cluster, ContainerImage } from 'aws-cdk-lib/aws-ecs'; import { ApplicationProtocol,Protocol, SslPolicy } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { PublicHostedZone } from 'aws-cdk-lib/aws-route53'; const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 1 }); const loadBalancedFargateService = new ecsPatterns.ApplicationMultipleTargetGroupsFargateService(this, 'myService', { cluster: new ecs.Cluster(this, 'EcsCluster', { vpc }), memoryLimitMiB: 256, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), }, enableExecuteCommand: true, loadBalancers: [ { name: 'lb', idleTimeout: Duration.seconds(400), domainName: 'api.example.com', domainZone: new PublicHostedZone(this, 'HostedZone', { zoneName: 'example.com' }), listeners: [ { name: 'listener', protocol: ApplicationProtocol.HTTPS, certificate: Certificate.fromCertificateArn(this, 'Cert', 'helloworld'), sslPolicy: SslPolicy.TLS12_EXT, }, ], }, { name: 'lb2', idleTimeout: Duration.seconds(120), domainName: 'frontend.com', domainZone: new PublicHostedZone(this, 'HostedZone', { zoneName: 'frontend.com' }), listeners: [ { name: 'listener2', protocol: ApplicationProtocol.HTTPS, certificate: Certificate.fromCertificateArn(this, 'Cert2', 'helloworld'), sslPolicy: SslPolicy.TLS12_EXT, }, ], }, ], targetGroups: [ { containerPort: 80, listener: 'listener', }, { containerPort: 90, pathPattern: 'a/b/c', priority: 10, listener: 'listener', }, { containerPort: 443, listener: 'listener2', }, { containerPort: 80, pathPattern: 'a/b/c', priority: 10, listener: 'listener2', }, ], }); loadBalancedFargateService.targetGroups[0].configureHealthCheck({ port: '8050', protocol: Protocol.HTTP, healthyThresholdCount: 2, unhealthyThresholdCount: 2, timeout: Duration.seconds(10), interval: Duration.seconds(30), healthyHttpCodes: '200', }); loadBalancedFargateService.targetGroups[1].configureHealthCheck({ port: '8050', protocol: Protocol.HTTP, healthyThresholdCount: 2, unhealthyThresholdCount: 2, timeout: Duration.seconds(10), interval: Duration.seconds(30), healthyHttpCodes: '200', }); ``` ### Set runtimePlatform for ApplicationLoadBalancedFargateService ```ts declare const cluster: ecs.Cluster; const applicationLoadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), }, runtimePlatform: { cpuArchitecture: ecs.CpuArchitecture.ARM64, operatingSystemFamily: ecs.OperatingSystemFamily.LINUX, }, }); ``` ### Customize Container Name for ScheduledFargateTask ```ts declare const cluster: ecs.Cluster; const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'ScheduledFargateTask', { cluster, scheduledFargateTaskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), containerName: 'customContainerName', memoryLimitMiB: 512, }, schedule: appscaling.Schedule.expression('rate(1 minute)'), platformVersion: ecs.FargatePlatformVersion.LATEST, }); ``` ### Customize Container Name for ScheduledEc2Task ```ts declare const cluster: ecs.Cluster; const ecsScheduledTask = new ecsPatterns.ScheduledEc2Task(this, 'ScheduledTask', { cluster, scheduledEc2TaskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), containerName: 'customContainerName', memoryLimitMiB: 256, environment: { name: 'TRIGGER', value: 'CloudWatch Events' }, }, schedule: appscaling.Schedule.expression('rate(1 minute)'), enabled: true, ruleName: 'sample-scheduled-task-rule', }); ``` ### Set PlatformVersion for ScheduledFargateTask ```ts declare const cluster: ecs.Cluster; const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'ScheduledFargateTask', { cluster, scheduledFargateTaskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), memoryLimitMiB: 512, }, schedule: appscaling.Schedule.expression('rate(1 minute)'), platformVersion: ecs.FargatePlatformVersion.VERSION1_4, }); ``` ### Set SecurityGroups for ScheduledFargateTask ```ts const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 1 }); const cluster = new ecs.Cluster(this, 'EcsCluster', { vpc }); const securityGroup = new ec2.SecurityGroup(this, 'SG', { vpc }); const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'ScheduledFargateTask', { cluster, scheduledFargateTaskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), memoryLimitMiB: 512, }, schedule: appscaling.Schedule.expression('rate(1 minute)'), securityGroups: [securityGroup], }); ``` ### Deploy application and metrics sidecar The following is an example of deploying an application along with a metrics sidecar container that utilizes `dockerLabels` for discovery: ```ts declare const cluster: ecs.Cluster; declare const vpc: ec2.Vpc; const service = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, vpc, desiredCount: 1, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), dockerLabels: { 'application.label.one': 'first_label', 'application.label.two': 'second_label', }, }, }); service.taskDefinition.addContainer('Sidecar', { image: ecs.ContainerImage.fromRegistry('example/metrics-sidecar'), }); ``` ### Select specific load balancer name ApplicationLoadBalancedFargateService ```ts declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, taskSubnets: { subnets: [ec2.Subnet.fromSubnetId(this, 'subnet', 'VpcISOLATEDSubnet1Subnet80F07FA0')], }, loadBalancerName: 'application-lb-name', }); ``` ### ECS Exec You can use ECS Exec to run commands in or get a shell to a container running on an Amazon EC2 instance or on AWS Fargate. Enable ECS Exec, by setting `enableExecuteCommand` to `true`. ECS Exec is supported by all Services i.e. `ApplicationLoadBalanced(Fargate|Ec2)Service`, `ApplicationMultipleTargetGroups(Fargate|Ec2)Service`, `NetworkLoadBalanced(Fargate|Ec2)Service`, `NetworkMultipleTargetGroups(Fargate|Ec2)Service`, `QueueProcessing(Fargate|Ec2)Service`. It is not supported for `ScheduledTask`s. Read more about ECS Exec in the [ECS Developer Guide](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html). Example: ```ts declare const cluster: ecs.Cluster; const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { cluster, memoryLimitMiB: 1024, desiredCount: 1, cpu: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, enableExecuteCommand: true }); ``` Please note, ECS Exec leverages AWS Systems Manager (SSM). So as a prerequisite for the exec command to work, you need to have the SSM plugin for the AWS CLI installed locally. For more information, see [Install Session Manager plugin for AWS CLI](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html). ### Propagate Tags from task definition for ScheduledFargateTask For tasks that are defined by a Task Definition, tags applied to the definition will not be applied to the running task by default. To get this behavior, set `propagateTags` to `ecs.PropagatedTagSource.TASK_DEFINITION` as shown below: ```ts import { Tags } from 'aws-cdk-lib'; const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 1 }); const cluster = new ecs.Cluster(this, 'EcsCluster', { vpc }); const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef', { memoryLimitMiB: 512, cpu: 256, }); taskDefinition.addContainer("WebContainer", { image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }); Tags.of(taskDefinition).add('my-tag', 'my-tag-value') const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'ScheduledFargateTask', { cluster, taskDefinition: taskDefinition, schedule: appscaling.Schedule.expression('rate(1 minute)'), propagateTags: ecs.PropagatedTagSource.TASK_DEFINITION, }); ``` ### Pass a list of tags for ScheduledFargateTask You can pass a list of tags to be applied to a Fargate task directly. These tags are in addition to any tags that could be applied to the task definition and propagated using the `propagateTags` attribute. ```ts const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 1 }); const cluster = new ecs.Cluster(this, 'EcsCluster', { vpc }); const scheduledFargateTask = new ecsPatterns.ScheduledFargateTask(this, 'ScheduledFargateTask', { cluster, scheduledFargateTaskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), memoryLimitMiB: 512, }, schedule: appscaling.Schedule.expression('rate(1 minute)'), tags: [ { key: 'my-tag', value: 'my-tag-value', }, ], }); ``` ### Use custom ephemeral storage for ECS Fargate tasks You can pass a custom ephemeral storage (21GiB - 200GiB) to ECS Fargate tasks on Fargate Platform Version 1.4.0 or later. ```ts const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 2, restrictDefaultSecurityGroup: false }); const cluster = new ecs.Cluster(this, 'FargateCluster', { vpc }); const applicationLoadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'ALBFargateServiceWithCustomEphemeralStorage', { cluster, memoryLimitMiB: 1024, cpu: 512, ephemeralStorageGiB: 21, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), }, }); const networkLoadBalancedFargateService = new ecsPatterns.NetworkLoadBalancedFargateService(this, 'NLBFargateServiceWithCustomEphemeralStorage', { cluster, memoryLimitMiB: 1024, cpu: 512, ephemeralStorageGiB: 200, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), }, }); ``` ### Set securityGroups for NetworkLoadBalancedFargateService ```ts declare const vpc: ec2.Vpc; declare const securityGroup: ec2.SecurityGroup; const queueProcessingFargateService = new ecsPatterns.NetworkLoadBalancedFargateService(this, 'Service', { vpc, memoryLimitMiB: 512, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), }, securityGroups: [securityGroup], }); ``` ### Use dualstack NLB ```ts import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2'; // The VPC and subnet must have associated IPv6 CIDR blocks. const vpc = new ec2.Vpc(this, 'Vpc', { ipProtocol: ec2.IpProtocol.DUAL_STACK, }); const cluster = new ecs.Cluster(this, 'EcsCluster', { vpc }); const networkLoadbalancedFargateService = new ecsPatterns.NetworkLoadBalancedFargateService(this, 'NlbFargateService', { cluster, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), }, ipAddressType: elbv2.IpAddressType.DUAL_STACK, }); const networkLoadbalancedEc2Service = new ecsPatterns.NetworkLoadBalancedEc2Service(this, 'NlbEc2Service', { cluster, taskImageOptions: { image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), }, ipAddressType: elbv2.IpAddressType.DUAL_STACK, }); ```