Experiences using Terraform

I've been working a lot with terraform recently, and it has been quite productive so far. Sure, there are some rough edges, but on the whole it's a really nice piece of software that lets you express all your infrastructure as code. The documentation does a fairly good job, but as with most software, there are still "gotchas" you could run into that may catch you by surprise. Here are some such things that I discovered, that I wish I knew before I started using terraform.

Use modules. Really. It doesn't matter if you think "well, I definitely wouldn't need to use this piece of code somewhere else", because you most certainly will. And in that case, it's going to be a pain to extract your configuration out into modules. To be fair, the process itself isn't that complicated, and terraform does provide you with tools to assist with the process (terraform state mv), but it's just a lot of effort that you don't have to put in if you use modules right from the beginning.

Just because terraform plan succeeded, doesn't mean terraform apply will. I'm mostly using AWS, so this may only be specific to AWS, but there are some operations that the AWS API doesn't allow, which plan wouldn't catch. So it's entirely possible that if you get a green light from plan, the apply fails somewhere in the middle because of a stupid 400 response from the AWS API. Keep the plan and apply cycle short. Meaning, make small changes, plan them, and apply them, to avoid having an error in the middle of a rather long apply. But I guess this point is not specific to terraform, and applies to software in general.

Keep terraform to strictly providing the backbone of your stack. This is a personal opinion, but I think the work of terraform ends as soon as your infrastructure is provisioned. Running scripts on, let's say EC2 instances provisioned via terraform, is OK, as long as those scripts are tiny and delegate everything else to your configuration management system. So something like sudo apt-get install salt-minion && ./configure-salt.sh && salt-call state.apply should be OK in the user data, but more than that is just asking for trouble.

Decide on a naming convention for your resources early. Having different styles in resource names is an eye-sore, and can be very confusing. Are you prepending your application name to each resource? Or appending? Are you using underscores? Hyphens? Spaces? Emojis? Deciding this one early enough in your project is definitely going to help.

Error messages don't always make sense. This one is not always true (hah!), but at times I do see errors that don't completely make sense and might be because of a stray } somewhere, or a missing parameter which may not be obvious.

Be careful of what you're committing. Avoid committing the .tfstate and .tfstate.backup files to git. This doesn't mean throw them away. But know that these would contain your application secrets, so having them in your git repository is probably not the best idea.

Lastly, and this is not really a gotcha. But terraform by itself is a very flexible tool, so it's really up to you how you want to use it. You might find a ton of different advice on the internet about, let's say, adding a staging environment to your infrastructure. And they'll all probably be right. But your setup might be different, and that's OK. As long as you know what you're doing and have read the documentation, terraform is really a joy to work with.

NOTE: As pointed out in a comment on reddit, the .tfstate files contain secrets only in case the provisioned resources involve secrets. So your RDS root password would end up in the state file, but if you don't provision any such resource, you're probably OK. The point is - be careful of what you're committing to Git!