Satu perubahan konfigurasi kecil — menaikkan worker_processes, mengganti port, menambah satu baris di sshd_config — adalah pekerjaan tiga menit di satu server. Kalikan lima puluh server, dan pekerjaan itu berubah menjadi sore yang hilang plus jaminan pasti ada server nomor 37 yang terlupa atau salah ketik. Configuration management menyelesaikannya dengan membalik arah kerja: alih-alih mengetik perintah di tiap mesin, kita menuliskan keadaan akhir yang benar, lalu mesin yang berjalan menyeret dirinya menuju keadaan itu. Chapter ini membedah konsep intinya — state akhir, idempotensi, konvergensi — dan membuktikannya dengan skrip bash yang bisa kita jalankan dan uji ulang di container latihan.

Masalah Lima Puluh Server #

Bayangkan kita mengelola lima puluh server web dan tim memutuskan worker_processes dinaikkan dari 1 ke 2. Jalan manualnya: ssh ke tiap mesin, vim berkasnya, restart nginx, lalu catat mana yang sudah. Tiga masalah muncul dari cara ini. Pertama, pekerjaannya membosankan sehingga mudah ceroboh — server nomor 37 mendapat worker_processs dan nobody knows. Kedua, tidak ada jejak: begitu selesai, tidak ada yang bisa menjawab “server mana saja yang sudah diubah, kapan, oleh siapa”. Ketiga, server yang terlanjur berbeda-beda akan semakin berbeda — yang di administrasi dunia nyata disebut configuration drift — sampai tiap mesin menjadi snowflake yang perlu perlakuan khusus.

Configuration drift juga datang dari arah yang tidak terduga: admin yang sedang buru-buru mengubah satu file lewat SSH “cuma sebentar”, hotfix tengah malam yang tak pernah dirapikan, atau server yang terlewat dari satu putaran update. Drift kecil yang dibiarkan lama-lama membuat armada server kita diam-diam terbelah menjadi banyak varian konfigurasi.

Deklarasikan State Akhir, Jalankan Berkali-kali #

Jalan keluarnya sudah kita kenali di Chapter Infrastructure Automation : berhenti menuliskan langkah, mulai menuliskan hasil. Sebuah manifest menyatakan “berkas ini harus berisi teks ini”, dan sebuah program aplikator membandingkan manifest dengan keadaan nyata lalu melakukan apa pun yang diperlukan — membuat berkas yang hilang, memperbaiki yang berubah, membiarkan yang sudah benar. Dua sifat penting lahir dari pola ini:

  • Idempoten: menjalankan penerapan yang sama berkali-kali menghasilkan keadaan akhir yang sama — lari kedua tidak mengubah apa-apa lagi.
  • Konvergen: sistem yang menyimpang ditarik kembali ke keadaan yang dideklarasikan setiap kali penerapan dijalankan.

Kedua kata itu bukan klaim pemasaran; keduanya bisa diuji. Dan karena itulah latihan chapter ini berbeda dari bab-bab sebelumnya — kita akan menjalankan buktinya sendiri.

Idempotensi dalam Praktik: kelola-konfigurasi.sh #

Bundle chapter ini membawa dua berkas: manifest sederhana berformat tujuan|isi, dan skrip kelola-konfigurasi.sh yang menerapkannya. Nama foldernya disederhanakan (etc-nginx/, bukan /etc/nginx/) karena container latihan tidak punya akses root — polanya sama, hanya skalanya yang dikecilkan. Berikut isi manifestnya:

bash
cat manifest.conf

Output yang Dihasilkan:

text
# format: tujuan|isi yang diharapkan (satu baris)
etc-nginx/umum.conf|worker_processes 2;
etc-nginx/situs.conf|listen 80; server_name contoh.example.com;
bin/lapor-harian.sh|echo laporan harian server

Baris pertama adalah komentar yang dijelaskan formatnya; tiga baris berikutnya menyatakan tiga berkas yang harus ada beserta isinya — dua konfigurasi nginx dan satu skrip laporan harian. Sekarang kita jalankan penerapannya untuk pertama kali pada direktori yang masih kosong:

bash
bash kelola-konfigurasi.sh manifest.conf

Output yang Dihasilkan:

text
changed  etc-nginx/umum.conf
changed  etc-nginx/situs.conf
changed  bin/lapor-harian.sh
== REKAP: total=3 changed=3 ok=0 ==

Ketiga berkas belum ada, jadi semuanya berstatus changed — persis laporan task di tools sungguhan. Mari kita bedah skripnya bagian demi bagian:

  1. if [ $# -ne 1 ]: gerbang argumen — tanpa path manifest, skrip hanya mencetak cara pakai dan berhenti dengan sukses.
  2. while IFS='|' read -r tujuan isi: membaca manifest baris demi baris, membelah pada tanda | sehingga spasi di dalam isi berkas tetap utuh — IFS lokal seperti yang kita latih di Chapter Bash Basics .
  3. case "$tujuan" in ''|'#'*) continue: melompati baris kosong dan baris komentar manifest.
  4. [ -f ... ] && [ "$(cat ...)" = "$isi" ]: inti idempotensi — berkas dianggap selesai hanya bila ada dan isinya persis sama; $(cat ...) otomatis membuang newline di akhir berkas agar perbandingannya adil.
  5. mkdir -p + printf '%s\n': berkas ditulis hanya di cabang changed — cabang ok tidak menyentuh disk sama sekali.

Sekarang ujian sesungguhnya. Idempotensi berarti lari kedua dan ketiga harus menghasilkan output yang identik — bukan sekadar “tampak sama”. Blok berikut membuang lari pertama ke /dev/null (sandbox selalu mulai kosong, jadi penerapan pertama harus dibuang dulu), lalu menangkap dua lari berikutnya dan membandingkannya:

bash
bash kelola-konfigurasi.sh manifest.conf > /dev/null
bash kelola-konfigurasi.sh manifest.conf > lari2.txt
bash kelola-konfigurasi.sh manifest.conf > lari3.txt
diff lari2.txt lari3.txt && echo "lari kedua dan ketiga: output identik"
cat lari2.txt

Output yang Dihasilkan:

text
lari kedua dan ketiga: output identik
ok       etc-nginx/umum.conf
ok       etc-nginx/situs.conf
ok       bin/lapor-harian.sh
== REKAP: total=3 changed=0 ok=3 ==

diff tidak mencetak apa pun karena kedua file sama persis, dan && menjadikan “output identik” sebagai pernyataan yang teruji — bukan kebetulan yang kita harapkan. REKAP changed=0 ok=3 menutup buktinya: penerapan ulang tidak mengubah apa pun. Inilah yang membuat configuration management aman dijadwalkan — boleh dijalankan tiap jam tanpa efek samping.

Arsitektur Tool: Agent, Agentless, Push, Pull #

Bagaimana definisi itu sampai ke lima puluh server? Ada dua sekolah:

ModelCara kerjaKelebihanHarga yang dibayar
Agent (pull)daemon di tiap server menarik konfigurasi dari server pusat secara berkalaserver pusat tahu kondisi terkini; cocok skala ribuanharus memasang dan mengelola daemon + infrastruktur pusat
Agentless (push)mesin kendali menjalankan SSH ke tiap server saat dibutuhkantanpa daemon, mulai cepat, permintaan sesuai kebutuhanbutuh akses SSH ke mana-mana; skala besar lebih lambat

Model pull memberi server otonomi untuk menyembuhkan dirinya — daemon menarik konfigurasi bahkan saat tidak ada yang menjalankan apa pun. Model push memberi admin kendali penuh atas kapan perubahan menyentuh produksi: tidak ada yang berubah sampai kita menekan enter. Puppet, Chef, dan Salt lahir dari sekolah agent; Ansible membuktikan agentless cukup untuk sebagian besar kebutuhan.

Konfigurasi sebagai Kode #

Manifest yang kita buat hanyalah teks — dan di situlah kekuatannya. Disimpan di Git, setiap perubahan konfigurasi server melewati alur yang sama dengan kode aplikasi: branch, review oleh rekan, pengujian di server staging, lalu peleburan. Ketika perubahan menimbulkan masalah di produksi, git revert mengembalikan definisi dan penerapan berikutnya mengembalikan server — rollback yang sebenarnya, bukan “coba ingat apa yang kemarin diubah”.

Dua kebiasaan menutup lingkaran ini. Pertama, uji dulu: perubahan besar diuji di satu server staging sebelum seluruh armada — bedakan dengan flag --check bila tool menyediakannya. Kedua, jaga kualitas skrip: aplikator buatan sendiri seperti kelola-konfigurasi.sh tetap skrip bash yang layak diperiksa shellcheck seperti di Chapter Shellcheck dan Script Quality .

Peta Tool Configuration Management #

Empat nama mendominasi lanskap ini, dan tabel berikut memetakan posisinya:

ToolModelFormat definisiCiri khas
Ansibleagentless, pushYAMLtanpa daemon, mulai dari SSH saja — default dunia Linux
Puppetagent, pullDSL sendirimatang, cocok armada besar dengan banyak tim
Chefagent, pullRuby“recipe” berorientasi programmer
Saltagent (bisa SSH), push/pullYAMLevent-driven, eksekusi paralel cepat

Ketiganya yang ber-agent lahir lebih dulu dan unggul di skala ribuan server; Ansible datang belakangan dengan tarikan sederhananya: tidak ada yang perlu dipasang di server selain SSH dan Python. Untuk sisa section ini kita memilih satu tool dan membedahnya sampai ke porosnya — inventaris, playbook, dan modulnya. Chapter berikutnya: Ansible .

Referensi lanjut: shellcheck untuk menjaga kualitas aplikator buatan sendiri, serta Debian Administrator’s Handbook untuk praktik mengelola armada server Debian.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

kelola-konfigurasi.sh

Unduh berkas
bash
#!/usr/bin/env bash
# kelola-konfigurasi.sh — terapkan manifest "tujuan|isi" secara idempoten.
# Pemakaian: bash kelola-konfigurasi.sh <manifest>
set -u
if [ $# -ne 1 ]; then
  echo "Pemakaian: bash kelola-konfigurasi.sh <manifest>"
  exit 0
fi
manifest=$1
dir_manifest=$(dirname "$manifest")
berubah=0
total=0
while IFS='|' read -r tujuan isi; do
  case "$tujuan" in ''|'#'*) continue ;; esac
  total=$((total + 1))
  if [ -f "$dir_manifest/$tujuan" ] && [ "$(cat "$dir_manifest/$tujuan")" = "$isi" ]; then
    printf 'ok       %s\n' "$tujuan"
  else
    mkdir -p "$(dirname "$dir_manifest/$tujuan")"
    printf '%s\n' "$isi" > "$dir_manifest/$tujuan"
    printf 'changed  %s\n' "$tujuan"
    berubah=$((berubah + 1))
  fi
done < "$manifest"
echo "== REKAP: total=$total changed=$berubah ok=$((total - berubah)) =="