Variable

Variable #

Dalam pengembangan otomatisasi infrastruktur berskala besar, fleksibilitas adalah salah satu pilar utama keberhasilan. Kita tidak ingin membuat puluhan playbook yang hampir identik hanya karena beberapa parameter kecil—seperti port layanan, nama database, atau lokasi direktori backup—berbeda di setiap server. Ansible mengatasi masalah ini melalui mekanisme Variables (Variabel). Dengan memisahkan logika playbook yang bersifat statis dengan data parameter yang bersifat dinamis di dalam inventaris, kita dapat menggunakan satu playbook yang sama untuk mengatur ratusan server yang berbeda. Artikel ini membedah metode pendefinisian variabel inventaris, pemanfaatan struktur folder variabel kompleks, variabel koneksi penting, urutan prioritas (precedence), hingga pengelolaan variabel per-lingkungan.

Abstraksi Konfigurasi Dinamis #

Secara filosofis, variabel dalam inventaris Ansible berfungsi sebagai jembatan abstraksi yang dinamis. Melalui variabel, kita dapat menerapkan konsep pemrograman berorientasi objek dalam pengelolaan server: kita menetapkan perilaku dasar (methods) di tingkat playbook, sedangkan data properti (properties) disuntikkan secara dinamis saat playbook dieksekusi berdasarkan host target.

Hal ini memberikan tiga keuntungan operasional yang sangat besar:

  1. Dapat Digunakan Kembali (Reusability): Playbook kita terbebas dari nilai-nilai keras (hardcoded values) sehingga aman dibagikan di repositori publik.
  2. Keamanan Data Sensitif: Kita dapat memisahkan variabel bernilai rahasia (seperti token API) untuk dienkripsi secara khusus, sementara kode playbook tetap terbaca dengan jelas.
  3. Portabilitas Lingkungan: Kita dapat dengan mudah meniru susunan infrastruktur produksi ke lingkungan pengembangan lokal hanya dengan merubah file variabel terkait.

Tiga Metode Pendefinisian Variabel #

Ansible menyediakan tiga tempat utama untuk meletakkan variabel di tingkat inventaris. Pemilihan tempat ini menentukan kemudahan pemeliharaan seiring berkembangnya tim kita.

1. Langsung di dalam File Inventaris (Inline Variables) #

Metode ini mendefinisikan variabel langsung di sebelah alamat IP atau nama host pada file hosts.ini atau hosts.yml.

  • Format INI (Inline Variables):
    # File: inventory/hosts.ini
    [webservers]
    web-01.example.com http_port=80 max_clients=200
    web-02.example.com http_port=8080 max_clients=100
    
    [webservers:vars]
    nginx_version=1.24
    deploy_dir=/opt/nginx
    
  • Format YAML (Inline Variables):
    # File: inventory/hosts.yml
    ---
    webservers:
      hosts:
        web-01.example.com:
          http_port: 80
          max_clients: 200
        web-02.example.com:
          http_port: 8080
          max_clients: 100
      vars:
        nginx_version: "1.24"
        deploy_dir: /opt/nginx
    
# ANTI-PATTERN: Menumpuk variabel langsung di file inventaris
# hosts.ini
web-01.example.com http_port=80 max_clients=200 db_user=root db_pass=secret log_level=debug path=/opt/app

# BENAR: Biarkan file inventaris tetap bersih hanya berisi daftar host dan grup
# hosts.ini
web-01.example.com

Menuliskan variabel inline seperti contoh anti-pattern di atas sangat tidak dianjurkan untuk proyek jangka panjang karena merusak keterbacaan file inventaris dan mempersulit pelacakan perubahan variabel lewat Git commit history.

2. Menggunakan Direktori group_vars/ (Variabel Tingkat Grup) #

Ansible secara otomatis memuat seluruh variabel dari direktori bernama group_vars/ yang berada sejajar dengan file inventaris atau file playbook kita. Nama berkas YAML di dalam folder ini harus mewakili nama grup server target.

inventory/
  ├── hosts.ini
  └── group_vars/
      ├── all.yml          # Variabel global untuk seluruh host
      ├── webservers.yml   # Hanya untuk host di grup webservers
      └── dbservers.yml    # Hanya untuk host di grup dbservers

Contoh isi berkas group_vars/webservers.yml:

# File: inventory/group_vars/webservers.yml
---
nginx_version: "1.24"
http_port: 80
https_port: 443
nginx_worker_processes: 4
deploy_path: /opt/webapp

3. Menggunakan Direktori host_vars/ (Variabel Tingkat Host) #

Untuk kasus di mana sebuah server memiliki parameter khusus yang berbeda dengan server lain di dalam grup yang sama (misalnya server database primary membutuhkan memori cache lebih besar dibanding replica), kita meletakkan variabelnya di direktori host_vars/.

inventory/
  ├── hosts.ini
  └── host_vars/
      ├── db-primary.example.com.yml
      └── db-replica-01.example.com.yml

Contoh isi berkas host_vars/db-primary.example.com.yml:

# File: inventory/host_vars/db-primary.example.com.yml
---
db_max_connections: 500
db_shared_buffers: "4GB"
# Indikator status primary server
db_is_primary: true

Struktur Folder untuk Variabel Kompleks #

Ketika proyek otomatisasi kita mengelola puluhan layanan yang kompleks, satu file group_vars/webservers.yml dapat membengkak hingga ratusan baris berisi campuran variabel Nginx, SSL, PHP, dan sistem pemantauan. Ini akan mempersulit proses modifikasi parameter.

Ansible mendukung pembagian variabel menggunakan struktur subdirektori. Kita dapat mengubah file group_vars/webservers.yml menjadi sebuah direktori bernama group_vars/webservers/, lalu membaginya ke dalam beberapa berkas terpisah berdasarkan kepentingannya:

inventory/group_vars/
  ├── all/
  │   ├── common.yml
  │   └── security.yml
  │
  └── webservers/                  # Menggantikan file webservers.yml
      ├── main.yml                 # Variabel umum grup
      ├── nginx.yml                # Konfigurasi spesifik web server Nginx
      ├── php-fpm.yml              # Konfigurasi PHP processor
      └── monitoring.yml           # Variabel agen pemantau prometheus

Ansible akan memproses seluruh berkas berakhiran .yml atau .yaml di dalam folder webservers/ secara alfabetis dan menggabungkannya ke dalam satu namespace variabel grup webservers.


Bedah Parameter Koneksi Penting #

Ansible memiliki kumpulan variabel khusus bawaan yang diawali dengan kata kunci ansible_. Variabel ini bukan digunakan untuk konfigurasi aplikasi kita, melainkan untuk mengatur perilaku taktis koneksi SSH dan otentikasi dari control node menuju managed node.

Berikut daftar variabel koneksi yang wajib kita pahami:

  • ansible_host: Alamat IP aktual atau nama host alternatif yang digunakan untuk koneksi jika nama host yang terdaftar di inventaris hanyalah sebuah alias.
    # Contoh penggunaan alias di hosts.ini:
    # prod-web-01 ansible_host=10.0.4.12
    
  • ansible_port: Port koneksi SSH target jika managed node dikonfigurasi untuk tidak menggunakan port SSH default (22).
  • ansible_user: Nama pengguna (username) yang digunakan untuk masuk ke target server via SSH.
  • ansible_ssh_private_key_file: Jalur ke file kunci privat SSH (misalnya ~/.ssh/id_ed25519) jika kita tidak menggunakan agent forwarding.
  • ansible_python_interpreter: Menentukan jalur absolut interpreter Python di server target. Sangat penting jika target server menggunakan versi Python kustom (seperti /usr/bin/python3 pada Ubuntu modern atau /usr/libexec/platform-python pada RHEL 8).
  • ansible_connection: Jenis koneksi yang digunakan. Default-nya adalah ssh. Opsi lainnya adalah local (untuk mengeksekusi mekanisme lokal di control node) atau winrm (untuk server Windows via WinRM).
  • ansible_ssh_common_args: Menambahkan argumen SSH tambahan yang bersifat global. Parameter ini sangat penting dalam topologi jaringan aman produksi di mana server managed node kita berada di dalam sub-jaringan tertutup (private subnet) tanpa akses IP publik langsung. Kita dapat menggunakan proxy tunneling melewati mesin Bastion (Jump Host):
    # Contoh melewatkan koneksi SSH ke target server melalui Bastion Host
    ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q [email protected]"'
    
  • ansible_ssh_extra_args: Digunakan untuk menambahkan argumen SSH ekstra yang hanya ditempelkan pada eksekusi perintah pemindahan data (seperti SFTP/SCP), sedangkan koneksi interaktif tetap menggunakan konfigurasi umum.
  • ansible_ssh_pass & ansible_become_pass: Menyimpan password SSH dan password eskalasi privilege sudo. Ingat, menyimpan data ini secara plaintext di file variabel adalah ancaman keamanan tinggi. Parameter ini harus selalu dienkripsi via Ansible Vault.

Contoh konfigurasi global parameter koneksi di group_vars/all.yml:

# File: inventory/group_vars/all.yml
---
ansible_user: deployer
ansible_port: 22
ansible_ssh_private_key_file: ~/.ssh/id_ed25519
ansible_python_interpreter: /usr/bin/python3
ansible_become: true
ansible_become_method: sudo

Hierarki dan Urutan Precedence #

Salah satu aspek yang paling sering memicu kebingungan dan kegagalan logika eksekusi playbook adalah pemahaman yang salah tentang Precedence (Urutan Prioritas). Ketika sebuah variabel dengan nama yang sama didefinisikan di beberapa tempat sekaligus, Ansible akan menerapkan aturan resolusi prioritas yang ketat.

Berikut urutan prioritas variabel khusus di tingkat inventaris, diurutkan dari prioritas terendah (paling mudah ditimpa) ke prioritas tertinggi (paling kuat menimpa):

Prioritas Variabel Inventaris (Prioritas Rendah ke Tinggi):
  1. group_vars/all (Tingkat Global)            ← Prioritas Terendah
  2. group_vars/parent (Grup Induk)             ← Mewarisi properti dasar
  3. group_vars/child (Grup Anak)              ← Lebih spesifik dari induk
  4. host_vars (Tingkat Host Spesifik)          ← Prioritas Tertinggi Inventaris

Visualisasi pewarisan prioritas ini dapat dilihat pada diagram berikut:

flowchart TD
    A["group_vars/all (Prioritas 1)"] -->|"Ditimpa oleh"| B["group_vars/parent (Prioritas 2)"]
    B -->|"Ditimpa oleh"| C["group_vars/child (Prioritas 3)"]
    C -->|"Ditimpa oleh"| D["host_vars/host.yml (Prioritas 4)"]
    D -->|"Ditimpa oleh"| E["Variabel tingkat Playbook / CLI (Prioritas 5+)"]

Studi Kasus Nyata Resolusi Precedence: #

Misalkan kita mendefinisikan port aplikasi http_port di beberapa file berikut:

  1. Di dalam group_vars/all.yml (semua server):
    http_port: 80
    
  2. Di dalam group_vars/webservers.yml (grup web):
    http_port: 8080
    
  3. Di dalam host_vars/web-01.example.com.yml (host tertentu):
    http_port: 9090
    

Hasil resolusi akhir saat Ansible memproses variabel:

  • Untuk server web-01.example.com, nilai http_port adalah 9090 (karena host_vars menimpa semuanya).
  • Untuk server web-02.example.com (yang juga anggota grup webservers), nilai http_port adalah 8080 (karena ditimpa oleh group_vars/webservers).
  • Untuk server db-01.example.com (yang bukan anggota grup webservers), nilai http_port adalah 80 (menggunakan nilai global dari group_vars/all).

Strategi Multi-Lingkungan #

Dalam siklus rilis aplikasi modern, kita wajib mengisolasi konfigurasi antara lingkungan Pengembangan (development), Pengujian (staging), dan Produksi (production). Kita menggunakan playbook yang sama, namun menyuntikkan variabel yang berbeda untuk masing-masing lingkungan menggunakan arsitektur folder inventaris terpisah.

Jalur implementasi layout multi-lingkungan:

environments/
  ├── staging/
  │   ├── hosts.ini
  │   └── group_vars/
  │       ├── all.yml          # Variabel global lingkungan Staging
  │       └── webservers.yml   # Konfigurasi web server Staging
  │
  └── production/
      ├── hosts.ini
      └── group_vars/
          ├── all.yml          # Variabel global lingkungan Produksi
          └── webservers.yml   # Konfigurasi web server Produksi

Perbedaan Nilai Variabel Berdasarkan Lingkungan #

  • Staging (environments/staging/group_vars/all.yml):
    env_label: "staging"
    db_host: "staging-db.internal"
    enable_debug_mode: true
    log_level: "debug"
    
  • Produksi (environments/production/group_vars/all.yml):
    env_label: "production"
    db_host: "prod-db-cluster.internal"
    enable_debug_mode: false
    log_level: "error"
    

Ketika kita memicu eksekusi, perbedaan perilaku ini dikontrol secara eksplisit dari baris perintah terminal kita:

# Menjalankan deployment ke staging
ansible-playbook -i environments/staging/ playbooks/deploy.yml

# Menjalankan deployment ke produksi
ansible-playbook -i environments/production/ playbooks/deploy.yml

Anti-Pattern dan Mitigasi #

Berikut adalah beberapa kesalahan umum (anti-pattern) dalam pengelolaan variabel inventaris beserta cara mengatasinya.

1. Menyimpan Kredensial Sensitif secara Polos (Plaintext Secrets) #

Menyimpan token API, password database, atau private key SSH langsung di file YAML dalam format plaintext yang dapat dibaca oleh siapa saja.

# ANTI-PATTERN: Kredensial polos di group_vars/all.yml
db_password: "MySuperSecretDBPassword123"
  • Mitigasi: Selalu gunakan Ansible Vault untuk mengenkripsi variabel sensitif. Kita direkomendasikan memisahkan variabel non-sensitif dengan variabel sensitif ke dalam file terpisah di dalam folder grup yang sama:
    • File non-sensitif: group_vars/webservers/vars.yml
    • File terenkripsi: group_vars/webservers/vault.yml (dienkripsi dengan perintah ansible-vault encrypt)

2. Duplikasi Variabel yang Berlebihan #

Mendefinisikan parameter yang bernilai sama di setiap berkas grup variabel secara berulang kali.

# ANTI-PATTERN: Duplikasi data di group_vars/webservers.yml dan group_vars/dbservers.yml
# group_vars/webservers.yml
timezone: "Asia/Jakarta"
ntp_server: "time.unisbadri.com"

# group_vars/dbservers.yml
timezone: "Asia/Jakarta"
ntp_server: "time.unisbadri.com"
  • Mitigasi: Pindahkan seluruh parameter yang bersifat homogen (sama untuk semua server) ke dalam berkas global group_vars/all.yml. Berkas grup spesifik hanya boleh berisi variabel yang unik untuk grup tersebut.

Ringkasan #

  • Pemisahan Logika & Parameter — Variabel memisahkan alur eksekusi playbook yang statis dengan data konfigurasi dinamis target server untuk mengoptimalkan reusability.
  • Tiga Metode Deklarasi — Variabel tingkat inventaris dapat ditulis secara inline di file hosts, dalam berkas group_vars/ (grup), atau berkas host_vars/ (host spesifik).
  • Abstraksi Folder Kompleks — Mengganti file grup YAML tunggal menjadi sebuah direktori dengan berkas-berkas terpisah berbasis concern (seperti nginx.yml, ssl.yml) memudahkan pemeliharaan jangka panjang.
  • Variabel Otentikasi Khusus — Opsi penentuan perilaku koneksi dikelola oleh parameter internal seperti ansible_user, ansible_port, dan ansible_python_interpreter.
  • Aturan Precedence Ketat — Pewarisan variabel mengikuti urutan prioritas: host_vars menimpa group_vars/child, yang kemudian menimpa group_vars/parent, lalu menimpa group_vars/all.
  • Isolasi Multi-Lingkungan — Pembagian data parameter dev/staging/production dikelola melalui pemisahan direktori inventaris secara fisik di bawah folder environments/.
  • Pencegahan Kebocoran Kredensial — Selalu gunakan enkripsi Ansible Vault untuk melindungi parameter sensitif (kunci rahasia, password) sebelum mengunggah kode otomatisasi ke Git.

← Sebelumnya: Apa itu Inventory?   Berikutnya: Cloud →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact