This project implements zero-downtime deployments for FastAPI applications using Ansible and Nginx with a blue/green deployment strategy.
- Vagrant 2.2+
- Ansible 2.9+
- VirtualBox 6.0+
- Python 3.6+
- Load Balancer:
lb.example.com
(Nginx) - Blue Environment:
blue.example.com
- Green Environment:
green.example.com
.
├── playbooks/
│ ├── deploy.yml # Deploys application
│ ├── setup_loadbalancer.yml # Configures Nginx
│ ├── switch.yml # Switches traffic
│ └── cleanup.yml # Cleans old deployments
├── templates/
│ ├── fastapi.service.j2 # Systemd service template
│ └── loadbalancer.conf.j2 # Nginx config template
├── inventory/
│ └── production # Inventory file
└── app/
├── blue/ # Blue deployment files
└── green/ # Green deployment files
# Create all VMs
vagrant up
# Configure load balancer
ansible-playbook -i inventory/production playbooks/setup_loadbalancer.yml
ansible-playbook -i inventory/production playbooks/deploy.yml \
-e "target_group=blue deployment_color=blue"
ansible-playbook -i inventory/production playbooks/deploy.yml \
-e "target_group=green deployment_color=green"
# Directly access green environment
curl http://green.example.com:8000
# Or through load balancer with test header
curl -H "X-Deployment: green" http://lb.example.com
ansible-playbook -i inventory/production playbooks/switch.yml \
-e "deployment_color=green"
ansible-playbook -i inventory/production playbooks/cleanup.yml \
-e "old_deployment_group=blue old_deployment_color=blue"
# Switch back to blue
ansible-playbook -i inventory/production playbooks/switch.yml \
-e "deployment_color=blue"
# Clean up green if needed
ansible-playbook -i inventory/production playbooks/cleanup.yml \
-e "old_deployment_group=green old_deployment_color=green"
Check current traffic distribution:
vagrant ssh lb
sudo tail -f /var/log/nginx/access.log | awk '{print $6}' | sort | uniq -c
Validate Nginx config:
vagrant ssh lb
sudo nginx -t
View service status:
# On blue/green nodes
systemctl status fastapi-blue
systemctl status fastapi-green
Set in inventory/production
:
[all:vars]
app_port=8000
domain=example.com
For canary releases:
ansible-playbook -i inventory/production playbooks/switch.yml \
-e "deployment_color=green blue_weight=90 green_weight=10"
ansible-playbook -i inventory/production playbooks/switch.yml \
-e "deployment_color=green blue_weight=50 green_weight=50"
ansible-playbook -i inventory/production playbooks/switch.yml \
-e "deployment_color=green blue_weight=10 green_weight=90"
ansible-playbook -i inventory/production playbooks/switch.yml \
-e "deployment_color=green blue_weight=0 green_weight=100"
- Always test new deployments before switching traffic
- Monitor both environments during cutover
- Keep previous deployment until new one is verified stable
- Use low DNS TTL if using DNS-based switching
- Implement health checks in your application
Nginx fails to reload:
- Check syntax:
sudo nginx -t
- Verify ports are open
- Ensure DNS resolution works
Service fails to start:
- Check logs:
journalctl -u fastapi-blue
- Verify Python dependencies
- Check port availability
This README provides:
1. Clear step-by-step deployment instructions
2. Rollback procedures
3. Maintenance commands
4. Customization options
5. Troubleshooting tips
6. Best practices
The workflow ensures zero-downtime deployments with proper testing and rollback capabilities.