Oct 23, 2021

Infrastructure-as-Code as Single Source of Truth

How many third-party services and resources does your application use? For a regular web application, you need a place to host your frontend, deploy your APIs, store files, a database for user accounts and other application data, maybe some queues for decoupling tasks, monitoring integrated with every service you deploy, analytics, DNS records, traffic management, the list keeps growing.

Now, what if you want to preview a change to your infrastructure? Say you're exchanging a service for something else or fiddling with traffic flow configuration. You certainly don't want to experiment on production.

But how do you spin up an environment that looks and feels exactly the same? If you have anywhere near the complexity outlined above, configuring services manually not only requires a lot of time, it's way too easy to accidentally miss a checkbox, so environments diverge in configuration. Sometimes it might just be a change your cloud provider silently added to the UI, which could lead to subtle but important differences.

All resources in one place

Infrastructure-as-Code (IaC) really isn't so much about the tool you use, it's about the concept of putting your infrastructure resources in one place, defined as code. It's about not using UIs to click together your infrastructure, but using well-known principles like version control to ensure reproducibility and consistency for all your resources.

And just because you collect all resources in one place, it doesn't mean that you have to adopt it all at once, it's just that it works best the more resources you manage with the same tool. Granted, if you have existing deployments, importing resources may be painful at first. But once you've reached the top, you have a lot of new possibilities waiting to be tried.

In the following, I'll outline some possible workflows that are enabled when using infrastructure-as-code tools.

Use Case: Multi-Cloud Made Easy

Managing DNS records with Cloudflare? Deploying services to AWS ECS or Containers on Kubernetes? Monitoring with NewRelic or Datadog? Whatever your stack is, if there's an API for it, you can use it with IaC tooling. Most popular cloud providers are already supported by Terraform and Pulumi (which also uses Terraform), the two main IaC projects.

Adding another provider is usually as simple as visiting the developer documentation and API reference, and adding the new resource. Existing services and resources can be imported in place, so you do not have to destroy and re-create important resources.

Use Case: Managing Secrets

The next case is that managing secrets has become much easier. Whether you're storing database passwords, API keys, or SSH key pairs, all of your secret resources can be managed by your IaC toolchain. This is different than copying over keys to a third-party password manager, as your keys are stored encrypted in one place, so whenever you roll a secret, you don't have to go to five other products to update the configuration.

Use Case: Migrating Databases

Similar to the previous point of storing your secrets in an encrypted, managed environment, you can build applications on top of that. One example is connecting to databases for routine maintenance and migrations. Previously, you might have stored the database connection string in some password manager and shared it with your DevOps team. Or you know, you might have sent connection strings via Slack. Whatever the case might have been, the time to duplicate secrets ends when you can access your IaC state from other applications.

For our database migration that means it can directly use an API (such as the Pulumi Automation API) to retrieve details about your infrastructure state, including all outputs (database secrets, service addresses, etc.). This radically simplifies the way you work with sensitive information since you can just plug in the data source once.

Use Case: Preview Environments

Another popular use case is to spin up copies of your infrastructure to preview changes to features, completely seamlessly. I recently wrote a long-form guide about this exact case, so if you want full-stack deployment previews for your team to preview changes in GitHub PRs with one click, check it out!

Integration Tests for the cloud

When you let automation take care of spinning up your cloud resources, you should make sure that you actually got what you wanted. In simple cases, this might not be as important, but when you configure networking details or complex resources with lots of interdependencies, you can write tests for your infrastructure. Similar to testing regular software, you'll test the code that creates your infrastructure this time around.

The future: APIs for IaC

Now that you can build applications based on your IaC tools and resources, we should make sure that existing service providers can access those a bit easier. You could for example share secrets from your Pulumi stack with AWS so your services receive them as environment variables or database connection strings with data exploration tools, so your data viz team doesn't have to ask for passwords.

The moment you can integrate more tools with your IaC setup, you really get to have one single source of truth. Until then, you might still be required to copy API tokens, addresses, and other details around, and that should be a thing of the past.

Try it once, never go back

If I haven't convinced you to try out an infrastructure-as-code tool yet, you might have an extremely specific use case, or you just like to go through the AWS Console. If this isn't you, make sure to play with IaC for a bit, create some resources, connect them, generate some secrets, and try to rebuild your existing infrastructure in IaC.

You should quickly notice that configuring services you want to use gets much easier, you get to know what you're actually running, and you get to understand the underlying architecture and data model of services in your stack much better.

I think for most teams, using IaC is not a question of if, but when. Tooling has gotten much faster, more predictable, and the experience is really smooth now. There are multiple providers, and cloud providers offer native APIs for dealing with IaC flows, that tools can simply adopt (see native providers in Pulumi).

In the rare case that a resource you need to use does not yet have IaC support, you can build it yourself with custom providers. This can bring steps like one-time migrations (setting up a database, copying/syncing files, etc.) into IaC.