When pushing application code changes to any environment, one of the most common problems you’ll encounter is that servers aren’t configured properly. How many of us have faced not having the same exact version of a dependency across all environments? I’d say, everyone. When our application is failing and we’re in a rush, we tend to log into the server, find the error, and apply the fix. This might not be seen as a big problem. But when the same problem arises in another environment and we don’t remember what we did to fix it, it is a big problem. Sound familiar?
We humans often forget things, especially when it only caused us a small amount of pain. But we’ll never forget what we did wrong when we brought down a production application. The struggle at that moment is horrible; it’s sometimes traumatic. Maybe that’s one of the reasons we usually have a set of scripts and commands that take the risk of human error down a notch. There’s a ton of information out there on how to install and configure helpful services, like a Nginx server. The blog posts and articles that provide this information give a recipe of steps we need to follow, and those become our scripts.
Nowadays, not only could you install and configure services but you could also do so for infrastructure. This mostly applies to cloud applications, but that doesn't mean it can't be done for your on-premise infrastructure. You can spin up a set of servers in minutes by just running a command or making an API call. Here’s where the term “infrastructure as code” (IaC) enters the game. IaC means you have cookbooks to help you manage and provision infrastructure in a consistent manner. You no longer have to remember which buttons to click or which commands to run in order to get an environment up and running. When you take this approach, several benefits come included.
Treat Infrastructure Like Application Code
When you treat your infrastructure like your application code, you can be confident that the infrastructure’s file definition won’t get lost easily. Why? Because, as with your application code, you’ll store this file in a version control system. And you’ll enjoy additional perks like change history, ease in rolling back changes, redundant storage, and one source of truth, among others.
When you implement IaC, gone are the days when you made manual changes to the server so the application worked. You and your team will get used to having an automated way of making changes to servers. Every change will be made in the infrastructure definition file. As for what language you’ll be working with, it can be any descriptive language. The most common language is YAML.
Every time you need to make a patch to the server, you’ll define that change in code. A good example of this is Dockerfiles. All the dependencies that the container will need to run the application are defined in the Dockerfile. There, you’ll place the exact same commands you’ll run: say, for example, updating the packages repository and then installing a specific version of the package.
As you do with code, you can deliver small changes frequently. This helps to increase the speed of deployments. According to several reports, you reduce risk by releasing small changes frequently. Fail fast, fail often. If it’s hard to do, do it more frequently so you can become better at it. When you start implementing IaC, you might feel like it’s not for you. But just keep doing it until you get it right because you’ll eliminate the lack of knowledge about what’s installed and how it’s configured.
Same Code for All Environments
I know. The first thing you’re going to tell me is, “Production environments are way different than development environments—and more expensive, also.” But when you define your IaC in a way that lets you control the resources you assign or how many replicas you want, it’s possible to have a small version of the infrastructure for development and a bigger one for production. Environments then become similar.
IaC is not just about provisioning; it’s also about configuration management. You’re reducing the chance of misconfigurations in the application. All the values that are different in each environment will be under version control. Of course, this presents an interesting challenge because you wouldn't put sensitive information like passwords there. The most common approach here is to use encryption or make use of environment variables where only certain people have access, like your Ops team.
If you embrace end-to-end automation in your delivery pipeline, you’ll be promoting changes from one environment to another. In order to take full advantage of this, you shouldn’t allow yourself or your team to make any manual changes that weren’t tested in a different environment first. By testing first, you’re minimizing the chances of introducing instability and differences into each environment.
Anyone Can Build an Environment Anytime
If you have the code and the proper access, you’ll be able to spin up a similar environment from production. You don’t need to bother operations anymore. Imagine that! Maybe you just need to experiment with the newest version of a dependency of the server. You wouldn’t want to interrupt your team if you break something in the environment.
By implementing IaC, you’re able to have a disposable and immutable infrastructure. Instead of making a change to the current servers, you’re replacing them with a new version built from your file definition. No more hidden or surprise changes to the environment. If something is broken by a recent change, you can always go back to a previous version and rebuild the environment. That’s the beauty of IaC.
Validate Infrastructure Before Deployment
When I said, “treat infrastructure like application code,” I meant it. The cloud came to revolutionize the way we thought about infrastructure. In the past, you didn’t have to worry about paying more money because you left-turned on a server for several hours. But when you’re in the cloud, you pay for every hour, minute, and even second the server is on. So instead of considering this a drawback, the industry found new ways to protect the budget. I myself had to deal with this problem. When I was developing the scripts to spin up instances and something went wrong, I had to pay for the fragment that instance ran. I needed to be very sure that my script was doing what I wanted.
That’s the reason you can even create unit tests for your infrastructure code. It’s also possible to do static code analysis (linting)—that will help you prevent some obvious problems. And as if that weren’t enough, you can also plan the changes your script will perform so you can preview how the infrastructure will look. It’s a pretty common feature in Terraform, and it was recently introduced in AWS CloudFormation. When the infrastructure is ready, you can also check that it’s properly configured by running some Serverspec tests. Could you ever have imagined these kinds of features with your infrastructure? I didn’t.
Always Know What Changed
You can keep track of all changes made to the infrastructure because you defined each one in a file. If you respect this rule when something goes wrong in the deployment and you don’t know why, you can always check the history, revert, and rebuild.
Tracking your changes is also useful for compliance reasons. Auditors love to see that an organization keeps track of how a change went from one environment to another. When was the change done? Who made the change? Who approved the changed? Is there a separation of duties in place? What’s awesome about IaC and DevOps is that you can tell them that you closed all doors and the only way to promote changes is through code. Plus, it’s automated. No human intervention needed.
IaC Will Put a Smile on Your Face
If you decide to go with IaC, you’ll be setting the foundation for a consistent and automated delivery pipeline for your applications. Your entire team will always know how the application is architected at the infrastructure level because now they’ll have a standard language. Anyone can make suggestions or apply fixes. If you’d like to restrict who’s pushing the changes, you can protect the master branch and limit the merge only to the Ops team, for example.
Developers can play around with similar infrastructure-as-test or prod before pushing application code changes. You can apply some proven practices from the development world to Ops. And there’s one last important aspect: you’ll provision and configure your infrastructure in the most elegant way possible through code. So it’s time to give some formality to those valuable scripts you always use and start implementing IaC.