Automating Infrastructure with Terraform and Ansible
Automating Infrastructure with Terraform and Ansible
Infrastructure as Code (IaC) has become essential in modern DevOps practices. In this post, I'll share my approach to combining Terraform and Ansible for end-to-end infrastructure automation.
The Two-Phase Approach
I use a two-phase approach for infrastructure automation:
- Terraform: Provision infrastructure (servers, networks, storage)
- Ansible: Configure and manage the provisioned resources
This separation of concerns makes the code more maintainable and follows the principle of using the right tool for the job.
Why This Combination?
Terraform Strengths
- Declarative syntax for infrastructure
- Excellent state management
- Multi-cloud support
- Large provider ecosystem
Ansible Strengths
- Agentless architecture
- Great for configuration management
- Powerful templating with Jinja2
- Extensive module library
Example Workflow
Here's a typical workflow I use:
1. Terraform Provisions Infrastructure
resource "aws_instance" "web_servers" {
count = 3
ami = var.ami_id
instance_type = "t3.medium"
tags = {
Name = "web-server-${count.index + 1}"
Role = "web"
}
}
# Generate Ansible inventory
resource "local_file" "ansible_inventory" {
content = templatefile("${path.module}/inventory.tpl", {
web_servers = aws_instance.web_servers[*].public_ip
})
filename = "../ansible/inventory/hosts"
}
2. Ansible Configures the Servers
---
- name: Configure web servers
hosts: web
become: yes
tasks:
- name: Install Nginx
apt:
name: nginx
state: present
update_cache: yes
- name: Copy configuration
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
Best Practices
- Use Terraform workspaces for different environments
- Store Terraform state remotely (S3, Azure Blob, etc.)
- Encrypt sensitive data in Ansible with Vault
- Use dynamic inventories generated by Terraform
- Keep modules/roles reusable and well-documented
Integration Tips
Automatic Inventory Generation
Use Terraform's local_file resource to automatically generate Ansible inventories:
locals {
ansible_groups = {
web = aws_instance.web_servers[*].public_ip
db = aws_instance.db_servers[*].private_ip
}
}
Passing Variables
Use Terraform outputs to create Ansible variable files:
output "database_endpoint" {
value = aws_db_instance.main.endpoint
}
Conclusion
Combining Terraform and Ansible provides a powerful, flexible approach to infrastructure automation. Terraform handles the "what" (infrastructure resources), while Ansible manages the "how" (configuration and state).
This separation makes your automation more maintainable and allows each tool to focus on what it does best.