Deploying InvokeAI on AWS ECS with Pulumi

Last updated May 29, 2023

⚠️ This article is a draft and is not yet complete. ⚠️

This article will show how to deploy InvokeAI on AWS with ECS using Pulumi. InvokeAI is a generative AI tool that allows you to generate images.

  • InvokeAI supports deploying with docker containers
  • I wanted to try this but the documentation on how to do this is limited
  • I have been able to set up IvokeAI on AWS by installing it directly via git, doing pip install and following instructions in their documentation
  • I wanted to get more hands-on experience with ECS, GPU instances, EFS, DataSync and Pulumi
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

// Create an ECS cluster
const ecsCluster = new aws.ecs.Cluster("my-ecs-cluster");

// Get the most recent Ubuntu 20.04 LTS image
const ubuntuAmi = pulumi.output(aws.ec2.getAmi({
    filters: [
        {
            name: "name",
            values: ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"],
        },
        {
            name: "virtualization-type",
            values: ["hvm"],
        },
    ],
    owners: ["099720109477"], // Canonical owner ID
    mostRecent: true,
}));

// Create a security group for the cluster
const clusterSecurityGroup = new aws.ec2.SecurityGroup("cluster-security-group", {
    ingress: [
        {
            fromPort: 0,
            toPort: 65535,
            protocol: "tcp",
            cidrBlocks: ["0.0.0.0/0"],
        },
    ],
});

// Create a launch configuration for the ASG
const launchConfiguration = new aws.ec2.LaunchConfiguration("ecs-launch-configuration", {
    imageId: "ami-xxxxxxxxxxxx",
    instanceType: "t2.micro",
    iamInstanceProfile: "<replace-with-your-iam-instance-profile>",
    associatePublicIpAddress: true,
    securityGroups: [clusterSecurityGroup.id],
    userData: `#!/bin/bash
echo ECS_CLUSTER=${ecsCluster.id} >> /etc/ecs/ecs.config`,
});

// Create an Auto Scaling Group
const autoScalingGroup = new aws.autoscaling.Group("ecs-asg", {
    desiredCapacity: 2,
    launchConfiguration: launchConfiguration.id,
    maxSize: 5,
    minSize: 1,
    tags: [
        { key: "Name", value: "my-ecs-asg", propagateAtLaunch: true },
    ],
});

// Create an ECS capacity provider
const capacityProvider = new aws.ecs.CapacityProvider("my-capacity-provider", {
    autoScalingGroupProvider: {
        autoScalingGroupArn: autoScalingGroup.arn,
        managedScaling: {
           : "ENABLED",
            targetCapacity: 75,
        },
        managedTerminationProtection: "ENABLED",
    },
});

// Add the capacity provider to the ECS cluster
const clusterCapacityProvider = new aws.ecs.ClusterCapacityProviders("ecs-cluster-capacity-providers", {
    capacityProviders: [capacityProvider.name],
    clusterName: ecsCluster.name,
});

// Export ECS cluster name
export const ecsClusterName = ecsCluster.name;
const targets = [];
for (let i = 0; i < subnetIds.length; i++) {
    targets.push(new aws.efs.MountTarget(`fs-mount-${i}`, {
        fileSystemId: filesystem.id,
        subnetId: subnetIds[i],
        securityGroups: [vpc.vpc.defaultSecurityGroupId],
    }));
}
const ap = new aws.efs.AccessPoint("ap", {
    fileSystemId: filesystem.id,
    posixUser: { uid: 1000, gid: 1000 },
    rootDirectory: { path: "/www", creationInfo: { ownerGid: 1000, ownerUid: 1000, permissions: "755" } },
}, { dependsOn: targets });


Join my mailing list to get updated whenever I publish a new article.

Thanks for checking out my site!
© 2024 Brian Caffey