Metric Collection

Metric Collection #

Node Exporter mengumpulkan metrik sistem. Tapi sistem produksi terdiri dari lebih dari sekadar CPU dan memory — ada PostgreSQL, nginx, Redis, RabbitMQ, dan puluhan komponen lain yang masing-masing perlu dipantau dengan metrik yang relevan. Ekosistem Prometheus menyediakan exporter untuk hampir semua software populer: agen kecil yang mengekspos metrik dalam format yang bisa di-scrape Prometheus. Mengotomasi instalasi dan konfigurasi exporter ini dengan Ansible memastikan setiap komponen langsung termonitor saat pertama kali diinstal.

PostgreSQL Exporter #

# roles/postgres-exporter/tasks/main.yml
---
- name: Download postgres_exporter
  get_url:
    url: >
      https://github.com/prometheus-community/postgres_exporter/releases/download/
      v{{ postgres_exporter_version }}/postgres_exporter-{{ postgres_exporter_version }}.linux-amd64.tar.gz      
    dest: /tmp/postgres_exporter.tar.gz
    checksum: "sha256:{{ postgres_exporter_checksum }}"

- name: Install postgres_exporter
  unarchive:
    src: /tmp/postgres_exporter.tar.gz
    dest: /usr/local/bin/
    extra_opts: ['--strip-components=1']
    include: ['postgres_exporter']
    remote_src: true
    creates: /usr/local/bin/postgres_exporter

- name: Buat file koneksi database untuk exporter
  template:
    src: postgres_exporter.env.j2
    dest: /etc/postgres_exporter.env
    owner: root
    group: postgres
    mode: '0640'
  notify: Restart postgres_exporter
  no_log: true

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

- name: Jalankan postgres_exporter
  systemd:
    name: postgres_exporter
    state: started
    enabled: true
{# templates/postgres_exporter.env.j2 #}
DATA_SOURCE_NAME=postgresql://{{ postgres_exporter_user }}:{{ vault_postgres_exporter_password }}@localhost:5432/postgres?sslmode=disable
{# templates/postgres_exporter.service.j2 #}
[Unit]
Description=Prometheus PostgreSQL Exporter
After=network.target postgresql.service

[Service]
User=postgres
EnvironmentFile=/etc/postgres_exporter.env
ExecStart=/usr/local/bin/postgres_exporter \
  --web.listen-address=:9187 \
  --log.level=warn
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Nginx Exporter #

# roles/nginx-exporter/tasks/main.yml
---
# nginx stub_status harus diaktifkan dulu di konfigurasi nginx
- name: Aktifkan stub_status di nginx
  blockinfile:
    path: /etc/nginx/conf.d/stub_status.conf
    create: true
    block: |
      server {
          listen 127.0.0.1:8080;
          server_name localhost;
          location /nginx_status {
              stub_status;
              allow 127.0.0.1;
              deny all;
          }
      }      
    marker: "# {mark} ANSIBLE MANAGED — nginx stub_status"
  notify: Reload nginx

- name: Install nginx-prometheus-exporter
  get_url:
    url: >
      https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/
      v{{ nginx_exporter_version }}/nginx-prometheus-exporter_{{ nginx_exporter_version }}_linux_amd64.tar.gz      
    dest: /tmp/nginx_exporter.tar.gz

- name: Extract dan install binary
  unarchive:
    src: /tmp/nginx_exporter.tar.gz
    dest: /usr/local/bin/
    include: ['nginx-prometheus-exporter']
    remote_src: true
    creates: /usr/local/bin/nginx-prometheus-exporter

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

Redis Exporter #

# roles/redis-exporter/tasks/main.yml
---
- name: Install redis_exporter
  get_url:
    url: >
      https://github.com/oliver006/redis_exporter/releases/download/
      v{{ redis_exporter_version }}/redis_exporter-v{{ redis_exporter_version }}.linux-amd64.tar.gz      
    dest: /tmp/redis_exporter.tar.gz

- name: Extract dan install
  unarchive:
    src: /tmp/redis_exporter.tar.gz
    dest: /usr/local/bin/
    extra_opts: ['--strip-components=1']
    include: ['redis_exporter']
    remote_src: true

- name: Deploy konfigurasi dan systemd unit
  template:
    src: redis-exporter.service.j2
    dest: /etc/systemd/system/redis_exporter.service
  notify:
    - Reload systemd
    - Restart redis_exporter
{# templates/redis-exporter.service.j2 #}
[Unit]
Description=Prometheus Redis Exporter
After=network.target redis.service

[Service]
ExecStart=/usr/local/bin/redis_exporter \
  --redis.addr=redis://127.0.0.1:{{ redis_port | default(6379) }} \
  {% if redis_password is defined %}
  --redis.password={{ redis_password }} \
  {% endif %}
  --web.listen-address=:9121
Restart=always

[Install]
WantedBy=multi-user.target

Konfigurasi Scrape Dinamis via File SD #

Untuk infrastruktur yang berubah-ubah, static_configs di prometheus.yml tidak cukup fleksibel. File-based service discovery memungkinkan target scrape diupdate tanpa reload Prometheus:

# playbooks/update-scrape-targets.yml
---
- name: Update daftar scrape target Prometheus
  hosts: prometheus_servers
  tasks:
    - name: Generate file target untuk setiap exporter
      template:
        src: "{{ item.template }}"
        dest: "/etc/prometheus/file_sd/{{ item.filename }}"
        owner: prometheus
        mode: '0644'
      loop:
        - template: targets-node.json.j2
          filename: targets-node.json
        - template: targets-postgres.json.j2
          filename: targets-postgres.json
        - template: targets-nginx.json.j2
          filename: targets-nginx.json
      # Tidak perlu reload Prometheus — file_sd otomatis memuat ulang
{# templates/targets-node.json.j2 #}
[
{% for host in groups['all'] %}
  {
    "targets": ["{{ hostvars[host]['ansible_default_ipv4']['address'] }}:9100"],
    "labels": {
      "hostname": "{{ host }}",
      "environment": "{{ hostvars[host]['env'] | default(env) }}",
      "role": "{{ group_names | first }}"
    }
  }{{ '' if loop.last else ',' }}
{% endfor %}
]

Konfigurasi Prometheus untuk menggunakan file_sd:

# Di prometheus.yml — gunakan file_sd_configs bukan static_configs
scrape_configs:
  - job_name: node_exporter
    file_sd_configs:
      - files:
          - /etc/prometheus/file_sd/targets-node.json
        refresh_interval: 5m    # Cek file setiap 5 menit

  - job_name: postgres_exporter
    file_sd_configs:
      - files:
          - /etc/prometheus/file_sd/targets-postgres.json

Metrik Aplikasi Custom #

Untuk aplikasi yang tidak punya exporter bawaan, tambahkan endpoint /metrics menggunakan library Prometheus client:

# roles/app-metrics/tasks/main.yml
---
- name: Install prometheus client library
  pip:
    name: prometheus-client
    virtualenv: "{{ app_venv }}"

- name: Verifikasi endpoint metrics tersedia
  uri:
    url: "http://localhost:{{ app_port }}/metrics"
    status_code: 200
  register: metrics_check
  changed_when: false

# Tambahkan ke scrape config
- name: Tambahkan aplikasi ke file SD target
  template:
    src: targets-app.json.j2
    dest: /etc/prometheus/file_sd/targets-{{ app_name }}.json
    owner: prometheus
    mode: '0644'
  delegate_to: "{{ groups['prometheus_servers'][0] }}"

Ringkasan #

  • Setiap komponen stack perlu exporter-nya sendiri: Node Exporter (OS), postgres_exporter (PostgreSQL), nginx-prometheus-exporter (nginx), redis_exporter (Redis).
  • Instal exporter sebagai bagian dari role komponen — saat nginx diinstal, nginx-exporter ikut terinstal otomatis.
  • File-based service discovery lebih fleksibel dari static_configs — target bisa diupdate tanpa reload Prometheus, dan Ansible bisa menggenerate file target dari inventory.
  • Simpan credential exporter (database password) di Ansible Vault dan kirim ke exporter via environment variable atau file yang permission-nya dibatasi.
  • Gunakan checksum saat mendownload binary exporter — memverifikasi integritas file sebelum diinstal adalah praktik keamanan dasar.
  • Untuk aplikasi custom, implementasikan endpoint /metrics menggunakan Prometheus client library — lebih baik dari solusi monitoring custom yang tidak standar.

← Sebelumnya: Dashboard   Berikutnya: Tracing →

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