Monitoring i Observability - Pytania Rekrutacyjne i Kompletny Przewodnik 2026
"Jak monitorujesz swoje systemy w produkcji?" - to pytanie pada na każdej rozmowie DevOps i SRE. Monitoring i observability to fundament utrzymania niezawodnych systemów. Bez nich lecisz na ślepo - dowiesz się o problemach od użytkowników zamiast z alertów.
W tym przewodniku znajdziesz 50+ pytań rekrutacyjnych z odpowiedziami, od podstaw monitoringu po zaawansowane tematy jak distributed tracing, SLI/SLO i incident management.
Monitoring vs Observability - Podstawy
Odpowiedź w 30 sekund
"Monitoring to zbieranie predefiniowanych metryk i alertowanie na znane problemy - odpowiada 'co się zepsuło'. Observability to zdolność do debugowania nieznanych problemów na podstawie trzech filarów: logs, metrics i traces - odpowiada 'dlaczego się zepsuło'. W nowoczesnych systemach rozproszonych potrzebujesz obu."
Odpowiedź w 2 minuty
Tradycyjny monitoring działa dobrze dla monolitów - definiujesz metryki, ustawiasz progi, dostajesz alert. Ale w świecie mikroserwisów i Kubernetes problem może być w interakcji między serwisami, której nie przewidziałeś. Tu wchodzi observability.
┌─────────────────────────────────────────────────────────────────┐
│ MONITORING vs OBSERVABILITY │
├─────────────────────────────────────────────────────────────────┤
│ │
│ MONITORING (Known Unknowns) │
│ ┌─────────────────────────────────────────┐ │
│ │ "CPU > 80%? → Alert!" │ │
│ │ "Error rate > 1%? → Alert!" │ │
│ │ "Disk > 90%? → Alert!" │ │
│ │ │ │
│ │ ✓ Co się zepsuło │ │
│ │ ✗ Dlaczego się zepsuło │ │
│ └─────────────────────────────────────────┘ │
│ │
│ OBSERVABILITY (Unknown Unknowns) │
│ ┌─────────────────────────────────────────┐ │
│ │ METRICS │ │
│ │ (What is happening?) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────┐ │ │
│ │ │ LOGS │◀── TRACES │ │
│ │ │ (Why it failed) │ (Where it failed)│ │
│ │ └─────────────────┘ │ │
│ │ │ │
│ │ ✓ Debug unknown problems │ │
│ │ ✓ Correlate across services │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Trzy filary observability:
| Filar | Opis | Narzędzia |
|---|---|---|
| Metrics | Numeryczne pomiary agregowane w czasie | Prometheus, InfluxDB, Datadog |
| Logs | Rekordy zdarzeń z timestampem | ELK, Loki, Splunk |
| Traces | Ścieżka requestu przez system | Jaeger, Zipkin, OpenTelemetry |
Prometheus - Pytania Rekrutacyjne
1. Jak działa Prometheus i jaka jest jego architektura?
Słaba odpowiedź: "Prometheus zbiera metryki z aplikacji."
Mocna odpowiedź:
Prometheus to pull-based monitoring system - aktywnie pobiera metryki z endpointów, zamiast czekać aż aplikacje je wyślą.
┌─────────────────────────────────────────────────────────────────┐
│ PROMETHEUS ARCHITECTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ PROMETHEUS SERVER │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │
│ │ │ Retrieval │ │ TSDB │ │ HTTP API │ │ │
│ │ │ (scraper) │ │ (storage) │ │ (PromQL) │ │ │
│ │ └─────┬──────┘ └────────────┘ └─────┬──────┘ │ │
│ └────────┼─────────────────────────────────┼───────┘ │
│ │ │ │
│ ┌──────▼──────┐ ┌──────▼──────┐ │
│ │ Targets │ │ Grafana │ │
│ │ ┌─────────┐ │ │ Alertmgr │ │
│ │ │ App 1 │ │ └─────────────┘ │
│ │ │ /metrics│ │ │
│ │ ├─────────┤ │ ┌─────────────────────────┐ │
│ │ │ App 2 │ │ │ ALERTMANAGER │ │
│ │ │ /metrics│ │◀────│ ┌─────┐ ┌─────┐ │ │
│ │ ├─────────┤ │ │ │Slack│ │Email│ │ │
│ │ │ Node │ │ │ └─────┘ └─────┘ │ │
│ │ │Exporter │ │ └─────────────────────────┘ │
│ │ └─────────┘ │ │
│ └─────────────┘ │
│ │
│ Service Discovery: Kubernetes, Consul, DNS, File SD │
└─────────────────────────────────────────────────────────────────┘
Kluczowe komponenty:
| Komponent | Rola |
|---|---|
| Prometheus Server | Scraping, storage, querying |
| TSDB | Time Series Database (local storage) |
| Alertmanager | Routing, grouping, silencing alertów |
| Pushgateway | Dla short-lived jobs (batch) |
| Exporters | Adaptery dla systemów bez native metrics |
Data model - labels są kluczowe:
http_requests_total{method="GET", status="200", service="api"} 1234
http_requests_total{method="POST", status="500", service="api"} 5
│ │ │
metric name labels (key-value pairs) value
Na co zwraca uwagę rekruter:
- Pull vs push model (Prometheus pulls)
- Znaczenie labels dla dimensional data
- Service discovery w Kubernetes
2. Napisz zapytanie PromQL które znajdzie serwisy z error rate > 1%
Odpowiedź:
# Error rate jako procent wszystkich requestów
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
> 0.01
# Bardziej czytelna wersja z pomocniczymi metrykami
# Zakładając że mamy http_requests_total z label status
# Krok 1: Rate błędów (5xx) per service
sum by (service) (
rate(http_requests_total{status=~"5.."}[5m])
)
# Krok 2: Podziel przez total rate
/ ignoring(status)
sum by (service) (
rate(http_requests_total[5m])
)
# Krok 3: Filtruj > 1%
> 0.01
Wyjaśnienie operatorów PromQL:
| Operator | Opis |
|---|---|
rate() |
Per-second rate w oknie czasowym |
sum by () |
Agregacja z grupowaniem |
{status=~"5.."} |
Regex match |
ignoring() |
Ignoruj label przy join |
[5m] |
Range vector 5 minut |
Inne przydatne zapytania:
# P99 latency per endpoint
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le, endpoint)
)
# Memory usage per pod
container_memory_usage_bytes{namespace="production"}
/ on(pod)
kube_pod_container_resource_limits{resource="memory"}
# Pods restarting frequently
increase(kube_pod_container_status_restarts_total[1h]) > 3
# CPU throttling
rate(container_cpu_cfs_throttled_seconds_total[5m])
/ rate(container_cpu_cfs_periods_total[5m]) > 0.2
3. Jak skonfigurować alerting w Prometheus?
Odpowiedź:
Alerting w Prometheus składa się z dwóch części: reguły alertów w Prometheus i routing w Alertmanager.
prometheus.yml - alert rules:
groups:
- name: service-alerts
rules:
# High error rate
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
> 0.01
for: 5m # Alert fires after 5m of condition being true
labels:
severity: critical
annotations:
summary: "High error rate on {{ $labels.service }}"
description: "Error rate is {{ $value | humanizePercentage }}"
# Service down
- alert: ServiceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "{{ $labels.job }} is down"
# High latency
- alert: HighLatency
expr: |
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service)
) > 0.5
for: 10m
labels:
severity: warning
annotations:
summary: "P99 latency > 500ms on {{ $labels.service }}"
alertmanager.yml - routing:
global:
slack_api_url: 'https://hooks.slack.com/services/...'
resolve_timeout: 5m
route:
receiver: 'default'
group_by: ['alertname', 'service']
group_wait: 30s # Wait before sending first notification
group_interval: 5m # Wait before sending updates
repeat_interval: 4h # Re-send if not resolved
routes:
# Critical alerts → PagerDuty + Slack
- match:
severity: critical
receiver: 'pagerduty-critical'
continue: true # Also send to next matching route
- match:
severity: critical
receiver: 'slack-critical'
# Warning alerts → Slack only
- match:
severity: warning
receiver: 'slack-warnings'
receivers:
- name: 'default'
slack_configs:
- channel: '#alerts'
- name: 'pagerduty-critical'
pagerduty_configs:
- service_key: '<pagerduty-key>'
- name: 'slack-critical'
slack_configs:
- channel: '#alerts-critical'
title: '🔥 {{ .CommonAnnotations.summary }}'
- name: 'slack-warnings'
slack_configs:
- channel: '#alerts-warnings'
# Silencing example - mute during maintenance
inhibit_rules:
- source_match:
alertname: 'ServiceDown'
target_match:
severity: 'warning'
equal: ['service']
Alert states:
- Inactive - condition not met
-
Pending - condition met, waiting for
forduration - Firing - alert active, notification sent
4. Prometheus vs InfluxDB vs Datadog - kiedy który?
Odpowiedź:
┌─────────────────────────────────────────────────────────────────┐
│ MONITORING SOLUTIONS COMPARISON │
├──────────────┬──────────────┬──────────────┬────────────────────┤
│ │ PROMETHEUS │ INFLUXDB │ DATADOG │
├──────────────┼──────────────┼──────────────┼────────────────────┤
│ Model │ Pull │ Push │ Agent (push) │
├──────────────┼──────────────┼──────────────┼────────────────────┤
│ Query │ PromQL │ InfluxQL/ │ Custom + SQL │
│ Language │ │ Flux │ │
├──────────────┼──────────────┼──────────────┼────────────────────┤
│ Storage │ Local TSDB │ Local/Cloud │ Managed │
├──────────────┼──────────────┼──────────────┼────────────────────┤
│ Cardinality │ Medium │ High │ Very High │
│ Support │ (labels) │ (tags) │ (managed) │
├──────────────┼──────────────┼──────────────┼────────────────────┤
│ Long-term │ Thanos/ │ Built-in │ Included │
│ Storage │ Cortex/Mimir │ │ │
├──────────────┼──────────────┼──────────────┼────────────────────┤
│ Cost │ Free (infra) │ Free/Paid │ $$$$ per host │
├──────────────┼──────────────┼──────────────┼────────────────────┤
│ Ops overhead │ Medium-High │ Medium │ None (SaaS) │
├──────────────┼──────────────┼──────────────┼────────────────────┤
│ K8s native │ ✅ Best │ Good │ Good │
├──────────────┼──────────────┼──────────────┼────────────────────┤
│ Best for │ Cloud-native,│ IoT, time │ Enterprise, │
│ │ K8s, DevOps │ series data │ full-stack obs. │
└──────────────┴──────────────┴──────────────┴────────────────────┘
Decision guide:
| Scenariusz | Wybór |
|---|---|
| Kubernetes native | Prometheus + Grafana |
| IoT / time series heavy | InfluxDB |
| No ops team / enterprise | Datadog |
| Cost sensitive | Prometheus |
| Need APM + infra + logs | Datadog or Elastic |
| High cardinality metrics | VictoriaMetrics or Datadog |
Grafana i Dashboards
5. Jak zaprojektować efektywny dashboard w Grafana?
Odpowiedź:
Dobry dashboard opowiada historię - od high-level overview do szczegółów. Stosuj zasadę USE (Utilization, Saturation, Errors) i RED (Rate, Errors, Duration).
┌─────────────────────────────────────────────────────────────────┐
│ DASHBOARD STRUCTURE │
├─────────────────────────────────────────────────────────────────┤
│ ROW 1: Golden Signals (overview) │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Request │ │ Error │ │ Latency │ │Saturation │ │
│ │ Rate │ │ Rate │ │ p99 │ │ (queue) │ │
│ │ 1.2k/s │ │ 0.1% │ │ 45ms │ │ 23% │ │
│ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │
│ │
│ ROW 2: Resource Utilization │
│ ┌─────────────────────────────┐ ┌─────────────────────────┐ │
│ │ CPU Usage │ │ Memory Usage │ │
│ │ ████████████░░░░ 75% │ │ ██████████░░░░░ 65% │ │
│ └─────────────────────────────┘ └─────────────────────────┘ │
│ │
│ ROW 3: Service-specific metrics │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Request Rate by Endpoint │ │
│ │ /api/users ████████████████████ 800/s │ │
│ │ /api/orders ████████████ 400/s │ │
│ │ /api/products ████████ 200/s │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ROW 4: Dependencies │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Database latency │ Cache hit rate │ External API │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Best practices:
# Dashboard design principles
1. Start with overview:
- Single stat panels for key metrics
- Red/yellow/green thresholds
- Trends (vs yesterday, vs last week)
2. Progressive disclosure:
- Click to drill down
- Variables for filtering (namespace, service)
- Links to detailed dashboards
3. Use appropriate visualizations:
- Time series: trends over time
- Gauge: current value vs threshold
- Heatmap: latency distribution
- Table: top N / bottom N
4. Consistent layout:
- Same metric types aligned
- Consistent colors (red = bad)
- Standard time ranges
Przykładowy dashboard JSON (fragment):
{
"panels": [
{
"title": "Request Rate",
"type": "stat",
"targets": [{
"expr": "sum(rate(http_requests_total[5m]))",
"legendFormat": "req/s"
}],
"fieldConfig": {
"defaults": {
"thresholds": {
"steps": [
{"color": "green", "value": null},
{"color": "yellow", "value": 1000},
{"color": "red", "value": 5000}
]
}
}
}
}
]
}
6. Jak zaimplementować RED i USE metrics?
Odpowiedź:
RED Method (dla serwisów):
- Rate - requests per second
- Errors - failed requests per second
- Duration - latency distribution
USE Method (dla zasobów):
- Utilization - % czasu resource jest zajęty
- Saturation - queue length, pending work
- Errors - error count
# RED Metrics dla HTTP serwisu
# Rate
sum(rate(http_requests_total[5m])) by (service)
# Errors (jako rate)
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
# Errors (jako procent)
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/ sum(rate(http_requests_total[5m])) by (service)
# Duration (percentyle z histogramu)
histogram_quantile(0.50, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
histogram_quantile(0.90, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
# USE Metrics dla CPU
# Utilization
avg(rate(node_cpu_seconds_total{mode!="idle"}[5m])) by (instance)
# Saturation (load average vs cores)
node_load1 / count(node_cpu_seconds_total{mode="idle"}) by (instance)
# Errors
rate(node_cpu_guest_seconds_total[5m]) # or hardware errors if available
# USE Metrics dla pamięci
# Utilization
1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)
# Saturation (swap usage indicates saturation)
node_memory_SwapTotal_bytes - node_memory_SwapFree_bytes
# Errors
rate(node_vmstat_oom_kill[5m])
Golden Signals (Google SRE):
- Latency
- Traffic
- Errors
- Saturation
Logging - ELK i Loki
7. ELK Stack vs Loki - kiedy który wybrać?
Odpowiedź:
┌─────────────────────────────────────────────────────────────────┐
│ ELK vs LOKI COMPARISON │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ELK STACK GRAFANA LOKI │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Kibana │ │ Grafana │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ ┌──────▼──────┐ ┌──────▼──────┐ │
│ │Elasticsearch│ │ Loki │ │
│ │ (full-text │ │ (labels │ │
│ │ indexing) │ │ only) │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ ┌──────▼──────┐ ┌──────▼──────┐ │
│ │ Logstash/ │ │ Promtail │ │
│ │ Beats │ │ │ │
│ └─────────────┘ └─────────────┘ │
│ │
├─────────────────────────────────────────────────────────────────┤
│ Feature │ ELK │ Loki │
├───────────────────┼────────────────┼───────────────────────────┤
│ Indexing │ Full content │ Labels only │
│ Query │ Lucene/KQL │ LogQL (PromQL-like) │
│ Storage cost │ High │ Low (S3/GCS) │
│ Ops complexity │ High │ Low │
│ Search speed │ Fast (indexed) │ Slower (grep-like) │
│ K8s integration │ Good │ Excellent │
│ Memory usage │ High │ Low │
│ Existing stack │ Standalone │ Grafana ecosystem │
└─────────────────────────────────────────────────────────────────┘
Kiedy ELK:
- Potrzebujesz full-text search w logach
- Complex analytics i aggregations
- Security/compliance wymagania (SIEM)
- Duży zespół z dedykowanymi ops
Kiedy Loki:
- Już używasz Prometheus + Grafana
- Kubernetes native environment
- Cost-sensitive
- Proste use cases (debug, tail logs)
Loki query example (LogQL):
# Logi z błędami dla konkretnego serwisu
{namespace="production", app="api"} |= "error"
# Parse JSON i filtruj
{app="api"} | json | status_code >= 500
# Metryki z logów (jak Prometheus)
sum(rate({app="api"} |= "error" [5m])) by (pod)
8. Jak skonfigurować centralne logowanie w Kubernetes?
Odpowiedź:
┌─────────────────────────────────────────────────────────────────┐
│ KUBERNETES LOGGING ARCHITECTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Option 1: Node-level agent (DaemonSet) │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Node │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Pod A │ │ Pod B │ │ Pod C │ │ │
│ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │
│ │ │ │ │ │ │
│ │ ▼ ▼ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ /var/log/containers/*.log │ │ │
│ │ └───────────────────────┬─────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌───────────────────────▼─────────────────────────────┐ │ │
│ │ │ Fluent Bit / Promtail (DaemonSet) │ │ │
│ │ └───────────────────────┬─────────────────────────────┘ │ │
│ └──────────────────────────┼────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────┐ │
│ │ Elasticsearch / Loki │ │
│ └─────────────────────────────┘ │
│ │
│ Option 2: Sidecar container │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Pod │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ App │────▶│ Sidecar │────▶ Backend │ │
│ │ │ Container │ │ (Fluent Bit)│ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ │ │ shared volume │ │ │
│ │ └───────────────┘ │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Fluent Bit DaemonSet configuration: ```yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: fluent-bit namespace: logging spec: selector: matchLabels: app: fluent-bit template: spec: containers: - name: fluent-bit image: fluent/fluent-bit:2.1 volumeMounts: - name: varlog mountPath: /var/log - name: config mountPath: /fluent-bit/etc/ resources: limits: memory: 200Mi cpu: 200m volumes: - name: varlog hostPath: path: /var/log - name: config configMap: name: fluent-bit-config
apiVersion: v1 kind: ConfigMap metadata: name: fluent-bit-config data: fluent-bit.conf: | [SERVICE] Flush 1 Log_Level info Parsers_File parsers.conf
[INPUT]
Name tail
Path /var/log/containers/*.log
Parser docker
Tag kube.*
Refresh_Interval 5
Mem_Buf_Limit 50MB
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Merge_Log On
K8S-Logging.Parser On
[OUTPUT]
Name es
Match *
Host elasticsearch
Port 9200
Index k8s-logs
Type _doc
**Structured logging best practice:**
```javascript
// Application should log JSON
logger.info({
message: "Order processed",
orderId: "12345",
userId: "user-789",
duration_ms: 150,
status: "success"
});
// Not plain text
logger.info("Order 12345 processed for user-789 in 150ms");
Distributed Tracing
9. Jak działa distributed tracing i kiedy go używać?
Odpowiedź:
Distributed tracing śledzi request przez wszystkie serwisy w systemie rozproszonym. Każdy request dostaje unikalne trace ID.
┌─────────────────────────────────────────────────────────────────┐
│ DISTRIBUTED TRACE │
├─────────────────────────────────────────────────────────────────┤
│ Request: GET /api/orders/123 │
│ Trace ID: abc123 │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ API Gateway (span-1) [0ms - 250ms] │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Order Service (span-2) [10ms - 200ms]│ │ │
│ │ │ ┌───────────────────────────────────────────────┐ │ │ │
│ │ │ │ User Service (span-3) [20ms - 50ms] │ │ │ │
│ │ │ └───────────────────────────────────────────────┘ │ │ │
│ │ │ ┌───────────────────────────────────────────────┐ │ │ │
│ │ │ │ Database Query (span-4) [60ms - 150ms] │ │ │ │
│ │ │ └───────────────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Total: 250ms │
│ Bottleneck: Database Query (90ms) │
└─────────────────────────────────────────────────────────────────┘
Kluczowe koncepcje:
| Concept | Opis |
|---|---|
| Trace | Pełna ścieżka requestu (tree of spans) |
| Span | Pojedyncza operacja z czasem start/end |
| Trace ID | Unikalny identyfikator trace (propagowany) |
| Span ID | Identyfikator pojedynczego span |
| Parent Span | Span który wywołał bieżący span |
| Baggage | Key-value data propagowana przez trace |
OpenTelemetry instrumentation (Node.js):
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
const { JaegerExporter } = require('@opentelemetry/exporter-jaeger');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const { ExpressInstrumentation } = require('@opentelemetry/instrumentation-express');
// Setup provider
const provider = new NodeTracerProvider();
provider.addSpanProcessor(
new SimpleSpanProcessor(new JaegerExporter({
endpoint: 'http://jaeger:14268/api/traces'
}))
);
provider.register();
// Auto-instrument HTTP and Express
registerInstrumentations({
instrumentations: [
new HttpInstrumentation(),
new ExpressInstrumentation(),
],
});
// Manual span creation
const tracer = provider.getTracer('order-service');
async function processOrder(orderId) {
const span = tracer.startSpan('processOrder');
span.setAttribute('order.id', orderId);
try {
// ... processing logic
span.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
span.recordException(error);
throw error;
} finally {
span.end();
}
}
Context propagation (HTTP headers):
# W3C Trace Context (standard)
traceparent: 00-abc123-span456-01
tracestate: vendor=value
# Jaeger format
uber-trace-id: abc123:span456:parent789:1
10. Jaeger vs Zipkin vs OpenTelemetry - co wybrać?
Odpowiedź:
┌─────────────────────────────────────────────────────────────────┐
│ TRACING SOLUTIONS COMPARISON │
├───────────────┬───────────────┬───────────────┬─────────────────┤
│ │ JAEGER │ ZIPKIN │ OPENTELEMETRY │
├───────────────┼───────────────┼───────────────┼─────────────────┤
│ Origin │ Uber │ Twitter │ CNCF (merged │
│ │ │ │ OpenTracing + │
│ │ │ │ OpenCensus) │
├───────────────┼───────────────┼───────────────┼─────────────────┤
│ Type │ Full platform │ Full platform │ Standard/SDK │
├───────────────┼───────────────┼───────────────┼─────────────────┤
│ Storage │ Cassandra, │ MySQL, │ N/A (exports │
│ │ Elasticsearch,│ Cassandra, │ to backends) │
│ │ Kafka │ Elasticsearch │ │
├───────────────┼───────────────┼───────────────┼─────────────────┤
│ UI │ ✅ Built-in │ ✅ Built-in │ ❌ Need backend │
├───────────────┼───────────────┼───────────────┼─────────────────┤
│ K8s support │ Excellent │ Good │ Excellent │
├───────────────┼───────────────┼───────────────┼─────────────────┤
│ Sampling │ Advanced │ Basic │ Configurable │
├───────────────┼───────────────┼───────────────┼─────────────────┤
│ Future │ Adopting OTel │ Adopting OTel │ THE standard │
└───────────────┴───────────────┴───────────────┴─────────────────┘
Rekomendacja 2026:
OpenTelemetry SDK (instrumentation)
│
├──▶ Jaeger (backend + UI) # Self-hosted
├──▶ Grafana Tempo (backend) # Grafana ecosystem
├──▶ AWS X-Ray # AWS native
└──▶ Datadog APM # SaaS
OpenTelemetry to standard - używaj OTel SDK do instrumentacji, a backend wybierz według potrzeb. Jaeger i Zipkin adoptują OTel jako źródło danych.
SLI, SLO, SLA i Error Budgets
11. Wyjaśnij różnicę między SLI, SLO i SLA
Odpowiedź:
┌─────────────────────────────────────────────────────────────────┐
│ SLI → SLO → SLA │
├─────────────────────────────────────────────────────────────────┤
│ │
│ SLI (Service Level Indicator) │
│ ───────────────────────────── │
│ METRYKA mierząca jakość usługi │
│ Przykłady: │
│ • Request latency p99 │
│ • Error rate (5xx / total) │
│ • Availability (successful / total requests) │
│ │
│ ↓ │
│ │
│ SLO (Service Level Objective) │
│ ───────────────────────────── │
│ CEL dla SLI (wewnętrzny) │
│ Przykłady: │
│ • "99.9% requestów < 200ms" │
│ • "Error rate < 0.1%" │
│ • "99.95% availability per month" │
│ │
│ ↓ │
│ │
│ SLA (Service Level Agreement) │
│ ───────────────────────────── │
│ KONTRAKT z klientem (zewnętrzny, z konsekwencjami) │
│ Przykłady: │
│ • "99.9% uptime, otherwise refund" │
│ • "Response time < 500ms, penalty for breach" │
│ │
│ SLA < SLO (zawsze zostawiaj bufor!) │
└─────────────────────────────────────────────────────────────────┘
Dobre SLI - zasady:
SLI powinno być:
- Mierzalne: konkretna metryka, nie "działa dobrze"
- User-facing: co odczuwa użytkownik, nie internal metrics
- Actionable: możesz coś z tym zrobić
- Owned: wiesz kto jest odpowiedzialny
Przykłady dobrych SLI:
availability: "successful requests / total requests"
latency: "requests served < 200ms / total requests"
throughput: "requests processed per second"
correctness: "valid responses / total responses"
Przykłady złych SLI:
- "CPU usage < 80%" (internal, nie user-facing)
- "No bugs" (nie mierzalne)
- "System is fast" (nie konkretne)
12. Co to jest Error Budget i jak go używać?
Odpowiedź:
Error Budget to "budżet" na błędy wynikający z SLO. Jeśli SLO = 99.9% availability, masz 0.1% error budget.
┌─────────────────────────────────────────────────────────────────┐
│ ERROR BUDGET CONCEPT │
├─────────────────────────────────────────────────────────────────┤
│ │
│ SLO: 99.9% availability per month │
│ │
│ Month = 43,200 minutes (30 days) │
│ Error Budget = 43,200 × 0.001 = 43.2 minutes downtime │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Month Progress: [████████████████████░░░░░] 80% │ │
│ │ Error Budget: [████████░░░░░░░░░░░░░░░░░] 30% │ │
│ │ │ │
│ │ Used: 30 min / 43.2 min │ │
│ │ Remaining: 13.2 min for rest of month │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ DECISIONS BASED ON ERROR BUDGET: │
│ │
│ Budget > 50% remaining: │
│ ✅ Ship new features │
│ ✅ Run experiments │
│ ✅ Risky deployments allowed │
│ │
│ Budget < 20% remaining: │
│ ⚠️ Feature freeze │
│ ⚠️ Focus on reliability │
│ ⚠️ Only critical fixes │
│ │
│ Budget exhausted: │
│ 🛑 Full freeze │
│ 🛑 All hands on reliability │
│ 🛑 No deployments until next period │
└─────────────────────────────────────────────────────────────────┘
Error budget policy:
error_budget_policy:
burn_rate_alerts:
- name: "2% budget burn in 1h"
window: 1h
burn_rate: 14.4 # 100% / (30*24) * 14.4 = 2% per hour
severity: critical
action: "Page on-call"
- name: "5% budget burn in 6h"
window: 6h
burn_rate: 6
severity: warning
action: "Slack notification"
exhaustion_actions:
25_percent_remaining:
- "Review all pending deployments"
- "Increase testing requirements"
10_percent_remaining:
- "Feature freeze"
- "Cancel non-critical releases"
0_percent:
- "Full deployment freeze"
- "Incident review required"
- "Reliability sprint"
Prometheus alert dla burn rate:
# Multi-window, multi-burn-rate alert (Google SRE)
groups:
- name: slo-alerts
rules:
- alert: ErrorBudgetBurn
expr: |
(
# Fast burn (2% in 1h)
(1 - avg_over_time(up[1h])) > 14.4 * 0.001
and
(1 - avg_over_time(up[5m])) > 14.4 * 0.001
)
or
(
# Slow burn (5% in 6h)
(1 - avg_over_time(up[6h])) > 6 * 0.001
and
(1 - avg_over_time(up[30m])) > 6 * 0.001
)
labels:
severity: critical
annotations:
summary: "Error budget burning too fast"
Incident Management
13. Jak zorganizować proces on-call?
Odpowiedź:
┌─────────────────────────────────────────────────────────────────┐
│ ON-CALL STRUCTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ESCALATION LEVELS │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ L1: Primary On-Call │ │
│ │ • First responder │ │
│ │ • Acknowledge in 5 min │ │
│ │ • Start investigation │ │
│ │ │ │ │
│ │ ▼ (escalate if no response in 15 min) │ │
│ │ L2: Secondary On-Call │ │
│ │ • Backup engineer │ │
│ │ • Different timezone often │ │
│ │ │ │ │
│ │ ▼ (escalate for major incidents) │ │
│ │ L3: Engineering Lead / Manager │ │
│ │ • P1 incidents │ │
│ │ • Customer-facing issues │ │
│ │ │ │ │
│ │ ▼ (escalate for business impact) │ │
│ │ L4: Executive │ │
│ │ • PR/communication decisions │ │
│ │ • Major outages │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ROTATION BEST PRACTICES: │
│ • Weekly rotation (not daily - context switching) │
│ • Handoff meeting at rotation │
│ • Follow-the-sun for global teams │
│ • Compensatory time off │
│ • Max 25% of time on-call (sustainable) │
│ • Runbooks for common issues │
└─────────────────────────────────────────────────────────────────┘
PagerDuty / Opsgenie configuration:
escalation_policy:
name: "API Service"
rules:
- targets:
- type: schedule
id: "primary-on-call"
escalation_delay_in_minutes: 15
- targets:
- type: schedule
id: "secondary-on-call"
escalation_delay_in_minutes: 15
- targets:
- type: user
id: "engineering-manager"
escalation_delay_in_minutes: 30
schedules:
- name: "primary-on-call"
rotation_type: weekly
start_time: "09:00"
users:
- alice
- bob
- charlie
restrictions:
- type: week_restriction
start_day: monday
end_day: friday
Runbook template:
# Alert: HighErrorRate on API Service
## Symptoms
- Error rate > 1% for 5+ minutes
- Users may see 500 errors
## Quick Checks (< 5 min)
1. Check Grafana dashboard: [link]
2. Check recent deployments: `kubectl rollout history deployment/api`
3. Check dependent services: Database, Redis, External APIs
## Common Causes & Fixes
### Database Connection Issues
- Check: `kubectl exec -it api-pod -- pg_isready -h db-host`
- Fix: Restart connection pool / Scale DB
### Memory Pressure
- Check: Pod memory usage in Grafana
- Fix: `kubectl rollout restart deployment/api`
### Bad Deploy
- Check: Recent releases in deployment history
- Fix: `kubectl rollout undo deployment/api`
## Escalation
- If not resolved in 30 min → Escalate to L2
- If customer impact → Notify #incidents channel
14. Jak przeprowadzić postmortem / incident review?
Odpowiedź:
Postmortem to blameless analiza incydentu skupiona na systemie, nie ludziach.
┌─────────────────────────────────────────────────────────────────┐
│ POSTMORTEM TEMPLATE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ INCIDENT SUMMARY │
│ ─────────────── │
│ Date: 2026-01-12 │
│ Duration: 45 minutes (14:30 - 15:15 UTC) │
│ Severity: P1 (customer-facing, >10% users affected) │
│ Services affected: API, Checkout │
│ │
│ IMPACT │
│ ────── │
│ • 15% of checkout requests failed │
│ • ~500 users affected │
│ • Estimated revenue loss: $X │
│ • Error budget consumed: 35% of monthly budget │
│ │
│ TIMELINE │
│ ──────── │
│ 14:15 - Deploy v2.3.1 to production │
│ 14:28 - Monitoring detects error rate spike │
│ 14:30 - Alert fires, on-call paged │
│ 14:35 - On-call acknowledges, starts investigation │
│ 14:45 - Root cause identified (DB connection leak) │
│ 14:50 - Rollback initiated │
│ 15:00 - Rollback complete, error rate dropping │
│ 15:15 - Incident resolved, monitoring back to normal │
│ │
│ ROOT CAUSE │
│ ────────── │
│ Database connection pool leak introduced in v2.3.1 │
│ New feature didn't properly release connections │
│ Pool exhausted after ~15 min of traffic │
│ │
│ CONTRIBUTING FACTORS │
│ ──────────────────── │
│ • No connection pool monitoring in staging │
│ • Canary deployment only ran for 5 min (leak needs 15 min) │
│ • Connection timeout was set to 30s (too long) │
│ │
│ ACTION ITEMS │
│ ──────────── │
│ □ Add connection pool metrics to Grafana (Owner: Alice, ETA: │
│ 2026-01-15) │
│ □ Extend canary deployment to 30 min (Owner: Bob, ETA: │
│ 2026-01-14) │
│ □ Reduce connection timeout to 5s (Owner: Charlie, ETA: │
│ 2026-01-13) │
│ □ Add load test for connection pool (Owner: Alice, ETA: │
│ 2026-01-20) │
│ │
│ LESSONS LEARNED │
│ ─────────────── │
│ • What went well: Fast detection, quick rollback │
│ • What went poorly: Missed in code review, short canary │
│ • Where we got lucky: Low traffic period │
└─────────────────────────────────────────────────────────────────┘
5 Whys example:
Problem: Checkout failed for 15% of users
Why 1: Database connections were exhausted
Why 2: New code didn't release connections properly
Why 3: Connection release was in finally block that wasn't reached
Why 4: Exception path wasn't tested
Why 5: No integration test for error scenarios
Root cause: Insufficient test coverage for error handling paths
Cloud-Native Monitoring
15. Jak monitorować aplikacje w Kubernetes?
Odpowiedź:
┌─────────────────────────────────────────────────────────────────┐
│ KUBERNETES MONITORING STACK │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ GRAFANA │ │
│ │ Dashboards │ Alerting │ Explore │ │
│ └──────┬─────────────┬──────────────┬───────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────────┐ ┌──────────┐ ┌────────────┐ │
│ │ Prometheus │ │ Loki │ │ Tempo │ │
│ │ (metrics) │ │ (logs) │ │ (traces) │ │
│ └─────┬──────┘ └────┬─────┘ └─────┬──────┘ │
│ │ │ │ │
│ ┌─────▼─────────────▼─────────────▼──────┐ │
│ │ KUBERNETES CLUSTER │ │
│ │ │ │
│ │ ┌─────────────────────────────────┐ │ │
│ │ │ kube-prometheus-stack │ │ │
│ │ │ • Prometheus Operator │ │ │
│ │ │ • Node Exporter (DaemonSet) │ │ │
│ │ │ • kube-state-metrics │ │ │
│ │ │ • Alertmanager │ │ │
│ │ └─────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────┐ │ │
│ │ │ Applications │ │ │
│ │ │ /metrics (Prometheus format) │ │ │
│ │ │ stdout (JSON logs) │ │ │
│ │ │ OpenTelemetry (traces) │ │ │
│ │ └─────────────────────────────────┘ │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
kube-prometheus-stack installation:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install kube-prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--set grafana.adminPassword=admin \
--set prometheus.prometheusSpec.retention=30d \
--set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=50Gi
ServiceMonitor for custom app:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: api-service
namespace: monitoring
labels:
release: kube-prometheus
spec:
selector:
matchLabels:
app: api
namespaceSelector:
matchNames:
- production
endpoints:
- port: metrics
interval: 30s
path: /metrics
Key Kubernetes metrics:
# Pod CPU usage vs requests
sum(rate(container_cpu_usage_seconds_total{namespace="production"}[5m])) by (pod)
/
sum(kube_pod_container_resource_requests{resource="cpu", namespace="production"}) by (pod)
# Pod memory usage vs limits
sum(container_memory_usage_bytes{namespace="production"}) by (pod)
/
sum(kube_pod_container_resource_limits{resource="memory", namespace="production"}) by (pod)
# Pod restart count
increase(kube_pod_container_status_restarts_total{namespace="production"}[1h])
# Deployment replicas available vs desired
kube_deployment_status_replicas_available / kube_deployment_spec_replicas
# PVC usage
kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes
16. AWS CloudWatch vs Prometheus - kiedy który?
Odpowiedź:
┌─────────────────────────────────────────────────────────────────┐
│ CLOUDWATCH vs PROMETHEUS │
├──────────────────────┬──────────────────────────────────────────┤
│ CLOUDWATCH │ PROMETHEUS │
├──────────────────────┼──────────────────────────────────────────┤
│ AWS-native │ Cloud-agnostic │
│ Managed (no ops) │ Self-hosted (or managed: Grafana Cloud) │
│ Pay per metric │ Infrastructure cost only │
│ AWS integrations │ K8s native │
│ 15-month retention │ Configurable retention │
│ Basic alerting │ Advanced alerting (Alertmanager) │
│ Insights (logs) │ PromQL (powerful) │
├──────────────────────┼──────────────────────────────────────────┤
│ Best for: │ Best for: │
│ • AWS services only │ • Kubernetes │
│ • Small teams │ • Multi-cloud │
│ • No K8s │ • Cost-sensitive │
│ • Lambda/Serverless │ • Advanced queries │
└──────────────────────┴──────────────────────────────────────────┘
Hybrid approach (common):
┌─────────────────────────────────────────────────────────────────┐
│ AWS Services EKS Workloads │
│ (RDS, Lambda, etc) (microservices) │
│ │ │ │
│ ▼ ▼ │
│ CloudWatch Prometheus │
│ │ │ │
│ └────────────┬───────────┘ │
│ ▼ │
│ Grafana (unified view) │
│ CloudWatch data source + Prometheus DS │
└─────────────────────────────────────────────────────────────────┘
CloudWatch Container Insights (EKS):
# Enable Container Insights
aws eks update-cluster-config \
--name my-cluster \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'
# CloudWatch agent DaemonSet (automatic with EKS add-on)
eksctl create addon --name aws-cloudwatch-observability --cluster my-cluster
Praktyczne Zadania
Zadanie 1: Debug slow API endpoint
API endpoint /api/orders ma P99 latency > 2s. Jak to zbadasz?
Podejście:
1. Metrics: Sprawdź histogram latency w Grafana
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket{path="/api/orders"}[5m]))
2. Traces: Znajdź slow traces w Jaeger/Tempo
- Filter: service=api, operation=/api/orders, duration>2s
- Analizuj span breakdown
3. Logs: Correlate z trace_id
{app="api"} |= "trace_id_from_jaeger"
4. Dependencies: Sprawdź latency DB, cache, external APIs
- Database query time
- Cache hit rate
- External API response time
Zadanie 2: Setup alerting for SLO
SLO: 99.9% availability. Skonfiguruj multi-window burn rate alert.
Rozwiązanie:
# Alert jeśli wypalamy 2% budżetu w 1h (fast burn)
# lub 5% w 6h (slow burn)
- alert: SLOBurnRate
expr: |
(
(1 - (sum(rate(http_requests_total{status!~"5.."}[1h])) / sum(rate(http_requests_total[1h])))) > (14.4 * 0.001)
and
(1 - (sum(rate(http_requests_total{status!~"5.."}[5m])) / sum(rate(http_requests_total[5m])))) > (14.4 * 0.001)
)
or
(
(1 - (sum(rate(http_requests_total{status!~"5.."}[6h])) / sum(rate(http_requests_total[6h])))) > (6 * 0.001)
and
(1 - (sum(rate(http_requests_total{status!~"5.."}[30m])) / sum(rate(http_requests_total[30m])))) > (6 * 0.001)
)
Zadanie 3: Zaprojektuj dashboard dla microservice
Rozwiązanie:
Row 1: Golden Signals (stat panels)
- Request rate
- Error rate
- P99 latency
- Saturation (queue depth)
Row 2: RED metrics over time (time series)
- Requests by endpoint
- Errors by type
- Latency histogram heatmap
Row 3: Dependencies
- Database latency
- Cache hit rate
- External API success rate
Row 4: Resources (for debugging)
- CPU usage vs limit
- Memory usage vs limit
- Network I/O
Podsumowanie
Monitoring i observability to fundament niezawodnych systemów. Na rozmowie rekrutacyjnej oczekuj pytań o:
- Podstawy - różnica monitoring vs observability, trzy filary
- Prometheus - architektura, PromQL, alerting
- Grafana - dashboard design, RED/USE metrics
- Logging - ELK vs Loki, structured logging
- Tracing - distributed tracing, OpenTelemetry
- SRE concepts - SLI/SLO/SLA, error budgets
- Incident management - on-call, postmortems
Klucz do sukcesu: pokazanie że rozumiesz end-to-end observability - od zbierania danych, przez alerting, po incident response i improvement.
Zobacz też
- Kompletny Przewodnik DevOps Engineer
- Kubernetes - Pytania Rekrutacyjne
- Docker - Pytania Rekrutacyjne
- AWS - Pytania Rekrutacyjne
Artykuł przygotowany przez zespół Flipcards - tworzymy materiały do nauki programowania i przygotowania do rozmów rekrutacyjnych.
Chcesz więcej pytań rekrutacyjnych?
To tylko jeden temat z naszego kompletnego przewodnika po rozmowach rekrutacyjnych. Uzyskaj dostęp do 800+ pytań z 13 technologii.
