Интеграция с Prometheus, Grafana, Jaeger, ELK Stack
Наблюдаемость (observability) — это возможность понять внутреннее состояние системы по её внешним выходам (логи, метрики, trace).
Проблема: Нужно мониторить производительность Kong, количество запросов, ошибки, latency.
Решение: Плагин prometheus экспортирует метрики в формате Prometheus.
# Глобальное включение
curl -X POST http://localhost:8001/plugins \
--data "name=prometheus"Плагин не требует конфигурации — все метрики экспортируются автоматически.
# Получение метрик
curl http://localhost:8001/metricsПример вывода:
# HELP kong_requests_total The total number of requests
# TYPE kong_requests_total counter
kong_requests_total{consumer="free-user",route="api-route",service="users-api",method="GET",code="200"} 150
kong_requests_total{consumer="premium-user",route="api-route",service="users-api",method="POST",code="201"} 45
# HELP kong_latency_request The request latency in milliseconds
# TYPE kong_latency_request histogram
kong_latency_request_bucket{service="users-api",le="5"} 100
kong_latency_request_bucket{service="users-api",le="10"} 180
kong_latency_request_bucket{service="users-api",le="50"} 195
kong_latency_request_bucket{service="users-api",le="+Inf"} 200
# HELP kong_status The HTTP status codes returned
# TYPE kong_status counter
kong_status{service="users-api",code="200"} 150
kong_status{service="users-api",code="401"} 10
kong_status{service="users-api",code="500"} 5
| Метрика | Описание | Labels |
|---|---|---|
kong_requests_total | Всего запросов | consumer, route, service, method, code |
kong_latency_request | Latency запроса (histogram) | service |
kong_latency_proxy | Latency проксирования (histogram) | service |
kong_bandwidth_received | Получено байт | consumer, route, service |
kong_bandwidth_sent | Отправлено байт | consumer, route, service |
kong_status | Запросы по статус-кодам | service, code |
kong_node_status | Статус узлов Kong | node |
Проблема: Нужна визуализация метрик.
Решение: Prometheus + Grafana.
version: '3.8'
services:
kong:
image: kong:3.5
environment:
KONG_DATABASE: off
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_PLUGINS: bundled,prometheus
ports:
- "8000:8000"
- "8001:8001"
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
depends_on:
- kong
grafana:
image: grafana/grafana:latest
environment:
GF_SECURITY_ADMIN_PASSWORD: admin
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
depends_on:
- prometheus
volumes:
grafana_data:global:
scrape_interval: 15s
scrape_configs:
- job_name: 'kong'
static_configs:
- targets: ['kong:8001']
metrics_path: /metricsНастройка Grafana:
Проблема: Нужно получать уведомления о проблемах.
Решение: Prometheus alerting rules.
# alerting_rules.yml
groups:
- name: kong
rules:
- alert: HighErrorRate
expr: sum(rate(kong_status{code=~"5.."}[5m])) / sum(rate(kong_requests_total[5m])) > 0.05
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate in Kong"
description: "Error rate is {{ $value | humanizePercentage }}"
- alert: HighLatency
expr: histogram_quantile(0.95, sum(rate(kong_latency_request_bucket[5m])) by (le, service)) > 1000
for: 5m
labels:
severity: warning
annotations:
summary: "High latency in Kong"
description: "P95 latency is {{ $value }}ms for service {{ $labels.service }}"
- alert: KongDown
expr: up{job="kong"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Kong instance is down"
description: "Kong instance {{ $labels.instance }} is not responding"Проблема: Нужно отправлять логи запросов во внешнюю систему для анализа.
Решение: Плагины http-log, tcp-log, udp-log.
Проблема: Нужно отправлять логи на HTTP endpoint (ELK, Splunk, кастомная система).
Решение: Плагин http-log.
curl -X POST http://localhost:8001/plugins \
--data "name=http-log" \
--data "config.http_endpoint=http://elk:9200/logs" \
--data "config.http_method=POST" \
--data "config.headers.Content-Type=application/json" \
--data "config.timeout=1000" \
--data "config.keepalive=60000" \
--data "config.queue_size=10000" \
--data "config.flush_timeout=2" \
--data "config.retry_delay=1" \
--data "config.max_retry_delay=10"Параметры:
http_endpoint — URL для отправки логовhttp_method — POST/PUTheaders — кастомные заголовкиtimeout — таймаут запроса (мс)keepalive — keepalive соединение (мс)queue_size — размер очереди логовflush_timeout — интервал отправки (сек)retry_delay — задержка перед retry (сек)Формат лога:
{
"request": {
"method": "GET",
"path": "/api/users",
"query": {},
"headers": {...}
},
"response": {
"status": 200,
"headers": {...},
"size": 1234
},
"latency": 45,
"client_ip": "192.168.1.100",
"user": "free-user",
"route": "api-route",
"service": "users-api"
}Проблема: Нужна отправка логов по TCP (Logstash, rsyslog).
Решение: Плагин tcp-log.
curl -X POST http://localhost:8001/plugins \
--data "name=tcp-log" \
--data "config.host=logstash" \
--data "config.port=5000" \
--data "config.timeout=1000" \
--data "config.keepalive=60000"Проблема: Нужна быстрая отправка логов без гарантии доставки.
Решение: Плагин udp-log.
curl -X POST http://localhost:8001/plugins \
--data "name=udp-log" \
--data "config.host=rsyslog" \
--data "config.port=514"Проблема: Нужен централизованный поиск и анализ логов.
Решение: Kong → http-log → Logstash → Elasticsearch → Kibana.
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.5.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
ports:
- "9200:9200"
logstash:
image: docker.elastic.co/logstash/logstash:8.5.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
ports:
- "5000:5000"
depends_on:
- elasticsearch
kibana:
image: docker.elastic.co/kibana/kibana:8.5.0
ports:
- "5601:5601"
depends_on:
- elasticsearch
kong:
image: kong:3.5
environment:
KONG_DATABASE: off
KONG_PLUGINS: bundled,http-log
ports:
- "8000:8000"
- "8001:8001"
depends_on:
- logstashinput {
tcp {
port => 5000
codec => json
}
}
filter {
date {
match => ["timestamp", "ISO8601"]
}
if [response][status] >= 500 {
mutate {
add_tag => ["error"]
}
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "kong-logs-%{+YYYY.MM.dd}"
}
}
Проблема: Нужно трассировать запрос через Kong и несколько микросервисов.
Решение: Плагин zipkin для интеграции с Jaeger/Zipkin.
curl -X POST http://localhost:8001/plugins \
--data "name=zipkin" \
--data "config.http_endpoint=http://jaeger:9411/api/v2/spans" \
--data "config.sample_ratio=0.1" \
--data "config.include_credential=true" \
--data "config.header_type=presence" \
--data "config.tls_verify=false"Параметры:
http_endpoint — URL Zipkin/Jaeger collectorsample_ratio — доля трассируемых запросов (0.0-1.0)include_credential — включать Consumer в traceheader_type — тип заголовков (presence/b3)tls_verify — проверка TLS сертификатаKong добавляет заголовки к запросам:
| Заголовок | Описание |
|---|---|
X-B3-TraceId | ID всего trace (сквозной) |
X-B3-SpanId | ID текущей span (Kong) |
X-B3-ParentSpanId | ID родительской span |
X-B3-Sampled | 1 если trace сэмплируется |
Проблема: Нужна визуализация trace.
Решение: Jaeger All-in-One для разработки.
version: '3.8'
services:
jaeger:
image: jaegertracing/all-in-one:latest
ports:
- "5775:5775/udp"
- "6831:6831/udp"
- "6832:6832/udp"
- "5778:5778"
- "16686:16686" # UI
- "14268:14268"
- "9411:9411" # Zipkin-compatible
environment:
- COLLECTOR_ZIPKIN_HOST_PORT=:9411
kong:
image: kong:3.5
environment:
KONG_DATABASE: off
KONG_PLUGINS: bundled,zipkin
ports:
- "8000:8000"
- "8001:8001"
depends_on:
- jaegerUI Jaeger: http://localhost:16686
Проблема: Бэкенд-сервисы должны продолжать trace.
Решение: Извлечение заголовков в коде сервиса.
from opentelemetry import trace
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
propagator = TraceContextTextMapPropagator()
@app.get("/api/users")
async def get_users(request: Request):
# Извлечение context из заголовков
context = propagator.extract(carrier=request.headers)
trace.use_span(trace.get_current_span(context))
# Дальнейшая обработка автоматически будет в том же trace
return await fetch_users()const { propagation } = require('@opentelemetry/api');
app.get('/api/users', (req, res) => {
const context = propagation.extract(
api.context.active(),
req.headers
);
api.context.with(context, async () => {
// Обработка в том же trace
await fetchUsers();
});
});Проблема: Используется Datadog для мониторинга.
Решение: Плагин datadog.
curl -X POST http://localhost:8001/plugins \
--data "name=datadog" \
--data "config.host=datadog-agent" \
--data "config.port=8125" \
--data "config.metrics[]=request_count" \
--data "config.metrics[]=request_latency" \
--data "config.metrics[]=response_size" \
--data "config.constant_tags[]=service:users-api" \
--data "config.flush_interval=10"Проблема: 100% трассировка создаёт слишком много данных.
Решение: Адаптивный sampling.
# 10% запросов для production
curl -X POST http://localhost:8001/plugins \
--data "name=zipkin" \
--data "config.sample_ratio=0.1"
# 100% для ошибок (все 5xx)
# Реализуется кастомным плагиномПроблема: Логи в текстовом формате сложно анализировать.
Решение: JSON формат логов.
curl -X POST http://localhost:8001/plugins \
--data "name=http-log" \
--data "config.http_endpoint=http://logstash:5000" \
--data "config.content_type=application/json"Проблема: Нужно связать логи с trace.
Решение: Добавление trace-id в логи.
-- В кастомном плагине
function MyPlugin:log(config)
local headers = kong.request.get_headers()
local trace_id = headers["x-b3-traceid"] or "unknown"
kong.log.info("Request processed", {
trace_id = trace_id,
path = kong.request.get_path(),
status = kong.response.get_status()
})
endПроблема: Нужно мониторить соответствие SLA.
Решение: Prometheus recording rules + SLO dashboard.
# recording_rules.yml
groups:
- name: slo
interval: 30s
rules:
- record: kong_availability
expr: |
1 - (
sum(rate(kong_status{code=~"5.."}[30d]))
/
sum(rate(kong_requests_total[30d]))
)
- record: kong_latency_p99
expr: |
histogram_quantile(0.99,
sum(rate(kong_latency_request_bucket[5m])) by (le, service)
)SLO Dashboard:
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.