124 lines
4.0 KiB
YAML
124 lines
4.0 KiB
YAML
---
|
|
# Ansible Playbook: Emergency Rollback
|
|
# Purpose: Rollback to previous working deployment
|
|
# Usage: ansible-playbook -i inventory/production.yml playbooks/rollback.yml
|
|
|
|
- name: Rollback Production Deployment
|
|
hosts: production_server
|
|
become: no
|
|
vars:
|
|
registry_url: "git.michaelschiemer.de:5000"
|
|
image_name: "framework"
|
|
stack_name: "framework"
|
|
rollback_tag: "{{ rollback_tag | default('latest') }}"
|
|
|
|
tasks:
|
|
- name: Display rollback warning
|
|
debug:
|
|
msg: |
|
|
⚠️ ROLLBACK IN PROGRESS
|
|
|
|
This will revert services to a previous image.
|
|
Current target: {{ rollback_tag }}
|
|
|
|
- name: Pause for confirmation (manual runs only)
|
|
pause:
|
|
prompt: "Press ENTER to continue with rollback, or Ctrl+C to abort"
|
|
when: ansible_check_mode is not defined
|
|
|
|
- name: Get list of available image tags
|
|
shell: |
|
|
docker images {{ registry_url }}/{{ image_name }} --format "{{`{{.Tag}}`}}" | grep -v buildcache | head -10
|
|
register: available_tags
|
|
changed_when: false
|
|
|
|
- name: Display available tags
|
|
debug:
|
|
msg: |
|
|
Available image tags for rollback:
|
|
{{ available_tags.stdout_lines | join('\n') }}
|
|
|
|
- name: Verify rollback image exists
|
|
docker_image:
|
|
name: "{{ registry_url }}/{{ image_name }}"
|
|
tag: "{{ rollback_tag }}"
|
|
source: pull
|
|
register: rollback_image
|
|
ignore_errors: yes
|
|
|
|
- name: Fail if image doesn't exist
|
|
fail:
|
|
msg: "Rollback image {{ registry_url }}/{{ image_name }}:{{ rollback_tag }} not found"
|
|
when: rollback_image is failed
|
|
|
|
- name: Rollback web service
|
|
docker_swarm_service:
|
|
name: "{{ stack_name }}_web"
|
|
image: "{{ registry_url }}/{{ image_name }}:{{ rollback_tag }}"
|
|
force_update: yes
|
|
update_config:
|
|
parallelism: 2
|
|
delay: 5s
|
|
state: present
|
|
register: web_rollback
|
|
|
|
- name: Rollback queue-worker service
|
|
docker_swarm_service:
|
|
name: "{{ stack_name }}_queue-worker"
|
|
image: "{{ registry_url }}/{{ image_name }}:{{ rollback_tag }}"
|
|
force_update: yes
|
|
update_config:
|
|
parallelism: 1
|
|
delay: 5s
|
|
state: present
|
|
register: worker_rollback
|
|
|
|
- name: Wait for rollback to complete
|
|
pause:
|
|
seconds: 30
|
|
|
|
- name: Verify rollback success
|
|
shell: |
|
|
docker service ps {{ stack_name }}_web --filter "desired-state=running" --format "{{`{{.CurrentState}}`}}" | head -1
|
|
register: rollback_state
|
|
changed_when: false
|
|
|
|
- name: Test service health
|
|
uri:
|
|
url: "https://michaelschiemer.de/health"
|
|
validate_certs: no
|
|
status_code: [200, 302]
|
|
timeout: 10
|
|
register: health_check
|
|
ignore_errors: yes
|
|
|
|
- name: Record rollback in history
|
|
copy:
|
|
content: |
|
|
Rollback: {{ ansible_date_time.iso8601 }}
|
|
Previous Image: {{ registry_url }}/{{ image_name }}:latest
|
|
Rollback Image: {{ registry_url }}/{{ image_name }}:{{ rollback_tag }}
|
|
Status: {{ health_check.status | default('UNKNOWN') }}
|
|
Reason: Manual rollback or deployment failure
|
|
dest: "/home/deploy/deployments/rollback-{{ ansible_date_time.epoch }}.log"
|
|
mode: '0644'
|
|
|
|
- name: Display rollback summary
|
|
debug:
|
|
msg: |
|
|
{% if health_check is succeeded %}
|
|
✅ Rollback completed successfully
|
|
{% else %}
|
|
❌ Rollback completed but health check failed
|
|
{% endif %}
|
|
|
|
Image: {{ registry_url }}/{{ image_name }}:{{ rollback_tag }}
|
|
Web Service: {{ web_rollback.changed | ternary('ROLLED BACK', 'NO CHANGE') }}
|
|
Worker Service: {{ worker_rollback.changed | ternary('ROLLED BACK', 'NO CHANGE') }}
|
|
Health Status: {{ health_check.status | default('FAILED') }}
|
|
|
|
- name: Alert if rollback failed
|
|
fail:
|
|
msg: "Rollback completed but health check failed. Manual intervention required."
|
|
when: health_check is failed
|