Glossary
Infrastructure as code
Also: IaC · Terraform
Infrastructure is described as versioned code instead of being clicked together in a web console.
The gain is traceability: every change to the environment has an author, a timestamp and a reason in the history. And it can be repeated identically in a second environment.
The second gain shows up on the bad day. An environment that comes from code can be rebuilt. A clicked one has to be reconstructed, and only the person who built it can do that.
The third gain, and the most important one day to day, is the preview. A plan shows before execution what will be created, changed and deleted. That makes an infrastructure change reviewable like a pull request, and the line that says "will be destroyed and recreated" next to a production database catches someone before it runs rather than afterwards.
The state file is the part that causes the most trouble. The tool keeps a record of which resource in the world belongs to which piece of code. If that file sits on a laptop, it is gone with the next change of staff and the environment can only be operated by hand from then on. It belongs in a shared backend with versioning and locking, so that two people do not apply at the same time.
The state also raises a security question that is often overlooked: it contains values that have passed through the configuration, possibly including credentials. It belongs encrypted, with tight permissions, and secrets do not belong in variable files but in a secrets manager that is read at runtime.
Drift between the code and reality is a topic of its own. Somebody changes something in the console during an incident, and from then on the code describes an environment that does not exist in that form. The next apply silently overwrites the manual work, in the worst case in the middle of the day. What helps is a regular comparison that reports differences, and the rule that an emergency change is either brought into the code or rolled back within a day.
As for dealing with grown environments: the way in is import, not recreation. Existing resources are adopted into the state so that the code describes the current situation and the plan reports "no changes". Only once that is reached does anything get changed. Building a parallel setup instead means operating two environments for the duration of the switch and moving the traffic across.
How you notice it
- Parts of the environment were created in the console.
- Test and production differ without anyone knowing how.
- Rebuilding after total loss would mean reconstructing from memory.
- The state file sits locally, or nobody knows where it is.
- After an emergency change in the console the code was never brought up to date.
Not to be confused with
- Configuration management
- Ansible, Chef and Puppet configure systems from the inside. IaC creates the resources they run on. The two complement each other, they do not replace each other.
- CloudFormation and CDK
- The AWS-native variants of the same principle. CDK generates templates from program code. The choice is usually a question of vendor lock-in and team experience, not of the concept.
- GitOps
- An operating model in which a reconciliation process continuously aligns the actual state with the repository. It assumes IaC and goes beyond it.
When it fits
- There is more than one environment that is meant to look the same.
- More than one person changes infrastructure.
- A rebuild after total loss has to be possible.
- Changes to the infrastructure should be reviewable.
When it does not
- For a short-lived experiment with a handful of resources.
- Half way: part in code, part by hand is worse than consistently by hand.
How to approach it
- Sort out the state backend firstA shared backend with versioning, encryption and locking. A state file on a laptop is the most common reason such an effort ends.
- Import what exists instead of rebuilding itThe goal is a plan that reports "no changes". Only once the code describes the current state does anything get changed.
- Start with the network and the permissionsThat is where recovery takes longest and where manual changes are most dangerous.
- Have the plan read before every applyThe plan belongs in the pull request, so that a second pair of eyes sees the lines saying "will be destroyed".
- Separate environments, share modulesSeparate state per environment, shared building blocks. One state for everything means a mistake in development can touch production.
- Move secrets outNot into variable files but into a secrets manager. Values that flow through the configuration end up in the state.
- Check for drift regularlyA scheduled run that only produces the plan and reports differences. Otherwise the next apply overwrites an emergency change unnoticed.
Frequently asked
How do I bring an existing environment into code?
Area by area and with import rather than recreation. Terraform can adopt existing resources so the code describes the current state without building anything new. Start with networking and permissions, because that is where recovery takes longest.
What do you do when somebody has changed something in the console?
Decide within a day: bring it into the code or roll it back. A regular run that only produces the plan makes such drift visible before the next apply silently overwrites it. For genuine emergencies the console is legitimate, but the change must not go unnoticed.
Terraform or CDK?
Terraform when several providers or third-party services are involved and the team prefers a declarative approach. CDK when only AWS is used and the team would rather work in a programming language. More important than the choice is that there is one: two tools on the same environment produce exactly the drift you wanted to avoid.
How do you stop the pipeline from having too much power?
Through a dedicated role per environment with tightly cut permissions and an approval before applying in production. The plan runs without approval, the apply does not. That keeps the benefit of the automation without letting a faulty pull request take effect in production directly.
