Update CDK project

Open NorthwindCdk.sln in Visual Studio.

Add following Nuget packages to the project:

  • Amazon.CDK.AWS.ECS
  • Amazon.CDK.AWS.ECS.Patterns

Nuget Nuget

Amazon.CDK.AWS.ECS.Patterns 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)

In your code you are going to use ApplicationLoadBalancedFargateService construct: a Fargate service running on an ECS cluster fronted by an application load balancer.

Open NorthwindCdkStack.cs.

Add following using statements:

using Amazon.CDK.AWS.ApplicationAutoScaling;
using Amazon.CDK.AWS.ECS;
using Amazon.CDK.AWS.ECS.Patterns;
using Amazon.CDK.AWS.IAM;

Please add the following changes at the end of NorthwindCdkStack constructor:

namespace NorthwindCdk
{
    public class NorthwindCdkStack : Stack
    {
        internal NorthwindCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            .......

            // ECS

            var cluster = new Cluster(this, "NorthwindCluster", new ClusterProps
            {
                Vpc = vpc,
                ClusterName = "NorthwindCluster"
            });
    
            // Create AWS Fargate service
            var fargateService = new ApplicationLoadBalancedFargateService(this, "NorthwindService", new ApplicationLoadBalancedFargateServiceProps
            {
                ServiceName = "NorthwindService",
                Cluster = cluster,
                TaskImageOptions = new ApplicationLoadBalancedTaskImageOptions
                {
                    Image = ContainerImage.FromEcrRepository(containerRegistry, "Latest"),
                    EnableLogging = true
                },
                PublicLoadBalancer = true
            });

            // Allow task to access Systems Manager Parameter Store
            fargateService.TaskDefinition.TaskRole.AddManagedPolicy(ManagedPolicy.FromManagedPolicyArn(this, "NorthwindTaskPolicy", "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"));

            // Allow task security group to access PostgreSQL database
            sg.Connections.AllowFrom(fargateService.Service, Port.Tcp(5432), "Allow container to access DB");

            // Setup AutoScaling policy
            var scaling = fargateService.Service.AutoScaleTaskCount(new EnableScalingProps { MaxCapacity = 2 });

            scaling.ScaleOnCpuUtilization("CpuScaling", new CpuUtilizationScalingProps
            {
                TargetUtilizationPercent = 50,
                ScaleInCooldown = Duration.Seconds(60),
                ScaleOutCooldown = Duration.Seconds(60)
            });

        }
    }
}

The code above is quite long and it does the following:

  • Creates new Amazon ECS cluster
  • Creates new AWS Fargate Service behind Application Load Balancer.
  • Uses container image that was published to Amazon ECR by your CI/CD pipeline.
Image = ContainerImage.FromEcrRepository(containerRegistry, "Latest")
  • Adds managed policy to the Task Role that allows access to AWS Systems Manager Parameter Store
fargateService.TaskDefinition.TaskRole.AddManagedPolicy(ManagedPolicy.FromManagedPolicyArn(this, "NorthwindTaskPolicy", "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"));
  • Updates database security group to allow connections from AWS Fargate security group
sg.Connections.AllowFrom(fargateService.Service, Port.Tcp(5432), "Allow container to access DB");
  • Set up autoscaling policy
var scaling = fargateService.Service.AutoScaleTaskCount(new EnableScalingProps { MaxCapacity = 2 });

scaling.ScaleOnCpuUtilization("CpuScaling", new CpuUtilizationScalingProps
{
    TargetUtilizationPercent = 50,
    ScaleInCooldown = Duration.Seconds(60),
    ScaleOutCooldown = Duration.Seconds(60)
});