Ebook Syafi
Koleksi
Admin
← DevOps Dari Homelab ke Production
Edit Bab
💾 Simpan
Batal
Syarat
Mukadimah
Bab
Penutup
B
I
H2
H3
List
1.
Quote
Code
Link
Img
Table
Edit
Split
Preview
0 perkataan
# Bab 7: Monitoring dan Observability Anda sudah belajar automate infrastructure dengan Ansible dan Terraform. Server sudah up, apps sudah deploy. Tapi macam mana anda tahu semuanya berjalan dengan baik? Macam mana anda tahu disk hampir penuh sebelum ia benar-benar penuh? Macam mana anda tahu response time API anda makin perlahan? Ini di mana monitoring masuk. Monitoring bukan sekadar "nice to have". Dalam production, ia adalah keperluan mutlak. Saya pernah belajar perkara ini secara hard way. Server homelab saya down selama 2 hari dan saya tidak perasan sebab tiada monitoring. Jangan jadi macam saya. Observability pula adalah konsep yang lebih luas. Ia bukan sekadar tahu "server up atau down", tetapi memahami kenapa sesuatu berlaku dalam sistem anda. ## Apa yang anda akan belajar: - Tiga pillars of observability: metrics, logs, traces - Setup Prometheus dan Grafana untuk metrics dan dashboards - Loki untuk centralized logging - Alerting dengan Alertmanager, PagerDuty, dan Telegram - Uptime monitoring dengan Uptime Kuma - Konsep SLI, SLO, dan SLA - Asas incident response - Practical: setup full monitoring stack untuk web app ## Tiga Pillars of Observability Observability dibina atas tiga komponen utama. ### 1. Metrics Metrics adalah numerical data yang menunjukkan status sistem pada sesuatu masa. Contohnya CPU usage 45%, memory usage 2.1GB, request count 1500 per minute, response time 120ms. Metrics sangat baik untuk dashboards dan alerting sebab ia lightweight dan mudah di-aggregate. ### 2. Logs Logs adalah event records yang describe apa yang berlaku dalam sistem. Contohnya "User john logged in at 14:23", "Database connection failed: timeout after 30s". Logs memberi context yang metrics tidak boleh bagi. ### 3. Traces Traces track perjalanan sesuatu request melalui pelbagai services. Dalam microservices architecture, satu user request mungkin melalui 5 atau 6 services. Traces membantu anda faham di mana bottleneck berlaku. Untuk homelab dan early production, fokus pada metrics dan logs dulu. Traces menjadi penting bila anda mula guna microservices architecture. ### Monitoring vs Observability Ramai orang guna istilah ini secara interchangeable, tapi sebenarnya ada perbezaan. **Monitoring** bermaksud anda tahu apa yang nak dipantau. Anda setup dashboard untuk CPU usage, memory usage, response time. Anda tahu soalan yang nak ditanya. **Observability** bermaksud sistem anda boleh memberitahu anda apa yang berlaku walaupun anda tidak tahu soalan yang nak ditanya. Bila ada masalah baru yang anda tidak pernah jangka, observability membolehkan anda investigate dan faham root cause tanpa perlu deploy new instrumentation. Dalam practice, anda mula dengan monitoring (setup dashboards dan alerts untuk perkara yang anda tahu penting) dan gradually move towards observability (add more instrumentation, structured logging, tracing) seiring sistem anda menjadi lebih complex. ### Pull vs Push Model Prometheus guna pull model. Ia secara aktif scrape metrics daripada targets pada interval yang ditetapkan. Ini berbeza daripada push model (macam StatsD atau InfluxDB Telegraf) di mana applications push metrics ke central server. Kelebihan pull model: Prometheus tahu bila sesuatu target down (sebab ia gagal scrape). Ia juga mudah untuk debug sebab anda boleh manually access metrics endpoint di browser. Kekurangan pull model: tidak ideal untuk short-lived jobs atau serverless functions. Untuk kes macam ini, Prometheus ada Pushgateway. ## Prometheus + Grafana: The Power Duo Prometheus adalah monitoring system yang collect dan store metrics. Grafana adalah visualization tool yang buat dashboards cantik daripada data Prometheus. Bersama, mereka adalah stack monitoring paling popular dalam dunia DevOps. ### Setup Prometheus dan Grafana Dengan Docker Compose Buat file `docker-compose.monitoring.yml`: ```yaml services: prometheus: image: prom/prometheus:latest container_name: prometheus volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - ./prometheus/alert-rules.yml:/etc/prometheus/alert-rules.yml - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.retention.time=30d' - '--web.enable-lifecycle' ports: - "9090:9090" restart: unless-stopped networks: - monitoring grafana: image: grafana/grafana:latest container_name: grafana environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} - GF_INSTALL_PLUGINS=grafana-clock-panel volumes: - grafana_data:/var/lib/grafana - ./grafana/provisioning:/etc/grafana/provisioning ports: - "3000:3000" restart: unless-stopped depends_on: - prometheus networks: - monitoring node-exporter: image: prom/node-exporter:latest container_name: node-exporter volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.rootfs=/rootfs' - '--path.sysfs=/host/sys' ports: - "9100:9100" restart: unless-stopped networks: - monitoring cadvisor: image: gcr.io/cadvisor/cadvisor:latest container_name: cadvisor volumes: - /:/rootfs:ro - /var/run:/var/run:ro - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro ports: - "8080:8080" restart: unless-stopped networks: - monitoring alertmanager: image: prom/alertmanager:latest container_name: alertmanager volumes: - ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml ports: - "9093:9093" restart: unless-stopped networks: - monitoring volumes: prometheus_data: grafana_data: networks: monitoring: driver: bridge ``` Node Exporter collect metrics daripada host machine (CPU, memory, disk, network). cAdvisor collect metrics daripada Docker containers. Kedua-duanya feed data ke Prometheus. ### Konfigurasi Prometheus Buat file `prometheus/prometheus.yml`: ```yaml global: scrape_interval: 15s evaluation_interval: 15s rule_files: - "alert-rules.yml" alerting: alertmanagers: - static_configs: - targets: - alertmanager:9093 scrape_configs: - job_name: "prometheus" static_configs: - targets: ["localhost:9090"] - job_name: "node-exporter" static_configs: - targets: ["node-exporter:9100"] - job_name: "cadvisor" static_configs: - targets: ["cadvisor:8080"] - job_name: "web-app" static_configs: - targets: ["web-app:8000"] metrics_path: /metrics scrape_interval: 10s ``` `scrape_interval` bermaksud Prometheus akan collect metrics setiap 15 saat. Untuk web app, kita set 10 saat sebab kita mahu data yang lebih granular. ### PromQL: Query Language Untuk Metrics PromQL adalah bahasa query untuk Prometheus. Anda perlu tahu basics untuk buat dashboards dan alerts yang berguna. Beberapa contoh PromQL yang sering digunakan: ```promql # CPU usage percentage 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) # Memory usage percentage (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 # Disk usage percentage (1 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})) * 100 # HTTP request rate (requests per second) rate(http_requests_total[5m]) # HTTP error rate (5xx responses) rate(http_requests_total{status=~"5.."}[5m]) # 95th percentile response time histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) # Container CPU usage rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100 # Container memory usage container_memory_usage_bytes{name!=""} / 1024 / 1024 ``` > **Nota Beginner:** Jangan takut dengan PromQL. Mulakan dengan query simple macam `up` (tunjuk mana targets yang up) dan `node_memory_MemAvailable_bytes` (memory available). Lepas tu explore dari situ. ### Grafana Dashboards Selepas Prometheus dan Grafana running, buka Grafana di `http://localhost:3000`. Login dengan admin credentials. Langkah pertama, tambah Prometheus sebagai data source: 1. Pergi ke Settings > Data Sources > Add data source. 2. Pilih Prometheus. 3. URL: `http://prometheus:9090`. 4. Klik Save & Test. Untuk dashboards, anda tidak perlu buat dari scratch. Import dashboards yang sedia ada dari Grafana community. Dashboard IDs yang saya recommend: - **1860** untuk Node Exporter Full. Tunjuk semua metrics host. - **893** untuk Docker dan system monitoring. - **14282** untuk cAdvisor. Pergi ke Dashboards > Import > masukkan dashboard ID > pilih Prometheus data source > Import. Untuk custom dashboard, contoh panel configuration: ```json { "title": "Request Rate", "type": "timeseries", "datasource": "Prometheus", "targets": [ { "expr": "rate(http_requests_total[5m])", "legendFormat": "{{method}} {{path}}" } ] } ``` ## Loki: Centralized Logging Grafana Loki adalah log aggregation system yang designed untuk work dengan Grafana. Ia macam Prometheus, tapi untuk logs. Loki tidak index full log text, ia hanya index labels. Ini menjadikan ia sangat efficient dari segi storage. Tambah Loki dan Promtail ke Docker Compose: ```yaml loki: image: grafana/loki:latest container_name: loki volumes: - loki_data:/loki - ./loki/loki-config.yml:/etc/loki/config.yml command: -config.file=/etc/loki/config.yml ports: - "3100:3100" restart: unless-stopped networks: - monitoring promtail: image: grafana/promtail:latest container_name: promtail volumes: - /var/log:/var/log:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro - ./promtail/promtail-config.yml:/etc/promtail/config.yml command: -config.file=/etc/promtail/config.yml restart: unless-stopped depends_on: - loki networks: - monitoring ``` File `promtail/promtail-config.yml`: ```yaml server: http_listen_port: 9080 positions: filename: /tmp/positions.yaml clients: - url: http://loki:3100/loki/api/v1/push scrape_configs: - job_name: system static_configs: - targets: - localhost labels: job: varlogs __path__: /var/log/*.log - job_name: docker static_configs: - targets: - localhost labels: job: docker __path__: /var/lib/docker/containers/*/*-json.log pipeline_stages: - json: expressions: log: log stream: stream time: time - output: source: log ``` Promtail collect logs dan hantar ke Loki. Tambah Loki sebagai data source dalam Grafana sama macam anda tambah Prometheus. URL: `http://loki:3100`. Dalam Grafana, anda boleh query logs dengan LogQL: ```logql # Semua logs dari docker job {job="docker"} # Filter logs yang contain "error" {job="docker"} |= "error" # Logs dari specific container {job="docker", container="web-app"} |= "500" # Count errors per minute count_over_time({job="docker"} |= "error" [1m]) ``` ## Alerting: Jangan Tunggu User Complain Monitoring tanpa alerting adalah macam pasang CCTV tapi tiada siapa yang tengok. Anda perlu alerts yang memberitahu anda bila ada masalah. ### Alert Rules Dalam Prometheus Buat file `prometheus/alert-rules.yml`: ```yaml groups: - name: system-alerts rules: - alert: HighCPUUsage expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80 for: 5m labels: severity: warning annotations: summary: "High CPU usage on {{ $labels.instance }}" description: "CPU usage is above 80% for 5 minutes. Current value: {{ $value }}%" - alert: HighMemoryUsage expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 85 for: 5m labels: severity: warning annotations: summary: "High memory usage on {{ $labels.instance }}" description: "Memory usage is above 85%. Current value: {{ $value }}%" - alert: DiskSpaceLow expr: (1 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})) * 100 > 85 for: 10m labels: severity: critical annotations: summary: "Low disk space on {{ $labels.instance }}" description: "Disk usage is above 85%. Current value: {{ $value }}%" - alert: ServiceDown expr: up == 0 for: 1m labels: severity: critical annotations: summary: "Service {{ $labels.job }} is down" description: "{{ $labels.instance }} has been down for more than 1 minute." - name: app-alerts rules: - alert: HighErrorRate expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05 for: 5m labels: severity: critical annotations: summary: "High error rate detected" description: "Error rate is above 5%. Current value: {{ $value }}" - alert: SlowResponseTime expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 2 for: 5m labels: severity: warning annotations: summary: "Slow response time detected" description: "95th percentile response time is above 2 seconds." ``` Field `for` bermaksud condition mesti bertahan selama tempoh tersebut sebelum alert di-fire. Ini mengelakkan false alarms daripada spike yang sementara. ### Alertmanager Configuration Alertmanager handle routing dan deduplication alerts. Ia boleh hantar notifications ke pelbagai channels. File `alertmanager/alertmanager.yml`: ```yaml global: resolve_timeout: 5m route: receiver: "telegram" group_by: ["alertname", "severity"] group_wait: 30s group_interval: 5m repeat_interval: 4h routes: - receiver: "telegram-critical" match: severity: critical repeat_interval: 1h receivers: - name: "telegram" telegram_configs: - bot_token: "${TELEGRAM_BOT_TOKEN}" chat_id: ${TELEGRAM_CHAT_ID} message: | {{ range .Alerts }} {{ .Labels.severity | toUpper }}: {{ .Annotations.summary }} {{ .Annotations.description }} {{ end }} - name: "telegram-critical" telegram_configs: - bot_token: "${TELEGRAM_BOT_TOKEN}" chat_id: ${TELEGRAM_CHAT_ID} message: | CRITICAL ALERT {{ range .Alerts }} {{ .Annotations.summary }} {{ .Annotations.description }} {{ end }} ``` > **Nota Beginner:** Saya recommend guna Telegram bot untuk alerting dalam homelab. Ia free, mudah setup, dan anda akan terima notifications terus pada phone. Untuk production, consider PagerDuty atau Opsgenie yang ada on-call rotation features. Untuk setup Telegram bot: 1. Chat dengan @BotFather di Telegram. 2. Buat bot baru dan dapatkan bot token. 3. Buat group atau channel dan dapatkan chat ID. 4. Masukkan token dan chat ID dalam Alertmanager config. ## Uptime Monitoring Dengan Uptime Kuma Uptime Kuma adalah self-hosted uptime monitoring tool. Ia check sama ada services anda accessible dari luar. Ia sangat mudah untuk setup dan mempunyai interface yang cantik. ```yaml uptime-kuma: image: louislam/uptime-kuma:latest container_name: uptime-kuma volumes: - uptime_kuma_data:/app/data ports: - "3001:3001" restart: unless-stopped networks: - monitoring ``` Selepas deploy, buka `http://localhost:3001` dan configure monitors: - HTTP(s) monitor untuk web apps. - TCP monitor untuk databases dan services. - Ping monitor untuk network devices. - DNS monitor untuk domain resolution. Uptime Kuma boleh hantar notifications ke Telegram, Discord, Slack, dan banyak lagi. Ia juga boleh generate status page yang boleh anda share dengan users. Saya guna Uptime Kuma untuk monitor semua services dalam homelab saya. Setiap kali sesuatu down, saya dapat notification di Telegram dalam masa 60 saat. ### Best Practices Untuk Alerting Alerting yang baik adalah tentang balance. Terlalu banyak alerts menyebabkan alert fatigue. Anda mula ignore alerts, dan bila ada real problem, anda miss it. Terlalu sedikit alerts bermaksud anda tidak tahu bila ada masalah. Beberapa guidelines yang saya ikut: **Alert on symptoms, not causes.** Alert bila response time tinggi (symptom), bukan bila CPU tinggi (cause). CPU tinggi mungkin normal semasa batch processing. Response time tinggi sentiasa bermaksud users affected. **Setiap alert perlu action.** Kalau anda receive alert dan response anda adalah "okay, noted" tanpa buat apa-apa, alert tersebut perlu dibuang atau ditukar threshold. Setiap alert sepatutnya require seseorang investigate atau take action. **Group dan deduplicate alerts.** Alertmanager handle ini dengan `group_by`. Kalau 10 servers semuanya report CPU tinggi pada masa yang sama, anda mahu satu alert yang summarize situasi, bukan 10 separate notifications. **Classify severity levels.** Saya guna tiga levels. Warning bermaksud investigate bila sempat, biasanya dalam beberapa jam. Critical bermaksud perlu perhatian segera, service mungkin affected. Emergency bermaksud outage sedang berlaku, users affected right now. ## SLI, SLO, dan SLA Konsep ini penting bila anda mula deal dengan production systems dan users sebenar. **SLI (Service Level Indicator)** adalah measurement sebenar performance service anda. Contoh: 99.5% requests berjaya, 95th percentile response time 200ms. **SLO (Service Level Objective)** adalah target yang anda tetapkan. Contoh: "99.9% uptime setiap bulan", "95th percentile response time mestilah di bawah 500ms". **SLA (Service Level Agreement)** adalah agreement formal dengan customer. Kalau anda gagal meet SLA, biasanya ada consequences seperti credit atau refund. Untuk homelab, anda tidak perlu SLA. Tapi menetapkan SLOs membantu anda decide berapa banyak effort nak letak pada reliability. Contoh SLO untuk web app: - Availability: 99.9% (bermaksud maximum 43.8 minit downtime sebulan) - Response time: p95 di bawah 500ms - Error rate: kurang daripada 0.1% Buat Grafana dashboard yang track SLIs anda supaya anda sentiasa tahu sama ada anda meet SLOs atau tidak. ## Asas Incident Response Bila alert berbunyi, anda perlu tahu apa nak buat. Incident response yang baik bermakna masalah diselesaikan dengan cepat dan systematic. **Langkah-langkah basic:** 1. **Acknowledge.** Terima alert dan maklumkan team bahawa anda sedang investigate. 2. **Assess.** Tentukan severity. Adakah ia affect users? Berapa ramai? 3. **Mitigate.** Selesaikan masalah secepat mungkin. Kadang-kadang ini bermaksud rollback, kadang-kadang restart service. 4. **Communicate.** Update stakeholders tentang status. 5. **Resolve.** Fix the root cause. 6. **Post-mortem.** Selepas incident selesai, tulis post-mortem. Apa yang berlaku, kenapa, dan macam mana nak prevent pada masa depan. > **Nota Beginner:** Post-mortem bukan untuk blame orang. Ia adalah blameless exercise untuk belajar daripada masalah. Fokus pada sistem dan proses, bukan individu. Dalam DevOps culture, kesilapan adalah peluang untuk improve. ### Contoh Post-Mortem Template Untuk reference, ini template post-mortem yang simple tapi effective: ```markdown # Incident Post-Mortem: [Tajuk Incident] **Tarikh:** 2026-03-15 **Severity:** Critical **Duration:** 45 minit (14:00 - 14:45 MYT) **Author:** Syafi ## Summary Web app down selama 45 minit disebabkan disk penuh pada database server. ## Timeline - 14:00 - Alert "DiskSpaceLow" triggered pada db1 - 14:05 - On-call engineer acknowledge alert - 14:10 - Investigate dan confirm disk 100% full - 14:20 - Clear old log files, free up 5GB space - 14:30 - Database service recovered - 14:45 - All services confirmed healthy ## Root Cause Database logs tidak di-rotate dan mengisi disk selama 3 bulan. ## Action Items - [ ] Setup log rotation pada semua database servers - [ ] Tambah alert untuk disk usage > 70% (early warning) - [ ] Automate log cleanup dengan cron job ``` Biasakan diri tulis post-mortem walaupun untuk incident kecil di homelab. Ini membina habit yang sangat berharga untuk production environment. ## Practical: Full Monitoring Stack Untuk Web App Jom combine semuanya. Katakan anda ada Node.js web app yang anda mahu monitor sepenuhnya. Pertama, app anda perlu expose metrics. Guna library `prom-client`: ```javascript const express = require('express'); const promClient = require('prom-client'); const app = express(); // Create metrics const httpRequestsTotal = new promClient.Counter({ name: 'http_requests_total', help: 'Total HTTP requests', labelNames: ['method', 'path', 'status'] }); const httpRequestDuration = new promClient.Histogram({ name: 'http_request_duration_seconds', help: 'HTTP request duration in seconds', labelNames: ['method', 'path'], buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5] }); // Collect default metrics (CPU, memory, etc.) promClient.collectDefaultMetrics(); // Middleware to track metrics app.use((req, res, next) => { const end = httpRequestDuration.startTimer({ method: req.method, path: req.path }); res.on('finish', () => { httpRequestsTotal.inc({ method: req.method, path: req.path, status: res.statusCode }); end(); }); next(); }); // Metrics endpoint for Prometheus app.get('/metrics', async (req, res) => { res.set('Content-Type', promClient.register.contentType); res.end(await promClient.register.metrics()); }); app.get('/', (req, res) => { res.json({ status: 'ok' }); }); app.listen(8000, () => { console.log('App running on port 8000'); }); ``` Untuk Python Flask app pula, anda boleh guna `prometheus_flask_instrumentator`: ```python from flask import Flask from prometheus_flask_instrumentator import FlaskInstrumentator app = Flask(__name__) FlaskInstrumentator().instrument(app) @app.route('/') def hello(): return {'status': 'ok'} if __name__ == '__main__': app.run(host='0.0.0.0', port=8000) ``` Idea utama sama untuk mana-mana language. Expose `/metrics` endpoint, dan Prometheus akan scrape data dari situ. Kebanyakan frameworks mempunyai library yang memudahkan proses ini. Kemudian, jalankan full monitoring stack: ```bash docker compose -f docker-compose.monitoring.yml up -d ``` Verify semua containers running: ```bash docker compose -f docker-compose.monitoring.yml ps ``` Sekarang buka Prometheus di `http://localhost:9090/targets` untuk confirm semua scrape targets berstatus UP. Kalau ada yang DOWN, check network connectivity dan pastikan port betul. Sekarang anda mempunyai: - **Prometheus** (port 9090) yang collect metrics daripada app, node exporter, dan cAdvisor. - **Grafana** (port 3000) untuk dashboards. - **Loki** (port 3100) untuk centralized logs. - **Alertmanager** (port 9093) untuk routing alerts ke Telegram. - **Uptime Kuma** (port 3001) untuk uptime monitoring. Ini adalah setup monitoring yang solid untuk homelab dan boleh di-scale untuk production. ### Monitoring Checklist Sebelum anda consider monitoring stack anda "complete", pastikan anda ada perkara berikut: **Infrastructure level:** - CPU, memory, dan disk usage untuk setiap server. - Network traffic in dan out. - Docker container health dan resource usage. **Application level:** - Request rate (requests per second). - Error rate (percentage of 5xx responses). - Response time (p50, p95, p99). - Active connections atau concurrent users. **Business level:** - Signup rate, login rate, atau transaction rate. - Key business metrics yang relevant. **Alerting:** - Alert untuk service down. - Alert untuk high error rate. - Alert untuk disk space low. - Alert untuk SSL certificate expiry. - Notification channel yang anda actually check (Telegram, email). Mulakan dengan yang basic dan tambah secara gradual. Anda tidak perlu setup semuanya dalam satu hari. Yang penting adalah anda mula dan terus improve monitoring coverage anda over time. ## Ringkasan Monitoring dan observability bukan luxury. Ia adalah keperluan untuk mana-mana sistem yang anda care tentang uptime dan performance. **Perkara penting yang anda belajar:** - Tiga pillars of observability: metrics (numerical data), logs (event records), dan traces (request journeys). - Prometheus collect dan store metrics. Grafana visualize data. Bersama, mereka adalah monitoring stack yang powerful. - PromQL adalah query language untuk Prometheus. Belajar basics untuk buat dashboards dan alerts yang berguna. - Loki adalah Prometheus untuk logs. Ia lightweight dan integrate baik dengan Grafana. - Alerting penting supaya anda tahu ada masalah sebelum users complain. Guna Telegram untuk homelab, PagerDuty untuk production. - Uptime Kuma adalah tool simple tapi powerful untuk monitor availability services anda. - SLI mengukur performance, SLO menetapkan target, SLA adalah agreement formal dengan customer. - Incident response yang baik adalah systematic dan blameless. Sentiasa buat post-mortem untuk belajar daripada masalah. Pada bab seterusnya, kita akan belajar tentang perjalanan dari homelab ke cloud. Bila homelab tidak cukup lagi dan anda perlu scale ke cloud providers. \newpage