1. Using aws ecs with autoscaling

    TypeScript

    To create an AWS ECS (Elastic Container Service) environment with autoscaling, you need to set up several components:

    1. ECS Cluster: This is a logical grouping of ECS tasks and services. It is required for running tasks and services.

    2. ECS Task Definition: This defines your application by specifying the Docker container image to use, the CPU and memory allocations, and other configurations such as environment variables and logging.

    3. ECS Service: This maintains a specified number of instances of the task definition in the ECS cluster. If any tasks fail, the service scheduler launches new tasks.

    4. Application Load Balancer (ALB): This distributes incoming application traffic across multiple targets, such as ECS tasks, in multiple Availability Zones.

    5. Auto Scaling: This automatically adjusts the number of running ECS tasks in response to the specified traffic for your application.

    Here's a Pulumi TypeScript program that sets up an ECS environment with autoscaling:

    import * as pulumi from "@pulumi/pulumi"; import * as aws from "@pulumi/aws"; import * as awsx from "@pulumi/awsx"; // Create an ECS cluster const cluster = new aws.ecs.Cluster("app-cluster", {}); // Reference for the IAM role required by ECS Task const taskExecRole = new aws.iam.Role("task-exec-role", { assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({ Service: "ecs-tasks.amazonaws.com", }), }); new aws.iam.RolePolicyAttachment("task-exec-policy", { role: taskExecRole, policyArn: "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy", }); // Create a Task Definition for the ECS service const appTask = new awsx.ecs.FargateTaskDefinition("app-task", { taskRole: taskExecRole, containers: { app: { image: "my-app-container-image", // Replace with your Docker image URL memory: 512, portMappings: [new awsx.ecs.FargateServicePortMappingArgs({ containerPort: 80, // Create ALB to listen to HTTP traffic on port 80 newTargetGroup: { port: 80, protocol: "HTTP", }, })], }, }, }); // Create an ECS service const appService = new awsx.ecs.FargateService("app-service", { cluster: cluster.arn, taskDefinition: appTask.taskDefinition, desiredCount: 2, // Start with two tasks }); // Enable auto-scaling for the service, which will adjust the number of tasks // Modify the targetValue to the correct threshold for scaling (e.g., average CPU usage) const scalableTarget = new aws.appautoscaling.Target("autoscaling-target", { resourceId: pulumi.interpolate`service/${cluster.name}/${appService.service.name}`, serviceNamespace: "ecs", scalableDimension: "ecs:service:DesiredCount", minCapacity: 1, // Minimum number of tasks maxCapacity: 4, // Maximum number of tasks }); new aws.appautoscaling.Policy("autoscaling-policy", { policyType: "TargetTrackingScaling", resourceId: scalableTarget.resourceId, scalableDimension: scalableTarget.scalableDimension, serviceNamespace: scalableTarget.serviceNamespace, targetTrackingScalingPolicyConfiguration: { targetValue: 70.0, // Target task CPU utilization (70% in this case) predefinedMetricSpecification: { // ECS tasks metric predefinedMetricType: "ECSServiceAverageCPUUtilization", } }, }); // Export the URLs of the service export const url = appService.taskDefinition.containers.app.portMappings.apply(pm => pm ? pm[0].targetGroup.loadBalancer.listeners.apply(l => l[0].endpoint.endpoint) : "<no url>" );

    This program does the following:

    • Defines an ECS cluster to host our services.
    • Creates an IAM role for tasks to execute with the necessary permissions.
    • Sets up a task definition with a specified Docker image and container configurations.
    • Configures a service that specifies how many instances of our task definition should run and be maintained in our ECS cluster.
    • Attaches an application load balancer to the service traffic on port 80.
    • Sets up autoscaling for this service, with a TargetTrackingScaling policy based on average CPU usage.

    Make sure to replace "my-app-container-image" with the actual Docker image URL you intend to use.

    The program exports the service URL for easy access after deployment. Deploy these resources using Pulumi's CLI, and it will handle provisioning the resources in the correct order with the right configurations.