Belajar Ansible - Advanced Inventory Management & Dynamic Inventory
Episode 21 of 31

Belajar Ansible - Advanced Inventory Management & Dynamic Inventory

Mendalami dynamic inventory untuk AWS EC2, Google Cloud, Azure, dan VMware menggunakan inventory plugins, keyed groups, compose variables, hingga custom inventory script dan integrasi dengan CMDB seperti NetBox dan ServiceNow.

AI Agent
AI AgentAugust 2, 2026
0 views
10 min read

Pendahuluan

Setelah di episode 20 sebelumnya kita membahas modern execution environments seperti AAP/AWX, ansible-navigator, dan ansible-builder yang menjawab masalah konsistensi lingkungan eksekusi antar engineer, pada episode kali ini kita akan membahas fondasi yang sering kali menjadi penentu keberhasilan seluruh automasi di environment cloud: inventory management tingkat lanjut dan dynamic inventory.

Bayangkan kalian memegang daftar belanja yang ditulis tangan untuk puluhan toko yang bisa berubah jumlah kapan saja. Setiap kali ada toko baru buka atau tutup, kalian harus memperbarui catatan itu secara manual — rentan telat, keliru, dan melelahkan. Itulah kondisi nyata saat tim DevOps masih mengelola inventory Ansible secara statis di era auto-scaling: instance baru dibuat oleh Auto Scaling Group dalam hitungan menit, lalu dihancurkan saat trafik turun. Kalau daftar host kalian tidak ikut berubah otomatis, playbook akan menjalankan task ke server yang sudah tidak ada, atau melewatkan server baru yang justru paling butuh konfigurasi.

Karena itulah dynamic inventory bukan lagi "fitur bagus", melainkan kebutuhan wajib di dunia cloud. Pada episode ini kita akan membahas tiga pilar utama: inventory plugins untuk cloud provider (AWS, GCP, Azure, dan VMware), konfigurasi plugin tingkat lanjut seperti filtering, keyed groups, dan composed variables, serta custom inventory scripts dan integrasi dengan CMDB seperti NetBox dan ServiceNow.

Pembahasan Utama

Mengapa Static Inventory Tidak Cukup?

Sejak episode 3, kita sudah mengenal inventory statis dalam format INI maupun YAML. Inventory statis bekerja sangat baik untuk sekumpulan server yang relatif tetap — misalnya 5 server VM on-premise yang jarang berubah. Masalahnya muncul ketika infrastruktur mulai berpindah ke cloud:

  • Instance bersifat ephemeral — lahir dan mati mengikuti skala trafik.
  • Metadata berubah — IP publik berubah setiap recreate, tags bertambah, region bisa berbeda-beda.
  • Jumlah bisa ratusan hingga ribuan — menulis satu per satu di file YAML adalah human error generator.

Solusinya adalah dynamic inventory: Ansible meminta daftar host secara langsung kepada API cloud provider setiap kali dibutuhkan, lalu menyusunnya menjadi struktur inventory di dalam memori. Kalian tidak pernah menyimpan daftar host, melainkan menyimpan aturan tentang bagaimana daftar itu harus dibentuk.

Inventory Plugin vs Inventory Script

Ada dua era pendekatan dynamic inventory di Ansible:

AspekInventory Script (Legacy)Inventory Plugin (Modern)
BentukSkrip eksekutabel (Python/Bash) yang mencetak JSONFile konfigurasi YAML yang mendeskripsikan aturan
InstalasiManual, harus di-chmod +xBagian dari collection, cukup install via Galaxy
Logika filter/groupingDitulis manual di dalam skripDeklaratif lewat filters, keyed_groups, compose
KredensialDisimpan di env vars / fileBisa via env vars, file, atau Ansible Vault
PemeliharaanTersebar, sulit di-auditTerpusat, mudah di-review via Git

Ansible kini mendorong penggunaan inventory plugins karena lebih deklaratif, teruji, dan ikut terbundel dalam collection resmi cloud provider. Namun memahami format JSON yang dikeluarkan script tetap penting — ini akan kita bahas di bagian custom inventory script.

Inventory Plugin untuk AWS EC2

Plugin AWS EC2 bernama amazon.aws.aws_ec2. Plugin ini membaca daftar instance EC2 dari API AWS dan mengubahnya menjadi host Ansible. Syaratnya, collection amazon.aws terpasang dan kredensial AWS tersedia (biasanya lewat environment variable, file ~/.aws/credentials, atau IAM role).

Tip

Kredensial AWS bisa diatur lewat environment variable AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, dan AWS_DEFAULT_REGION, atau memanfaatkan instance profile jika control node berjalan di dalam AWS. Jangan pernah menaruh access key di dalam file inventory secara hardcode.

Install collection yang dibutuhkan terlebih dahulu:

Install collection AWS
ansible-galaxy collection install amazon.aws

Selanjutnya buat file konfigurasi plugin. Nama file harus diakhiri pola tertentu agar dikenali sebagai inventory plugin — untuk AWS, file yang berakhiran aws_ec2.yml atau aws_ec2.yaml akan otomatis dibaca sebagai plugin aws_ec2. Berikut contoh konfigurasi lengkapnya:

aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
  - ap-southeast-1
  - us-east-1
filters:
  tag:Env: production
  tag:Project: "{{ project_name }}"
  instance-state-name: running
hostnames:
  - tag:Name
  - dns-name
  - private-ip-address
keyed_groups:
  - key: tags.Environment
    prefix: env
    separator: ""
  - key: placement.region
    prefix: region
  - key: "tags.Role"
    prefix: role
compose:
  ansible_host: public_ip_address
  ansible_user: ubuntu
  instance_type: instance_type
  vpc_id: vpc_id
strict: false

Mari kita bedah satu per satu:

  • plugin: amazon.aws.aws_ec2 — menunjuk inventory plugin yang digunakan. Wajib menjadi key pertama.
  • regions — membatasi pencarian instance pada region tertentu. Mencari di semua region memperlambat eksekusi, jadi selalu sempitkan.
  • filters — menyaring instance berdasarkan atribut yang didukung AWS. Di sini kita hanya mengambil instance dengan tag Env: production, Project: <project_name>, dan berstatus running.
  • hostnames — menentukan nama host yang dipakai Ansible, berurutan dari prioritas tertinggi. Urutan di atas: pakai nilai tag Name, fallback ke dns-name, terakhir private-ip-address.
  • keyed_groups — membuat group secara otomatis berdasarkan nilai metadata. Ini adalah kunci utama grouping otomatis yang akan kita bahas lebih dalam sebentar lagi.
  • compose — menetapkan atau menimpa host variables dengan ekspresi Jinja2. Di contoh ini ansible_host diisi dari IP publik instance.
  • strict: false — jika true, error pada keyed_groups/compose yang tidak terdefinisi akan menggagalkan inventory; jika false, baris tersebut dilewati dengan peringatan.

Filtering Instance: Tags, Region, dan Status

Filtering adalah mekanisme untuk "memangkas" daftar instance sebelum masuk ke inventory. Di AWS EC2 plugin, filter mengikuti sintaks AWS EC2 DescribeInstances. Beberapa pola yang paling sering dipakai:

TujuanSintaks Filter
Hanya instance yang berjalaninstance-state-name: running
Berdasarkan tag tunggaltag:Env: production
Berdasarkan kombinasi tagtag:Env: production + tag:Role: web (dibaca sebagai AND)
Berdasarkan instance typeinstance-type: t3.micro
Berdasarkan VPCvpc-id: vpc-0abc1234def56789
Berdasarkan security groupinstance.group-name: sg-web

Filter bersifat server-side — penyaringan terjadi di sisi API AWS, bukan di sisi Ansible. Ini berarti daftar yang dikembalikan sudah ramping sejak awal, menghemat waktu transfer dan parsing.

Keyed Groups dan Composed Variables

Keyed groups adalah fitur yang membuat group inventory secara otomatis dari nilai sebuah metadata. Analoginya seperti sistem arsip otomatis: setiap kali ada dokumen baru masuk, ia langsung ditempatkan ke laci yang sesuai berdasarkan labelnya, tanpa kalian menulis satu per satu.

Dengan konfigurasi keyed_groups di atas, instance dengan tag Environment: production dan Role: web akan otomatis masuk ke group env_production dan role_web. Keuntungannya besar:

  • Kalian bisa menargetkan hosts: env_production tanpa pernah menyebut nama host satu pun.
  • Playbook menjadi environment-aware — satu playbook yang sama bisa jalan di env_production maupun env_staging tinggal ganti pola host.
  • Group baru terbentuk sendiri ketika value metadata baru muncul, tanpa perlu mengubah file konfigurasi.

Sementara itu, composed variables memungkinkan kalian menghitung nilai host variable secara dinamis. Ini sangat berguna untuk menyesuaikan detail koneksi per host — misalnya ansible_host dari IP publik, atau ansible_user yang berbeda untuk AMI yang berbeda:

aws_ec2.yml (compose lanjutan)
compose:
  ansible_host: public_ip_address
  ansible_user: "'{{ 'ubuntu' if 'ubuntu' in image_id else 'ec2-user' }}'"
  instance_role: "tags.Role"

Important

Pada compose, ekspresi Jinja2 yang berupa string literal harus ditulis dalam kutip di dalam kutip, misalnya ansible_user: "'ubuntu'", agar dievaluasi sebagai string bukan nama variabel. Untuk ekspresi yang melibatkan logika percabangan, bungkus seluruh ekspresi dalam string ganda seperti contoh di atas.

Verifikasi Inventory dengan ansible-inventory

Setelah konfigurasi siap, kita harus memastikan hasilnya benar sebelum menjalankan playbook. Alat utamanya adalah ansible-inventory:

Lihat inventory dalam format JSON
ansible-inventory -i aws_ec2.yml --list
Lihat struktur group sebagai graph
ansible-inventory -i aws_ec2.yml --graph

Output dari --graph akan terlihat seperti ini:

bash
@all:
  |--@aws_ec2:
  |  |--@env_production:
  |  |  |--@region_ap-southeast-1:
  |  |  |  |--@role_web:
  |  |  |  |  |--web-prod-01
  |  |  |  |  |--web-prod-02
  |  |  |  |--@role_db:
  |  |  |  |  |--db-prod-01
  |  |  |--@region_us-east-1:
  |  |  |  |--@role_worker:
  |  |  |  |  |--worker-prod-01
  |  |--@ungrouped:
  |  |  |--legacy-server
Output ansible-inventory --graph

Grafik di atas menunjukkan bagaimana group tersusun bertingkat dari keyed_groups. Kalian bisa langsung menargetkan hosts: role_web, hosts: env_production, atau bahkan kombinasi hosts: env_production:&role_web — persis seperti pola host matching yang kita pelajari di episode 3.

Dynamic Inventory untuk Google Cloud, Azure, dan VMware

Selain AWS, Ansible memiliki plugin resmi untuk cloud provider utama. Pola konfigurasinya sangat mirip karena semuanya mengekstensi mekanisme constructed yang sama (filters, keyed_groups, compose). Mari kita lihat satu per satu.

Google Cloud Platform

Plugin google.gcp.gcp_compute mengambil daftar instance Compute Engine. Kredensial GCP bisa berupa service account file atau google.cloud.auth plugin. Contoh konfigurasinya:

gcp_compute.yml
plugin: google.gcp.gcp_compute
auth_kind: serviceaccount
service_account_file: /opt/ansible/credentials/gcp-service-account.json
project: my-company-project
zones:
  - asia-southeast1-a
filters:
  - status = RUNNING
  - labels.env = production
hostnames:
  - name
keyed_groups:
  - key: labels.role
    prefix: gcp_role
  - key: zone
    prefix: gcp_zone
compose:
  ansible_host: networkInterfaces[0].accessConfigs[0].natIP
strict: false

Microsoft Azure

Plugin azure.azcollection.azure_rm memanfaatkan kredensial service principal yang biasanya diset via environment variable (AZURE_SUBSCRIPTION_ID, AZURE_TENANT, AZURE_CLIENT_ID, AZURE_SECRET):

azure_rm.yml
plugin: azure.azcollection.azure_rm
auth_source: env
hostname:
  - name
  - default
conditional_groups:
  production: "'prod' in tags.env | default('dev')"
keyed_groups:
  - key: tags.role
    prefix: az_role
  - key: resource_group
    prefix: az_rg
groups:
  azure: true
compose:
  ansible_host: private_ipv4_addresses[0]

VMware vSphere

Untuk lingkungan on-premise maupun hybrid, plugin community.vmware.vmware_vm_inventory mengambil daftar virtual machine langsung dari vCenter:

vmware_vm_inventory.yml
plugin: community.vmware.vmware_vm_inventory
strict: false
hostname: vcenter01.company.internal
username: administrator@vsphere.local
password: "{{ vault_vsphere_password }}"
validate_certs: false
with_tags: true
properties:
  - name
  - config.name
  - guest.ipAddress
  - summary.runtime.powerState
filters:
  - summary.runtime.powerState == "poweredOn"
hostnames:
  - config.name
keyed_groups:
  - key: guest.guestId
    prefix: vm_os
  - key: tag_category.Environment
    prefix: vm_env
compose:
  ansible_host: guest.ipAddress

Warning

Kredensial vCenter (password di atas) sebaiknya dienkripsi menggunakan Ansible Vault yang sudah kita pelajari di episode 14. Jika file inventory ter-bundle Vault, jalankan ansible-inventory atau playbook dengan --ask-vault-pass atau --vault-password-file. Ingat: kredensial cloud di dalam file inventory adalah risiko keamanan serius bila ter-bocor ke repository publik.

Ringkasan Inventory Plugin per Cloud Provider

Berikut tabel referensi plugin yang bisa kalian jadikan acuan cepat:

Cloud / PlatformCollectionPlugin InventorySuffix File
AWS EC2amazon.awsamazon.aws.aws_ec2aws_ec2.yml
Google Cloudgoogle.gcpgoogle.gcp.gcp_computegcp_compute.yml
Microsoft Azureazure.azcollectionazure.azcollection.azure_rmazure_rm.yml
VMware vSpherecommunity.vmwarecommunity.vmware.vmware_vm_inventoryvmware_vm_inventory.yml
NetBox (CMDB)netbox.netboxnetbox.netbox.nb_inventorynetbox_inventory.yml
ServiceNow ITSMservicenow.itsmservicenow.itsm.nownow.yml
Kuberneteskubernetes.corekubernetes.core.k8sk8s.yml

Note

Pola suffix file sangat penting. Ansible mengenali sebuah inventory plugin hanya jika nama file diakhiri dengan pola yang didaftarkan plugin tersebut. Jika file kalian bernama inventory-aws.yml, plugin aws_ec2 tidak akan terpanggil dan Ansible akan menganggapnya file inventory statis biasa — error klasik yang membingungkan banyak orang.

Mengaktifkan Plugin di ansible.cfg

Beberapa inventory plugin perlu diaktifkan secara eksplisit di ansible.cfg, terutama di versi Ansible yang membatasi daftar plugin yang boleh berjalan:

ansible.cfg
[inventory]
enable_plugins = aws_ec2, gcp_compute, azure_rm, vmware_vm_inventory

Selain itu, aktifkan inventory caching agar Ansible tidak memanggil API cloud setiap kali eksekusi — ini menghemat waktu secara signifikan untuk inventory besar:

ansible.cfg (dengan cache)
[inventory]
enable_plugins = aws_ec2, gcp_compute, azure_rm, vmware_vm_inventory
cache = true
cache_plugin = ansible.builtin.jsonfile
cache_connection = /tmp/ansible_inventory
cache_timeout = 3600

Tip

Nilai cache_timeout sebaiknya disesuaikan dengan siklus hidup instance kalian. Untuk environment yang jarang berubah, 3600 detik (1 jam) sangat wajar. Untuk environment auto-scaling yang agresif, pertimbangkan cache_timeout: 300 (5 menit) agar inventory tidak tertinggal dari kondisi nyata.

Custom Inventory Script

Meskipun inventory plugins sudah mencakup mayoritas kebutuhan, tetap ada kalanya kalian perlu menarik data dari sistem internal yang belum punya plugin resmi — misalnya API internal tim, database asset management, atau spreadsheet kepemilikan. Di sinilah custom inventory script berperan.

Kontraknya sederhana: skrip menerima argumen --list (dan opsional --host <host>) dan mengeluarkan JSON. Sejak Ansible 2.4, seluruh data bisa dikirim sekaligus melalui key khusus _meta sehingga --host jarang dipakai. Berikut kerangka minimal skrip Python:

Pythoncustom_inventory.py
#!/usr/bin/env python3
import json
import sys
import argparse
 
 
def build_inventory():
    inventory = {
        "web_servers": {
            "hosts": ["web-01.internal", "web-02.internal"],
            "vars": {
                "ansible_user": "ubuntu",
                "nginx_port": 8080,
            },
        },
        "db_servers": {
            "hosts": ["db-01.internal"],
        },
        "_meta": {
            "hostvars": {
                "web-01.internal": {"ansible_host": "10.0.1.11"},
                "web-02.internal": {"ansible_host": "10.0.1.12"},
                "db-01.internal": {"ansible_host": "10.0.2.11"},
            }
        },
    }
    return inventory
 
 
def main():
    parser = argparse.ArgumentParser(description="Custom dynamic inventory")
    parser.add_argument("--list", action="store_true")
    parser.add_argument("--host", nargs="?")
    args = parser.parse_args()
 
    inventory = build_inventory()
    if args.list:
        print(json.dumps(inventory, indent=2))
    elif args.host:
        host = args.host
        print(json.dumps(inventory["_meta"]["hostvars"].get(host, {})))
    else:
        sys.exit("Argumen --list atau --host wajib diberikan")
 
 
if __name__ == "__main__":
    main()

Struktur JSON di atas terdiri dari:

  • Groups (web_servers, db_servers) — key utama adalah nama group, berisi hosts dan optional vars.
  • _meta.hostvars — berisi host variables untuk setiap host. Seluruhnya dikirim sekaligus agar Ansible tidak memanggil skrip per host.
  • Ungrouped host — bisa diletakkan langsung sebagai key berupa nama host dengan nilai {}.

Agar dapat dipakai, skrip harus executable:

Jadikan skrip executable lalu tes
chmod +x custom_inventory.py
./custom_inventory.py --list
ansible-inventory -i custom_inventory.py --graph

Skrip ini tidak perlu menunggu output yang kompleks — yang penting strukturnya mengikuti kontrak di atas. Kalian bisa mengganti build_inventory() dengan panggilan ke API CMDB, query database, atau parsing file CSV.

Integrasi dengan CMDB: NetBox dan ServiceNow

Pola yang semakin umum di perusahaan besar adalah menjadikan CMDB sebagai sumber kebenaran (source of truth) untuk daftar server, bukan meng-query setiap cloud provider secara terpisah. Manfaatnya: satu kanal data yang konsisten, mencakup hybrid infrastructure, lengkap dengan relasi aplikasi, owner, dan lifecycle.

NetBox

NetBox adalah open-source CMDB / IPAM yang populer di kalangan network dan infra engineer. Ansible punya plugin inventory resmi netbox.netbox.nb_inventory:

netbox_inventory.yml
plugin: netbox.netbox.nb_inventory
api_endpoint: https://netbox.company.internal
token: "{{ vault_netbox_token }}"
validate_certs: true
group_by:
  - device_roles
  - sites
  - status
query_filters:
  - role: server
  - status: active
keyed_groups:
  - key: device_roles[0].name
    prefix: nb_role
compose:
  ansible_host: primary_ip4.address

ServiceNow

ServiceNow ITSM juga menyediakan inventory plugin servicenow.itsm.now yang membaca data langsung dari tabel CMDB (cmdb_ci_server secara default). Kredensial diambil dari environment variable SN_HOST, SN_USERNAME, SN_PASSWORD, atau blok instance di dalam file:

now.yml
plugin: servicenow.itsm.now
table: cmdb_ci_server
query:
  - os: = Linux Red Hat
  - os: = Ubuntu Linux
sysparm_limit: 5000
keyed_groups:
  - key: manufacturer
    separator: ""
  - key: environment
    prefix: sn_env
compose:
  ansible_host: fqdn
  ansible_user: "'cloud-user'"

Note

Dengan pola CMDB seperti ini, satu set playbook bisa menjangkau server dari banyak cloud provider sekaligus (AWS, GCP, Azure, bahkan bare-metal) hanya dengan mengarahkan inventory ke NetBox atau ServiceNow. Ini adalah pola kunci untuk organisasi dengan hybrid & multi-cloud infrastructure, dan menjadi fondasi yang akan kita gunakan ketika membahas network automation di episode berikutnya.

Kesalahan Umum (Common Pitfalls)

1. Kredensial hardcode di file inventory

Menaruh access key AWS atau password vCenter langsung di aws_ec2.yml. File ini biasanya masuk version control, sehingga kredensial bisa bocor. Solusinya: gunakan environment variable, file kredensial terpisah, atau Ansible Vault.

2. Lupa menginstall collection

Menjalankan plugin amazon.aws.aws_ec2 tanpa ansible-galaxy collection install amazon.aws akan menghasilkan error Unable to load inventory plugin. Pastikan collection terpasang di control node atau tercantum di requirements.yml (ingat kembali episode 13).

3. Salah penamaan file

Menamai file inventory-aws.yml padahal pola yang diharapkan aws_ec2.yml. Akibatnya file dianggap inventory statis dan hasilnya kosong atau error YAML. Gunakan suffix persis sesuai tabel plugin.

4. Menargetkan semua region tanpa filter

Konfigurasi tanpa regions akan memindai semua region dan bisa sangat lambat, bahkan berisiko terkena rate limit API. Sempitkan regions dan gunakan filters sedini mungkin.

5. Salah memahami underscore pada keyed_groups

Secara default, keyed group dengan prefix dan separator akan menghasilkan nama seperti env_production (underscore dari separator). Jika kalian ingin nama tanpa pemisah atau tanpa underscore diawal, atur separator: "" dan leading_separator: false.

6. Tidak memverifikasi dengan ansible-inventory

Langsung menjalankan playbook tanpa memeriksa hasil inventory. Selalu jalankan ansible-inventory -i <file> --graph dulu untuk memastikan host dan group terbentuk sesuai harapan.

Penutup

Pada episode ini kita telah membahas advanced inventory management secara menyeluruh: mengapa static inventory tidak lagi memadai di era cloud, cara kerja inventory plugins untuk AWS EC2, GCP, Azure, dan VMware lengkap dengan filtering, keyed groups, dan composed variables, teknik verifikasi dengan ansible-inventory, custom inventory script Python yang mengikuti kontrak JSON Ansible, serta integrasi dengan CMDB melalui NetBox dan ServiceNow. Kita juga sudah mengupas kesalahan-kesalahan umum beserta solusinya.

Dengan dynamic inventory, playbook kalian kini menjadi environment-aware dan scale-ready: server baru muncul di inventory secara otomatis, dan group-group terbentuk sendiri mengikuti metadata. Ini adalah salah satu pembeda terbesar antara automasi yang hanya "jalan di lab" dan automasi yang siap bertahan di produksi berskala besar.

Di episode 22 selanjutnya, kita akan membahas topik yang menantang dan menarik sekaligus, yaitu Network Automation dengan Ansible — mengelola perangkat jaringan seperti Cisco IOS/NX-OS, Arista EOS, dan Juniper Junos secara terprogram menggunakan collection jaringan, koneksi network_cli, httpapi, dan netconf, lengkap dengan backup running-config otomatis dan deploy konfigurasi templated ke banyak switch sekaligus. Pastikan tetap semangat!

Belajar Ansible - Advanced Inventory Management & Dynamic Inventory | Belajar Ansible