SLO & SLA

SLO & SLA #

Monitoring memperlihatkan bahwa service lambat. Alert memberitahu bahwa latensi naik. Tapi pertanyaan yang paling penting bagi bisnis adalah: seberapa banyak insiden yang bisa kita toleransi sebelum melanggar komitmen ke pelanggan? SLO (Service Level Objective) dan SLA (Service Level Agreement) memberikan jawaban yang terukur dan terstruktur. Ansible bisa mengotomasi seluruh infrastruktur pengukuran — dari recording rules di Prometheus hingga dashboard SLO di Grafana — sehingga kepatuhan terhadap SLO selalu terukur secara real-time.

Konsep Dasar #

SLI (Service Level Indicator)
  → Metrik aktual yang diukur
  → Contoh: persentase request dengan latensi < 200ms

SLO (Service Level Objective)
  → Target yang ingin dicapai untuk SLI
  → Contoh: 99.9% request harus selesai dalam < 200ms

Error Budget
  → Seberapa banyak SLO boleh dilanggar dalam periode tertentu
  → Error budget = 100% - SLO target
  → Contoh: dengan SLO 99.9%, error budget = 0.1% = ~43 menit/bulan

SLA (Service Level Agreement)
  → Komitmen formal ke pelanggan eksternal, dengan konsekuensi jika dilanggar
  → Biasanya lebih longgar dari SLO internal

Recording Rules untuk SLI yang Efisien #

Kalkulasi SLI yang kompleks bisa sangat mahal jika dikalkulasi setiap kali di-query. Recording rules menghitung dan menyimpan hasilnya secara berkala:

# roles/prometheus/tasks/slo-rules.yml
---
- name: Deploy recording rules untuk SLO
  template:
    src: rules/slo-recording.yml.j2
    dest: /etc/prometheus/rules/slo-recording.yml
    owner: prometheus
    mode: '0644'
    validate: promtool check rules %s
  notify: Reload Prometheus
{# templates/rules/slo-recording.yml.j2 #}
groups:
  - name: slo_recording_rules
    interval: 30s
    rules:
      # SLI: Availability — persentase request yang berhasil (non-5xx)
      - record: job:http_requests_total:success_rate5m
        expr: >
          sum(rate(http_requests_total{status!~"5.."}[5m])) by (job, service)
          /
          sum(rate(http_requests_total[5m])) by (job, service)

      # SLI: Latency — persentase request dengan latensi < threshold
      - record: job:http_request_duration_seconds:p99_5m
        expr: >
          histogram_quantile(0.99,
            sum(rate(http_request_duration_seconds_bucket[5m])) by (job, service, le)
          )

      # Error budget burn rate (multi-window, multi-burn-rate)
      # Alert jika burn rate 14x lebih cepat dari normal (akan habis dalam ~2 hari)
      - record: job:error_budget_burn_rate:1h
        expr: >
          (1 - job:http_requests_total:success_rate5m) /
          (1 - {{ slo_availability_target | default(0.999) }})

Alert Berbasis Error Budget #

Alert tradisional (CPU > 80%, latensi > 200ms) sering memunculkan false alarm. Alert berbasis error budget jauh lebih presisi — hanya alert saat error budget benar-benar terbakar dengan cepat:

{# templates/rules/slo-alerts.yml.j2 #}
groups:
  - name: slo_alerts
    rules:
      # Alert level: page (kritis, butuh respons segera)
      # Kondisi: burn rate sangat tinggi dalam window pendek
      - alert: HighErrorBudgetBurnRate
        expr: >
          job:error_budget_burn_rate:1h > 14
          and
          job:error_budget_burn_rate:5m > 14
        for: 2m
        labels:
          severity: critical
          slo: availability
        annotations:
          summary: "Error budget terbakar cepat: {{ '{{' }} $labels.service {{ '}}' }}"
          description: >
            Burn rate {{ '{{' }} $value | humanize {{ '}}' }}x dari normal.
            Error budget akan habis dalam {{ '{{' }} (1 / $value * 100 | humanize) {{ '}}' }} jam.
          runbook_url: "https://wiki.company.com/runbooks/error-budget-burn"

      # Alert level: ticket (perlu diperbaiki hari ini)
      - alert: MediumErrorBudgetBurnRate
        expr: >
          job:error_budget_burn_rate:6h > 3
          and
          job:error_budget_burn_rate:30m > 3
        for: 15m
        labels:
          severity: warning
          slo: availability
        annotations:
          summary: "Error budget terbakar lebih cepat dari normal: {{ '{{' }} $labels.service {{ '}}' }}"
          description: >
            Burn rate {{ '{{' }} $value | humanize {{ '}}' }}x dari normal.
            Perlu diselidiki sebelum error budget habis.

Dashboard SLO di Grafana #

- name: Deploy SLO dashboard ke Grafana
  copy:
    src: files/dashboards/slo-overview.json
    dest: /var/lib/grafana/dashboards/slo-overview.json
    owner: grafana
    mode: '0640'
  notify: Reload Grafana dashboards

Untuk membuat dashboard SLO yang informatif, struktur yang direkomendasikan:

Panel 1: Current Availability (gauge)
  → Menunjukkan % availability saat ini vs target SLO

Panel 2: Error Budget Remaining (gauge)
  → Sisa error budget dalam bulan berjalan (%)

Panel 3: Availability History (time series)
  → Trend availability 30 hari terakhir dengan garis SLO target

Panel 4: Latency P50/P95/P99 (time series)
  → Distribusi latensi dengan garis SLO threshold

Panel 5: Error Budget Burn Rate (time series)
  → Seberapa cepat error budget terbakar (1x = normal)

Panel 6: SLO Status per Service (table)
  → Status semua service sekaligus

Laporan SLA Otomatis #

Generate laporan kepatuhan SLA secara otomatis menggunakan Ansible dan Prometheus API:

# playbooks/generate-sla-report.yml
---
- name: Generate laporan SLA bulanan
  hosts: localhost
  vars:
    report_month: "{{ lookup('pipe', 'date +%Y-%m') }}"
    prometheus_url: "https://prometheus.company.com"

  tasks:
    - name: Ambil data availability bulan ini
      uri:
        url: "{{ prometheus_url }}/api/v1/query_range"
        method: GET
        body_format: form-urlencoded
        body:
          query: 'avg_over_time(job:http_requests_total:success_rate5m{service="myapp"}[30d])'
          start: "{{ lookup('pipe', 'date -d\"first day of this month\" +%s') }}"
          end: "{{ lookup('pipe', 'date +%s') }}"
          step: "3600"
        headers:
          Authorization: "Bearer {{ vault_prometheus_token }}"
        return_content: true
      register: availability_data
      no_log: true

    - name: Kalkulasi availability rate rata-rata
      set_fact:
        avg_availability: >-
          {{ availability_data.json.data.result[0].values
             | map(attribute=1) | map('float') | sum
             / availability_data.json.data.result[0].values | length * 100 }}          

    - name: Generate file laporan
      template:
        src: sla-report.md.j2
        dest: "/var/reports/sla-{{ report_month }}.md"

    - name: Kirim laporan ke email tim
      community.general.mail:
        host: "{{ smtp_host }}"
        to: "{{ sla_report_recipients }}"
        subject: "Laporan SLA {{ report_month }} — {{ 'COMPLIANT' if avg_availability | float >= 99.9 else 'BREACH' }}"
        body: "{{ lookup('file', '/var/reports/sla-' + report_month + '.md') }}"

Ringkasan #

  • SLI → SLO → Error Budget adalah rantai yang logis: ukur SLI, tetapkan target SLO, hitung error budget yang tersisa.
  • Recording rules untuk kalkulasi SLI yang kompleks — jauh lebih efisien dari query real-time di setiap evaluasi alert.
  • Alert berbasis error budget burn rate mengurangi false alarm secara dramatis — hanya alert saat error budget benar-benar terancam habis.
  • Multi-window burn rate (1h+5m untuk critical, 6h+30m untuk warning) menangkap masalah yang cepat maupun lambat tanpa terlalu banyak noise.
  • Dashboard SLO harus menampilkan sisa error budget secara prominan — ini adalah angka yang paling bermakna untuk keputusan prioritas engineering.
  • Laporan SLA otomatis via Ansible dan Prometheus API menghilangkan pekerjaan manual penyusunan laporan bulanan ke pelanggan atau manajemen.

← Sebelumnya: Incident Response   Berikutnya: Best Practice →

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