Module #
Jika playbook diibaratkan sebagai skenario rencana dan inventori adalah daftar aktor sasaran, maka module (modul) adalah perkakas nyata yang melakukan pekerjaan fisik di lapangan. Modul merupakan unit eksekusi terkecil di dalam ekosistem Ansible. Setiap baris tugas (task) yang kita tulis di dalam playbook pada dasarnya berfungsi untuk memanggil satu modul spesifik dengan parameter-parameter tertentu. Memahami secara mendalam cara kerja modul, status respon yang dihasilkan, serta pemilihan modul yang tepat adalah pondasi utama untuk menciptakan otomatisasi infrastruktur yang aman dan efisien.
Modul sebagai Unit Eksekusi Utama #
Modul adalah program mandiri (self-contained scripts) yang dirancang khusus untuk menjalankan fungsi administrasi sistem yang sangat spesifik — seperti menginstal paket, memodifikasi file konfigurasi, mengelola user, atau berinteraksi dengan API cloud provider.
Meskipun Ansible ditulis menggunakan Python, modul Ansible tidak terbatas pada bahasa Python saja. Kita dapat menulis modul kustom menggunakan bahasa pemrograman apa pun (seperti Bash atau Go) selama modul tersebut dapat menerima parameter input dalam format JSON dan mengembalikan status hasil eksekusi dalam format JSON standar pula.
Ketika playbook dijalankan, Ansible akan mengompilasi parameter tugas kita ke dalam modul terkait, mengirimkan script tersebut ke server target, menjalankannya secara lokal di sisi target, lalu segera menghapusnya setelah eksekusi selesai untuk menjaga kebersihan sistem target.
Mekanisme Idempotensi dan Status Respon #
Setiap modul standar di dalam Ansible dirancang secara ketat untuk mematuhi prinsip idempotensi. Sebelum melakukan modifikasi sistem, modul akan melakukan inspeksi awal terhadap kondisi nyata di Managed Node saat itu. Modul hanya akan melakukan tindakan perbaikan jika kondisi nyata sistem belum sesuai dengan kondisi akhir (desired state) yang kita deklarasikan di playbook.
Berikut adalah visualisasi alur pengambilan keputusan suatu modul Ansible untuk mencapai sifat idempotensi:
flowchart TD
CN["Control Node (Kirim Parameter Modul via JSON)"] -->|1. Transfer & Jalankan Script| MN["Managed Node (Eksekusi Lokal)"]
MN --> Check{"2. Inspeksi Kondisi Nyata\n(Apakah Kondisi Saat Ini == Desired State?)"}
Check -- "Ya" --> NoChange["3. Lewati Modifikasi\n(ok / changed: false)"]
Check -- "Tidak" --> ApplyChange["3. Terapkan Modifikasi Sistem\n(changed / changed: true)"]
NoChange --> Response["4. Kembalikan Output JSON\n(status, stdout, rc)"]
ApplyChange --> Response
Response -->|5. Tangkap Respon JSON| CN
Setelah selesai mengeksekusi tugas, modul akan mengembalikan struktur data JSON ke Control Node. Parameter paling krusial di dalam JSON respon tersebut adalah status perubahan:
ok(Green State): Kondisi server target sudah sesuai dengan deklarasi kita, sehingga modul tidak melakukan tindakan modifikasi apa pun. Respon JSON akan berisi"changed": false.changed(Yellow State): Kondisi server target belum sesuai, dan modul telah berhasil menerapkan perubahan untuk menyelaraskannya. Respon JSON akan berisi"changed": true.failed(Red State): Terjadi kegagalan eksekusi (misalnya karena kesalahan hak akses, jaringan terputus, atau parameter tidak valid). Respon JSON akan berisi"failed": truebeserta pesan kesalahan di parameter"msg".
Berikut contoh representasi JSON respon sukses dari modul file yang mengonfirmasi direktori sudah ada:
{
"path": "/var/www/html",
"changed": false,
"state": "directory",
"owner": "www-data",
"group": "www-data",
"mode": "0755"
}
Klasifikasi Modul Berdasarkan Fungsi #
Ansible menyediakan ribuan modul siap pakai yang dikelompokkan berdasarkan area kerja sistem. Memahami klasifikasi ini membantu kita memilih perkakas yang paling efisien untuk menyelesaikan tugas tertentu.
1. Manajemen Paket (Package Management) #
Digunakan untuk mengelola siklus hidup software (instalasi, pembaruan, penghapusan) di berbagai sistem operasi secara deklaratif:
# Modul apt — Khusus untuk keluarga Debian/Ubuntu
- name: Pastikan Git versi terbaru terpasang
apt:
name: git
state: latest
update_cache: true
# Modul dnf — Khusus untuk RHEL/CentOS/Rocky Linux modern
- name: Pastikan MariaDB Client terpasang
dnf:
name: mariadb
state: present
2. Manajemen File dan Direktori (Files & Directories) #
Digunakan untuk menyalin file, merender template dinamis, atau mengatur hak akses direktori:
# Modul copy — Menyalin file statis dari Control Node ke Managed Node
- name: Salin file konfigurasi firewall statis
copy:
src: files/iptables.rules
dest: /etc/iptables.rules
owner: root
group: root
mode: '0600'
# Modul template — Merender file konfigurasi dinamis menggunakan engine Jinja2
- name: Render file konfigurasi virtual host Nginx
template:
src: templates/vhost.conf.j2
dest: /etc/nginx/sites-available/myapp.conf
# Modul file — Mengelola direktori, symlink, dan izin akses file
- name: Buat direktori logs aplikasi dengan permission ketat
file:
path: /var/log/myapp
state: directory
owner: deploy
group: deploy
mode: '0750'
3. Manajemen Layanan (Service Management) #
Digunakan untuk mengontrol status jalannya layanan sistem background daemon:
# Modul systemd — Mengelola service systemd standar Linux modern
- name: Pastikan layanan SSH berjalan dan aktif saat booting
systemd:
name: ssh
state: started
enabled: true
Perbandingan Modul Eksekusi Perintah (Execution Modules) #
Ada kalanya kita perlu menjalankan perintah shell murni karena tidak ada modul Ansible standar yang mendukung aplikasi kustom kita. Untuk kebutuhan ini, Ansible menyediakan empat modul eksekusi perintah: command, shell, raw, dan script.
Kita harus sangat berhati-hati dalam menggunakan modul-modul ini karena tidak bersifat idempoten secara bawaan.
| Modul | Cara Kerja | Idempotensi Bawaan | Skenario Penggunaan Terbaik |
|---|---|---|---|
command |
Mengeksekusi perintah biner langsung di target tanpa melalui shell. | ✗ Tidak | Menjalankan aplikasi biner lokal (misal: openssl). Lebih aman karena tidak terpengaruh oleh variabel shell lokal. |
shell |
Mengeksekusi perintah melalui interpreter shell (seperti /bin/sh atau /bin/bash). |
✗ Tidak | Mengeksekusi perintah yang membutuhkan operator pipa (` |
raw |
Mengirimkan string perintah langsung via SSH tanpa membungkusnya menjadi modul Python. | ✗ Tidak | Melakukan bootstrap instalasi Python pertama kali di server minimalis atau router jaringan. |
script |
Menyalin script lokal kita ke target, mengeksekusinya, lalu menghapusnya kembali. | ✗ Tidak | Menjalankan script migrasi database kompleks yang sudah kita miliki tanpa perlu menulis ulang ke YAML. |
Mitigasi Idempotensi pada Modul Eksekusi Perintah #
Jika kita terpaksa menggunakan modul command atau shell, kita dapat memaksakan sifat idempotensi secara manual menggunakan parameter pembatas seperti creates, removes, atau mengontrol status pelaporan dengan changed_when.
# Contoh Mitigasi Idempotensi pada Modul Shell/Command
- name: Unduh script installer eksternal jika file installer belum ada
get_url:
url: https://example.com/install.sh
dest: /tmp/install.sh
- name: Jalankan installer hanya jika file biner hasil instalasi belum terbentuk
command: bash /tmp/install.sh
creates: /usr/local/bin/myapp # Task ini dilewati jika file /usr/local/bin/myapp sudah ada
- name: Periksa konfigurasi aplikasi kustom tanpa melaporkan status 'changed' palsu
command: myapp --check-syntax
register: check_result
changed_when: false # Menginstruksikan Ansible untuk selalu melaporkan status OK/SUCCESS (bukan CHANGED)
Menggunakan register dan Conditional (when) #
Hasil keluaran (output) dari eksekusi suatu modul dapat kita tangkap dan simpan ke dalam variabel memori menggunakan parameter register. Kita dapat memanfaatkan variabel hasil tangkapan tersebut untuk menentukan logika eksekusi pada tugas berikutnya menggunakan kondisional when.
Berikut adalah contoh skenario playbook yang dinamis: Kita memeriksa status eksistensi file konfigurasi menggunakan modul stat, menyimpan hasilnya, lalu hanya membuat file konfigurasi baru jika file tersebut belum ada di sistem.
---
- name: Skenario pengecekan dan konfigurasi file dinamis
hosts: all
become: true
vars:
config_path: /etc/myapp/config.yml
tasks:
- name: Periksa informasi detail mengenai file konfigurasi
stat:
path: "{{ config_path }}"
register: file_status # Hasil modul stat disimpan ke variabel file_status
- name: Tampilkan isi variabel check untuk debugging
debug:
var: file_status.stat.exists
- name: Salin konfigurasi default jika file dikonfirmasi belum ada
copy:
src: files/default-config.yml
dest: "{{ config_path }}"
owner: root
group: root
mode: '0644'
when: not file_status.stat.exists # Hanya dijalankan jika file tidak ada
Ansible Collections dan Modul Komunitas #
Pada versi Ansible terdahulu, seluruh modul dimasukkan ke dalam satu paket core utama. Seiring berkembangnya industri cloud, ukuran paket Ansible core menjadi terlalu besar dan lambat dalam mendistribusikan pembaruan modul.
Mulai versi 2.10, Ansible memperkenalkan konsep Ansible Collections. Ansible Core kini dipertahankan agar tetap sangat ringan, hanya berisi modul-modul sistem operasi dasar. Seluruh modul cloud provider (seperti AWS, GCP, OpenStack) dan modul perangkat jaringan dipisahkan ke dalam repositori eksternal yang dikelola secara modular oleh komunitas atau vendor terkait.
Kita dapat mencari dan menginstal koleksi modul eksternal ini secara mudah melalui portal Ansible Galaxy:
# Menginstal koleksi modul AWS terbaru dari Ansible Galaxy
ansible-galaxy collection install amazon.aws
Di dalam playbook, modul dari koleksi eksternal tersebut dipanggil menggunakan nama namespace yang lengkap (Fully Qualified Collection Name - FQCN):
- name: Buat EC2 instance baru menggunakan modul AWS kustom
amazon.aws.ec2_instance:
name: web-app-prod
instance_type: t3.medium
Ringkasan #
- Modul adalah unit eksekusi terisolasi — Ansible memanggil modul spesifik dengan parameter JSON untuk melakukan tugas nyata di managed node.
- Idempotensi Bawaan — Sebagian besar modul memeriksa status sistem target terlebih dahulu dan hanya melakukan perubahan jika status nyata tidak sesuai dengan desired state.
- Tiga Status Respon Utama — Modul mengembalikan status
ok(kondisi sudah sesuai),changed(berhasil dimodifikasi), ataufailed(kegagalan eksekusi).- Gunakan Modul Deklaratif — Hindari penggunaan modul
command/shellkecuali mendesak; gunakan modul bawaan yang sudah terjamin idempotensinya secara otomatis.- Register & When — Kita dapat menangkap output eksekusi modul ke dalam variabel memori terdaftar (
register) untuk mengontrol alur playbook secara kondisional (when).