Pulumi Crosswalk for AWS

Well-Architected Infrastructure as Code for AWS

The easiest way to build modern applications on AWS — from development to production.

Build and deploy modern cloud architectures on AWS quickly using reusable, well-architected patterns with infrastructure as code. Available in TypeScript/JavaScript, Python, Go, .NET, Java, and YAML.

Easiest Way to AWS

Provision services that are Well-Architected by default. Benefit from patterns that worked for customers who have gone to production. Easy to get started, and easy to do the right thing.

Desktop to Production

Best in class productivity means you can rapidly deploy applications and infrastructure, with the confidence that what you build is production ready out-of-the-box.

Use Familiar Languages

Use familiar languages and your favorite tools. Pulumi supports TypeScript/JavaScript, Python, Go, .NET, Java, and YAML.

Modern Architectures like containers and serverless

Get up and running on "day one" with containers -- using Amazon Elastic Container Service (ECS), including "Fargate" or Kubernetes (EKS) -- or serverless -- using AWS Lambda or API Gateway. Benefit from secure and reliable defaults, and customize only where you need to.

With Pulumi's unique approach to infrastructure as code, you'll focus more on code and business logic, and less on DSL configuration languages.

Get Started

"use strict";
const pulumi = require("@pulumi/pulumi");
const aws = require("@pulumi/aws");
const awsx = require("@pulumi/awsx");

const lb = new awsx.lb.ApplicationLoadBalancer("lb");
const cluster = new aws.ecs.Cluster("cluster");

const service = new awsx.ecs.FargateService("service", {
    cluster: cluster.arn,
    assignPublicIp: true,
    desiredCount: 2,
    taskDefinitionArgs: {
        container: {
            name: "my-service",
            image: "nginx:latest",
            cpu: 128,
            memory: 512,
            essential: true,
            portMappings: [
                {
                    containerPort: 80,
                    targetGroup: lb.defaultTargetGroup,
                },
            ],
        },
    },
});

exports.url = pulumi.interpolate`http://${lb.loadBalancer.dnsName}`;
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";

const lb = new awsx.lb.ApplicationLoadBalancer("lb");
const cluster = new aws.ecs.Cluster("cluster");

const service = new awsx.ecs.FargateService("service", {
    cluster: cluster.arn,
    assignPublicIp: true,
    desiredCount: 2,
    taskDefinitionArgs: {
        container: {
            name: "my-service",
            image: "nginx:latest",
            cpu: 128,
            memory: 512,
            essential: true,
            portMappings: [
                {
                    containerPort: 80,
                    targetGroup: lb.defaultTargetGroup,
                },
            ],
        },
    },
});

export const url = pulumi.interpolate`http://${lb.loadBalancer.dnsName}`;
import pulumi
import pulumi_aws as aws
import pulumi_awsx as awsx

lb = awsx.lb.ApplicationLoadBalancer("lb")
cluster = aws.ecs.Cluster("cluster")

service = awsx.ecs.FargateService("service",
    cluster=cluster.arn,
    assign_public_ip=True,
    desired_count=2,
    task_definition_args=awsx.ecs.FargateServiceTaskDefinitionArgs(
        container=awsx.ecs.TaskDefinitionContainerDefinitionArgs(
            name="my-service",
            image="nginx:latest",
            cpu=128,
            memory=512,
            essential=True,
            port_mappings=[awsx.ecs.TaskDefinitionPortMappingArgs(
                container_port=80,
                target_group=lb.default_target_group,
            )],
        ),
    ))

pulumi.export("url", pulumi.Output.concat("http://", lb.load_balancer.dns_name))
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/ecs"
	ecsx "github.com/pulumi/pulumi-awsx/sdk/v2/go/awsx/ecs"
	"github.com/pulumi/pulumi-awsx/sdk/v2/go/awsx/lb"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		lb, err := lb.NewApplicationLoadBalancer(ctx, "lb", nil)
		if err != nil {
			return err
		}

		cluster, err := ecs.NewCluster(ctx, "cluster", nil)
		if err != nil {
			return err
		}

		_, err = ecsx.NewFargateService(ctx, "service", &ecsx.FargateServiceArgs{
			Cluster:        cluster.Arn,
			AssignPublicIp: pulumi.Bool(true),
			DesiredCount:   pulumi.Int(2),
			TaskDefinitionArgs: &ecsx.FargateServiceTaskDefinitionArgs{
				Container: &ecsx.TaskDefinitionContainerDefinitionArgs{
					Name:      pulumi.String("my-service"),
					Image:     pulumi.String("nginx:latest"),
					Cpu:       pulumi.Int(128),
					Memory:    pulumi.Int(512),
					Essential: pulumi.Bool(true),
					PortMappings: ecsx.TaskDefinitionPortMappingArray{
						&ecsx.TaskDefinitionPortMappingArgs{
							ContainerPort: pulumi.Int(80),
							TargetGroup:   lb.DefaultTargetGroup,
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}

		ctx.Export("url", pulumi.Sprintf("http://%s", lb.LoadBalancer.DnsName()))
		return nil
	})
}
using System.Collections.Generic;
using Pulumi;
using Aws = Pulumi.Aws;
using Awsx = Pulumi.Awsx;

return await Deployment.RunAsync(() =>
{
    var lb = new Awsx.Lb.ApplicationLoadBalancer("lb");
    var cluster = new Aws.Ecs.Cluster("cluster");

    var service = new Awsx.Ecs.FargateService("service", new()
    {
        Cluster = cluster.Arn,
        AssignPublicIp = true,
        TaskDefinitionArgs = new Awsx.Ecs.Inputs.FargateServiceTaskDefinitionArgs
        {
            Container = new Awsx.Ecs.Inputs.TaskDefinitionContainerDefinitionArgs
            {
                Name = "my-service",
                Image = "nginx:latest",
                Cpu = 128,
                Memory = 512,
                Essential = true,
                PortMappings = new()
                {
                    new Awsx.Ecs.Inputs.TaskDefinitionPortMappingArgs
                    {
                        ContainerPort = 80,
                        TargetGroup = lb.DefaultTargetGroup,
                    },
                },
            },
        },
    });

    return new Dictionary<string, object?>
    {
        ["url"] = lb.LoadBalancer.Apply(loadBalancer => Output.Format($"http://{loadBalancer.DnsName}")),
    };
});
package myproject;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.awsx.ecr.Repository;
import com.pulumi.awsx.ecr.RepositoryArgs;
import com.pulumi.aws.ecs.Cluster;
import com.pulumi.awsx.lb.ApplicationLoadBalancer;
import com.pulumi.awsx.ecs.FargateService;
import com.pulumi.awsx.ecs.FargateServiceArgs;
import com.pulumi.awsx.ecs.inputs.FargateServiceTaskDefinitionArgs;
import com.pulumi.awsx.ecs.inputs.TaskDefinitionContainerDefinitionArgs;
import com.pulumi.awsx.ecs.inputs.TaskDefinitionPortMappingArgs;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var cluster = new Cluster("cluster");
        var lb = new ApplicationLoadBalancer("lb");

        var service = new FargateService("service", FargateServiceArgs.builder()
            .cluster(cluster.arn())
            .assignPublicIp(true)
            .taskDefinitionArgs(FargateServiceTaskDefinitionArgs.builder()
                .container(TaskDefinitionContainerDefinitionArgs.builder()
                    .name("my-service")
                    .image("nginx:latest")
                    .cpu(128)
                    .memory(512)
                    .essential(true)
                    .portMappings(TaskDefinitionPortMappingArgs.builder()
                        .containerPort(80)
                        .targetGroup(lb.defaultTargetGroup())
                        .build())
                    .build())
                .build())
            .build());

        ctx.export("url", Output.format("http://%s", lb.loadBalancer().applyValue(loadBalancer -> loadBalancer.dnsName())));
    }
}
name: awsx-load-balanced-fargate-nginx-yaml
runtime: yaml
resources:
  lb:
    type: awsx:lb:ApplicationLoadBalancer
  cluster:
    type: aws:ecs:Cluster
  service:
    type: awsx:ecs:FargateService
    properties:
      cluster: ${cluster.arn}
      assignPublicIp: true
      taskDefinitionArgs:
        container:
          name: my-service
          image: "nginx:latest"
          cpu: 128
          memory: 512
          essential: true
          portMappings:
            - containerPort: 80
              targetGroup: ${lb.defaultTargetGroup}
outputs:
  url: http://${lb.loadBalancer.dnsName}

Secure, Scalable, and Observable Architectures

Create, manage, and integrate "day two and beyond" infrastructure for security (e.g., IAM), networking (e.g., VPC), scaling (e.g., Auto Scaling, ELB), and monitoring (e.g., CloudWatch and CloudWatch Logs). Instead of relearning best practices time and time again, use hardened packages that automatically encapsulate Well-Architected patterns and practices.

Pulumi's unique approach to infrastructure as code means you can leverage highly configurable and extensible components to enforce best practices within your team.

Get Started

"use strict";
const pulumi = require("@pulumi/pulumi");
const aws = require("@pulumi/aws");
const awsx = require("@pulumi/awsx");

// Allocate (or get) a custom VPC.
const vpc = new awsx.ec2.Vpc("vpc");

// Create a load balancer in the default VPC listening on port 80.
const alb = new awsx.lb.ApplicationLoadBalancer("lb", {
    listener: {
        port: 80,
    },

    // Associate the load balancer with the VPC's `public` or `private` subnet.
    subnetIds: vpc.publicSubnetIds,
});

// Export the resulting URL so that it's easy to access.
exports.endpoint = alb.loadBalancer.dnsName;
import * as awsx from "@pulumi/awsx";

// Allocate (or get) a custom VPC.
const vpc = new awsx.ec2.Vpc("vpc");

// Create a load balancer in the default VPC listening on port 80.
const alb = new awsx.lb.ApplicationLoadBalancer("lb", {
    listener: {
        port: 80,
    },

    // Associate the load balancer with the VPC's `public` or `private` subnet.
    subnetIds: vpc.publicSubnetIds,
});

// Export the resulting URL so that it's easy to access.
export const endpoint = alb.loadBalancer.dnsName;
import pulumi
import pulumi_awsx as awsx

# Allocate (or get) a custom VPC.
vpc = awsx.ec2.Vpc("vpc");

# Create a load balancer in the default VPC listening on port 80.
alb = awsx.lb.ApplicationLoadBalancer(
    "lb",
    awsx.lb.ApplicationLoadBalancerArgs(
        listener=awsx.lb.ListenerArgs(
            port=80,
        ),

        # Associate the load balancer with the VPC's `public` or `private` subnet.
        subnet_ids=vpc.public_subnet_ids,
    ),
)

# Export the resulting URL so that it's easy to access.
pulumi.export("endpoint", alb.load_balancer.dns_name)
package main

import (
	"github.com/pulumi/pulumi-awsx/sdk/v2/go/awsx/ec2"
	"github.com/pulumi/pulumi-awsx/sdk/v2/go/awsx/lb"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {

		// Allocate (or get) a custom VPC.
		vpc, err := ec2.NewVpc(ctx, "vpc", nil)
		if err != nil {
			return err
		}

		// Create a load balancer in the default VPC listening on port 80.
		alb, err := lb.NewApplicationLoadBalancer(ctx, "lb", &lb.ApplicationLoadBalancerArgs{
			Listener: &lb.ListenerArgs{
				Port: pulumi.Int(80),
			},

			// Associate the load balancer with the VPC's `public` or `private` subnet.
			SubnetIds: vpc.PrivateSubnetIds,
		})
		if err != nil {
			return err
		}

		// Export the resulting URL so that it's easy to access.
		ctx.Export("endpoint", alb.LoadBalancer.DnsName())
		return nil
	})
}
using Pulumi;
using Awsx = Pulumi.Awsx;
using System.Collections.Generic;

return await Deployment.RunAsync(() =>
{
   // Allocate (or get) a custom VPC.
   var vpc = new Awsx.Ec2.Vpc("vpc");

   // Create a load balancer in the default VPC listening on port 80.
   var alb = new Awsx.Lb.ApplicationLoadBalancer("lb", new()
   {
        Listener = new()
        {
            Port = 80,
        },

         // Associate the load balancer with the VPC's `public` or `private` subnet.
        SubnetIds = vpc.PublicSubnetIds,
   });

    // Export the resulting URL so that it's easy to access.
    return new Dictionary<string, object?>
    {
        ["endpoint"] = alb.LoadBalancer.Apply(lb => lb.DnsName),
    };
});
package myproject;

import com.pulumi.Pulumi;
import com.pulumi.awsx.ec2.Vpc;
import com.pulumi.awsx.lb.ApplicationLoadBalancer;
import com.pulumi.awsx.lb.ApplicationLoadBalancerArgs;
import com.pulumi.awsx.lb.inputs.ListenerArgs;

public class App {
    public static void main(String[] args) {
        Pulumi.run(ctx -> {

            // Allocate (or get) a custom VPC.
            var vpc = new Vpc("vpc");

            // Create a load balancer in the default VPC listening on port 80.
            var alb = new ApplicationLoadBalancer("lb", ApplicationLoadBalancerArgs.builder()
                .listener(ListenerArgs.builder()
                    .port(80)
                    .build())

                // Associate the load balancer with the VPC's `public` or `private` subnet.
                .subnetIds(vpc.publicSubnetIds())
                .build());

            // Export the resulting URL so that it's easy to access.
            ctx.export("endpoint", alb.loadBalancer().apply(loadBalancer -> loadBalancer.dnsName()));
        });
    }
}
name: awsx-elb-vpc-yaml
runtime: yaml
description: An example that deploys an ApplicationLoadBalancer in a VPC.

resources:
  # Allocate (or get) a custom VPC.
  vpc:
    type: awsx:ec2:Vpc

  # Create a load balancer in the default VPC listening on port 80.
  alb:
    type: awsx:lb:ApplicationLoadBalancer
    properties:
      listener:
        port: 80

      # Associate the load balancer with the VPC's `public` or `private` subnet.
      subnetIds: ${vpc.publicSubnetIds}

outputs:
  # Export the resulting URL so that it's easy to access.
  endpoint: ${alb.loadBalancer.dnsName}

We've been happily using Pulumi's EKS support for more than three months now. Our team was looking for an end-to-end solution to tame the complexity of Kubernetes on AWS and ensure we adhere to AWS best practices. Pulumi's Crosswalk effort has equipped our team to scale far better than the alternative approaches of home-grown solutions, scripts and DSLs. Our delivery is now automated and we can now deliver new application and infrastructure features with much faster turn-around, sometimes in just a few hours. Pulumi is a key contributor to our team's improvement in productivity.

Pankaj Dhingra

Senior Director of Cloud Engineering