Introduction to Pulumi

Discover the Pulumi technology and its basics 01/10/2020

These days, who has not heard the term Infrastructure as Code (IaC) ? With the expansion of the cloud based solutions, this becomes very trendy! As I am more focused on Azure for the moment, I worked with some ARM and/or Terraform templates but as the word indicates, it's about templating and not really code... So when I heard about Pulumi, as a developer who prefers lines of codes as lines of templates I was very curious to know how it works. In this article, I will describe everything I learned during my journey with Pulumi and Azure.

What is Pulumi ?

Pulumi is an opensource platform to deploy and manage your cloud infrastructure in your favourite programming language on multiple cloud platforms. As of January 2019, the available languages are Javascript, Typescript, Python, C# (preview) and Go (preview). Pulumi supports the main cloud platforms (Azure, AWS, GCP) and some other cloud services providers (DigitalOcean, OpenStack, Linode, etc...). Pulumi can easily integrate into your CI/CD systems : there are example with Github Actions or Azure Devops pipelines. The documentation is very well written and you can find almost everything you need to start your own project on their github

pulumy description 1

Why Pulumi ?

Pulumi is 100% opensource and free as long as you're using it on your own as a single developer and that's my case. As I said in my introduction, I prefer writing code than templates. I'm not sick with JSON (or YAML) but when I can avoid them doing IaC I do. Moreover, I think bringing programming language as C# or Typescript into the IaC process can help developers to work with operators in a sustainable devops environment. I am currently using it with Azure but tomorrow if I want to migrate to AWS, it would be easier with Pulumi.

Pre-requisites

To continue in this introduction to Pulumi, you will need the following :

How to install it ?

Download the latest version from here.
Unzip it and add the 'bin' folder to your path environment variable.
There are other ways to install it using powershell or chocolatey very well explained on the same url.
To work with Azure, Pulumi relies on the Azure SDK to authenticate requests from your computer.

Set up a Pulumi project

To start with Pulumi, you first need to initialize a project with the command :

pulumi new

Then, select the template you want to work with (I choose the 'azure-csharp'). Choose a project name and its description. Pulumi then asks for a default location and will store it as a configuration parameter named 'azure:location' of the new created stack for the project (I'll be back on that later).

pulumy new

Open the project in your favorite code editor and let's have a look at the code of the file 'Program.cs' :


using System.Collections.Generic;
using System.Threading.Tasks;
using Pulumi;
using Pulumi.Azure.Core;
using Pulumi.Azure.Storage;

class Program
{
    static Task<int> Main()
    {
        return Deployment.RunAsync(() => {

            // Create an Azure Resource Group
            var resourceGroup = new ResourceGroup("resourceGroup");

            // Create an Azure Storage Account
            var storageAccount = new Account("storage", new AccountArgs
            {
                ResourceGroupName = resourceGroup.Name,
                AccountReplicationType = "LRS",
                AccountTier = "Standard",
            });

            // Export the connection string for the storage account
            return new Dictionary<string, object>
            {
                { "connectionString", storageAccount.PrimaryConnectionString },
            };
        });
    }
}
                

We can see that two resources will be created in the minimal template : a resource group and a storage account. What's interesting here is that the program will export the connection string for the storage account directly at the end of the deployment of our stack. Now let's deploy it using the command :

pulumi up

pulumy up

Now let's have a look from my azure portal on what's been created :

az portal 1

Everything's been created as expected !
This is ok but I don't really like the auto-generated names of the created resources. So let's define ours plus let's add some tags on the resources (I see you FinOps ^^).
Replace all the code with the following :


using System.Collections.Generic;
using System.Threading.Tasks;
using Pulumi;
using Pulumi.Azure.Core;
using Pulumi.Azure.Storage;

class Program
{
    static Task<int> Main()
    {
        return Deployment.RunAsync(() => {

            // Create an Azure Resource Group
            var resourceGroup = new ResourceGroup("resourceGroup", new ResourceGroupArgs()
            {
                Name = "myResourceGroupForPulumi",
                Tags = new InputMap<object>() { { "environment", "dev" } }
            });

            // Create an Azure Storage Account
            var storageAccount = new Account("storage", new AccountArgs
            {
                Name = "storageforpulumi",
                ResourceGroupName = resourceGroup.Name,
                AccountReplicationType = "LRS",
                AccountTier = "Standard",
                Tags = new InputMap<string>() { { "environment", "dev" } }
            });

            // Export the connection string for the storage account
            return new Dictionary<string, object>
            {
                { "connectionString", storageAccount.PrimaryConnectionString },
            };
        });
    }
}
                

Run another Pulumi up command to update your stack.

pulumy up 2

We can see that Pulumi detected the changes in our source code and informed us about the differencies with the previous deployed version of our stack.
Changing the name of a resource implies to replace it so take care of your company naming convention before deploying anything.
I really appreciate this Pulumi feature because it permits to check everything's ok before deploying.
Pulumi can also detects obvious errors when checking the current stack : for example, it shows an error if the storage account name contains uppercase caracters or if you write 'LTS' instead of 'LRS' for the replication type. Now let's destroy our stack with the command :

pulumi destroy

Pulumi stacks and configuration

A stack is an isolated, independently configurable instance of a Pulumi program. Stacks are commonly used to denote different phases of development (such as development, staging and production).
As a stack own its isolated instance, Pulumi manages a configuration system to define values and stores them in a 'Pulumi.<stack-name>.yaml' at the root of the project. In our previous example, we could have set the resource group name as a configuration value with the command :

pulumi config set rgName myResourceGroupForPulumi

We can retrieve the value from the command :

pulumi config get rgName

pulumy config

We can then use the defined configuration values from the source code. There are two ways of using them :

  • Requiring a value : it will block the deployment if the configuration value is missing
  • Getting a value : it will continue even if the configuration value does not exist so think about a default value in your code


//Get configuration object instance
var config = new Config();
//Require resource group name
var rgName = config.Require("rgName");
//Get vm size
var vmSize = config.Get("vmSize") ?? "Standard_B2s";
                

Pulumi can also manage encrypted secrets but at the moment, I did not try this feature (more information here)

Summary

Pulumi is a great tool to deploy infrastructures on various cloud platforms : the documentation is clear and the examples provided are a good start (I love the Kubernetes ones ^^).
Actually, I think this is a great solution for developers who do not want to spend too much time to learn ARM and/or Terraform templating.
I did not have the opportunity to use it in a company context but I'm sure with the stacks and configurations system combined with some CI/CD tools (GitHub Actions, Azure DevOps pipelines...) it could really empower a devops environment. I'll try to write something about it later.
Pulumi also covers subjects I did not address like the management of Docker or Kubernetes so do not hesitate to visit https://www.pulumi.com/

Share On