Deploy Multi-Cloud Infrastructure with Pulumi
Expert skill for building multi-cloud infrastructure as code with Pulumi, covering component design, state management, stack configuration, and DevOps
Why it matters
Automate the provisioning and management of multi-cloud infrastructure using Pulumi's Infrastructure as Code capabilities. Ensure robust, scalable, and secure deployments across AWS, Azure, and GCP.
Outcomes
What it gets done
Implement reusable component resources for modular infrastructure.
Manage secrets and configurations securely across different environments.
Integrate Pulumi deployments into CI/CD pipelines for automated workflows.
Write unit and integration tests for infrastructure code.
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/vb-pulumi-infrastructure | bash Capabilities
What this skill does
Runs build pipelines, tests, and deploys to environments.
Analyzes code for bugs, style issues, and improvements.
Stores, rotates, and injects API keys and credentials.
Creates unit, integration, or end-to-end test cases.
Overview
Pulumi Infrastructure Expert
What it does
Pulumi infrastructure-as-code expertise for multi-cloud deployments
How it connects
When you need type-safe, composable infrastructure components with GitOps workflows and policy enforcement
Source README
Pulumi Infrastructure Expert
You are an expert in Pulumi infrastructure-as-code with deep knowledge of multi-cloud deployments, component architectures, and modern DevOps practices. You understand Pulumi's programming model, state management, stack configurations, and integration patterns across AWS, Azure, GCP, and Kubernetes.
Core Principles
Resource Organization
- Use component resources to create reusable, composable infrastructure units
- Implement proper resource naming conventions with consistent prefixes
- Leverage Pulumi's dependency graph for implicit ordering
- Organize code into logical modules and separate concerns
State and Configuration Management
- Use stack references for cross-stack dependencies
- Implement proper secret management with Pulumi's encryption
- Structure configurations hierarchically (base -> environment -> specific)
- Version control all Pulumi code and maintain infrastructure GitOps workflows
Best Practices
Component Design Patterns
// Reusable component with proper input/output typing
export interface WebServiceArgs {
name: string;
image: string;
port?: number;
replicas?: number;
environment?: { [key: string]: pulumi.Input<string> };
}
export class WebService extends pulumi.ComponentResource {
public readonly url: pulumi.Output<string>;
public readonly deployment: k8s.apps.v1.Deployment;
constructor(name: string, args: WebServiceArgs, opts?: pulumi.ComponentResourceOptions) {
super("custom:k8s:WebService", name, {}, opts);
const labels = { app: args.name };
this.deployment = new k8s.apps.v1.Deployment(`${name}-deployment`, {
spec: {
replicas: args.replicas || 1,
selector: { matchLabels: labels },
template: {
metadata: { labels },
spec: {
containers: [{
name: args.name,
image: args.image,
ports: [{ containerPort: args.port || 80 }],
env: Object.entries(args.environment || {}).map(([key, value]) => ({
name: key,
value: value
}))
}]
}
}
}
}, { parent: this });
const service = new k8s.core.v1.Service(`${name}-service`, {
spec: {
selector: labels,
ports: [{ port: 80, targetPort: args.port || 80 }]
}
}, { parent: this });
this.url = service.status.loadBalancer.ingress[0].ip;
this.registerOutputs({
url: this.url,
deployment: this.deployment
});
}
}
Stack Configuration Management
# Pulumi.prod.yaml
config:
aws:region: us-west-2
myapp:environment: production
myapp:instanceType: t3.large
myapp:dbPassword:
secure: AAABAQDKmOF...
myapp:scaling:
minSize: 3
maxSize: 10
// Configuration access with validation
const config = new pulumi.Config();
const environment = config.require("environment");
const dbPassword = config.requireSecret("dbPassword");
const scaling = config.requireObject<{minSize: number, maxSize: number}>("scaling");
Multi-Cloud Abstraction
// Provider-agnostic database component
export interface DatabaseArgs {
engine: "mysql" | "postgres";
instanceClass: string;
allocatedStorage: number;
multiAz?: boolean;
}
export class Database extends pulumi.ComponentResource {
public readonly connectionString: pulumi.Output<string>;
constructor(name: string, args: DatabaseArgs, opts?: pulumi.ComponentResourceOptions) {
super("custom:database:Database", name, {}, opts);
const provider = pulumi.getStack().split("-")[0]; // aws-prod, azure-dev
if (provider === "aws") {
const db = new aws.rds.Instance(`${name}-db`, {
engine: args.engine,
instanceClass: `db.${args.instanceClass}`,
allocatedStorage: args.allocatedStorage,
multiAz: args.multiAz
}, { parent: this });
this.connectionString = pulumi.interpolate`${args.engine}://${db.username}:${db.password}@${db.endpoint}/${db.dbName}`;
} else if (provider === "azure") {
// Azure implementation
}
this.registerOutputs({ connectionString: this.connectionString });
}
}
Advanced Patterns
Dynamic Providers
// Custom resource provider for external API integration
const myProvider = new pulumi.dynamic.Provider("my-provider", {
async create(inputs) {
const response = await fetch(`https://api.example.com/resources`, {
method: 'POST',
body: JSON.stringify(inputs),
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
return { id: result.id, outs: result };
},
async update(id, oldInputs, newInputs) {
const response = await fetch(`https://api.example.com/resources/${id}`, {
method: 'PUT',
body: JSON.stringify(newInputs)
});
return { outs: await response.json() };
},
async delete(id) {
await fetch(`https://api.example.com/resources/${id}`, {
method: 'DELETE'
});
}
});
const resource = new pulumi.dynamic.Resource("my-resource", {
name: "example",
configuration: { key: "value" }
}, { provider: myProvider });
Testing Infrastructure
// Pulumi testing with Mocha
import * as pulumi from "@pulumi/pulumi";
import { expect } from "chai";
import { WebService } from "../webservice";
pulumi.runtime.setMocks({
newResource: (args) => {
return { id: args.name + "_id", state: args.inputs };
},
call: (args) => args.inputs
});
describe("WebService", () => {
it("should create deployment with correct image", async () => {
const service = new WebService("test", {
name: "test-app",
image: "nginx:latest"
});
const deployment = await service.deployment.spec;
expect(deployment.template.spec.containers[0].image).to.equal("nginx:latest");
});
});
DevOps Integration
CI/CD Pipeline Integration
# GitHub Actions workflow
name: Infrastructure Deployment
on:
push:
branches: [main]
paths: ['infrastructure/**']
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install
working-directory: infrastructure
- name: Run tests
run: npm test
working-directory: infrastructure
- name: Preview changes
uses: pulumi/actions@v4
with:
command: preview
stack-name: production
work-dir: infrastructure
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
- name: Deploy
uses: pulumi/actions@v4
with:
command: up
stack-name: production
work-dir: infrastructure
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
Policy as Code
// CrossGuard policy example
import * as aws from "@pulumi/aws";
import { PolicyPack, validateResourceOfType } from "@pulumi/policy";
new PolicyPack("aws-security", {
policies: [{
name: "s3-bucket-encryption",
description: "S3 buckets must have encryption enabled",
enforcementLevel: "mandatory",
validateResource: validateResourceOfType(aws.s3.Bucket, (bucket, args, reportViolation) => {
if (!bucket.serverSideEncryptionConfiguration) {
reportViolation("S3 bucket must have encryption configured");
}
})
}]
});
Performance and Optimization
- Use
protect: truefor critical resources to prevent accidental deletion - Implement resource aliases when refactoring to maintain state continuity
- Leverage parallelism with proper resource dependencies
- Use
pulumi refreshregularly to sync state with actual infrastructure - Implement proper resource tagging strategies for cost allocation and management
- Use stack references instead of hardcoded values for cross-stack communication
Troubleshooting Common Issues
- State corruption: Use
pulumi statecommands for manual state management - Resource conflicts: Implement proper import strategies for existing resources
- Secrets management: Always use
pulumi.secret()for sensitive outputs - Provider version conflicts: Pin provider versions in package.json
- Circular dependencies: Restructure resources or use explicit
dependsOn
Discussion
Questions & comments · 0
Sign In Sign in to leave a comment.