🚀 Introduction: The Power of IaC for Resilient Deployments
Hook: Tired of manual deployments? Imagine your web app going down because a single server failed painful, avoidable, and common when infrastructure and configuration are done by hand.
Introduce IaC: Infrastructure as Code (IaC) lets you describe infrastructure in declarative files you can version, test, and reuse. With IaC you get consistency, repeatability, speed, and fewer manual mistakes.
Project Goal: This guide walks you through building a highly available (HA) Flask web application on AWS, fully automated using Terraform for infrastructure provisioning and Ansible for application configuration and deployment.
Key Takeaways: After this guide you'll understand:
- How Terraform and Ansible complement each other.
- Basic HA design patterns on AWS (multi-AZ, multiple instances).
- How to provision infra, generate dynamic inventories, and deploy a Flask app across multiple instances.
đź’ˇ Why Terraform AND Ansible? Understanding the Synergy
Terraform
Think of Terraform as the architect of your cloud environment. It’s declarative, provider-rich, and ideal for creating resources like VPCs, subnets, security groups, and EC2 instances.
Ansible
Ansible is the craftsman that configures what Terraform builds. It’s agentless (SSH-based), idempotent, and great for installing packages, copying app files, and starting services.
The Handover
A key pattern: Terraform provisions EC2 instances and writes an inventory.ini that Ansible uses. Terraform’s local_file resource or templatefile() can dynamically render an Ansible inventory containing instance IPs and ansible_user variables creating a seamless handoff.
🏗️ Architecting for High Availability: Our AWS Design
High-Level Diagram:
+------------------+ +-----------------------+ +-------------------+ +---------------------+ +---------------------+ +----------------------+
| 1. Local Dev Env | --> | 2. Code Repository | --> | 3. Terraform Init | --> | 4. Terraform Apply | --> | 5. Ansible Playbook | --> | 6. Application Access|
| (KodeKloud) | | (ha-flask-project/) | | (Downloads AWS | | (Builds AWS Infra) | | (Configures EC2s) | |(Browser/Verification)|
| | | - main.tf | | Provider) | | - VPC, Subnets | | - Installs Python | | - http://IP:8000 |
| | | - ansible/* | | | | - IGW, RouteTable | | - Deploys Flask App | | - Two different IPs |
| | | - .gitignore | | | | - Security Group | | - Starts Flask Svc | | - HA Adventure Game |
| | | | | | | - 2 EC2 Instances | | | | |
| | | | | | | - Generates | | | | |
| | | | | | |ansible/inventory.ini| | | | |
+------------------+ +-----------------------+ +-------------------+ +---------------------+ +---------------------+ +----------------------+
|
| (Wait 90s for SSH)
V
+---------------------+
| 4a. AWS Resources |
| (Live) |
+---------------------+
VPC (Your Private Cloud):
Create a dedicated VPC (e.g. 10.100.0.0/16) instead of the default for isolation and predictable network layout.
Public Subnets & Multi-AZ:
Use two public subnets in distinct AZs for redundancy. Terraform’s data "aws_availability_zones" {} + count on subnet resources is a clean pattern.
Security Groups:
Open SSH (22) for admin (tighten in prod) and open the Flask port (e.g. 8000) for demo purposes. For production, restrict CIDRs and use a load balancer instead of open ports.
EC2 Instances:
Use count = 2 on aws_instance to create one EC2 per AZ (e.g. t2.micro for demo), and pass in key_name for SSH access.
Commands
terraform init
terraform plan # review which resources Terraform will create
terraform apply # apply infrastructure changes (type 'yes' to confirm)
After apply you’ll see success and the ansible/inventory.ini created by Terraform.
Tips & Troubleshooting
-
InvalidKeyPair.NotFound: Ensurekey_namematches a key pair present in your AWS region (aws ec2 describe-key-pairsor check console). - YAML errors like
mapping values not allowed: usually a colon or indentation problem runansible-playbook --syntax-checkon playbooks. - If Terraform can’t fetch AZs: check IAM permissions or region.
Running the playbook
ansible-playbook -i ansible/inventory.ini ansible/run_deployment.yml
You should see tasks succeed for both hosts.
Common Ansible issues
-
Permission denied (publickey): check SSH key, EC2key_name, and in your generated inventory includeansible_user=ubuntu(orec2-user) to match the AMI. - Put
[webservers:vars] ansible_user=ubuntuin the inventory template if needed.
âś… Verification: Experience the HA Adventure Game
How to Access
- Terraform output (or AWS console) shows public IPs. Use:
http://<IP-1>:8000
http://<IP-2>:8000
- Refresh the pages; the app displays the hostname of whichever instance served the request.
Proof of HA
- Visiting both IPs shows different hostnames (two different servers). This proves multi-instance deployment across AZs.
- Try putting an item in the game (if you implement session or DB later) to show state isn’t shared between servers good motivation to add a shared DB or load balancer next.
Screenshot
🗑️ Cleanup: Destroying Your Resources
Importance: Always clean up cloud resources to avoid unexpected billing.
Command
terraform destroy
Confirm by typing yes when prompted. This will remove the EC2 instances, VPC, subnets, and any other resources created by Terraform.
🚀 Conclusion & Next Steps
Recap: You built an HA Flask app: Terraform created a multi-AZ foundation and generated an Ansible inventory; Ansible configured each server and deployed a small Flask app. This pattern provides repeatable infrastructure and consistent application deployments.
Future Enhancements
- Load Balancer (ALB/ELB): Provide a single entry point and health checks.
- Auto Scaling Group (ASG): Automatically scale instances by load.
- Centralized Terraform State: Use S3 + DynamoDB for remote state and locking.
- CI/CD: Integrate GitHub Actions to run Terraform + Ansible on merges.
- Shared Database (RDS): Move game state to a common DB for persistence.
- Configuration Management Improvements: Use systemd unit files or dockerize the app for better process management and monitoring.
Call to Action: Try it yourself fork the repo, adapt region/AMI/keys to your env, and share improvements!
đź”— GitHub Repository
👉 Hritikraj8804/terraform-ansible-ha-flask
đź’Ľ Connect with me on LinkedIn
👉 https://www.linkedin.com/in/hritik-raj-8804hr/
🌟 Conclusion
By combining Terraform and Ansible, you achieve a clean separation of concerns:
- Terraform builds your infrastructure once.
- Ansible ensures consistent app setup every time.
Simple, automated, and scalable that’s real DevOps power 💪
If you enjoyed this, follow for more DevOps deep dives and IaC tutorials.







Top comments (0)