2019-05-06

Terraform is Terrible: Part 1

So I had this bright idea. I've been learning cloud deployment and infrastructure for quite a few years now and it always seems like each cloud provider has its own custom set of management tools. That's unsurprising, but also really disappointing. If you deploy a service to Amazon AWS and you've finally had enough of random mystery microcharges to your account, porting that service to a different cloud provider is going to require rearchitecting your entire stack. Even if you just want to upload a custom virtual machine image and can handle converting it between one format to another, you are going to have to rethink your storage backend, your networking setup, your monitoring and notification toolkit, your management of secrets, and the list goes on.

Moving off of your cloud provider is a real pain in the ass, and the providers all like it that way.

I like freedom of choice, and there are a couple of tools out there that claim to offer a platform-agnostic infrastructure management solution that will fit you regardless of whether you're on Google or Amazon or Microsoft or any of the smaller fry swimming in the digital ocean. (See what I did there?)

My idea was to write a great little "how to get started" tutorial for one of these tools, but in using it I found it to be so brittle, so badly documented, and its default settings so unusably broken that it made me need to shut my computer off and go do something else just to clear my head.

I'm sorry, I... I have to talk about this.

The name of this tool is Terraform, and it is terrible. Here's why.

Why Terraform Looks Like a Good Idea

If you're like me, you use the cloud. And since you've been using the cloud for a while now, you have a couple of different ways you've managed your VMs over the years. You did it by hand through the website, but that was a tiresome, manual process that was prone to error:

"Did I call my last deployment My-Service-1 or My_Service_1? Or MyService1? I forget. If I go back and check I'll lose my work on this page. If I open a new window I'm going to have to re-authenticate with my username and password again for some reason."

It was a pain. So as soon as you find out there's an API for it, you use their tools to automate it. For me this was Azure PowerShell and eventually Azure CLI. These tools are dedicated to their own cloud provider, so if you use anything other than Microsoft Azure you're out of luck here. Still, you write up a bunch of scripts that upload your base images and create your cloud configs in a nice, automatable way.

Face it: you definitely have scripts named "data_upload1.ps1", "data_upload2.ps1", and "data_upload1.ps1.backup" and they all do something a little bit different and you can't remember exactly why one works when the others don't. When you get tired of running your own library of custom scripts, you start looking to see if anyone's Figured It All Out. Maybe there's some clever concept where you can templatize how you want your cloud service to look and then on any cloud provider it can do the translation for you. If you can build a good abstraction layer that can speak the language to everyone, everywhere, then you just need to define your service settings and dependencies one last time in Cloud Esperanto (or whatever it may be) and you're done until the tech industry's next big paradigm shift.

I learned about Terraform from Mastodon, and it looked like a great tool. I had just learned about libcloud: a set of Python (insert sadface here) libraries that you could leverage to write a supposedly versatile script to do deployments to any of the dozens of supported cloud companies. But as I have well explained, I hate Python, and so writing Python scripts to replace my PowerShell scripts sounded like sheer misery for not much benefit.

Someone mentioned Terraform as an alternative to libcloud, so I took a look and I immediately liked what I saw. It's not a scripting language but rather self-contained deployment software with an easy to read JSON-like config syntax. Terraform has no dependencies on a SQL server backend or obscure, bespoke kernel event handling libraries. It can be installed with Chocolatey in a heartbeat:

choco install -y terraform --pre

Done. Since I want to deploy to Azure, I need two more lines:

choco install -y azure-cli
az login --use-device-code

I'm going to use the Azure CLI for user authentication, but Terraform supports other methods of authentication to Azure. This one just happens to be the easiest. So far, so great.

You write your Terraform config as a file called "main.tf" in a very AzureRM template-like syntax:

provider "azurerm" {
  version         = "=1.27.0"
  subscription_id = "bba8a111-a014-4dbf-aa90-9692362fd971"
}

resource "azurerm_resource_group" "mygroup" {
  name     = "MyFirstTerraformGroup"
  location = "East US 2"
}

This is all pretty easy to read and understand. And there are no commas to quietly ruin your day because you forgot one and a parser somewhere is complaining but it won't explain why! I was hooked. I spent a couple of weeks looking at docs and "getting started" guides and a bunch of examples. From that I compiled a list of links, commands, and examples to help me write up a deployment. I was excited. Finally, my web services could spring forth from a simple set of config files and I could deploy and redeploy as needed by just running a couple of commands.

What a fool I was. Next time: Mockumentation.

No comments: