18.2 forks — Παράλληλη εκτέλεση 🔀
Τι είναι τα forks
Το forks καθορίζει πόσα hosts εκτελούν ένα task ταυτόχρονα. Είναι η πιο άμεση ρύθμιση για performance.
📝 Αναλογία: Σκέψου τα forks σαν σεφ σε κουζίνα:
forks = 1: 1 σεφ → μαγειρεύει 1 πιάτο τη φορά forks = 5: 5 σεφ → μαγειρεύουν 5 πιάτα ταυτόχρονα forks = 20: 20 σεφ → 20 πιάτα ταυτόχρονα (αλλά χρειάζεσαι κουζίνα!)
Default τιμή και πρόβλημα
# Δες την τρέχουσα τιμή
ansible --version | grep "config file"
# Στο ansible.cfg:
[defaults]
forks = 5 # ← default: μόνο 5 hosts ταυτόχρονα!
Πρόβλημα: 50 webservers, forks=5 (default)
Task: Install nginx (2s ανά host)
Batch 1: hosts 1-5 → 2s
Batch 2: hosts 6-10 → 2s
Batch 3: hosts 11-15 → 2s
...
Batch 10: hosts 46-50 → 2s
Σύνολο: 10 batches × 2s = 20s ← μόνο για 50 hosts! ❌
Ρύθμιση forks
Μέθοδος 1: ansible.cfg (μόνιμη)
# ansible.cfg
[defaults]
forks = 20 # ← συνίσταται για τυπικό infrastructure
Μέθοδος 2: Command line (εφάπαξ)
# -f ή --forks
ansible-playbook site.yml -f 20
ansible-playbook site.yml --forks 20
# Ad-hoc command
ansible all -m ping -f 50
Μέθοδος 3: Environment variable
export ANSIBLE_FORKS=20
ansible-playbook site.yml
Πόσα forks να βάλεις;
Οδηγός επιλογής forks:
│
├── Controller specs:
│ ├── 2 CPU, 2GB RAM → forks = 10-15
│ ├── 4 CPU, 4GB RAM → forks = 20-30
│ └── 8 CPU, 8GB RAM → forks = 50+
│
├── Network:
│ ├── LAN (fast) → forks ↑↑
│ └── WAN (slow) → forks ↓
│
├── Managed hosts:
│ ├── Λίγα (< 20) → forks = αριθμός hosts
│ ├── Μεσαία (20-100) → forks = 20-30
│ └── Πολλά (100+) → forks = 50-100
│
└── Τύπος tasks:
├── Network I/O heavy → forks ↑↑ (περιμένουν)
└── CPU heavy → forks = CPU cores
💡 Γρήγορος κανόνας:
forks = αριθμός_hostsαν ο controller έχει αρκετή RAM. Κάθε fork καταναλώνει ~5-10MB RAM.
Benchmark — Μέτρηση επίδρασης
# Μέτρηση χρόνου εκτέλεσης με διαφορετικά forks
time ansible-playbook site.yml -f 1
time ansible-playbook site.yml -f 5
time ansible-playbook site.yml -f 20
time ansible-playbook site.yml -f 50
# Παράδειγμα αποτελεσμάτων (50 hosts):
# forks=1 → real 1m43s
# forks=5 → real 0m22s
# forks=20 → real 0m08s
# forks=50 → real 0m04s ← σχεδόν γραμμικό!
forks με pipelining
Ο συνδυασμός forks + pipelining δίνει τη μέγιστη βελτίωση:
# ansible.cfg — Optimized configuration
[defaults]
forks = 20
[ssh_connection]
pipelining = true
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ServerAliveInterval=30
control_path = ~/.ansible/cp/%%h-%%p-%%r
Επίδραση pipelining:
Χωρίς pipelining (1 task):
1. SSH connect
2. Upload Python module (~20KB)
3. Execute module
4. SSH disconnect
→ 4 operations per task
Με pipelining (1 task):
1. SSH connect (επαναχρησιμοποίηση)
2. Execute module (inline)
→ 1-2 operations per task → ~3x γρηγορότερο!
⚠️ Προϋπόθεση pipelining: Το
requirettyπρέπει να είναι απενεργοποιημένο στο/etc/sudoersτων managed hosts. Στα σύγχρονα συστήματα (RHEL 8+, Ubuntu 20.04+) είναι ήδη απενεργοποιημένο.
forks και Throttling ανά host group
Μπορείς να ορίσεις διαφορετικά forks ανά play:
---
# Διαφορετικά forks ανά group
- name: Γρήγορα tasks σε webservers
hosts: webservers
gather_facts: false
# Χρησιμοποιεί global forks (20)
tasks:
- name: Reload nginx config
ansible.builtin.service:
name: nginx
state: reloaded
---
- name: Αργά tasks σε database servers
hosts: databases
gather_facts: false
throttle: 1 # ← ΜΟΝΟ 1 database server τη φορά!
# (ανεξάρτητα από τα global forks)
tasks:
- name: Database maintenance
ansible.builtin.command:
cmd: /opt/db/maintenance.sh
changed_when: true
📝 Το
throttlekeyword ελέγχει τη μέγιστη παράλληλη εκτέλεση ανά task ή ανά play — είναι πιο λεπτομερές από τα global forks.
throttle ανά task
tasks:
- name: Κανονικό task (τρέχει με global forks)
ansible.builtin.apt:
name: nginx
state: present
- name: Resource-intensive task (περιορισμένο)
ansible.builtin.command:
cmd: /opt/backup/full-backup.sh
throttle: 2 # ← max 2 hosts ταυτόχρονα
# ακόμα κι αν forks=50!
async: 3600
poll: 0
changed_when: true
- name: API call με rate limit
ansible.builtin.uri:
url: "https://api.example.com/register"
method: POST
throttle: 1 # ← σειριακά (ένα-ένα)
# για rate-limited APIs
Πρακτικό παράδειγμα — forks benchmark playbook
---
# forks-benchmark.yml
# Χρησιμοποίησε με: ansible-playbook forks-benchmark.yml -f N
- name: Forks Benchmark
hosts: all
gather_facts: false
tasks:
- name: Timestamp έναρξης
ansible.builtin.command:
cmd: date +%s%N
register: start_time
changed_when: false
run_once: true # ← εκτελείται ΜΟΝΟ σε 1 host
- name: Simulate work (sleep 1s)
ansible.builtin.command:
cmd: sleep 1
changed_when: false
- name: Timestamp λήξης
ansible.builtin.command:
cmd: date +%s%N
register: end_time
changed_when: false
run_once: true
- name: Αποτέλεσμα
ansible.builtin.debug:
msg: >
Forks: {{ ansible_play_hosts | length }} hosts,
Χρόνος: {{ ((end_time.stdout | int) -
(start_time.stdout | int)) / 1e9
| round(2) }}s
run_once: true
# Σύγκριση
ansible-playbook playbooks/forks-benchmark.yml -f 1 -v
ansible-playbook playbooks/forks-benchmark.yml -f 5 -v
ansible-playbook playbooks/forks-benchmark.yml -f 20 -v
Σύνοψη 18.2
forks — Παράλληλη εκτέλεση
│
├── Ορισμός: N hosts εκτελούν task ταυτόχρονα
│
├── Ρύθμιση:
│ ├── ansible.cfg → forks = N (μόνιμο)
│ ├── -f N → εφάπαξ
│ └── ANSIBLE_FORKS=N → env variable
│
├── Επιλογή τιμής:
│ ├── Μικρό infra → forks = αριθμός hosts
│ ├── Μεσαίο → forks = 20-30
│ └── Μεγάλο → forks = 50-100
│
├── Βελτιστοποίηση:
│ ├── pipelining = true → ~3x γρηγορότερο
│ └── ControlPersist → SSH reuse
│
└── Throttling:
├── throttle: N (ανά task/play)
└── Χρήση: rate limits, resource-intensive tasks