Why Infrastructure as Code Matters
In today’s fast-paced software development world, automation and efficiency are essential. Infrastructure as Code (IaC) meets this need by enabling teams to manage and provision infrastructure through code instead of manual processes.
IaC offers several key advantages:
- Consistency across environments
- Faster deployments
- Version control for infrastructure
- Easy integration with CI/CD pipelines
Why Choose Pulumi?
Pulumi stands out for its modern, developer-friendly approach to IaC. Unlike traditional tools that rely on domain-specific languages (DSLs), Pulumi lets developers use familiar programming languages such as .NET, TypeScript, or Python.
This approach enables more complex logic, shared packages, and general software development practices within infrastructure management. Pulumi operates on a declarative model, maintaining a state file to keep track of your infrastructure’s current state. It is composed of an SDK for defining resources, a CLI for operating your infrastructure, and a deployment engine that orchestrates the provisioning process on any cloud platform.
Getting Started with Pulumi and TypeScript
To begin using Pulumi with TypeScript, you’ll need to have Pulumi and a package manager installed. For those who prefer pnpm, here’s how you can install both tools with just a couple of lines:
npm install -g pulumi
npm install -g pnpm
Building Our Example Architecture
Before diving into code, let’s outline the architecture we aim to deploy. Our goal is to create a scalable web application hosted on Azure, utilizing Azure App Service for hosting and Azure SQL Database for persistent storage.
Then create a new project :
pulumi new azure-typescript
Create a new stack (e.g., development):
pulumi stack init dev
Defining Configuration
Adding Configuration and Complex Structures
Pulumi’s configuration system allows you to manage environment-specific settings.
Example from Pulumi.yaml
:
config:
azure:location: West US
database:
username: admin
password:
secret: true
Use this configuration in your code:
import * as pulumi from "@pulumi/pulumi";
const config = new pulumi.Config();
const dbUsername = config.require("database:username");
const dbPassword = config.requireSecret("database:password");
Managing Dependencies with Inputs and Outputs
Pulumi automatically manages resource dependencies through Inputs and Outputs. For example, you can define an Azure SQL Database and an Azure App Service that depend on each other. Pulumi ensures they are created in the correct order without extra effort from you. This removes complexity and reduces errors while keeping your infrastructure consistent.
Previewing and Deploying
Pulumi’s Inputs and Outputs are essential for managing dependencies between resources. Outputs from one resource can be used as Inputs for another, and Pulumi automatically ensures resources are created in the correct order.
Let’s look at a practical example by creating an Azure SQL Database and an Azure App Service.
Azure SQL Database
Here, Pulumi provisions a SQL Server and a Database on Azure, with credentials pulled securely from configuration.
import * as azure from "@pulumi/azure-native";
const sqlServer = new azure.sql.Server("sqlServer", {
resourceGroupName: resourceGroup.name,
administratorLogin: dbUsername,
administratorLoginPassword: dbPassword,
version: "12.0",
});
const database = new azure.sql.Database("sqlDatabase", {
resourceGroupName: resourceGroup.name,
serverName: sqlServer.name,
requestedServiceObjectiveName: "S0",
});
Azure App Service
- The App Service Plan is created first.
- The Web App references it using
serverFarmId
. - The DATABASE_URL uses
sqlServer
anddatabase
outputs.
const appServicePlan = new azure.web.AppServicePlan("appServicePlan", {
resourceGroupName: resourceGroup.name,
kind: "App",
sku: {
tier: "Basic",
size: "B1",
},
});
const appService = new azure.web.WebApp("webApp", {
resourceGroupName: resourceGroup.name,
serverFarmId: appServicePlan.id,
siteConfig: {
appSettings: [
{
name: "DATABASE_URL",
value: pulumi.interpolate`Server=tcp:${sqlServer.name}.database.windows.net;Initial Catalog=${database.name};Persist Security Info=False;User ID=${dbUsername};Password=${dbPassword};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;`,
},
],
},
});
In our example, Inputs and Outputs play a crucial role in defining dependencies between resources. Pulumi ensures they are created in the correct order and properly configured.
For instance, the azure.web.WebApp
resource requires the ID of the azure.web.AppServicePlan
as an input. Pulumi automatically resolves this dependency: outputs from one resource become inputs for another.
This system removes the need for explicit orchestration. Developers don’t have to manage creation order manually, making infrastructure management simpler, more intuitive, and less error-prone.
Previewing and Deploying with Pulumi
Once your project is ready, you’ll use the Pulumi CLI to interact with your infrastructure.
Pulumi Login
Log in to Pulumi locally or with the managed service:
pulumi login --local
This stores your infrastructure’s state, which is critical for tracking current resources and collaborating with your team.
Storing State in Azure
You can also manage Pulumi state in Azure Blob Storage for secure, durable, and team-accessible state files.
pulumi login azblob://<container-path>?storage_account=account_name
Make sure you have authenticated with the Azure CLI beforehand, and set either AZURE_STORAGE_KEY
or AZURE_STORAGE_SAS_TOKEN
to authorize access.
Pulumi Preview
This shows which resources will be created, updated, or deleted, helping you understand the impact of your changes. Check the proposed changes before applying them.
pulumi preview
Pulumi up
This gives you a detailed preview, asks for confirmation, and then applies the changes. The output includes deployment status, any resource outputs, and possible errors. It’s also a powerful way to troubleshoot issues and track how your infrastructure evolves over time. When ready to deploy, run.
pulumi up
The output of Pulumi Up includes a wealth of information, including the status of resource deployment, outputs (if any), and any errors that might have occurred. It’s a critical tool for diagnosing deployment issues and understanding how your infrastructure changes over time.
Wrapping Up
By now, you’ve seen how Pulumi enables infrastructure management with familiar programming concepts, making it easier to deploy and manage cloud resources.
The example showed how to set up a scalable architecture on Azure, using key Pulumi concepts like projects, stacks, configuration, resources, and Inputs/Outputs.
Pulumi bridges the gap between developers and operations, creating a collaborative, efficient, and scalable approach to infrastructure management.
Whether you’re deploying a small project or architecting multi-cloud systems, Pulumi helps you achieve your goals with flexibility and ease.
At MDW, we’re dedicated to enhancing your business operations through tailored technological innovations. Reach out for a personalized consultation and find out how we can support your tech needs.