1. Pengenalan Ansible
Ansible adalah platform automation open-source yang dikembangkan oleh Red Hat (sekarang IBM). Ansible memungkinkan Anda mengotomatiskan provisioning, configuration management, application deployment, dan orchestration β semuanya tanpa menginstal agen di target server.
Keunggulan utama Ansible dibanding tool sejenis (Puppet, Chef) adalah pendekatan agentless. Ansible menggunakan SSH untuk berkomunikasi dengan target server, sehingga tidak perlu menginstal software tambahan. Cukup punya Python di target, dan Ansible sudah bisa bekerja.
Mengapa Ansible Penting?
| Keunggulan | Penjelasan |
|---|---|
| Agentless | Tidak perlu instal agen di target β cukup SSH + Python |
| Idempotent | Menjalankan playbook berkali-kali tetap aman β hanya melakukan perubahan jika diperlukan |
| YAML-Based | Mudah dibaca dan ditulis β menggunakan format YAML yang human-readable |
| Modular | Ratusan module built-in untuk berbagai kebutuhan automation |
| Galaxy | Ekosistem roles dan collections dari komunitas |
| Scalabel | Bisa mengelola ratusan hingga ribuan server sekaligus |
| Cross-Platform | Support Linux, Windows, macOS, network devices, cloud providers |
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β ANSIBLE ARCHITECTURE β β β β ββββββββββββββββββββββββββββββββββββββββ β β β CONTROL NODE (Ansible) β β β β ββββββββββββ ββββββββββββ β β β β β Inventoryβ β Playbook β β β β β β (hosts) β β (tasks) β β β β β ββββββββββββ ββββββββββββ β β β β ββββββββββββ ββββββββββββ β β β β β Modules β β Config β β β β β β β β (ansibleβ β β β β β β β β .cfg) β β β β β ββββββββββββ ββββββββββββ β β β ββββββββββββββββ¬ββββββββββββββββββββββββ β β β SSH (Agentless) β β ββββββββββββββΌβββββββββββββββββ β β β β β β β βΌ βΌ βΌ β β ββββββββββ ββββββββββ ββββββββββ β β βServer 1β βServer 2β βServer 3β β β β (web) β β (db) β β (cache)β β β β Python β β Python β β Python β β β ββββββββββ ββββββββββ ββββββββββ β β β β Kunci: β β - Tidak ada agen di target server β β - Komunikasi via SSH (Linux) atau WinRM (Windows) β β - Hanya butuh Python di target β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Konsep dasar Ansible meliputi:
- Control Node β mesin tempat Ansible diinstall dan playbook dijalankan
- Managed Nodes β server yang dikelola oleh Ansible (target)
- Inventory β daftar host yang akan dikelola
- Playbook β file YAML berisi daftar task yang akan dijalankan
- Module β unit kerja dasar (copy file, install package, manage service, dll)
- Role β cara mengorganisir playbook, tasks, variables, dan handlers
2. Instalasi Ansible
Ansible hanya perlu diinstall di control node. Target server hanya butuh Python dan SSH access.
Linux (Ubuntu/Debian)
# Tambah PPA repository sudo apt update sudo apt install -y software-properties-common sudo add-apt-repository --yes --update ppa:ansible/ansible # Install Ansible sudo apt install -y ansible # Verifikasi ansible --version # ansible [core 2.17.0] # config file = /etc/ansible/ansible.cfg # python version = 3.12.3
Linux (RHEL/CentOS/Fedora)
# Fedora sudo dnf install -y ansible # RHEL/CentOS sudo yum install -y epel-release sudo yum install -y ansible
macOS
# Install menggunakan Homebrew brew install ansible # Verifikasi ansible --version
menggunakan pip (Semua Platform)
# Install dengan pip (Python package manager) pip install ansible # Install dengan pipx (isolated environment) pip install pipx pipx install ansible # Install specific version pip install ansible==9.5.1 # Install collections dan roles ansible-galaxy collection install community.general ansible-galaxy install geerlingguy.nginx
Setup SSH Keys
# Generate SSH key pair ssh-keygen -t ed25519 -C "ansible@beebanelabs" -f ~/.ssh/ansible_key # Copy public key ke target servers ssh-copy-id -i ~/.ssh/ansible_key.pub user@server1 ssh-copy-id -i ~/.ssh/ansible_key.pub user@server2 ssh-copy-id -i ~/.ssh/ansible_key.pub user@server3 # Test koneksi ssh -i ~/.ssh/ansible_key user@server1 "echo OK"
3. Inventory
Inventory adalah daftar host (server) yang akan dikelola oleh Ansible. Inventory bisa berupa file statis (INI atau YAML) atau dinamis (script yang menghasilkan daftar host).
Inventory Statis (INI Format)
# inventory/hosts.ini # === Server Web === web1 ansible_host=192.168.1.10 ansible_user=deploy web2 ansible_host=192.168.1.11 ansible_user=deploy web3 ansible_host=192.168.1.12 ansible_user=deploy # === Server Database === db1 ansible_host=192.168.1.20 ansible_user=dbadmin ansible_port=2222 db2 ansible_host=192.168.1.21 ansible_user=dbadmin ansible_port=2222 # === Server Cache === redis1 ansible_host=192.168.1.30 ansible_user=deploy # === Server Monitoring === monitor1 ansible_host=192.168.1.40 ansible_user=admin # === Groups === [webservers] web1 web2 web3 [dbservers] db1 db2 [cacheservers] redis1 [monitoring] monitor1 # === Group of Groups (Parent Group) === [production:children] webservers dbservers cacheservers monitoring # === Group Variables === [webservers:vars] http_port=80 https_port=443 nginx_version=1.27.0 [dbservers:vars] mysql_port=3306 mysql_datadir=/var/lib/mysql [all:vars] ansible_python_interpreter=/usr/bin/python3 ansible_ssh_common_args='-o StrictHostKeyChecking=no'
Inventory Format YAML
# inventory/hosts.yaml
all:
vars:
ansible_python_interpreter: /usr/bin/python3
ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
children:
production:
children:
webservers:
hosts:
web1:
ansible_host: 192.168.1.10
ansible_user: deploy
web2:
ansible_host: 192.168.1.11
ansible_user: deploy
web3:
ansible_host: 192.168.1.12
ansible_user: deploy
vars:
http_port: 80
https_port: 443
nginx_version: "1.27.0"
dbservers:
hosts:
db1:
ansible_host: 192.168.1.20
ansible_user: dbadmin
ansible_port: 2222
db2:
ansible_host: 192.168.1.21
ansible_user: dbadmin
ansible_port: 2222
vars:
mysql_port: 3306
cacheservers:
hosts:
redis1:
ansible_host: 192.168.1.30
ansible_user: deploy
monitoring:
hosts:
monitor1:
ansible_host: 192.168.1.40
ansible_user: admin
Perintah Inventory Berguna
# List semua host ansible-inventory -i inventory/hosts.yaml --list # List host dalam format grafik ansible-inventory -i inventory/hosts.yaml --graph # List host dari group tertentu ansible-inventory -i inventory/hosts.yaml --graph webservers # List semua group ansible-inventory -i inventory/hosts.yaml --list --yaml # Verifikasi koneksi ke semua host ansible all -i inventory/hosts.yaml -m ping # Verifikasi koneksi ke group tertentu ansible webservers -i inventory/hosts.yaml -m ping
4. Ad-Hoc Commands
Ad-hoc commands adalah perintah Ansible yang dijalankan langsung dari command line tanpa menggunakan playbook. Berguna untuk task satu kali atau testing koneksi.
Sintaks Dasar
# Sintaks umum
ansible <target> -m <module> -a "<args>" -i <inventory>
# Contoh: ping semua host
ansible all -m ping -i inventory/hosts.yaml
# web1 | SUCCESS => {"changed": false, "ping": "pong"}
# web2 | SUCCESS => {"changed": false, "ping": "pong"}
# db1 | SUCCESS => {"changed": false, "ping": "pong"}
# Jalankan command shell di semua host
ansible all -m command -a "uptime" -i inventory/hosts.yaml
ansible all -m shell -a "df -h" -i inventory/hosts.yaml
# Lihat info sistem
ansible all -m setup -i inventory/hosts.yaml
ansible all -m setup -a "filter=ansible_distribution" -i inventory/hosts.yaml
Contoh Ad-Hoc Commands
# Install package di semua web servers
ansible webservers -m apt -a "name=nginx state=present" \
-i inventory/hosts.yaml --become
# Restart service nginx
ansible webservers -m service -a "name=nginx state=restarted" \
-i inventory/hosts.yaml --become
# Copy file ke semua servers
ansible webservers -m copy \
-a "src=./config/nginx.conf dest=/etc/nginx/nginx.conf mode=0644" \
-i inventory/hosts.yaml --become
# Buat user baru
ansible all -m user \
-a "name=deploy state=present shell=/bin/bash" \
-i inventory/hosts.yaml --become
# Cek disk space
ansible all -m shell -a "df -h /" -i inventory/hosts.yaml
# Cek memory usage
ansible all -m shell -a "free -m" -i inventory/hosts.yaml
# Tambah SSH authorized key
ansible all -m authorized_key \
-a "user=deploy key='{{ lookup(\"file\", \"~/.ssh/ansible_key.pub\") }}'" \
-i inventory/hosts.yaml
# Jalankan dengan parallel (fork 10)
ansible all -m ping -i inventory/hosts.yaml -f 10
# Jalankan dengan sudo (--become)
ansible webservers -m shell -a "apt update" \
-i inventory/hosts.yaml --become
# Jalankan dengan specific user
ansible webservers -m ping -i inventory/hosts.yaml \
-u deploy --private-key ~/.ssh/ansible_key
5. Playbooks
Playbook adalah file YAML yang berisi daftar plays. Setiap play mendefinisikan sekumpulan tasks yang akan dijalankan pada host tertentu. Playbook adalah cara utama menggunakan Ansible untuk automation yang kompleks.
Struktur Playbook
# playbooks/setup-webserver.yaml
---
- name: Setup Web Server # Nama play
hosts: webservers # Target hosts
become: yes # Gunakan sudo
vars: # Variables untuk play ini
nginx_version: "1.27.0"
app_port: 8080
tasks: # Daftar tasks
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
- name: Install Nginx
apt:
name: "nginx={{ nginx_version }}"
state: present
- name: Copy Nginx config
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
notify: Restart Nginx
- name: Ensure Nginx is running
service:
name: nginx
state: started
enabled: yes
- name: Open firewall port
ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- "22"
- "80"
- "443"
handlers: # Handlers (triggered by notify)
- name: Restart Nginx
service:
name: nginx
state: restarted
Multi-Play Playbook
# playbooks/full-stack.yaml
---
# Play 1: Setup Database Server
- name: Setup Database Server
hosts: dbservers
become: yes
tasks:
- name: Install MySQL
apt:
name:
- mysql-server
- mysql-client
- python3-mysqldb
state: present
- name: Start MySQL
service:
name: mysql
state: started
enabled: yes
- name: Create database
mysql_db:
name: "{{ app_db_name }}"
state: present
encoding: utf8mb4
collation: utf8mb4_unicode_ci
- name: Create database user
mysql_user:
name: "{{ app_db_user }}"
password: "{{ app_db_password }}"
priv: "{{ app_db_name }}.*:ALL"
state: present
# Play 2: Setup Web Server
- name: Setup Web Server
hosts: webservers
become: yes
vars:
app_port: 8080
tasks:
- name: Install packages
apt:
name:
- nginx
- python3
- python3-pip
- certbot
- python3-certbot-nginx
state: present
- name: Copy app config
template:
src: templates/app.conf.j2
dest: /etc/nginx/sites-available/app.conf
notify: Restart Nginx
- name: Enable site
file:
src: /etc/nginx/sites-available/app.conf
dest: /etc/nginx/sites-enabled/app.conf
state: link
notify: Restart Nginx
handlers:
- name: Restart Nginx
service:
name: nginx
state: restarted
# Play 3: Setup Monitoring
- name: Setup Monitoring
hosts: monitoring
become: yes
tasks:
- name: Install Prometheus
apt:
name: prometheus
state: present
- name: Install Grafana
apt:
name: grafana
state: present
Error Handling di Playbook
# Error handling dengan block/rescue/always
- name: Deploy application with error handling
hosts: webservers
become: yes
tasks:
- block:
- name: Pull latest code
git:
repo: "https://github.com/app/repo.git"
dest: /opt/app
version: main
- name: Install dependencies
command: pip install -r requirements.txt
args:
chdir: /opt/app
- name: Restart application
service:
name: myapp
state: restarted
rescue:
- name: Rollback to previous version
git:
repo: "https://github.com/app/repo.git"
dest: /opt/app
version: "{{ previous_version }}"
- name: Send failure notification
mail:
to: admin@example.com
subject: "Deploy FAILED on {{ inventory_hostname }}"
body: "Deploy gagal, rolling back ke {{ previous_version }}"
always:
- name: Log deployment result
lineinfile:
path: /var/log/deployments.log
line: "{{ ansible_date_time.iso8601 }} - Deploy attempted on {{ inventory_hostname }}"
create: yes
Menjalankan Playbook
# Jalankan playbook ansible-playbook -i inventory/hosts.yaml playbooks/setup-webserver.yaml # Dry-run (check mode) β tanpa eksekusi ansible-playbook -i inventory/hosts.yaml playbooks/setup-webserver.yaml --check # Verbose mode (-v, -vv, -vvv) ansible-playbook -i inventory/hosts.yaml playbooks/setup-webserver.yaml -vvv # Jalankan dengan specific tag ansible-playbook -i inventory/hosts.yaml playbooks/setup-webserver.yaml --tags "nginx,firewall" # Skip tags tertentu ansible-playbook -i inventory/hosts.yaml playbooks/setup-webserver.yaml --skip-tags "firewall" # Jalankan dengan extra variables ansible-playbook -i inventory/hosts.yaml playbooks/setup-webserver.yaml \ -e "nginx_version=1.27.1 app_port=9090" # Limit ke host tertentu ansible-playbook -i inventory/hosts.yaml playbooks/setup-webserver.yaml \ --limit web1,web2 # Step-by-step (konfirmasi setiap task) ansible-playbook -i inventory/hosts.yaml playbooks/setup-webserver.yaml --step # Mulai dari task tertentu ansible-playbook -i inventory/hosts.yaml playbooks/setup-webserver.yaml \ --start-at-task="Copy Nginx config"
6. Modules
Module adalah unit kerja dasar Ansible. Setiap task menggunakan satu module. Ansible memiliki ratusan module built-in dan ribuan lagi dari komunitas.
Module Populer
| Module | Fungsi | Contoh |
|---|---|---|
| apt | Manage packages Debian/Ubuntu | apt: name=nginx state=present |
| yum | Manage packages RHEL/CentOS | yum: name=nginx state=present |
| service | Manage system services | service: name=nginx state=started |
| copy | Copy file dari local ke remote | copy: src=./file dest=/etc/file |
| template | Render Jinja2 template lalu copy | template: src=t.j2 dest=/etc/t |
| file | Manage file/directory | file: path=/opt/app state=directory |
| user | Manage user accounts | user: name=deploy state=present |
| git | Manage Git repositories | git: repo=... dest=/opt/app |
| command | Run command (no shell) | command: ls -la /opt |
| shell | Run shell command | shell: cat /etc/passwd | grep root |
| docker_container | Manage Docker containers | docker_container: name=web image=nginx |
| pip | Manage Python packages | pip: name=flask state=present |
| cron | Manage cron jobs | cron: name="backup" job="/opt/backup.sh" |
| lineinfile | Manage lines in text file | lineinfile: path=/etc/hosts line="..." |
| ufw | Manage firewall (UFW) | ufw: rule=allow port=80 |
| systemd | Manage systemd services | systemd: name=nginx state=restarted |
Contoh Penggunaan Module
# Module apt β install packages
- name: Install required packages
apt:
name:
- nginx
- python3
- git
- curl
state: present
update_cache: yes
# Module file β buat direktori
- name: Create app directory
file:
path: /opt/myapp
state: directory
owner: deploy
group: deploy
mode: '0755'
# Module git β clone repository
- name: Clone application repository
git:
repo: "https://github.com/app/repo.git"
dest: /opt/myapp
version: main
force: yes
# Module template β render dan copy config
- name: Generate nginx config
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/myapp.conf
owner: root
group: root
mode: '0644'
notify: Restart nginx
# Module service β manage service
- name: Ensure nginx is running
service:
name: nginx
state: started
enabled: yes
# Module user β buat user
- name: Create application user
user:
name: deploy
shell: /bin/bash
groups: sudo
append: yes
create_home: yes
# Module cron β tambah cron job
- name: Add backup cron job
cron:
name: "Database backup"
minute: "0"
hour: "2"
job: "/opt/scripts/backup.sh >> /var/log/backup.log 2>&1"
user: deploy
# Module lineinfile β edit file
- name: Set timezone
lineinfile:
path: /etc/environment
regexp: "^TZ="
line: "TZ=Asia/Jakarta"
7. Variables & Facts
Variables memungkinkan playbook menjadi fleksibel dan reusable. Facts adalah informasi tentang sistem target yang dikumpulkan otomatis oleh Ansible.
Definisi Variables
# Definisi di playbook
- name: Configure web server
hosts: webservers
vars:
app_name: "myapp"
app_port: 8080
app_env: "production"
db_host: "192.168.1.20"
max_clients: 200
tasks:
- name: Print variables
debug:
msg: "Deploying {{ app_name }} on port {{ app_port }}"
# Definisi di file terpisah
# group_vars/webservers.yaml
app_name: "myapp"
app_port: 8080
db_host: "192.168.1.20"
# group_vars/dbservers.yaml
mysql_root_password: "{{ vault_mysql_root_password }}"
mysql_datadir: "/var/lib/mysql"
# host_vars/web1.yaml
app_port: 9090 # Override untuk web1 saja
Facts
# Lihat semua facts dari host
# ansible web1 -m setup -i inventory/hosts.yaml
# Gunakan facts di playbook
- name: Print system info
hosts: all
tasks:
- name: Show OS info
debug:
msg: "{{ ansible_distribution }} {{ ansible_distribution_version }}"
- name: Show IP address
debug:
msg: "IP: {{ ansible_default_ipv4.address }}"
- name: Show memory
debug:
msg: "RAM: {{ ansible_memtotal_mb }} MB"
- name: Conditional berdasarkan OS
apt:
name: nginx
state: present
when: ansible_distribution == "Ubuntu"
- name: Conditional berdasarkan versi
yum:
name: nginx
state: present
when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "8"
Register Variables
# Simpan output task ke variable
- name: Check service status
hosts: webservers
tasks:
- name: Check nginx status
command: systemctl is-active nginx
register: nginx_status
ignore_errors: yes
- name: Print status
debug:
msg: "Nginx status: {{ nginx_status.stdout }}"
- name: Start nginx if not running
service:
name: nginx
state: started
when: nginx_status.rc != 0
- name: Get disk usage
command: df -h /
register: disk_info
- name: Print disk usage
debug:
msg: "{{ disk_info.stdout_lines }}"
Loops
# Simple loop
- name: Install multiple packages
apt:
name: "{{ item }}"
state: present
loop:
- nginx
- python3
- git
- curl
# Loop dengan dictionary
- name: Create multiple users
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
shell: "{{ item.shell }}"
loop:
- { name: "deploy", groups: "sudo", shell: "/bin/bash" }
- { name: "monitor", groups: "adm", shell: "/bin/bash" }
- { name: "backup", groups: "www-data", shell: "/bin/sh" }
# Loop dengan register
- name: Check multiple services
command: systemctl is-active {{ item }}
loop:
- nginx
- mysql
- redis
register: service_results
ignore_errors: yes
- name: Show failed services
debug:
msg: "{{ item.item }} is {{ item.stdout }}"
loop: "{{ service_results.results }}"
when: item.rc != 0
8. Roles
Roles adalah cara Ansible untuk mengorganisir playbook, tasks, variables, handlers, dan files ke dalam struktur direktori yang terstruktur dan reusable. Role mempromosikan reusability dan separation of concerns.
Struktur Role
# Membuat role baru dengan ansible-galaxy ansible-galaxy init roles/nginx # Hasil: roles/nginx/ βββ defaults/ β βββ main.yml # Default variables (lowest priority) βββ files/ # Static files βββ handlers/ β βββ main.yml # Handlers βββ meta/ β βββ main.yml # Metadata & dependencies βββ tasks/ β βββ main.yml # Main tasks βββ templates/ # Jinja2 templates βββ tests/ β βββ inventory β βββ test.yml βββ vars/ β βββ main.yml # Variables (higher priority) βββ README.md
Contoh Role Lengkap: Nginx
# roles/nginx/defaults/main.yml nginx_port: 80 nginx_worker_processes: "auto" nginx_worker_connections: 1024 nginx_keepalive_timeout: 65 nginx_client_max_body_size: "16m" nginx_server_name: "localhost" nginx_root_dir: "/var/www/html" nginx_enable_ssl: false nginx_ssl_certificate: "" nginx_ssl_certificate_key: ""
# roles/nginx/tasks/main.yml
---
- name: Install Nginx
apt:
name: nginx
state: present
update_cache: yes
tags: install
- name: Remove default config
file:
path: /etc/nginx/sites-enabled/default
state: absent
tags: config
- name: Copy Nginx configuration
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
notify: Restart Nginx
tags: config
- name: Copy site configuration
template:
src: site.conf.j2
dest: /etc/nginx/sites-available/{{ nginx_server_name }}.conf
owner: root
group: root
mode: '0644'
notify: Reload Nginx
tags: config
- name: Enable site
file:
src: /etc/nginx/sites-available/{{ nginx_server_name }}.conf
dest: /etc/nginx/sites-enabled/{{ nginx_server_name }}.conf
state: link
notify: Reload Nginx
tags: config
- name: Ensure Nginx is running
service:
name: nginx
state: started
enabled: yes
tags: service
# roles/nginx/handlers/main.yml
---
- name: Restart Nginx
service:
name: nginx
state: restarted
- name: Reload Nginx
service:
name: nginx
state: reloaded
Menggunakan Role di Playbook
# playbooks/site.yaml
---
- name: Configure Web Servers
hosts: webservers
become: yes
roles:
- role: common # Role dasar (selalu dipakai)
- role: nginx # Role Nginx
vars:
nginx_port: 80
nginx_server_name: "app.example.com"
nginx_enable_ssl: true
- role: app # Role aplikasi custom
tags: app
- name: Configure Database Servers
hosts: dbservers
become: yes
roles:
- role: common
- role: mysql
vars:
mysql_port: 3306
- role: monitoring
Role dari Ansible Galaxy
# Cari role di Galaxy ansible-galaxy search nginx # Install role ansible-galaxy install geerlingguy.nginx ansible-galaxy install geerlingguy.mysql ansible-galaxy install geerlingguy.redis # Install collection ansible-galaxy collection install community.general ansible-galaxy collection install community.docker # Install dari requirements file ansible-galaxy install -r requirements.yml # List installed roles ansible-galaxy list
9. Jinja2 Templates
Ansible menggunakan Jinja2 sebagai template engine. Template memungkinkan Anda membuat file konfigurasi yang dinamis berdasarkan variables.
Contoh Template Nginx
# templates/nginx.conf.j2
# Managed by Ansible β jangan edit manual!
# Generated: {{ ansible_date_time.iso8601 }}
worker_processes {{ nginx_worker_processes }};
events {
worker_connections {{ nginx_worker_connections }};
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout {{ nginx_keepalive_timeout }};
# Logging
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# Gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript;
server {
listen {{ nginx_port }};
server_name {{ nginx_server_name }};
root {{ nginx_root_dir }};
client_max_body_size {{ nginx_client_max_body_size }};
{% if nginx_enable_ssl %}
listen 443 ssl http2;
ssl_certificate {{ nginx_ssl_certificate }};
ssl_certificate_key {{ nginx_ssl_certificate_key }};
ssl_protocols TLSv1.2 TLSv1.3;
{% endif %}
location / {
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://127.0.0.1:{{ app_port }};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
{% for server in upstream_servers %}
upstream backend_{{ server.name }} {
server {{ server.address }}:{{ server.port }};
}
{% endfor %}
}
}
Loop di Template
# templates/hosts.j2
# Managed by Ansible
127.0.0.1 localhost
{% for host in groups['webservers'] %}
{{ hostvars[host]['ansible_default_ipv4']['address'] }} {{ host }}
{% endfor %}
{% for host in groups['dbservers'] %}
{{ hostvars[host]['ansible_default_ipv4']['address'] }} {{ host }}
{% endfor %}
10. Ansible Vault
Ansible Vault memungkinkan Anda mengenkripsi sensitive data seperti password, API keys, dan certificates. Data terenkripsi bisa disimpan bersama playbook di Git tanpa khawatir kebocoran.
# Buat encrypted file ansible-vault create secrets.yml # Edit encrypted file ansible-vault edit secrets.yml # Encrypt file yang sudah ada ansible-vault encrypt group_vars/production/secrets.yml # Decrypt file ansible-vault decrypt secrets.yml # View encrypted file (tanpa decrypt) ansible-vault view secrets.yml # Change vault password ansible-vault rekey secrets.yml # Jalankan playbook dengan vault password ansible-playbook site.yml --ask-vault-pass # Jalankan dengan vault password file ansible-playbook site.yml --vault-password-file ~/.vault_pass
# group_vars/production/secrets.yml (encrypted)
$ANSIBLE_VAULT;1.1;AES256
38326665383036346463356266363964323531306363656238393539383232323838376537656439
...
# Referensi di playbook
- name: Configure database
mysql_user:
name: "{{ app_db_user }}"
password: "{{ vault_db_password }}" # Disimpan di file terenkripsi
priv: "{{ app_db_name }}.*:ALL"
11. Best Practices
Struktur Proyek Ansible
ansible-project/ βββ ansible.cfg # Ansible configuration βββ inventory/ β βββ production/ β β βββ hosts.yaml # Production hosts β β βββ group_vars/ β β β βββ all.yaml β β β βββ webservers.yaml β β β βββ dbservers.yaml β β βββ host_vars/ β β βββ web1.yaml β βββ staging/ β βββ hosts.yaml β βββ group_vars/ βββ roles/ β βββ common/ β βββ nginx/ β βββ mysql/ β βββ app/ βββ playbooks/ β βββ site.yaml # Main playbook β βββ webservers.yaml β βββ dbservers.yaml β βββ deploy.yaml βββ templates/ βββ files/ βββ requirements.yml # Galaxy dependencies βββ README.md
Checklist Best Practices
| Praktik | Rekomendasi |
|---|---|
| Idempotency | Pastikan playbook idempotent β jalankan berkali-kali hasilnya sama |
| Tags | Gunakan tags untuk menjalankan sebagian playbook |
| Lint | Jalankan ansible-lint sebelum commit |
| Vault | Enkripsi semua sensitive data dengan Ansible Vault |
| Roles | Gunakan roles untuk organisasi playbook yang baik |
| Versions | Pin versi roles di requirements.yml |
| Testing | Gunakan --check mode sebelum deploy ke production |
| Documentation | Tambahkan README.md di setiap role |
| Handlers | Gunakan handlers untuk restart service (bukan task biasa) |
| Minimal Privilege | Gunakan become: yes hanya saat diperlukan |
Jangan pernah menyimpan password atau API keys dalam plaintext di inventory atau playbook. Selalu gunakan Ansible Vault atau external secret management (HashiCorp Vault, AWS Secrets Manager) untuk data sensitif.
12. Quiz Pemahaman
1. Apa arti "agentless" pada Ansible?
2. Apa perbedaan antara "command" dan "shell" module?
3. Apa fungsi Ansible Vault?
4. Apa fungsi "handlers" di Ansible playbook?
5. Apa itu "idempotent" dalam konteks Ansible?