Getting Started with Pulumi: Deploying a Demo App to AWS and GCP Using TypeScript
Pulumi is a modern infrastructure as code (IaC) tool that empowers developers to define multi cloud resources using familiar programming languages such as TypeScript, Python, Go, and C#. In this blog post, I will guide you through the process of getting started with Pulumi, setting up your environment, and deploying a demo application to both AWS and GCP using TypeScript. I'll also highlight the differences between Pulumi and Terraform and discuss the benefits of using Pulumi.
Prerequisites
Before we dive in, make sure you have the following installed:
Step 1: Install Pulumi
First, let’s get the Pulumi CLI installed. You can do this using npm:
npm install -g pulumi
To check if it’s installed correctly, run:
pulumi version
Step 2: Set Up Your Pulumi Project
Create a new Pulumi project:
mkdir pulumi-demo
cd pulumi-demo
pulumi new typescript
Pulumi will prompt you to log in (you can use your Pulumi account, GitHub, or other options) and then guide you through setting up your new project. You’ll be asked to provide a project name, description, and stack name.
Step 3: Configure AWS and GCP Credentials
AWS
Configure your AWS credentials using the AWS CLI:
aws configure
GCP
For GCP, set up your credentials and authenticate using the SDK:
gcloud auth login
gcloud auth application-default login
Step 4: Define Your Infrastructure in TypeScript
Now, let's open the index.ts
file in your Pulumi project and define some infrastructure. We'll start with AWS.
AWS Example
In this example, we’ll create an S3 bucket and an EC2 instance.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// create an S3 bucket
const bucket = new aws.s3.Bucket("my-bucket");
// create an EC2 instance
const size = "t2.micro"; // EC2 instance size
const ami = "ami-0c55b159cbfafe1f0"; // amazon Linux 2 AMI for us-west-2
const server = new aws.ec2.Instance("my-instance", {
instanceType: size,
ami: ami,
tags: {
Name: "MyInstance",
},
userData: `
#!/bin/bash
echo "hello, world!" > index.html
nohup python -m SimpleHTTPServer 80 &
`,
});
// export the bucket and instance details
export const bucketName = bucket.id;
export const instancePublicIp = server.publicIp;
export const instancePublicDns = server.publicDns;
In this code:
An S3 bucket is created with a default configuration.
An EC2 instance is launched using a specified AMI and instance type. The instance runs a simple HTTP server serving a "hello, world!" page.
Deploy to AWS
To deploy your stack to AWS, run:
pulumi up
Pulumi will show you a preview of the resources to be created. Confirm the deployment by typing yes
.
Step 5: Deploying to GCP
Next, we'll set up a GCP Cloud Storage bucket and a Compute Engine instance. Create a new stack for GCP:
pulumi stack init gcp-demo
pulumi config set gcp:project YOUR_GCP_PROJECT_ID
pulumi config set gcp:region us-central1
Open the index.ts
file again and define the GCP resources:
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
// create a Cloud Storage bucket
const bucket = new gcp.storage.Bucket("my-gcp-bucket");
// create a Compute Engine instance
const instance = new gcp.compute.Instance("my-instance", {
machineType: "f1-micro",
bootDisk: {
initializeParams: {
image: "debian-cloud/debian-9",
},
},
networkInterfaces: [{
network: "default",
accessConfigs: [{}],
}],
metadataStartupScript: `
#!/bin/bash
echo "hello, world!" > /var/www/html/index.html
sudo apt-get update
sudo apt-get install -y apache2
sudo systemctl start apache2
sudo systemctl enable apache2
`,
});
// export the bucket and instance details
export const bucketName = bucket.name;
export const instanceName = instance.name;
export const instanceIP = instance.networkInterfaces[0].accessConfigs[0].natIp;
In this code:
A GCP Cloud Storage bucket is created.
A Compute Engine instance is launched with a startup script that installs Apache and serves a "hello, world!" page.
Deploy to GCP
Switch to the GCP stack and deploy:
pulumi stack select gcp-demo
pulumi up
Again, Pulumi will preview the resources. Confirm by typing yes
.
Step 6: Clean Up Resources
When you’re done, make sure to clean up your resources. Use the pulumi destroy
command for each stack:
pulumi stack select aws-demo
pulumi destroy
pulumi stack select gcp-demo
pulumi destroy
Pulumi vs. Terraform: Differences and Benefits
Pulumi and Terraform are both popular IaC tools, but they have some key differences:
Programming Languages
Pulumi: Uses general-purpose programming languages like TypeScript, Python, Go, and C#. This allows developers to use familiar languages and leverage existing ecosystems, libraries, and tools.
Terraform: Uses its own domain-specific language (HCL - HashiCorp Configuration Language). While HCL is powerful and expressive, it is different from general-purpose programming languages.
State Management
Pulumi: Manages state in the cloud (via the Pulumi service) by default, but also supports local state management and custom backends. This can simplify collaboration and state storage.
Terraform: Typically manages state in local files or remote backends (e.g., S3, Consul). This requires additional setup for team collaboration.
Extensibility
Pulumi: Offers more straightforward extensibility through the use of full programming languages. This makes it easier to create custom abstractions, utilities, and integrations.
Terraform: Extends functionality through custom providers and modules, but writing these requires knowledge of Go (for providers) and HCL (for modules).
Benefits of Pulumi
Familiarity and Productivity: By using general-purpose programming languages, developers can quickly get started without learning a new language.
Rich Ecosystem: Leverage existing libraries and tools from the broader programming ecosystem.
Integrated Testing: Easily write unit tests for infrastructure code using standard testing frameworks.
Flexibility: Use programming constructs like loops, conditionals, and functions to manage complex infrastructure logic.
Unified Workflow: Manage infrastructure for multiple cloud providers and services using a single tool and consistent workflow.
Conclusion
In this blog post, we’ve learned how to get started with Pulumi and deploy multiple resources to both AWS and GCP using TypeScript. Pulumi's approach allows you to leverage your existing programming skills to manage cloud infrastructure efficiently. Compared to Terraform, Pulumi offers the flexibility of using general-purpose languages, which can enhance productivity and integration with existing codebases. For more advanced scenarios, you can extend these examples to include complex infrastructure setups, integrate with CI/CD pipelines, and more.