Scheduled Task #
Tidak semua otomasi perlu dipicu oleh manusia atau oleh push kode. Backup database harus berjalan setiap malam. Security patch harus diterapkan setiap minggu. Certificate yang mendekati kadaluarsa harus diperbarui otomatis. Drift detection harus berjalan setiap hari. Semua ini adalah scheduled task — otomasi yang berjalan berdasarkan jadwal, tanpa intervensi manual. Artikel ini membahas cara menjadwalkan eksekusi Ansible secara andal.
Cron: Pendekatan Paling Sederhana #
Cara paling sederhana adalah menambahkan cronjob yang menjalankan ansible-playbook di control node:
# playbooks/setup-control-node.yml
- name: Setup scheduled Ansible jobs di control node
hosts: localhost
tasks:
- name: Jadwalkan backup database harian
cron:
name: "Ansible — backup database"
minute: "0"
hour: "2"
job: >
/usr/bin/ansible-playbook
-i /opt/ansible/inventory/production/
/opt/ansible/playbooks/backup-database.yml
--vault-password-file /opt/ansible/.vault_pass
>> /var/log/ansible/backup.log 2>&1
state: present
user: ansible
- name: Jadwalkan patch management mingguan
cron:
name: "Ansible — weekly patch"
minute: "0"
hour: "3"
weekday: "0" # Minggu dini hari
job: >
/usr/bin/ansible-playbook
-i /opt/ansible/inventory/production/
/opt/ansible/playbooks/patch-management.yml
--vault-password-file /opt/ansible/.vault_pass
>> /var/log/ansible/patch.log 2>&1
state: present
user: ansible
- name: Jadwalkan drift detection harian
cron:
name: "Ansible — drift detection"
minute: "30"
hour: "6"
job: >
/usr/bin/ansible-playbook
-i /opt/ansible/inventory/production/
/opt/ansible/playbooks/detect-drift.yml
--check
>> /var/log/ansible/drift.log 2>&1
state: present
user: ansible
Pola Playbook yang Aman untuk Scheduled Jobs #
Playbook yang dijalankan tanpa pengawasan harus ekstra defensif:
# playbooks/backup-database.yml
---
- name: Backup database otomatis
hosts: dbservers
gather_facts: true
pre_tasks:
- name: Log awal eksekusi
local_action:
module: lineinfile
path: /var/log/ansible/job-history.log
line: "{{ ansible_date_time.iso8601 }} START backup-database @ {{ inventory_hostname }}"
create: true
run_once: false
- name: Cek disk space sebelum backup
assert:
that:
- ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first > 5368709120
fail_msg: >
Disk space tidak cukup untuk backup di {{ inventory_hostname }}!
Tersedia: {{ (ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first / 1073741824) | round(1) }}GB
Minimal: 5GB
tasks:
- name: Jalankan backup
command: /opt/scripts/backup-db.sh
register: backup_result
- name: Verifikasi backup berhasil
stat:
path: "{{ backup_result.stdout | trim }}"
register: backup_file
failed_when: not backup_file.stat.exists
post_tasks:
- name: Log selesai eksekusi
local_action:
module: lineinfile
path: /var/log/ansible/job-history.log
line: "{{ ansible_date_time.iso8601 }} END backup-database @ {{ inventory_hostname }} — OK"
create: true
handlers:
- name: Log kegagalan
local_action:
module: lineinfile
path: /var/log/ansible/job-history.log
line: "{{ ansible_date_time.iso8601 }} FAILED backup-database @ {{ inventory_hostname }}"
create: true
listen: job failed
Menghindari Job yang Tumpang Tindih #
Satu masalah umum dengan scheduled task adalah job yang berjalan lebih lama dari interval jadwalnya — job berikutnya mulai sebelum yang sebelumnya selesai, menyebabkan kondisi race:
# Gunakan lockfile untuk mencegah eksekusi tumpang tindih
- name: Cek apakah job sebelumnya masih berjalan
stat:
path: /tmp/ansible-backup.lock
register: lockfile
- name: Hentikan jika job sebelumnya masih berjalan
fail:
msg: "Job backup masih berjalan (lockfile ada). Skip eksekusi ini."
when: lockfile.stat.exists
- name: Buat lockfile
file:
path: /tmp/ansible-backup.lock
state: touch
- name: Jalankan backup
command: /opt/scripts/backup-db.sh
register: backup_result
- name: Hapus lockfile setelah selesai
file:
path: /tmp/ansible-backup.lock
state: absent
when: true # Selalu hapus, bahkan jika task sebelumnya gagal
Patch Management Otomatis #
Salah satu use case paling umum untuk scheduled task adalah patch management:
# playbooks/patch-management.yml
---
- name: Terapkan security patch secara terjadwal
hosts: all
serial: "25%" # Update 25% server sekaligus (rolling)
become: true
pre_tasks:
- name: Catat state sebelum patch
command: uname -r
register: kernel_before
changed_when: false
tasks:
- name: Update apt cache
apt:
update_cache: true
when: ansible_os_family == "Debian"
- name: Install security updates saja
apt:
upgrade: dist
update_cache: false
only_upgrade: true
when: ansible_os_family == "Debian"
register: patch_result
- name: Cek apakah reboot diperlukan
stat:
path: /var/run/reboot-required
register: reboot_required
- name: Reboot jika diperlukan
reboot:
reboot_timeout: 300
post_reboot_delay: 30
msg: "Reboot untuk menerapkan kernel update"
when: reboot_required.stat.exists
post_tasks:
- name: Catat state setelah patch
command: uname -r
register: kernel_after
changed_when: false
- name: Laporkan jika kernel berubah
debug:
msg: "Kernel diupdate: {{ kernel_before.stdout }} → {{ kernel_after.stdout }}"
when: kernel_before.stdout != kernel_after.stdout
Notifikasi Hasil Scheduled Job #
Scheduled job yang gagal tanpa notifikasi adalah masalah yang tidak terdeteksi. Tambahkan notifikasi:
# roles/notify/tasks/slack.yml
- name: Kirim notifikasi Slack
uri:
url: "{{ slack_webhook_url }}"
method: POST
body_format: json
body:
text: "{{ slack_message }}"
attachments:
- color: "{{ 'good' if job_status == 'success' else 'danger' }}"
text: "{{ job_detail }}"
delegate_to: localhost
run_once: true
no_log: true
# Di akhir playbook scheduled job
post_tasks:
- name: Notifikasi sukses ke Slack
include_role:
name: notify
vars:
slack_message: "✅ Backup database berhasil"
job_status: success
job_detail: "Backup selesai di {{ groups['dbservers'] | length }} server"
run_once: true
rescue:
- name: Notifikasi gagal ke Slack
include_role:
name: notify
vars:
slack_message: "❌ Backup database GAGAL"
job_status: failure
job_detail: "Error di {{ ansible_failed_result.msg }}"
run_once: true
Ringkasan #
- Cron + ansible-playbook adalah cara termudah untuk scheduled task — sederhana, tidak butuh infrastruktur tambahan.
- Selalu arahkan output ke log file di cronjob —
>> /var/log/ansible/job.log 2>&1untuk menyimpan semua output termasuk error.- Playbook scheduled task harus defensif: cek prasyarat (disk space, lockfile), log awal dan akhir, handle failure secara eksplisit.
- Gunakan lockfile untuk mencegah job yang sama berjalan bersamaan saat eksekusi sebelumnya belum selesai.
- Gunakan
serial:untuk patch management — jangan update semua server sekaligus, lakukan bertahap untuk menghindari downtime total.- Notifikasi otomatis untuk hasil scheduled job — kegagalan yang tidak terdeteksi bisa berbahaya.
← Sebelumnya: CI/CD Integration Berikutnya: Error Handling →