Basic Ansible Scripting

 

Ansible: From Zero to Paham Beneran


1. Pengertian

Ansible adalah configuration management & automation tool yang ngizinin lu ngontrol ratusan server sekaligus dari satu mesin — tanpa perlu install agent di server target.


2. Konsep & Teori

  • Agentless — komunikasi pure lewat SSH (Linux) atau WinRM (Windows). Nggak ada daemon jalan di server target.
  • Idempotent — jalanin playbook 10x = hasilnya sama. Nggak bakal double-install atau rusak state yang udah bener.
  • Push-based — Control Node yang push perintah ke managed nodes. Kebalikan dari Puppet/Chef yang pull.
  • Ditulis pake YAML — human-readable, nggak perlu belajar bahasa baru.
  • Berbasis Python — modulnya semua Python, bisa di-extend.

3. Arsitektur & Komponen Inti

┌─────────────────────────────────────────────────────┐
│                  CONTROL NODE                        │
│   (Laptop/Server lo yang jalanin Ansible)            │
│                                                      │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────┐  │
│  │Inventory │  │Playbook  │  │ansible.cfg       │  │
│  │(hosts)   │  │(task list│  │(global config)   │  │
│  └──────────┘  └──────────┘  └──────────────────┘  │
└───────────────────────┬─────────────────────────────┘
                        │ SSH / WinRM
          ┌─────────────┼─────────────┐
          ▼             ▼             ▼
   ┌────────────┐ ┌────────────┐ ┌────────────┐
   │  Node 1   │ │  Node 2   │ │  Node 3   │
   │ web-01    │ │ db-01     │ │ lb-01     │
   └────────────┘ └────────────┘ └────────────┘
        MANAGED NODES (target server)

Komponen wajib paham:

Komponen Fungsi
Control Node Mesin yang lu pake buat jalanin Ansible
Managed Node Server target yang dikontrol
Inventory Daftar server target (file hosts)
Playbook Script YAML berisi urutan task
Task Satu unit pekerjaan (install nginx, copy file, dll)
Module "Tool" bawaan Ansible (apt, yum, copy, service, dll)
Role Kumpulan playbook + file yang distrukturkan rapi
Handler Task yang cuma jalan kalau dipanggil (triggered)
Vault Enkripsi secret/password di dalam playbook
Facts Info otomatis tentang server target (OS, IP, RAM, dll)

4. Cara Kerja

Step 1: Lu tulis Inventory → siapa server targetnya
    ↓
Step 2: Lu tulis Playbook → mau ngapain di server itu
    ↓
Step 3: ansible-playbook dijalanin
    ↓
Step 4: Ansible SSH ke tiap node
    ↓
Step 5: Ansible push Python module (temporary) ke /tmp di target
    ↓
Step 6: Module dieksekusi di target
    ↓
Step 7: Output balik ke Control Node
    ↓
Step 8: Ansible hapus temporary file → BERSIH
    ↓
Step 9: Lu dapat laporan: OK / CHANGED / FAILED

5. Tujuan

  • Provisioning massal — setup 100 server baru sekaligus dalam menit
  • Config management — pastiin semua server punya config yang sama
  • Deployment aplikasi — deploy code ke staging/production otomatis
  • Compliance — enforce security policy di semua node
  • Orchestration — koordinasi urutan task antar banyak server

6. Analogi

Bayangin lu mandor proyek konstruksi.

Lu punya blueprint (Playbook), daftar tukang (Inventory), dan toolbox (Modules).

Lu nggak perlu ada di tiap lokasi — lu kirim instruksi lewat radio (SSH), tukang-tukang lu kerjain sesuai blueprint, lalu laporan balik ke lu. Kalau ada yang udah beres, lu nggak suruh ngerjain ulang (idempotent).


7. Pros & Cons

Kelebihan Kekurangan
Agentless, setup cepet Lambat kalau node ribuan (banding Puppet)
YAML mudah dibaca siapapun YAML indent-sensitive, error gampang
Idempotent by design Debugging playbook kompleks bisa pusing
Library modul sangat luas Nggak ada native GUI (butuh AWX/Tower)
Komunitas besar, dokumentasi oke Windows support lebih terbatas

8. Core Config & Praktik Langsung

8.1 — Instalasi di Control Node

# Update repo dulu
$ sudo apt update

# Install Ansible (Ubuntu/Debian)
$ sudo apt install ansible -y

# Cek versi
$ ansible --version

# Cek path config yang aktif
$ ansible --version | grep "config file"

8.2 — Struktur Project yang Rapi

my-ansible-project/
├── ansible.cfg          # Config global project ini
├── inventory/
│   ├── hosts            # Daftar server
│   └── group_vars/
│       ├── all.yml      # Variabel berlaku ke semua group
│       └── webservers.yml
├── playbooks/
│   ├── site.yml         # Master playbook
│   ├── webservers.yml
│   └── dbservers.yml
└── roles/
    └── nginx/
        ├── tasks/
        │   └── main.yml
        ├── handlers/
        │   └── main.yml
        ├── templates/
        │   └── nginx.conf.j2
        └── vars/
            └── main.yml

8.3 — ansible.cfg

# File: ansible.cfg (taruh di root project)

[defaults]
# Lokasi inventory default
inventory      = ./inventory/hosts

# User SSH yang dipake ke managed node
remote_user    = ubuntu

# Private key SSH
private_key_file = ~/.ssh/id_rsa

# Matiin host key checking (hati-hati di prod!)
host_key_checking = False

# Jumlah host yang diproses paralel
forks          = 10

# Log semua aktivitas ansible
log_path       = ./ansible.log

[privilege_escalation]
# Aktifin sudo otomatis
become         = True
become_method  = sudo
become_user    = root

8.4 — Inventory (INI Format)

# File: inventory/hosts

# ── Group: webservers ──
[webservers]
web-01 ansible_host=192.168.1.10
web-02 ansible_host=192.168.1.11
web-03 ansible_host=192.168.1.12

# ── Group: dbservers ──
[dbservers]
db-01 ansible_host=192.168.1.20 ansible_port=2222  # Port SSH non-standard
db-02 ansible_host=192.168.1.21

# ── Group of Groups ──
[production:children]   # Group "production" berisi webservers + dbservers
webservers
dbservers

# ── Variabel per-group ──
[webservers:vars]
http_port=80
ansible_user=ubuntu

8.5 — Playbook Pertama (Basic)

# File: playbooks/webservers.yml
---
- name: Setup Web Server                  # Nama play (deskriptif)
  hosts: webservers                       # Target group dari inventory
  become: true                            # Jalanin sebagai sudo

  vars:                                   # Variabel lokal playbook ini
    app_port: 80
    pkg_list:
      - nginx
      - curl
      - git

  tasks:

    - name: Update apt cache              # Task 1: update repo
      apt:
        update_cache: yes
        cache_valid_time: 3600            # Cache valid 1 jam, skip kalau masih fresh

    - name: Install required packages     # Task 2: install paket
      apt:
        name: "{{ pkg_list }}"            # Pakai variabel list di atas
        state: present                    # Pastiin terinstall (idempotent)

    - name: Start dan enable nginx        # Task 3: pastiin nginx running
      service:
        name: nginx
        state: started
        enabled: yes                      # Auto-start saat boot

    - name: Copy konfigurasi nginx        # Task 4: push config file
      template:
        src: ../roles/nginx/templates/nginx.conf.j2   # Template Jinja2
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: '0644'
      notify: Restart nginx               # Trigger handler kalau ada perubahan

  handlers:                               # Hanya jalan kalau di-notify
    - name: Restart nginx
      service:
        name: nginx
        state: restarted

8.6 — Variabel & Facts

# Cara akses Facts (info otomatis dari target server)
- name: Debug info server
  hosts: all
  tasks:

    - name: Tampilkan semua facts          # Lihat semua facts yang tersedia
      debug:
        var: ansible_facts

    - name: Tampilkan IP address           # Akses fact spesifik
      debug:
        msg: "IP server ini: {{ ansible_default_ipv4.address }}"

    - name: Tampilkan versi OS
      debug:
        msg: "OS: {{ ansible_distribution }} {{ ansible_distribution_version }}"

    - name: Kondisional berdasarkan OS     # Task hanya jalan di Ubuntu
      apt:
        name: nginx
        state: present
      when: ansible_distribution == "Ubuntu"

8.7 — Loop & Kondisional

tasks:
  # ── LOOP: buat banyak user sekaligus ──
  - name: Buat user developer
    user:
      name: "{{ item }}"                  # item = tiap elemen di loop
      shell: /bin/bash
      create_home: yes
    loop:                                 # Iterasi list ini
      - alice
      - bob
      - charlie

  # ── KONDISIONAL: hanya di server production ──
  - name: Disable root SSH login
    lineinfile:
      path: /etc/ssh/sshd_config
      regexp: '^PermitRootLogin'
      line: 'PermitRootLogin no'
    when: "'production' in group_names"   # Cek apakah host ada di group production

  # ── REGISTER: simpan output task ke variabel ──
  - name: Cek apakah file config ada
    stat:
      path: /etc/app/config.yml
    register: config_file                 # Simpan hasil ke variabel config_file

  - name: Buat config kalau belum ada
    copy:
      content: "key: value\n"
      dest: /etc/app/config.yml
    when: not config_file.stat.exists    # Hanya jalan kalau file belum ada

8.8 — Ansible Vault (Enkripsi Secret)

# Buat file encrypted baru
$ ansible-vault create secrets.yml

# Encrypt file yang udah ada
$ ansible-vault encrypt group_vars/all/vault.yml

# Lihat isi file terenkripsi
$ ansible-vault view secrets.yml

# Edit file terenkripsi
$ ansible-vault edit secrets.yml

# Decrypt permanen
$ ansible-vault decrypt secrets.yml

# Jalanin playbook yang pakai vault
$ ansible-playbook site.yml --ask-vault-pass

# Atau pakai password file (buat CI/CD)
$ ansible-playbook site.yml --vault-password-file ~/.vault_pass
# secrets.yml (setelah di-encrypt, isinya jadi gibberish)
# Sebelum encrypt, isinya:
db_password: "S3cr3tP@ssw0rd"
api_key: "sk-prod-xxxxxxxxxxxx"

# Pake di playbook:
- name: Set DB password
  lineinfile:
    path: /etc/app/.env
    line: "DB_PASS={{ db_password }}"  # Referensi variabel dari vault

8.9 — Command Harian & Troubleshooting

# ── AD-HOC COMMAND (tanpa playbook) ──

# Ping semua host (cek koneksi)
$ ansible all -m ping

# Ping group tertentu
$ ansible webservers -m ping

# Jalanin command shell di semua node
$ ansible all -m shell -a "uptime"

# Cek disk di dbservers
$ ansible dbservers -m shell -a "df -h"

# Copy file ke semua web server
$ ansible webservers -m copy -a "src=/local/file dest=/remote/path"

# Install paket di satu host spesifik
$ ansible web-01 -m apt -a "name=htop state=present" --become


# ── JALANIN PLAYBOOK ──

# Dry-run (check mode, nggak ada yang berubah)
$ ansible-playbook site.yml --check

# Lihat diff perubahan file sebelum apply
$ ansible-playbook site.yml --check --diff

# Jalanin hanya task dengan tag tertentu
$ ansible-playbook site.yml --tags "nginx,ssl"

# Skip task tertentu
$ ansible-playbook site.yml --skip-tags "update"

# Limit ke host/group tertentu
$ ansible-playbook site.yml --limit webservers
$ ansible-playbook site.yml --limit web-01

# Verbose mode (debug)
$ ansible-playbook site.yml -v     # Verbose level 1
$ ansible-playbook site.yml -vvv   # Verbose level 3 (paling detail)

# Mulai dari task tertentu (kalau gagal di tengah)
$ ansible-playbook site.yml --start-at-task="Copy konfigurasi nginx"


# ── TROUBLESHOOTING ──

# Lihat semua facts server (debug awal)
$ ansible web-01 -m setup

# Filter facts tertentu
$ ansible web-01 -m setup -a "filter=ansible_distribution*"

# Cek inventory sudah terbaca benar
$ ansible-inventory --list
$ ansible-inventory --graph   # Tampilkan tree

# Syntax check playbook (sebelum jalanin)
$ ansible-playbook site.yml --syntax-check

# Test koneksi SSH manual ke node
$ ssh -i ~/.ssh/id_rsa ubuntu@192.168.1.10

9. Best Practice

  • Selalu --check dulu sebelum apply ke production. Nggak ada undo di Ansible.
  • Pakai Roles, bukan satu playbook raksasa. Roles bikin kode reusable & maintainable.
  • Simpan secrets di Vault, bukan hardcode di playbook. Apalagi kalau repo lu public.
  • Idempotent check — selalu tanya: "Kalau task ini dijalanin 2x, apakah aman?" Kalau nggak aman, pake creates: atau when:.
  • Naming convention — nama task harus deskriptif kayak kalimat. Bukan task1 tapi Install nginx web server.
  • Pakai group_vars & host_vars buat pisahin variabel dari playbook.
  • Version control — semua Ansible project wajib masuk Git. Infrastructure as Code.
  • Test dengan Molecule — kalau udah advance, pake Molecule buat unit test roles.
  • Jangan pake shell: kalau ada modulnyashell: apt install nginx itu salah. Pake modul apt. Shell nggak idempotent.
  • Forks — default 5, naikkan ke 20-50 kalau node banyak dan jaringan oke.

10. Glosarium

Istilah Penjelasan
Agentless Ansible nggak perlu software tambahan di server target, cukup SSH
Idempotent Dijalanin berkali-kali hasilnya tetap sama, nggak nambah-nambahin
Inventory File daftar server target yang dikelola Ansible
Playbook File YAML berisi daftar tasks yang mau dijalanin ke host
Task Satu instruksi tunggal dalam playbook (jalanin satu modul)
Module Kode Python bawaan Ansible untuk satu fungsi spesifik (apt, copy, service)
Role Struktur direktori terstandarisasi untuk kumpulan playbook yang reusable
Handler Task khusus yang cuma jalan kalau dipanggil via notify
Facts Variabel otomatis berisi info sistem target yang dikumpulkan saat playbook mulai
Vault Fitur enkripsi Ansible untuk menyimpan data sensitif
Jinja2 Template engine yang dipake Ansible untuk variabel dinamis di file config
YAML Format file yang dipake Ansible untuk nulis playbook
Ad-hoc Command Ansible satu baris tanpa playbook, buat task cepat
become Mekanisme privilege escalation (sudo) di Ansible
Register Simpan output task ke variabel buat dipakai task berikutnya
notify Trigger handler setelah task selesai (biasanya buat restart service)

Comments

Popular posts from this blog

Apa itu Link Aggregation?

Apa Itu Port Security di Switch Cisco