For companies that primarily host their services in "legacy" systems, the movement toward Infrastructure-as-code poses the question of tool choice. Terraform and Ansible are commonly used tools in this area. But, when, how to use Terraform, Ansible? And do we have to use both?
Important Note: This article intentionally ignores Kubernetes and cloud-native provisioning tools and their advanced abstract infrastructure layer.
First, let’s go back in time a bit.
Wikipedia:
"Infrastructure as code (IaC) is the process of managing and provisioning computer data centers through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools. The IT infrastructure managed by this process includes both physical equipment, such as bare -metal servers, as well as virtual machines, and associated configuration resources…"
From the beginning, the goal of IaC has been to deploy an infrastructure with files (declarative description) representing resources (i.e. components, variables, etc.). Ideally, to track changes, the files are in a source code repository.
Many tools exist to perform this task, Ansible and Terraform are among them.
But, before comparing, let’s quickly return to the paradigms commonly mentioned in IaC
When you want to change an element of an existing infrastructure.
Mutable In a Mutable infrastructure: we update it.
Immutable In an Immutable infrastructure: we destroy it and recreate it
Imperative Specifies the How? It’s a workflow, a procedure
Declarative Describes the What to do? It’s a model
Terraform is a declarative tool: it will achieve the desired state. Below is an example of provisioning an Nginx container with Docker and Terraform:
Terraform HCL:
Ansible is an imperative tool, at the module level. It provides, on a larger scale, the orchestration of modules. Loop, test condition, wait, repeat, error detection… are possible. In the same way as the coding language.
Ansible Yaml:
Terraform
Terraform loads all required files, binaries, configurations, and modules. Once everything is configured, Terraform compares the persisted state and the objects in the real infrastructure. Then, Terraform executes the commands to apply on this infrastructure. Finally, a new state is saved.
Communication between the Terraform CLI and targeted hosts depends on vendors. The protocol between Terraform and vendor plugins is gRPC. Vendor plugins use their own API to interact with the framework.
Ansible
Ansible gets the required dependencies for each playbook. Then it retrieves the list of target hosts from the inventory and plays the commands. There is no centralized state, a caching mechanism allows for optimization and eventual replay.
Communication with hosts is done by default using the SSH protocol. For the cloud, Ansible plugins (aws, azure, gcp,…) communicate with the infrastructure in the same way as Terraform providers (via web services).
Both tools have a public registry to extend their capability.
Terraform Registry is new with approximately 1500 providers.
Ansible Galaxy has a large number of extensions (roles, plugins, collections,…), with around 30,000 items.
File structure
Terraform has a lightweight structure. Simple conventions are applied.
Ansible has a folder/yml file structure that can lead to a complex project.
The precedence of variables in Ansible speaks to the complex structure you can achieve.
Ansible | Terraform | |
---|---|---|
Purpose of the tool | Help infrastructure setup from code. | Manage an infrastructure to achieve consistency and predictability of deployments |
infrastructure | Mutable: Immutable possible. Depends on modules and how to code | Immutable: Updating of the infra also possible |
Language | Yaml, JSON | HCL (DSL Hashicorp), JSON |
Provisioning | Yes | Yes |
Setup | Yes | Yes |
Orchestration | Yes, good resource orchestration capability | Yes, partially automatic: Depends on vendor implementation |
State | No: A state exists per module, it is discovered during execution | Yes centralized: It is still possible to use stateless Terraform. |
Idempotence | Depends on modules | Yes |
Agentless | Yes | Yes |
Cooperation with other tools | Yes | Yes |
Language Source | Python | Go |
Setup | Easy, multiple binaries | Easy, a binary |
SourceCode | https://github.com/ansible/ansible | https://github.com/hashicorp/terraform |
Language (see Pulumi which supports Python, Go…) | yaml | HCL or JSON |
Literature | Excellent | Excellent |
OSS License | apache | MPL |
Popularity (google trends) | Good | Good |
Activity (Github) | Committers (5K) Stars (50K) | Committers (1.5K) Stars (30K) |
Last month: | Last month: | |
16 merged Pull Request | 67 merged Pull Request | |
25 closed issues | 93 closed issues | |
Commits/y last 1y: | Commits/y last 1y: | |
1230 (24 commits/week) | 1636 (31 commits/week) |
Google Trend: Global Search
Google Trend: by country
Ansible | Terraform | |
---|---|---|
Editor (VSCode) | Ansible RedHat plugin (5K installed) | Terraform Hashicorp plugin (+1.2M installed) |
Dependency Management | When using out-of-the-box modules or developing Items: Collections improves dependency management. No specific repository needed, Collections supports Git and version control | Public providers and modules are well managed. Even though Git is supported for Modules, to deploy, a private registry is still useful (ie Cloudsmith, Terraform Cloud,…) JFrog, Nexus do not yet support Terraform |
Build and run | Better to use containers | Better to use containers |
Orchestration | You can chain Ansible tasks, manually. Many control possibilities exist | Terraform automatically handles dependency and orchestration,…until you need to explicitly link tasks |
Google Cloud GCP | GCP Ansible Plugin has 171 supported functions | GCP Terraform Providers has 929 supported functions (not 100% coverage) |
GCP BigQuery | Ansible implements ONLY 2 objects: dataset, table | Terraform implements almost the entire API: connection, dataset, dataset_access, dataset_iam, data_transfer, job, routine, reservation, table, table_iam |
AWS | Ansible has weak AWS support, ONLY ~30 services | Terraform implements 800 functions covering AWS services well |
bigip | Good support | Good support |
Open Stack | Good support | Good support |
| Ansible | Terraform | |
---|---|---|---|
Testing | Jinja test: External tools | no test: External tools: Terratest | |
Security | no RBAC it’s a CLI. Vault builtin exists to do encryption | no RBAC it’s a CLI. Sensitive data can be masked. Beware of the "terraform destroy" command which can delete an entire infrastructure | |
CICD | Jenkins Ansible & Tower / AWX GitLab GitHub actions (Lint…) | GitLab Jenkins GitHub actions (Lint, Test…) | |
Web interface (collaboration, audit, jobs,…) | Tower (AWX Open Source version) | Terraform Cloud (up to 5 users). Terraform Enterprise |
Terraform and Ansible are CLIs, it is recommended to run the code in the CICD tool and/or in a container to link to the company context (access rights, configurations, secrets…)
Terraform allows destroying the entire infrastructure with a single command: "terraform destroy", it is strongly recommended to protect access to the command line interface.
STRENGTH
ANSIBLE
TERRAFORM
WEAKNESS
ANSIBLE
TERRAFORM
How to choose the right tool?
This is the first question to ask: what layer do you want to dedicate your tool to?
Terraform is the best tool for cloud resource management
Assess your needs:
Ansible has more flexibility and huge support on "legacy" systems.
Are you ready to adopt enacted practices in GitOps?
Terraform is not enough to implement GitOps, Ansible lags behind, especially without a centralized state implementation.
The scenario to have the two together is also commonly used.
Example "rebuild an entire infrastructure from scratch":