Terraform is a tool for provisioning. Challenges:
- Day 1: we haven’t run anything yet. How do we go from running nothing to something?
- Day 2+: we have an existing set of infrastructure. How do we evolve it?
- Day n: we no longer need this infrastructure. How do we remove it?
Terraform solves these challenges by defining Infrastructure as Code. Declaratively define structures in config files. Describe your overall topology in that config file.
For example, you may have a VPC, on top of that a security group rule, and within that a virtual machine, a load balancer, etc. In a config file, you can evolve your infrastructure by adding those components gradually and reference them together. Terraform gives you a workflow to create and manage these things more easily.
Terraform generates an execution plan to describe what it will do and asks your approval before making any infrastructure changes. This lets you review before Terraform creates, updates, or destroys infrastructure.
Terraform builds a resource graph and creates or modifies non-dependent resources in parallel. This lets Terraform build resources as efficiently as possible and gives you greater insight into your infrastructure.
Terraform can apply complex changesets to your infrastructure with minimal human interaction. When you update configuration files, Terraform determines what changed and creates incremental execution plans that respect dependencies.
Reconciles what terraform thinks the real world looks like (view) with what the real world actually is. Gets an up-to-date view.
Where Terraform figures out what it needs to do. Reconciles real world config (what things are actually running) with what our desired config is.
Takes the plan and executes it against the real world. The order in which the pieces of the plan are executed matters and is defined in the graph-like structure of the plan config. In our example, VPC must be defined before all other things, and then we can boot VMs and security group roles in parallel as they are not dependent on each other; in the end, load balancer can be created.
Let’s say we run all the above commands and successfully get our first Day1 infrastructure set up. After that, we want to add a monitor to the VMs, a DNS server to the load balancer, and a CDN to the DNS.
All we need to do is update the plan config and run all the same commands again. terraform refresh will see the initial 4 nodes (VPC, SG, VM, LB) but not the new ones we just defined. terraform plan will see that the initial 4 nodes are in the desired state already and don’t need to be changed, while the new 3 nodes need to be created. terraform apply adds the 3 new nodes so it reconciles real world state with desired state.
We reach a point where we no longer need the infrastructure we created.
This is like a specialized terraform apply that executes a specific destroy plan to properly clean up the resources and decommission your infrastructure.
How does Terraform actually work?
We talked high level about Terraform’s workflow but not about any specific technologies.
- taking the terraform config
- taking the terraform state
- figuring out the graph of the the infrastructure (lifecycle). How do the different nodes of the infrastructure graph relate to each other, what needs to be created, updated, destroyed.
Support for providers
How Terraform connects to the outside world. There are many types of providers, such as
- Infrastructure as a Service
- cloud providers (AWS, Azure, GCP)
- on-premise infrastructure (OpenStack, VMWare)
- Platforms as a Service (Heroku, Kubernetes, Lambdas)
- Software as a Service
- monitoring (DataDog)
- CDNs (Fastly)
- GitHub Teams
Anything that has an API — how can we enable that API to create a provider out of it for Terraform to use?
We have over a 100 providers that can individually manage over a 1000 resources (like an Azure provider’s Blobstore resource).
For a single Terraform “practitioner” (software developer/operations engineer):
- Create a TF config
terraform planwhich will examine the config you created
- If that looks good, run
terraform applyto create the infrastructure
For a Terraform team: use Terraform Enterprise. Like other code, we develop the plan configs locally, push them to a remote version control system like GitHub, and then Terraform Enterprise manages state accordingly.
State File needs to be carefully managed so that different versions of an infrastructure are not actually affecting each other or conflicting.
TFE operates sequentially so there is no concurrency problem with more than one developer trying to run infrastructure changes at the same time.
How to manage developers using local variables on their machines with other potentially sensitive environment variables in higher environments? TFE provides secrets encryption management as well which is version- and access-controlled.
Modules help encapsulate knowledge of infrastructure and promote best practices so that folks such as developers only get what the need to know and have guidelines and how to use pieces properly. We can publish modules to a central registry. We have a global, public official one at registry.terraform.io. Organizations can form their own private registries as well.
This creates a split between publishers who manage and register modules and consumers (developers, etc.) who use the modules.
Modules are like a WYSIWIG for Terraform that provides scaffolding for common infrastructure components.
Chef, Puppet, etc. are configuration management tools that install and manage software on a machine that already exists. Terraform is not a config management tool. It allows existing tooling to focus on their strengths: bootstrapping and initializing resources. Terraform gives higher-level abstractions of a datacenter and its associated services, allowing you to use config management tools on individual systems. You can use traditional config management within your compute instances along with Terraform to configure bootstrapping software like cloud-init to activate your config management software on first sytem boot.
CloudFormation, Heat, etc. allow details of an infrastructure to be codified into a config gile. The config files allow the infrastructure to be elastically created, modified, and destroyed. Terraform was inspired by the problems they solve. Terraform builds off those principles by being cloud-agnostic and enabling multiple providers and services to be combined and composed. It also provides a single unified syntax instead of requiring operators to use independent and non-interoperable tools for each platform and service. Terraform further separates planning from execution with the execution plan — promoting safer understanding and propagation of changes by outlining and visualizing proposed changes before they are made for the human user.
Boto, Fog, and other libraries provide native access to cloud providers and services by using their APIs. Using a client library only provides low-level access to APIs, requiring application developers to create their own tooling to build and manage their infrastructure. Terraform provides high-level syntax for describing how cloud resources and services should be created, provisioned, and combined. Terraform is flexible, using a plugin-based model to support providers and provisioners, giving it ability to support almost any service that exposes APIs.
Custom solutions are often an organization’s MVP, but they are brittle, difficult to maintain and scale. Terraform’s uniform syntax that supports multiple providers is robust and easily scalable.
Common use cases
- Multi-cloud deployment
- Heroku app setup
- Multi-tier applications
- Self-service clusters
- Software demos
- Disposable environments
- Software defined networking
- Resource schedulers