D10.6 Πρακτικό παράδειγμα — Production Swarm 🏭
Αρχιτεκτονική
3-node Swarm cluster:
manager-01 ┐
manager-02 ├── Manager nodes (Raft quorum)
manager-03 ┘
worker-01 ┐
worker-02 ├── Worker nodes (εκτελούν containers)
worker-03 ┘
Services:
├── nginx (3 replicas, workers, ingress :80/:443)
├── myapp (2 replicas, workers)
├── postgres (1 replica, manager, volume)
├── redis (1 replica, worker)
└── node_exporter (global, all nodes)
Full playbook
---
# swarm-production.yml
- name: "Init Swarm cluster"
import_playbook: setup-swarm.yml
# ─────────────────────────────────────────────────────
- name: "Setup Swarm infrastructure"
hosts: manager-01
become: true
gather_facts: true
vars:
app_version: "{{ new_version | mandatory }}"
app_domain: "example.com"
tasks:
# ════════════════════════════════════════
# NETWORKS
# ════════════════════════════════════════
- name: "🌐 Frontend overlay network"
community.docker.docker_network:
name: frontend
driver: overlay
state: present
- name: "🌐 Backend overlay network (internal)"
community.docker.docker_network:
name: backend
driver: overlay
state: present
internal: true
# ════════════════════════════════════════
# SECRETS
# ════════════════════════════════════════
- name: "🔐 Database secret"
community.docker.docker_secret:
name: pg_password
data: "{{ vault_postgres_pass }}"
state: present
no_log: true
- name: "🔐 App secret"
community.docker.docker_secret:
name: app_secret_key
data: "{{ vault_app_secret }}"
state: present
no_log: true
# ════════════════════════════════════════
# CONFIGS
# ════════════════════════════════════════
- name: "⚙️ Nginx config"
community.docker.docker_config:
name: nginx_conf
data: "{{ lookup('template', 'templates/nginx.conf.j2') }}"
state: present
# ════════════════════════════════════════
# NODE LABELS
# ════════════════════════════════════════
- name: "🏷️ Label manager nodes (storage)"
ansible.builtin.command:
cmd: "docker node update --label-add storage=true {{ item }}"
loop: "{{ groups['swarm_managers'] }}"
changed_when: true
# ════════════════════════════════════════
# SERVICES
# ════════════════════════════════════════
- name: "📡 node_exporter (global)"
community.docker.docker_swarm_service:
name: node_exporter
image: "prom/node-exporter:v1.7.0"
state: present
mode: global
mounts:
- source: /
target: /host
type: bind
readonly: true
publish:
- published_port: 9100
target_port: 9100
mode: host
- name: "🐘 PostgreSQL (manager, 1 replica)"
community.docker.docker_swarm_service:
name: postgres
image: "postgres:15-alpine"
state: present
replicas: 1
placement:
constraints:
- "node.role == manager"
- "node.labels.storage == true"
networks:
- name: backend
secrets:
- secret_name: pg_password
filename: /run/secrets/pg_password
env:
POSTGRES_PASSWORD_FILE: /run/secrets/pg_password
POSTGRES_USER: appuser
POSTGRES_DB: myapp
mounts:
- source: postgres_data
target: /var/lib/postgresql/data
type: volume
- name: "🚀 App service (2 replicas, rolling)"
community.docker.docker_swarm_service:
name: myapp
image: "myapp:{{ app_version }}"
state: present
replicas: 2
placement:
constraints:
- "node.role == worker"
networks:
- name: frontend
- name: backend
secrets:
- secret_name: app_secret_key
filename: /run/secrets/secret_key
env:
NODE_ENV: production
SECRET_FILE: /run/secrets/secret_key
update_config:
parallelism: 1
delay: 15s
failure_action: rollback
order: start-first
- name: "🌐 Nginx (3 replicas)"
community.docker.docker_swarm_service:
name: nginx
image: "nginx:1.25-alpine"
state: present
replicas: 3
placement:
constraints:
- "node.role == worker"
networks:
- name: frontend
configs:
- config_name: nginx_conf
filename: /etc/nginx/nginx.conf
publish:
- published_port: 80
target_port: 80
mode: ingress
- published_port: 443
target_port: 443
mode: ingress
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
# ════════════════════════════════════════
# VERIFICATION
# ════════════════════════════════════════
- name: "📊 Service list"
ansible.builtin.command: >
docker service ls --format "table {{ '{{' }}.Name{{ '}}' }}\t{{ '{{' }}.Replicas{{ '}}' }}\t{{ '{{' }}.Image{{ '}}' }}"
register: services
changed_when: false
- name: "✅ Swarm Production Report"
ansible.builtin.debug:
msg:
- "╔══════════════════════════════════════╗"
- "║ 🐝 SWARM PRODUCTION DEPLOYED! ║"
- "╠══════════════════════════════════════╣"
- "{{ services.stdout_lines }}"
- "╚══════════════════════════════════════╝"
# Deploy
ansible-playbook swarm-production.yml \
-e "new_version=2.5.0" \
--ask-vault-pass
# Update μόνο app service
ansible-playbook swarm-production.yml \
-e "new_version=2.6.0" \
--tags app \
--ask-vault-pass
Σύνοψη Κεφ. D10
Docker Swarm με Ansible
│
├── D10.1: Concepts (Manager/Worker, Service/Task)
├── D10.2: Setup (init + join managers + join workers)
├── D10.3: Services (replicated/global) + Stacks
├── D10.4: Rolling updates + scaling + rollback
├── D10.5: Secrets (encrypted) + Configs
└── D10.6: Production stack (6 services, 3+3 nodes)
Swarm = Simple HA για Docker → Bridge to Kubernetes