function track_msdynmkt_websiteinteractions_114741865() { window["msdynmkt"].setUser({ authId: ""}); // ID, e-mail or phone number - see instructions window["msdynmkt"].trackEvent({ name: "msdynmkt_websiteinteractions_114741865", //Trigger title: Website Interactions ingestionKey : "d12470e34c7a4283ac8769a2797687ca-fab4c50f-f357-4516-a3f8-b908fdfbc681-7154", version: "1.0.0" ,     properties: { "dateandtime" : "", "url" : "", "bindingid" : "" } }); } global eia # ID, e-mail or phone number - see instructions user = User(auth_id='') eia.set_user(user) #Trigger title: Website Visit sampleEvent = Event('msdynmkt_websitevisit_083156767') sampleEvent.set_property("bindingid", "") eia.track_event(sampleEvent) Infrastructure as Code (IaC) with Pulumi: A Hands-On Guide
top of page

Infrastructure as Code (IaC) with Pulumi: A Hands-On Guide



In the fast-paced world of software development, the need for automation and efficient practices has never been greater. Infrastructure as Code (IaC) is a pivotal practice that addresses this need by allowing developers to manage and provision infrastructure through code instead of manual processes.


IaC brings several advantages, including consistency across environments, speed in deployment, version control for infrastructure, and the ability to integrate with continuous integration/continuous deployment (CI/CD) pipelines. It's a practice that not only enhances productivity but also significantly reduces the potential for human error.


Why Pulumi?


Pulumi stands out in the realm of IaC for its modern and developer-friendly approach. Unlike traditional IaC tools that use domain-specific languages (DSLs), Pulumi leverages familiar programming languages, allowing developers to define infrastructure using .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.


Infrastructure as Code

Creating Projects and Stacks


A Pulumi project is a container for your infrastructure code, usually tied to a specific cloud project. Stacks, on the other hand, represent different environments (e.g., development, staging, production) for your project.

Create a new Pulumi project:

pulumi new azure-typescript

Create a new stack (e.g., development):

pulumi stack init dev

Adding Configuration and Complex Structures


Configuration in Pulumi is a powerful way to manage environment-specific settings. Let's add a complex configuration structure for a hypothetical scenario:

Define the configuration in 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 Resources with Inputs and Outputs


Pulumi's concept of Inputs and Outputs is crucial for managing dependencies between resources automatically. Let's create an Azure SQL Database and an App Service, demonstrating the use of Inputs and Outputs.

Azure SQL Database:

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:

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, Pulumi's Inputs and Outputs play a crucial role in defining dependencies between resources, ensuring they are created in the correct order and configured properly. For instance, the azure.web.WebApp resource requires the ID of the azure.web.AppServicePlan as an input.

Pulumi automatically understands these dependencies due to the Inputs and Outputs mechanism: Outputs from one resource become Inputs to another. This system allows Pulumi to manage the creation order without explicit instruction, ensuring resources that depend on others are not attempted until their dependencies are satisfied. Thus, developers are freed from the complexity of managing these dependencies manually, making infrastructure management more intuitive and error-resistant.

Previewing and Deploying with Pulumi

With your project set up, it's crucial to understand how to interact with your infrastructure using the Pulumi CLI.


Pulumi login


To log in to Pulumi locally or use a Pulumi-managed service for state storage, you can run:

pulumi login --local

This command will store your infrastructure's state, which is crucial for tracking the current state of your resources and for collaboration.


Pulumi state in Azure


To manage your Pulumi state in Azure, you can use Azure Blob Storage as a backend. This method ensures your state file is securely stored in the cloud, providing both durability and accessibility across your team. The process involves using the Azure CLI to log in to your Azure account and then configuring Pulumi to use Azure Blob Storage for its state files.

You can log in to the Azure Blob storage backend with Pulumi using:

pulumi login azblob://<container-path>?storage_account=account_name

Note: set either AZURE_STORAGE_KEY or AZURE_STORAGE_SAS_TOKEN to authorize access


This tells Pulumi to store the state files in the specified Azure Blob Container. When using Azure Blob Storage as the backend, Pulumi utilizes the Azure CLI's authentication to manage access to the blob container, so make sure your Azure CLI session is authenticated before running Pulumi login.


Pulumi preview


To see the proposed changes before applying them, you can use the Pulumi preview command. This provides a detailed view of what Pulumi intends to do, and which resources will be created, updated, or deleted. It's an essential step for understanding the impact of your changes.

pulumi preview

Pulumi up


When you're ready to deploy your infrastructure, use the Pulumi up command. This command does more than just apply changes; it gives you a detailed preview, similar to the Pulumi preview, and then prompts for confirmation before proceeding with the changes.

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 through familiar programming concepts and languages, simplifying the process of deploying and managing cloud resources. The example provided walks you through setting up a basic but scalable architecture on Azure, highlighting key Pulumi concepts like projects, stacks, configuration, resources, inputs, and outputs.


Remember, Pulumi is a powerful tool that bridges the gap between developers and operations, facilitating a more collaborative and efficient approach to infrastructure management. Whether you're building a simple project or architecting a complex system across multiple clouds, Pulumi's approach to Infrastructure as Code can help you achieve your goals with greater ease and flexibility.


For more detailed information and advanced scenarios, the Pulumi documentation is an invaluable resource, offering comprehensive guides, reference materials, and tutorials to deepen your understanding of Pulumi's capabilities.


 

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.



bottom of page