Claude
Skills
Sign in
Back

pulumi-stacks

Included with Lifetime
$97 forever

Use when managing multiple environments with Pulumi stacks for development, staging, and production deployments.

General

What this skill does


# Pulumi Stacks

Manage multiple environments and configurations with Pulumi stacks for consistent infrastructure across development, staging, and production.

## Overview

Pulumi stacks are isolated, independently configurable instances of a Pulumi program. Each stack has its own state, configuration, and resources, enabling you to deploy the same infrastructure code to multiple environments.

## Stack Basics

### Creating and Selecting Stacks

```bash
# Initialize a new project
pulumi new aws-typescript

# Create a new stack
pulumi stack init dev

# List all stacks
pulumi stack ls

# Select a stack
pulumi stack select dev

# Show current stack
pulumi stack

# Remove a stack
pulumi stack rm dev
```

### Stack Configuration

```bash
# Set configuration values
pulumi config set aws:region us-east-1
pulumi config set instanceType t3.micro

# Set secret values (encrypted)
pulumi config set --secret dbPassword mySecurePassword123

# Get configuration values
pulumi config get aws:region

# List all configuration
pulumi config

# Remove configuration
pulumi config rm instanceType
```

## Stack Configuration Files

### Pulumi.yaml (Project File)

```yaml
name: my-infrastructure
user-invocable: false
runtime: nodejs
description: Multi-environment infrastructure

config:
  aws:region:
    description: AWS region for deployment
    default: us-east-1
  instanceType:
    description: EC2 instance type
    default: t3.micro
  environment:
    description: Environment name
```

### Pulumi.dev.yaml (Stack Config)

```yaml
config:
  aws:region: us-east-1
  my-infrastructure:instanceType: t3.micro
  my-infrastructure:environment: development
  my-infrastructure:minSize: "1"
  my-infrastructure:maxSize: "3"
  my-infrastructure:enableMonitoring: "false"
```

### Pulumi.staging.yaml

```yaml
config:
  aws:region: us-east-1
  my-infrastructure:instanceType: t3.small
  my-infrastructure:environment: staging
  my-infrastructure:minSize: "2"
  my-infrastructure:maxSize: "5"
  my-infrastructure:enableMonitoring: "true"
```

### Pulumi.prod.yaml

```yaml
config:
  aws:region: us-west-2
  my-infrastructure:instanceType: t3.medium
  my-infrastructure:environment: production
  my-infrastructure:minSize: "3"
  my-infrastructure:maxSize: "10"
  my-infrastructure:enableMonitoring: "true"
  my-infrastructure:backupRetention: "30"
```

## Reading Configuration in Code

### TypeScript Configuration

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

// Get configuration
const config = new pulumi.Config();
const instanceType = config.get("instanceType") || "t3.micro";
const environment = config.require("environment");
const minSize = config.getNumber("minSize") || 1;
const maxSize = config.getNumber("maxSize") || 3;
const enableMonitoring = config.getBoolean("enableMonitoring") || false;

// Get secret
const dbPassword = config.requireSecret("dbPassword");

// Use configuration
const instance = new aws.ec2.Instance("web-server", {
    instanceType: instanceType,
    ami: "ami-0c55b159cbfafe1f0",
    tags: {
        Name: `web-server-${environment}`,
        Environment: environment,
    },
    monitoring: enableMonitoring,
});

// Export stack name
export const stackName = pulumi.getStack();
export const instanceId = instance.id;
```

### Python Configuration

```python
import pulumi
import pulumi_aws as aws

# Get configuration
config = pulumi.Config()
instance_type = config.get("instanceType") or "t3.micro"
environment = config.require("environment")
min_size = config.get_int("minSize") or 1
max_size = config.get_int("maxSize") or 3
enable_monitoring = config.get_bool("enableMonitoring") or False

# Get secret
db_password = config.require_secret("dbPassword")

# Use configuration
instance = aws.ec2.Instance(
    "web-server",
    instance_type=instance_type,
    ami="ami-0c55b159cbfafe1f0",
    tags={
        "Name": f"web-server-{environment}",
        "Environment": environment,
    },
    monitoring=enable_monitoring,
)

# Export outputs
pulumi.export("stack_name", pulumi.get_stack())
pulumi.export("instance_id", instance.id)
```

## Environment-Specific Resources

### Conditional Resource Creation

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const config = new pulumi.Config();
const environment = config.require("environment");
const enableHighAvailability = config.getBoolean("enableHA") || false;

// Create VPC
const vpc = new aws.ec2.Vpc("main", {
    cidrBlock: "10.0.0.0/16",
    tags: {
        Name: `vpc-${environment}`,
        Environment: environment,
    },
});

// Production gets multiple availability zones
const azCount = environment === "production" ? 3 : 1;
const subnets: aws.ec2.Subnet[] = [];

for (let i = 0; i < azCount; i++) {
    const subnet = new aws.ec2.Subnet(`subnet-${i}`, {
        vpcId: vpc.id,
        cidrBlock: `10.0.${i}.0/24`,
        availabilityZone: `us-east-1${String.fromCharCode(97 + i)}`,
        tags: {
            Name: `subnet-${environment}-${i}`,
            Environment: environment,
        },
    });
    subnets.push(subnet);
}

// Only create NAT gateway in production
let natGateway: aws.ec2.NatGateway | undefined;
if (environment === "production") {
    const eip = new aws.ec2.Eip("nat-eip", {
        vpc: true,
    });

    natGateway = new aws.ec2.NatGateway("nat", {
        allocationId: eip.id,
        subnetId: subnets[0].id,
        tags: {
            Name: `nat-${environment}`,
            Environment: environment,
        },
    });
}

// Create RDS with multi-AZ only in production
const db = new aws.rds.Instance("database", {
    engine: "postgres",
    engineVersion: "14.7",
    instanceClass: environment === "production" ? "db.t3.medium" : "db.t3.micro",
    allocatedStorage: environment === "production" ? 100 : 20,
    dbName: "myapp",
    username: "admin",
    password: config.requireSecret("dbPassword"),
    multiAz: environment === "production",
    backupRetentionPeriod: environment === "production" ? 30 : 7,
    skipFinalSnapshot: environment !== "production",
    tags: {
        Name: `db-${environment}`,
        Environment: environment,
    },
});

export const vpcId = vpc.id;
export const subnetIds = subnets.map(s => s.id);
export const dbEndpoint = db.endpoint;
```

## Stack References

### Cross-Stack References

```typescript
// Infrastructure stack (infra/index.ts)
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const vpc = new aws.ec2.Vpc("shared-vpc", {
    cidrBlock: "10.0.0.0/16",
    tags: {
        Name: "shared-vpc",
    },
});

const subnet = new aws.ec2.Subnet("shared-subnet", {
    vpcId: vpc.id,
    cidrBlock: "10.0.1.0/24",
    tags: {
        Name: "shared-subnet",
    },
});

// Export for other stacks
export const vpcId = vpc.id;
export const subnetId = subnet.id;
export const vpcCidr = vpc.cidrBlock;
```

```typescript
// Application stack (app/index.ts)
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

// Reference infrastructure stack
const infraStack = new pulumi.StackReference("myorg/infra/prod");

// Get outputs from infrastructure stack
const vpcId = infraStack.getOutput("vpcId");
const subnetId = infraStack.getOutput("subnetId");

// Use referenced values
const securityGroup = new aws.ec2.SecurityGroup("app-sg", {
    vpcId: vpcId,
    description: "Security group for application",
    ingress: [{
        protocol: "tcp",
        fromPort: 80,
        toPort: 80,
        cidrBlocks: ["0.0.0.0/0"],
    }],
});

const instance = new aws.ec2.Instance("app-server", {
    instanceType: "t3.micro",
    ami: "ami-0c55b159cbfafe1f0",
    subnetId: subnetId,
    vpcSecurityGroupIds: [securityGroup.id],
    tags: {
        Name: "app-server",
    },
});

export const instanceIp = instance.publicIp;
```

### Stack Reference Commands

```bash
# Deploy infrastructure stack first
cd infra
pulumi stack select prod
pulumi up

# Then deploy application

Related in General