Terraform vs. Pulumi : A Look at Both Tools
Paul Delcogliano
Posted on July 8, 2023
Cloud-native applications embrace the widely accepted practice of Infrastructure as Code, or IaC. IaC applies software development practices to the management of infrastructure, i.e., networks, virtual machines, and load balancers, etc.
Applying software development techniques to managing infrastructure provides several benefits, including versioning using a repository like GitHub, and streamlining provisioning and maintenance by creating repeatable processes. Code reviews and audits can be done to ensure changes to infrastructure are correct and won't introduce errors.
With IaC, infrastructure becomes reproducible in a consistent manner, and can be included in a CI/CD deployment pipeline. IaC is scalable and helps to eliminate human error.
Many IaC tools are available to facilitate the provisioning of cloud-native applications across all the major cloud platforms. Terraform and Pulumi are two such tools. In this article we'll take a look at both and provide a comparison between them.
Terraform
Terraform, is an open-source tool created by Hashicorp. It is probably the most well-known IaC infrastructure provisioning tool. Terraform is cloud-agnostic and allows automating infrastructure stacks from multiple cloud service providers simultaneously. Terraform uses its own domain-specific language called Hashicorp Configuration Language (HCL).
Terraform uses "plans" to validate the configuration and display exactly what elements are going to change before the changes are applied. For a detailed look at plans, check out the intro to Terraform plans article on spacelift.io.
Pulumi
Pulumi is an IaC tool that uses a declarative format to deploy infrastructure. Like Terraform, it is open source on GitHub and is free to use. It offers the ability to use any major development language in the creation of infrastructure template files. Pulumi, like Terraform, supports all of the major cloud providers.
Feature Comparison Between Terraform and Pulumi
Both tools are software that automate the management of cloud computing infrastructure using code and templates. They help businesses provision and configure servers, storage, databases, and networks without manual intervention or hardware controls.
They store the documented configurations in version control systems that ensure consistency and reduce turnaround time. They support DevOps and NetOps practices, enabling agility, scalability, and resilience. They can be cloud-specific or cloud-agnostic, depending on the provider and the environment.
The following table lists the major differences between each tool.
Terraform | Pulumi | |
---|---|---|
Language Support | Proprietary language - Hashicorp Configuration Language (HCL) | Pulumi SDK supports many languages including TypeScript, JavaScript, Go, C#, F#, Java, YAML. Also provides Pulumi YAML, which is a configuration language used to describe infrastructure. |
IDE Features | Limited; through extensions | Code completion, strong typing, error indicators, etc |
OSS License | Mozilla Public License 2.0 | Apache License 2.0 |
Testability | Integration testing via third party tools like Terratest | Supports unit, property, and integration tests. Supports modern test frameworks |
Cloud Providers | Multi-Provider Support | Multi-Provider Support |
State Mgmt | Local state file by default; Cloud options available | Remote state by default managed via Pulumi cloud; Local file available |
Secrets Mgmt | Unencrypted in state file | Encrypted in transit and state file |
Infrastructure Reuse | Can reuse Terraform modules | Functions, classes, packages and Pulumi components can be reused |
Let's take a deeper look into each of the differences listed above.
Language Support
Terraform's HCL is JSON-compatible and is used to create the configuration files that describe the infrastructure resources in the stack. It uses proprietary syntax for common programming constructs like conditionals and loops. Terraform recently released the beta of a development kit that allows you to use programming languages that compile to HCL.
Here's a look at a typical Terrafrom configuration file created using HCL to provision an Azure Resource Group.
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=3.0.0"
}
}
}
variable "region" {
description = "Azure location for the resource group"
type = string
}
provider "azurerm" {
features { }
}
resource "azurerm_resource_group" "iac" {
name = "rg-iac-example-centralus"
location = var.region
tags = {name: "iac-test"}
}
Pulumi supports familiar programming languages like TypeScript, JavaScript, Python, Go, and C#, among others. This flexibility allows you write to your templates in the language you are most comfortable with. Pulumi will also convert HCL configurations into Pulumi templates.
This reference provides a document listing Terraform terminology and command equivalents in Pulumi. A Pulumi template file written in C# to create the same Resource Group in Azure looks like this:
using Pulumi;
using Azure = Pulumi.Azure;
class MyStack : Stack
{
public MyStack()
{
var config = new Config();
var region = config.Require("region");
var iac = new Azure.Core.ResourceGroup("iac", new Azure.Core.ResourceGroupArgs
{
Location = region,
Tags =
{
{ "name", "iac-test" },
},
});
}
}
IDE Features
Plugins for Terraform are available for some IDEs like VS Code. IDE integration is limited to the capabilities of the plugin itself.
Pulumi's support for common programming languages means you get the rich IDE integration that comes with the language you choose. For example, when using C#, Visual Studio provides code completion, strong data types, intellisense, etc.
Open Source Licenses
Terraform uses the Mozilla Public License 2.0. Pulumi uses the Apache License 2.0. There are differences between each licensing model. Your use case will determine the license that is appropriate for you.
Testability
Pulumi's support for common programming languages like C# allows you to perform unit tests on your IaC templates using .Net test tools, like xUnit. Pulumi also provides the ability to perform tests that mock external calls.
Terraform supports integration testing. The plan
command shows the proposed infrastructure changes before they are applied, allowing you to review the changes prior to their execution. There are also commands to validate, and format a configuration file. Robust integration testing can be performed using third party tools like Terratest. Terratest is a Go library which enables you to write automated tests for infrastructure code. It provides many helper functions and patterns for common infrastructure testing tasks such as unit testing, integration testing, end-to-end testing, dependency injection, testing parallelism, retry logic, error handling, and static analysis.
Cloud Provider Support
A resource provider handles communications with a cloud service to manage the infrastructure resources defined in IaC configurations.
Both tools support all the major cloud services. Terraform has a community of developers writing custom providers for a myriad of services. Navigating their provider registry you'll find provider support for services like Ansible and Atlassian. New cloud services aren’t always available to deploy using Terraform on day one.
Pulumi supports over 60 of the major cloud services. They also create "Native" providres for AWS, Azure, Google, and Kubernetes, which receive same-day support with every new release. The Pulumi registry provides detailed information for each provider they support. Also of note, Pulumi is able to adapt Terraform providers, so you can use the custom providers created by the Terraform community in your Pulumi templates.
State Management
IaC tools store metadata about your infrastructure so that it can manage your cloud resources. This metadata is called state. Both Terraform and Pulumi offer a desired state model where the code represents the desired infrastructure state and the tool compares this desired state with the stack’s current state to determine the resources to be created, updated, or deleted.
By default, Terraform stores state locally in a file named terraform.tfstate. Terraform state can be stored using a centrally located file, i.e. Azure blob container. This is the recommended configuration for the state file. Storing state in a centrally located file provides for backup and recovery scenarios, and allows larger teams to collaborate and manage infrastructure with shared state.
In contrast, Pulumi stores it state in the Pulumi Cloud by default. Pulumi's use of common development languages allows state to be compared as a "diff", like how code is compared and reviewed across versions.
Secrets Management
The management of secrets, e.g., database credentials, API keys, etc., in code can become a security risk. Terraform manages secrets through a separate product named Vault. Vault enables the management secrets without the need for developers to have direct access to the secrets. Vault encrypts the values it stores. It can be deployed as a SaaS or run locally as a service. Variables marked as "secret" will be excluded from an output unless the secrets
command line arguement is provided.
terraform output secrets
It is important to note that Terraform state files store secrets in plain text. Because of this you should restrict access to the state file to only those with the appropriate level of authorization. A recommended best practice is to always encrypt your state file to prevent accidentally leaking sensitive information.
As mentioned above, Pulumi stores secrets in state in the Pulumi Cloud. You can also choose your own provider to store your secrets. Pulumi always stores and transmits secrets securely. It also supports encrypting sensitive data for extra protection. Configuration settings can be encrypted via the CLI command config set
with the --secret flag
. Secrets can also be set during runtime.
Infrastructure Reuse
A development best practice is to avoid duplicating code. The same practice applies to IaC. The ability to reuse configurations lowers the overall overhead involved with managing infrastructure.
Terraform provides a library of reusable modules. A module is comprised of a collection of .tf and/or .tf.json files stored in the same folder. Modules are the main way to package and reuse resource configurations with Terraform. Modules can be referenced from a public online registry or your own local module library.
Since Pulumi uses common programming languages, structures like classes, functions, and packages are reusable. Pulumi also provides a searchable registry where you can find packages that can be installed directly into your project. You can also create your own library of reusable packages.
Terraform or Pulumi: Which Should You Choose?
As in most decisions in software development, the answer is - it depends. Pulumi's native language support is its biggest advantage. By using native languages, you can embed IaC code directly within your application, perform unit testing, and reduce the learning curve by using a familiar language. This would be most important to developers who are new to DevOps. IT administrators with little coding experience will probably prefer the simplicity of HCL.
Bottom line, if the prospect of having to learn a proprietary language like HCL scares you, or if you think you'll need to integrate your IaC deployments within your application, choose Pulumi. Otherwise, go with Terraform. Either way, there is no wrong choice with Terraform or Pulumi. Both are more than capable of meeting your IaC requirements.
Conclusion
If you are looking to manage infrastructure as code, Spacelift is the way to go. It supports Git workflows, policy as code, programmatic configuration, context sharing, and many more great features. It currently works with Terraform, Pulumi, CloudFormation, and Kubernetes and has initial support for Ansible. You can test drive it by creating a free trial account.
Posted on July 8, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.