121 lines
3.8 KiB
YAML
121 lines
3.8 KiB
YAML
---
|
|
# Ansible Playbook: Update Production Deployment
|
|
# Purpose: Pull new Docker image and update services with zero-downtime
|
|
# Usage: Called by Gitea Actions or manual deployment
|
|
|
|
- name: Update Production Services with New Image
|
|
hosts: production_server
|
|
become: no
|
|
vars:
|
|
image_tag: "{{ image_tag | default('latest') }}"
|
|
git_commit_sha: "{{ git_commit_sha | default('unknown') }}"
|
|
deployment_timestamp: "{{ deployment_timestamp | default(ansible_date_time.iso8601) }}"
|
|
registry_url: "git.michaelschiemer.de:5000"
|
|
image_name: "framework"
|
|
stack_name: "framework"
|
|
|
|
tasks:
|
|
- name: Log deployment start
|
|
debug:
|
|
msg: |
|
|
🚀 Starting deployment
|
|
Image: {{ registry_url }}/{{ image_name }}:{{ image_tag }}
|
|
Commit: {{ git_commit_sha }}
|
|
Time: {{ deployment_timestamp }}
|
|
|
|
- name: Pull new Docker image
|
|
docker_image:
|
|
name: "{{ registry_url }}/{{ image_name }}"
|
|
tag: "{{ image_tag }}"
|
|
source: pull
|
|
force_source: yes
|
|
register: image_pull
|
|
retries: 3
|
|
delay: 5
|
|
until: image_pull is succeeded
|
|
|
|
- name: Tag image as latest locally
|
|
docker_image:
|
|
name: "{{ registry_url }}/{{ image_name }}:{{ image_tag }}"
|
|
repository: "{{ registry_url }}/{{ image_name }}"
|
|
tag: latest
|
|
source: local
|
|
|
|
- name: Update web service with rolling update
|
|
docker_swarm_service:
|
|
name: "{{ stack_name }}_web"
|
|
image: "{{ registry_url }}/{{ image_name }}:{{ image_tag }}"
|
|
force_update: yes
|
|
update_config:
|
|
parallelism: 1
|
|
delay: 10s
|
|
failure_action: rollback
|
|
monitor: 30s
|
|
max_failure_ratio: 0.3
|
|
rollback_config:
|
|
parallelism: 1
|
|
delay: 5s
|
|
state: present
|
|
register: web_update
|
|
|
|
- name: Update queue-worker service
|
|
docker_swarm_service:
|
|
name: "{{ stack_name }}_queue-worker"
|
|
image: "{{ registry_url }}/{{ image_name }}:{{ image_tag }}"
|
|
force_update: yes
|
|
update_config:
|
|
parallelism: 1
|
|
delay: 10s
|
|
failure_action: rollback
|
|
state: present
|
|
register: worker_update
|
|
|
|
- name: Wait for services to stabilize
|
|
pause:
|
|
seconds: 20
|
|
|
|
- name: Verify service status
|
|
shell: |
|
|
docker service ps {{ stack_name }}_web --filter "desired-state=running" --format "{{`{{.CurrentState}}`}}" | head -1
|
|
register: service_state
|
|
changed_when: false
|
|
|
|
- name: Check if deployment succeeded
|
|
fail:
|
|
msg: "Service deployment failed: {{ service_state.stdout }}"
|
|
when: "'Running' not in service_state.stdout"
|
|
|
|
- name: Get running replicas count
|
|
shell: |
|
|
docker service ls --filter "name={{ stack_name }}_web" --format "{{`{{.Replicas}}`}}"
|
|
register: replicas
|
|
changed_when: false
|
|
|
|
- name: Record deployment in history
|
|
copy:
|
|
content: |
|
|
Deployment: {{ deployment_timestamp }}
|
|
Image: {{ registry_url }}/{{ image_name }}:{{ image_tag }}
|
|
Commit: {{ git_commit_sha }}
|
|
Status: SUCCESS
|
|
Replicas: {{ replicas.stdout }}
|
|
dest: "/home/deploy/deployments/{{ image_tag }}.log"
|
|
mode: '0644'
|
|
|
|
- name: Display deployment summary
|
|
debug:
|
|
msg: |
|
|
✅ Deployment completed successfully
|
|
|
|
Image: {{ registry_url }}/{{ image_name }}:{{ image_tag }}
|
|
Commit: {{ git_commit_sha }}
|
|
Web Service: {{ web_update.changed | ternary('UPDATED', 'NO CHANGE') }}
|
|
Worker Service: {{ worker_update.changed | ternary('UPDATED', 'NO CHANGE') }}
|
|
Replicas: {{ replicas.stdout }}
|
|
Time: {{ deployment_timestamp }}
|
|
|
|
handlers:
|
|
- name: Cleanup old images
|
|
shell: docker image prune -af --filter "until=72h"
|
|
changed_when: false
|