Task & Module Execution #
Menulis alur tugas (tasks) di dalam berkas playbook adalah langkah deklaratif awal. Namun, memahami bagaimana Ansible memproses, mentransfer, mengeksekusi, dan membersihkan skrip tugas tersebut di balik layar adalah tingkat keahlian lanjut yang wajib dikuasai oleh pengembang otomatisasi tingkat produksi. Tanpa pemahaman mendalam tentang siklus eksekusi ini, kita akan kesulitan menganalisis kegagalan jaringan di tengah jalan, menelusuri performa eksekusi yang lambat, atau menangani skenario deployment aplikasi multi-host secara atomik. Artikel ini membedah siklus hidup eksekusi modul, membandingkan strategi Linear vs Free, melakukan tuning kapasitas konkurensi (forks), menyimpan variabel luaran (register), memanipulasi status akhir (changed_when dan failed_when), hingga memaksakan proses berhenti secara global (any_errors_fatal).
Siklus Hidup Eksekusi Modul #
Setiap kali kita memicu jalannya satu baris tugas di playbook, Ansible tidak mengirimkan perintah teks mentah melalui terminal SSH. Ansible mengeksekusi rantai proses penyiapan dan transfer berkas yang sangat teratur.
Berikut adalah 7 tahapan siklus hidup eksekusi satu tugas di target server:
- Penyusunan Kode Modul (Compilation): Ansible Core di control node mengambil berkas source code modul Python terkait (misalnya
apt.pyatautemplate.py) dan menggabungkannya secara dinamis dengan argumen parameter yang kita tulis di task. - Kompresi Payload (Packaging): Hasil penggabungan kode tersebut dikompresi menjadi sebuah paket arsip Python mandiri bertipe Zip.
- Transfer Berkas (Transmission): Ansible membuka koneksi SSH dan mentransfer berkas Zip tersebut ke managed node target menggunakan protokol SFTP atau SCP. Secara default, berkas diletakkan di direktori temporer tersembunyi di dalam folder home user login target (misalnya
~/.ansible/tmp/). - Ekstraksi & Eksekusi (Execution): Ansible menginstruksikan target interpreter Python di managed node untuk mengekstrak berkas Zip tersebut ke memori, menjalankannya secara lokal, dan mengumpulkan output eksekusinya.
- Pengembalian Laporan (Reporting): Modul mengembalikan laporan hasil kerja dalam format teks berstruktur JSON bersih melalui saluran standar koneksi SSH aktif menuju control node.
- Analisis Status (Status Parsing): Ansible di control node mem-parsing respon JSON tersebut untuk menentukan status akhir tugas: hijau (
ok), kuning (changed), atau merah (failed). - Pembersihan Sampah (Cleanup): Ansible mengirimkan perintah SSH terakhir untuk menghapus berkas temporer Zip di folder
~/.ansible/tmp/managed node agar tidak mengotori kapasitas penyimpanan piringan keras server.
Proses penyiapan, transfer, dan eksekusi di atas terjadi secara berulang untuk setiap tugas di setiap host target. Pipelining SSH (jika diaktifkan di ansible.cfg) akan menyatukan langkah 3, 4, dan 5 langsung melalui input standar SSH tanpa transfer file fisik SFTP, mempercepat proses ini hingga 3 kali lipat.
Linear Strategy (Mekanisme Default) #
Secara default, Ansible menerapkan metode penyelarasan tugas bernama Linear Strategy. Di bawah strategi ini, Ansible bertindak sebagai dirigen orkestra yang ketat: tugas pertama harus selesai dieksekusi di seluruh host target yang memenuhi syarat sebelum tugas kedua boleh dimulai.
Ilustrasi linear strategy pada tiga server target:
Task 1: Pasang Nginx
├── Eksekusi di web-01.example.com ✓ (Sukses)
├── Eksekusi di web-02.example.com ✓ (Sukses)
└── Eksekusi di web-03.example.com ✓ (Sukses)
↓ (Seluruh host selesai memproses Task 1)
Task 2: Salin File Konfigurasi Nginx
├── Eksekusi di web-01.example.com ✓ (Sukses)
├── Eksekusi di web-02.example.com ✓ (Sukses)
└── Eksekusi di web-03.example.com ✓ (Sukses)
↓ (Seluruh host selesai memproses Task 2)
Task 3: Nyalakan Layanan Nginx
├── Eksekusi di web-01.example.com ✓
├── Eksekusi di web-02.example.com ✓
└── Eksekusi di web-03.example.com ✓
Jika salah satu host (misalnya web-02) mengalami kegagalan di Task 1, Ansible secara otomatis akan mengeluarkan web-02 dari antrian eksekusi tugas berikutnya. Namun, host lain (web-01 dan web-03) yang sukses tetap diizinkan melanjutkan ke Task 2. Keunggulan utama strategi linear ini adalah konsistensi: kita dijamin bahwa seluruh server target berada dalam tahapan state yang sama di setiap waktu.
forks dan Paralelisme Batch #
Meskipun menggunakan strategi linear yang mensinkronkan langkah tugas, Ansible tidak memproses server target satu per satu secara bergantian (sequential). Ansible menjalankan tugas tersebut secara paralel pada kelompok server target menggunakan kapasitas soket koneksi yang disebut Forks.
Jumlah default forks di Ansible adalah 5. Parameter ini menentukan batasan ukuran batch paralel eksekusi:
Skenario: forks = 3, target = 6 server
Task 1: Pasang Nginx
- Batch 1 (Paralel): web-01, web-02, web-03 ← Berjalan bersamaan
- Batch 2 (Paralel): web-04, web-05, web-06 ← Berjalan setelah Batch 1 selesai
Tuning nilai forks dapat disesuaikan pada berkas ansible.cfg proyek kita:
# File: ansible.cfg
[defaults]
# Tingkatkan forks untuk meningkatkan paralelisme di jaringan besar
forks = 20
Meningkatkan forks akan mempercepat durasi total playbook di ratusan server, tetapi membutuhkan kapasitas CPU dan RAM control node yang lebih besar untuk mengelola proses kompilasi payload paralel.
Free Strategy (Independensi Host) #
Jika kita memiliki skenario di mana tugas-tugas di setiap server sama sekali tidak memiliki ketergantungan satu sama lain, dan kita ingin agar setiap server menyelesaikan seluruh tugas secepat mungkin tanpa harus menunggu server lain yang lambat (misalnya karena latensi jaringan regional berbeda), kita dapat mengaktifkan Free Strategy.
# File: playbooks/deploy-free.yml
---
- name: Deploy Kode Aplikasi Secara Bebas dan Mandiri
hosts: webservers
# Mengubah dari Linear (Default) ke Free Strategy
strategy: free
tasks:
- name: Tarik repositori Git terbaru
git:
repo: https://github.com/org/app.git
dest: /opt/app
- name: Jalankan instalasi dependensi npm
npm:
path: /opt/app
Di bawah Free Strategy, jalannya tugas tidak disinkronkan. Server yang memiliki koneksi internet lebih cepat akan langsung menyelesaikan Task 1, Task 2, hingga selesai, sementara server yang lambat masih memproses Task 1.
Perbandingan visual antara Linear dan Free strategy digambarkan pada diagram di bawah:
flowchart TD
subgraph "Linear Strategy (Default - Sinkron)"
direction TB
L1["Task 1 (Host A, B, C)"] -->|"Tunggu Semua Host Selesai"| L2["Task 2 (Host A, B, C)"]
L2 -->|"Tunggu Semua Host Selesai"| L3["Task 3 (Host A, B, C)"]
end
subgraph "Free Strategy (Asinkron / Bebas)"
direction TB
F1["Host A: Task 1 -> Task 2 -> Task 3"]
F2["Host B: Task 1 -> Task 2 -> Task 3"]
F3["Host C: Task 1 -> Task 2 -> Task 3"]
F1 & F2 & F3 -->|"Eksekusi Independen Secepatnya"| F4["Selesai (Waktu Berbeda-beda)"]
end
register: Menyimpan State Keluaran #
Setiap kali tugas berjalan, modul Ansible mengembalikan data JSON (seperti output perintah shell, status perubahan file, error message). Kita dapat menangkap dan menyimpan data respon ini ke dalam variabel memori menggunakan kata kunci register agar dapat digunakan oleh tugas berikutnya untuk pencabangan logika.
Struktur objek JSON yang disimpan oleh register umumnya memiliki beberapa properti kunci berikut:
changed: Bernilai boolean (true/false), menandakan apakah tugas tersebut berhasil memodifikasi status target server.failed: Bernilai boolean, menandakan apakah tugas mengalami kegagalan eksekusi.rc: Return code (exit status) khusus untuk modul yang menjalankan perintah CLI (seperticommandataushell). Angka0menandakan sukses, dan angka selain0menandakan kegagalan.stdout: Berupa string teks mentah yang berisi keluaran standar (standard output) dari perintah terminal yang dijalankan.stderr: Berupa string teks mentah yang berisi laporan kesalahan (standard error) jika perintah mengalami masalah.stdout_lines: Hasil pemisahan teksstdoutmenjadi array baris demi baris, memudahkan kita melakukan iterasi loop Jinja2 di task berikutnya.skipped: Bernilai boolean, menandakan apakah tugas tersebut dilewati karena tidak memenuhi kondisi conditionalwhen.
# File: playbooks/conditional-restart.yml
---
- name: Kelola Layanan Web Berdasarkan Status
hosts: webservers
become: true
tasks:
- name: Ambil status aktual layanan Nginx saat ini
systemd:
name: nginx
register: nginx_runtime_status # Simpan respon JSON ke variabel
- name: Tampilkan isi variabel hasil register (Debugging)
debug:
var: nginx_runtime_status
- name: Nyalakan kembali Nginx HANYA JIKA statusnya saat ini aktif
systemd:
name: nginx
state: restarted
# Mengevaluasi properti JSON di dalam variabel register
when: nginx_runtime_status.status.ActiveState == "active"
changed_when dan failed_when #
Secara default, Ansible menentukan status tugas changed (kuning) jika mendeteksi adanya modifikasi pada managed node, dan failed (merah) jika perintah mengembalikan kode error (exit code non-zero). Namun, ada kasus di mana kriteria default ini menghasilkan laporan yang salah. Kita dapat memanipulasi kriteria tersebut menggunakan parameter kendali.
1. changed_when (Manipulasi Status Perubahan) #
Banyak modul eksekusi perintah (seperti command atau shell) akan selalu mengembalikan status changed = true setiap kali dijalankan karena Ansible tidak tahu apakah perintah shell tersebut memodifikasi sistem atau tidak.
Jika perintah tersebut hanya bertugas membaca informasi (seperti mengecek versi atau status kapasitas disk), kita harus memaksanya bernilai false agar tidak mengotori statistik idempotensi playbook kita:
# Contoh mematikan status changed palsu
- name: Dapatkan versi PostgreSQL terpasang
command: psql --version
register: postgres_version
# ANTI-PATTERN: Membiarkan status changed kuning menyala untuk perintah baca murni
# (Tanpa changed_when)
# BENAR: Paksa status tetap hijau (ok) karena tidak ada modifikasi sistem
changed_when: false
Kita juga dapat menggunakan ekspresi kondisional. Tandai changed hanya jika ada baris keluaran tertentu:
- name: Jalankan migrasi database
command: bundle exec rake db:migrate
register: db_migrate_output
# Hanya tandai changed jika output tidak berisi kalimat 'no migrations'
changed_when: "'No migrations to apply' not in db_migrate_output.stdout"
2. failed_when (Manipulasi Status Kegagalan) #
Kadang-kala sebuah perintah mengembalikan error code non-zero yang sebenarnya merupakan hal normal dan bukan kegagalan sistem. Sebaliknya, adakalanya perintah berjalan sukses (exit code 0) tetapi output-nya berisi teks error kritis. Kita dapat memanipulasi kriteria kegagalan ini:
- name: Memeriksa utilitas kapasitas penyimpanan partisi root
command: df -h /
register: root_disk_usage
# Definisikan kriteria kegagalan sendiri:
# Gagal jika exit code non-zero ATAU jika kapasitas penggunaan mencapai 95%
failed_when:
- root_disk_usage.rc != 0
- "'95%' in root_disk_usage.stdout"
Pola Penantian State (until, retries, delay) #
Dalam otomatisasi sistem, adakalanya kita harus memicu proses dan menunggu sampai layanan tersebut benar-benar siap menerima koneksi sebelum melanjutkan ke tugas berikutnya (misalnya setelah merestart database server, kita harus menunggu port database 5432 merespon koneksi TCP).
Ansible menyediakan mekanisme perulangan bersyarat menggunakan kombinasi parameter until, retries, dan delay:
# Alur penantian port database aktif
- name: Menunggu database PostgreSQL siap menerima koneksi
wait_for:
port: 5432
state: started
timeout: 5
register: port_status
# Ulangi tugas ini...
until: port_status is succeeded
# Coba maksimal 12 kali (Total penantian: 12 * 5s = 60 detik)
retries: 12
# Beri jeda 5 detik di antara setiap percobaan kueri port
delay: 5
any_errors_fatal #
Secara default, jika kita menjalankan playbook di 10 server, dan 2 server mengalami kegagalan eksekusi (failed task), Ansible akan menghentikan eksekusi khusus untuk 2 server tersebut, sedangkan 8 server lainnya tetap melanjutkan tugas berikutnya.
Namun, dalam skenario deployment rilis aplikasi multi-host yang bersifat atomik (seperti di belakang cluster Load Balancer), membiarkan sebagian server memperbarui aplikasi sementara sebagian server gagal dapat memicu kondisi inkonsistensi data yang merusak sistem (split-brain scenario).
Kita dapat mengatur parameter any_errors_fatal: true di level Play untuk memastikan bahwa jika ada satu saja server target yang gagal memproses tugas, seluruh eksekusi playbook untuk seluruh server lainnya akan langsung dihentikan seketika.
# File: playbooks/deploy-atomic.yml
---
- name: Rilis Pembaruan Aplikasi Skala Besar (Atomik)
hosts: webservers
become: true
# Keamanan Kritis: Kegagalan satu server menghentikan seluruh proses secara global
any_errors_fatal: true
tasks:
- name: Download paket rilis aplikasi terbaru
get_url:
url: "https://artifacts.unisbadri.com/apps/release-v2.tar.gz"
dest: /tmp/release-v2.tar.gz
- name: Ekstrak kode aplikasi ke direktori produksi
unarchive:
src: /tmp/release-v2.tar.gz
dest: /var/www/html/
remote_src: true
Ringkasan #
- Siklus Zip Payload — Eksekusi modul Ansible bekerja dengan membungkus skrip Python ke dalam arsip Zip, mengirimkannya via SSH ke folder
/tmp, mengekstraknya secara lokal, dan mengembalikan laporan respon JSON sebelum dibersihkan.- Konsistensi Linear Strategy — Metode default penjamin sinkronisasi state di mana satu tugas wajib diselesaikan di seluruh host target sebelum melangkah ke tugas berikutnya.
- Tuning Forks Konkurensi — Sesuaikan nilai forks pada
ansible.cfguntuk mempercepat pemrosesan batch paralel pada infrastruktur berskala besar sesuai kapasitas mesin control node.- Pemanfaatan Free Strategy — Gunakan
strategy: freejika tugas-tugas antar host tidak memiliki ketergantungan urutan kerja demi meminimalkan durasi total eksekusi.- Pencabangan Logika via register — Tangkap dan simpan respon eksekusi modul ke dalam variabel register untuk mengevaluasi data properti JSON di dalam tugas kondisional berikutnya.
- Penegakan Idempotensi — Gunakan
changed_when: falseuntuk mematikan status perubahan palsu pada tugas pembacaan murni agar statistik eksekusi tetap akurat.- Kondisi Gagal Kustom — Gunakan
failed_whenuntuk mendefinisikan batas kegagalan operasional sendiri, terlepas dari kode keluaran exit code default modul.- Penantian Port database — Kombinasikan parameter
until,retries, dandelayuntuk memandu proses pooling status kesiapan port layanan target setelah proses restart.- Deploy Proteksi Atomik — Aktifkan
any_errors_fatal: truepada play deployment rilis aplikasi guna mencegah kondisi sistem inkonsisten akibat kegagalan sebagian server.