Monitoring

Monitoring #

Log memberitahu apa yang sudah terjadi. Monitoring memberitahu apa yang sedang terjadi — dan memperingatkan sebelum masalah menjadi insiden. Mengotomasi setup monitoring dengan Ansible memastikan setiap server langsung termonitor sejak pertama kali di-provision, dengan konfigurasi yang konsisten. Artikel ini membahas cara mendeploy stack monitoring Prometheus + Grafana menggunakan Ansible.

Instalasi Node Exporter #

Node Exporter adalah agen yang mengekspos metrik sistem (CPU, memory, disk, network) dalam format Prometheus:

# roles/node-exporter/tasks/main.yml
---
- name: Buat user node_exporter
  user:
    name: node_exporter
    system: true
    shell: /usr/sbin/nologin
    home: /var/lib/node_exporter
    create_home: false

- name: Download Node Exporter
  get_url:
    url: >
      https://github.com/prometheus/node_exporter/releases/download/
      v{{ node_exporter_version }}/node_exporter-{{ node_exporter_version }}.linux-amd64.tar.gz      
    dest: /tmp/node_exporter.tar.gz
    checksum: "sha256:{{ node_exporter_checksum }}"

- name: Extract Node Exporter
  unarchive:
    src: /tmp/node_exporter.tar.gz
    dest: /tmp/
    remote_src: true

- name: Instal binary Node Exporter
  copy:
    src: "/tmp/node_exporter-{{ node_exporter_version }}.linux-amd64/node_exporter"
    dest: /usr/local/bin/node_exporter
    owner: root
    group: root
    mode: '0755'
    remote_src: true

- name: Deploy systemd unit file
  template:
    src: node_exporter.service.j2
    dest: /etc/systemd/system/node_exporter.service
  notify:
    - Reload systemd
    - Restart node_exporter

- name: Jalankan Node Exporter
  systemd:
    name: node_exporter
    state: started
    enabled: true

Konfigurasi Prometheus #

Prometheus scrapes metrik dari semua target yang dikonfigurasi. Konfigurasi Prometheus bisa dibuat dinamis menggunakan template Jinja2 yang membaca inventory:

# roles/prometheus/tasks/main.yml
---
- name: Deploy konfigurasi Prometheus
  template:
    src: prometheus.yml.j2
    dest: /etc/prometheus/prometheus.yml
    owner: prometheus
    group: prometheus
    mode: '0644'
    validate: promtool check config %s
  notify: Reload Prometheus
{# roles/prometheus/templates/prometheus.yml.j2 #}
global:
  scrape_interval: {{ prometheus_scrape_interval | default('15s') }}
  evaluation_interval: {{ prometheus_evaluation_interval | default('15s') }}
  external_labels:
    cluster: {{ cluster_name }}
    environment: {{ env }}

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093

rule_files:
  - /etc/prometheus/rules/*.yml

scrape_configs:
  # Prometheus scraping itself
  - job_name: prometheus
    static_configs:
      - targets: ['localhost:9090']

  # Node Exporter dari semua server di inventory
  - job_name: node_exporter
    static_configs:
{% for host in groups['all'] %}
      - targets: ['{{ hostvars[host]['ansible_default_ipv4']['address'] }}:9100']
        labels:
          hostname: {{ host }}
          environment: {{ env }}
{% endfor %}

  # Application metrics jika tersedia
  - job_name: {{ app_name }}
    static_configs:
{% for host in groups['appservers'] %}
      - targets: ['{{ hostvars[host]['ansible_default_ipv4']['address'] }}:{{ app_metrics_port | default(9090) }}']
        labels:
          hostname: {{ host }}
{% endfor %}
    metrics_path: /metrics

Alert Rules sebagai Kode #

Alert rules mendefinisikan kondisi yang memicu notifikasi. Menyimpannya sebagai file yang di-manage Ansible memastikan alert yang sama berlaku di semua lingkungan:

# roles/prometheus/tasks/alert-rules.yml
---
- name: Deploy alert rules
  template:
    src: "{{ item }}"
    dest: "/etc/prometheus/rules/{{ item | basename | replace('.j2', '') }}"
    owner: prometheus
    mode: '0644'
  with_fileglob:
    - "templates/rules/*.j2"
  notify: Reload Prometheus
# roles/prometheus/templates/rules/system.yml.j2
---
groups:
  - name: system
    rules:
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > {{ alert_cpu_threshold | default(85) }}
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU usage tinggi di {{ '{{' }} $labels.instance {{ '}}' }}"
          description: "CPU usage {{ '{{' }} $value | humanizePercentage {{ '}}' }}"

      - alert: LowDiskSpace
        expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) < {{ alert_disk_threshold | default(0.15) }}
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Disk hampir penuh di {{ '{{' }} $labels.instance {{ '}}' }}"
          description: "Disk tersisa {{ '{{' }} $value | humanizePercentage {{ '}}' }}"

      - alert: HostDown
        expr: up == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Host tidak responsif: {{ '{{' }} $labels.instance {{ '}}' }}"

Setup Grafana #

# roles/grafana/tasks/main.yml
---
- name: Install Grafana
  apt:
    name: "grafana={{ grafana_version }}"
    state: present

- name: Deploy konfigurasi Grafana
  template:
    src: grafana.ini.j2
    dest: /etc/grafana/grafana.ini
    owner: root
    group: grafana
    mode: '0640'
  notify: Restart Grafana

- name: Provisioning datasource Prometheus
  template:
    src: datasource-prometheus.yml.j2
    dest: /etc/grafana/provisioning/datasources/prometheus.yml
    owner: root
    group: grafana
    mode: '0640'
  notify: Restart Grafana

- name: Provisioning dashboard otomatis
  copy:
    src: "files/dashboards/{{ item }}"
    dest: "/etc/grafana/provisioning/dashboards/{{ item }}"
    owner: root
    group: grafana
    mode: '0640'
  with_fileglob:
    - "*.json"
  notify: Restart Grafana
{# templates/datasource-prometheus.yml.j2 #}
apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://{{ prometheus_host }}:9090
    isDefault: true
    editable: false

Ringkasan #

  • Node Exporter di setiap managed node mengekspos metrik sistem — instal ini di semua server sebagai bagian dari role common.
  • Template konfigurasi Prometheus menggunakan hostvars dan groups untuk otomatis menambahkan semua server di inventory sebagai scrape target — tidak perlu edit manual saat server baru ditambahkan.
  • validate: promtool check config %s untuk memvalidasi konfigurasi Prometheus sebelum disimpan — konfigurasi yang salah bisa membuat Prometheus tidak mau reload.
  • Alert rules sebagai file template yang di-manage Ansible adalah monitoring as code — review di Git, konsisten di semua lingkungan, dan bisa di-rollback.
  • Grafana provisioning via file YAML memungkinkan datasource dan dashboard dikonfigurasi otomatis saat Grafana di-restart — tidak perlu klik manual di UI.
  • Selalu pin versi Prometheus, Node Exporter, dan Grafana — update yang tidak terkontrol bisa membreak dashboard atau mengubah format metrik.

← Sebelumnya: Logging   Berikutnya: Alerting →

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