Sanitized mirror from private repository - 2026-03-24 12:45:58 UTC
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
---
|
||||
# Container Dependency Orchestrator
|
||||
# Smart restart ordering with dependency management across hosts
|
||||
# Run with: ansible-playbook -i hosts.ini playbooks/container_dependency_orchestrator.yml
|
||||
|
||||
- name: Container Dependency Orchestration
|
||||
hosts: all
|
||||
gather_facts: yes
|
||||
vars:
|
||||
# Define service dependency tiers (restart order)
|
||||
dependency_tiers:
|
||||
tier_1_infrastructure:
|
||||
- "postgres"
|
||||
- "mariadb"
|
||||
- "mysql"
|
||||
- "redis"
|
||||
- "memcached"
|
||||
- "mongo"
|
||||
tier_2_core_services:
|
||||
- "authentik-server"
|
||||
- "authentik-worker"
|
||||
- "gitea"
|
||||
- "portainer"
|
||||
- "nginx-proxy-manager"
|
||||
tier_3_applications:
|
||||
- "plex"
|
||||
- "sonarr"
|
||||
- "radarr"
|
||||
- "lidarr"
|
||||
- "bazarr"
|
||||
- "prowlarr"
|
||||
- "jellyseerr"
|
||||
- "immich-server"
|
||||
- "paperlessngx"
|
||||
tier_4_monitoring:
|
||||
- "prometheus"
|
||||
- "grafana"
|
||||
- "alertmanager"
|
||||
- "node_exporter"
|
||||
- "snmp_exporter"
|
||||
tier_5_utilities:
|
||||
- "watchtower"
|
||||
- "syncthing"
|
||||
- "ntfy"
|
||||
|
||||
# Cross-host dependencies
|
||||
cross_host_dependencies:
|
||||
- service: "immich-server"
|
||||
depends_on:
|
||||
- host: "atlantis"
|
||||
service: "postgres"
|
||||
- service: "gitea"
|
||||
depends_on:
|
||||
- host: "calypso"
|
||||
service: "postgres"
|
||||
|
||||
tasks:
|
||||
- name: Gather container information
|
||||
docker_host_info:
|
||||
containers: yes
|
||||
register: docker_info
|
||||
when: ansible_facts['os_family'] != "Synology"
|
||||
|
||||
- name: Get Synology container info via docker command
|
||||
shell: docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
|
||||
register: synology_containers
|
||||
when: ansible_facts['os_family'] == "Synology"
|
||||
become: yes
|
||||
|
||||
- name: Parse container information
|
||||
set_fact:
|
||||
running_containers: "{{ docker_info.containers | selectattr('State', 'equalto', 'running') | map(attribute='Names') | map('first') | list if docker_info is defined else [] }}"
|
||||
stopped_containers: "{{ docker_info.containers | rejectattr('State', 'equalto', 'running') | map(attribute='Names') | map('first') | list if docker_info is defined else [] }}"
|
||||
|
||||
- name: Categorize containers by dependency tier
|
||||
set_fact:
|
||||
tier_containers:
|
||||
tier_1: "{{ running_containers | select('match', '.*(' + (dependency_tiers.tier_1_infrastructure | join('|')) + ').*') | list }}"
|
||||
tier_2: "{{ running_containers | select('match', '.*(' + (dependency_tiers.tier_2_core_services | join('|')) + ').*') | list }}"
|
||||
tier_3: "{{ running_containers | select('match', '.*(' + (dependency_tiers.tier_3_applications | join('|')) + ').*') | list }}"
|
||||
tier_4: "{{ running_containers | select('match', '.*(' + (dependency_tiers.tier_4_monitoring | join('|')) + ').*') | list }}"
|
||||
tier_5: "{{ running_containers | select('match', '.*(' + (dependency_tiers.tier_5_utilities | join('|')) + ').*') | list }}"
|
||||
|
||||
- name: Display container categorization
|
||||
debug:
|
||||
msg: |
|
||||
Container Dependency Analysis for {{ inventory_hostname }}:
|
||||
|
||||
Tier 1 (Infrastructure): {{ tier_containers.tier_1 | length }} containers
|
||||
{{ tier_containers.tier_1 | join(', ') }}
|
||||
|
||||
Tier 2 (Core Services): {{ tier_containers.tier_2 | length }} containers
|
||||
{{ tier_containers.tier_2 | join(', ') }}
|
||||
|
||||
Tier 3 (Applications): {{ tier_containers.tier_3 | length }} containers
|
||||
{{ tier_containers.tier_3 | join(', ') }}
|
||||
|
||||
Tier 4 (Monitoring): {{ tier_containers.tier_4 | length }} containers
|
||||
{{ tier_containers.tier_4 | join(', ') }}
|
||||
|
||||
Tier 5 (Utilities): {{ tier_containers.tier_5 | length }} containers
|
||||
{{ tier_containers.tier_5 | join(', ') }}
|
||||
|
||||
- name: Check container health status
|
||||
shell: docker inspect {{ item }} --format='{{.State.Health.Status}}' 2>/dev/null || echo "no-healthcheck"
|
||||
register: health_checks
|
||||
loop: "{{ running_containers }}"
|
||||
become: yes
|
||||
failed_when: false
|
||||
|
||||
- name: Identify unhealthy containers
|
||||
set_fact:
|
||||
unhealthy_containers: "{{ health_checks.results | selectattr('stdout', 'equalto', 'unhealthy') | map(attribute='item') | list }}"
|
||||
healthy_containers: "{{ health_checks.results | selectattr('stdout', 'in', ['healthy', 'no-healthcheck']) | map(attribute='item') | list }}"
|
||||
|
||||
- name: Display health status
|
||||
debug:
|
||||
msg: |
|
||||
Container Health Status for {{ inventory_hostname }}:
|
||||
- Healthy/No Check: {{ healthy_containers | length }}
|
||||
- Unhealthy: {{ unhealthy_containers | length }}
|
||||
{% if unhealthy_containers %}
|
||||
|
||||
Unhealthy Containers:
|
||||
{% for container in unhealthy_containers %}
|
||||
- {{ container }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
- name: Restart unhealthy containers (Tier 1 first)
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: started
|
||||
restart: yes
|
||||
loop: "{{ tier_containers.tier_1 | intersect(unhealthy_containers) }}"
|
||||
when:
|
||||
- restart_unhealthy | default(false) | bool
|
||||
- unhealthy_containers | length > 0
|
||||
become: yes
|
||||
|
||||
- name: Wait for Tier 1 containers to be healthy
|
||||
shell: |
|
||||
for i in {1..30}; do
|
||||
status=$(docker inspect {{ item }} --format='{{.State.Health.Status}}' 2>/dev/null || echo "no-healthcheck")
|
||||
if [[ "$status" == "healthy" || "$status" == "no-healthcheck" ]]; then
|
||||
echo "Container {{ item }} is ready"
|
||||
exit 0
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
echo "Container {{ item }} failed to become healthy"
|
||||
exit 1
|
||||
loop: "{{ tier_containers.tier_1 | intersect(unhealthy_containers) }}"
|
||||
when:
|
||||
- restart_unhealthy | default(false) | bool
|
||||
- unhealthy_containers | length > 0
|
||||
become: yes
|
||||
|
||||
- name: Restart unhealthy containers (Tier 2)
|
||||
docker_container:
|
||||
name: "{{ item }}"
|
||||
state: started
|
||||
restart: yes
|
||||
loop: "{{ tier_containers.tier_2 | intersect(unhealthy_containers) }}"
|
||||
when:
|
||||
- restart_unhealthy | default(false) | bool
|
||||
- unhealthy_containers | length > 0
|
||||
become: yes
|
||||
|
||||
- name: Generate dependency report
|
||||
copy:
|
||||
content: |
|
||||
# Container Dependency Report - {{ inventory_hostname }}
|
||||
Generated: {{ ansible_date_time.iso8601 }}
|
||||
|
||||
## Container Summary
|
||||
- Total Running: {{ running_containers | length }}
|
||||
- Total Stopped: {{ stopped_containers | length }}
|
||||
- Healthy: {{ healthy_containers | length }}
|
||||
- Unhealthy: {{ unhealthy_containers | length }}
|
||||
|
||||
## Dependency Tiers
|
||||
|
||||
### Tier 1 - Infrastructure ({{ tier_containers.tier_1 | length }})
|
||||
{% for container in tier_containers.tier_1 %}
|
||||
- {{ container }}
|
||||
{% endfor %}
|
||||
|
||||
### Tier 2 - Core Services ({{ tier_containers.tier_2 | length }})
|
||||
{% for container in tier_containers.tier_2 %}
|
||||
- {{ container }}
|
||||
{% endfor %}
|
||||
|
||||
### Tier 3 - Applications ({{ tier_containers.tier_3 | length }})
|
||||
{% for container in tier_containers.tier_3 %}
|
||||
- {{ container }}
|
||||
{% endfor %}
|
||||
|
||||
### Tier 4 - Monitoring ({{ tier_containers.tier_4 | length }})
|
||||
{% for container in tier_containers.tier_4 %}
|
||||
- {{ container }}
|
||||
{% endfor %}
|
||||
|
||||
### Tier 5 - Utilities ({{ tier_containers.tier_5 | length }})
|
||||
{% for container in tier_containers.tier_5 %}
|
||||
- {{ container }}
|
||||
{% endfor %}
|
||||
|
||||
{% if unhealthy_containers %}
|
||||
## Unhealthy Containers
|
||||
{% for container in unhealthy_containers %}
|
||||
- {{ container }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if stopped_containers %}
|
||||
## Stopped Containers
|
||||
{% for container in stopped_containers %}
|
||||
- {{ container }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
dest: "/tmp/container_dependency_{{ inventory_hostname }}_{{ ansible_date_time.epoch }}.md"
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Display report location
|
||||
debug:
|
||||
msg: "Dependency report saved to: /tmp/container_dependency_{{ inventory_hostname }}_{{ ansible_date_time.epoch }}.md"
|
||||
Reference in New Issue
Block a user