11 серпня 2026 р.
Логування через Loki та Grafana

Централізовані логи дають змогу бачити події всіх застосунків Kubernetes в одному місці, шукати помилки за namespace, pod або контейнером і швидко переходити від метрики до причини збою. Якщо метрики вже зібрані за попередньою інструкцією про моніторинг Kubernetes через Prometheus та Grafana, наступний логічний крок — додати Loki як сховище логів, Grafana Alloy як агент збору та Grafana як інтерфейс пошуку.
У цій інструкції розглянемо практичну схему для невеликого або середнього кластера: Loki працює в режимі Monolithic із постійним диском, Alloy читає stdout і stderr контейнерів, а Grafana підключається до Loki як datasource. Така конфігурація зрозуміла для першого запуску та не заважає надалі перейти до розподіленої архітектури.
Як працюють Loki, Alloy та Grafana
Loki часто порівнюють із Prometheus, але для логів. Він не створює повнотекстовий індекс для кожного рядка. Натомість Loki індексує набір міток, наприклад `cluster`, `namespace`, `pod`, `container` і `app`, а самі записи зберігає окремо. Через це система потребує менше ресурсів, якщо мітки спроєктовані правильно.
Grafana Alloy запускається в кластері, знаходить pod-и через Kubernetes API, читає їхні логи та надсилає записи до Loki. Grafana виконує запити мовою LogQL, будує таблиці й графіки та дозволяє пов'язувати логи з метриками на одному дашборді.
Для невеликої інсталяції достатньо одного Loki в режимі Monolithic. Усі його внутрішні компоненти працюють в одному процесі, тому конфігурацію простіше підтримувати. Для великого навантаження та високої доступності варто планувати Distributed-режим, кілька реплік і сумісне з S3 об'єктне сховище. Режим Simple Scalable більше не варто обирати для нової інсталяції.
Перед початком перевірте, що в кластері є StorageClass, DNS між namespace та встановлені `kubectl` і Helm. Для супроводу кластера, оновлень і спостережуваності також можна залучити послугу DevOps.
Встановлення Loki через Helm
Створіть окремий namespace та додайте репозиторій чартів. У робочому середовищі зафіксуйте перевірену версію чарта у змінній, щоб випадкове оновлення залежностей не змінило інсталяцію.
kubectl create namespace logging
helm repo add grafana-community https://grafana-community.github.io/helm-charts
helm repo update
helm search repo grafana-community/loki --versions | head
export LOKI_CHART_VERSION="ВКАЖІТЬ_ПЕРЕВІРЕНУ_ВЕРСІЮ"
helm show values grafana-community/loki \
--version "$LOKI_CHART_VERSION" > loki-default-values.yamlСтворіть файл `loki-values.yaml`. Приклад нижче використовує файлове сховище та одну репліку, тому підходить для навчального, тестового або невеликого внутрішнього кластера. Назву StorageClass і розмір диска змініть відповідно до своєї інфраструктури.
deploymentMode: Monolithic
loki:
auth_enabled: false
commonConfig:
replication_factor: 1
schemaConfig:
configs:
- from: "2024-04-01"
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: loki_index_
period: 24h
monolithic:
replicas: 1
persistence:
enabled: true
storageClass: standard
size: 30Gi
read:
replicas: 0
backend:
replicas: 0
write:
replicas: 0
chunksCache:
enabled: false
resultsCache:
enabled: falseВстановіть реліз і дочекайтеся готовності pod-ів:
helm upgrade --install loki grafana-community/loki \
--namespace logging \
--version "$LOKI_CHART_VERSION" \
--values loki-values.yaml \
--wait --timeout 10m
kubectl -n logging get pods,pvc,svc
kubectl -n logging logs statefulset/loki --tail=100Не використовуйте тимчасовий диск для даних, які потрібно зберегти після перезапуску. Для production-кластера замініть filesystem на об'єктне сховище, увімкніть потрібну кількість реплік і перевірте резервування даних. `auth_enabled: false` допустимий лише тоді, коли Loki не відкритий у публічну мережу та доступ контролюється всередині кластера.
Збір логів Kubernetes через Grafana Alloy
Promtail довго був типовим агентом Loki, але для нової конфігурації доцільно використовувати Grafana Alloy. Він виконує discovery ресурсів Kubernetes, додає корисні мітки, обробляє записи й передає їх через HTTP endpoint Loki.
Нижче наведено базову конфігурацію Alloy. Вона знаходить pod-и, залишає низькокардинальні мітки та надсилає записи через сервіс gateway. Ім'я сервісу обов'язково звірте командою `kubectl -n logging get svc`.
discovery.kubernetes "pods" {
role = "pod"
}
discovery.relabel "pod_logs" {
targets = discovery.kubernetes.pods.targets
rule {
source_labels = ["__meta_kubernetes_namespace"]
target_label = "namespace"
}
rule {
source_labels = ["__meta_kubernetes_pod_name"]
target_label = "pod"
}
rule {
source_labels = ["__meta_kubernetes_pod_container_name"]
target_label = "container"
}
rule {
source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_name"]
target_label = "app"
}
}
loki.source.kubernetes "pod_logs" {
targets = discovery.relabel.pod_logs.output
forward_to = [loki.process.pod_logs.receiver]
}
loki.process "pod_logs" {
stage.static_labels {
values = { cluster = "main" }
}
forward_to = [loki.write.default.receiver]
}
loki.write "default" {
endpoint {
url = "http://loki-gateway.logging.svc.cluster.local/loki/api/v1/push"
}
}Збережіть її у `alloy-config.alloy`, підставте до values-файлу актуального Alloy chart і встановіть агент як DaemonSet. Спочатку перегляньте стандартні values саме зафіксованої версії: назви параметрів чартів можуть змінюватися.
helm search repo grafana-community/alloy --versions | head
export ALLOY_CHART_VERSION="ВКАЖІТЬ_ПЕРЕВІРЕНУ_ВЕРСІЮ"
helm show values grafana-community/alloy \
--version "$ALLOY_CHART_VERSION" > alloy-default-values.yaml
kubectl -n logging get pods -l app.kubernetes.io/name=alloy
kubectl -n logging logs daemonset/alloy --tail=100Агенту потрібні RBAC-права на читання метаданих pod-ів, namespace і node. Офіційний chart створює необхідні ресурси, але власні обмежені ролі слід перевірити окремо. Не додавайте як мітки `request_id`, час, UUID користувача або інші майже унікальні значення: висока кардинальність різко збільшує індекс. Такі поля краще залишати в тексті JSON або structured metadata.
Підключення Loki до Grafana та запити LogQL
Якщо Grafana вже встановлена через kube-prometheus-stack, додайте Loki до її values як додаткове джерело даних. Внутрішній URL не потребує Ingress і залишається доступним лише з кластера.
grafana:
additionalDataSources:
- name: Loki
type: loki
access: proxy
url: http://loki-gateway.logging.svc.cluster.local
isDefault: false
editable: falseЗастосуйте той самий Helm release і той самий основний values-файл, які використовували під час початкової інсталяції Grafana. Не запускайте upgrade лише з коротким фрагментом вище, якщо інші параметри релізу не збережені: Helm може повернути їх до значень за замовчуванням.
У Grafana відкрийте Explore, виберіть datasource Loki та почніть із простого селектора:
{cluster="main", namespace="production"}Фільтр знаходить помилки без створення окремої мітки для рівня логування:
{namespace="production", app="api"} | json | level="error"Щоб порахувати кількість помилок за п'ять хвилин і згрупувати результат за pod, використайте metric query:
sum by (pod) (
count_over_time({namespace="production"} |= "error" [5m])
)Спочатку звужуйте потік індексованими мітками, а потім застосовуйте текстові або JSON-фільтри. Це зменшує обсяг даних, який Loki має прочитати. Для регулярної діагностики збережіть запити в dashboard і додайте посилання з панелей Prometheus на відповідний часовий діапазон у Loki.
Retention, безпека та типові проблеми
До запуску визначте строк зберігання логів. Він залежить від доступного диска, швидкості надходження даних і вимог до аудиту. Контролюйте заповнення PVC, помилки запису, затримку ingestion та ресурси самого Loki. Зменшення retention не замінює моніторинг диска, а збільшення PVC не замінює політику очищення.
Якщо в Explore немає записів, перевіряйте шлях послідовно: Alloy знайшов pod-и, агент читає файли, endpoint доступний із його namespace, Loki приймає push, datasource відповідає. Корисні команди:
kubectl -n logging get pods
kubectl -n logging logs daemonset/alloy --since=10m
kubectl -n logging logs statefulset/loki --since=10m
kubectl -n logging port-forward svc/loki-gateway 3100:80
curl -fsS http://127.0.0.1:3100/readyПомилка `429` зазвичай означає перевищення лімітів або надто інтенсивний потік. `401` чи `403` вказують на автентифікацію, проксі або неправильний tenant. Тайм-аути часто пов'язані з DNS, NetworkPolicy чи невірною назвою сервісу. Якщо один запит споживає забагато ресурсів, звузьте часовий діапазон і селектор міток.
Не публікуйте gateway Loki без автентифікації. Доступ до Grafana захистіть ролями, TLS та окремими обліковими записами, а секрети маскуйте ще на етапі обробки в Alloy. Команда моніторингу сайтів і серверів допоможе налаштувати сповіщення, контроль ресурсів і регулярну перевірку всього контуру.
Що варто зробити після запуску
Після інсталяції переконайтеся, що логи надходять з усіх потрібних namespace, перезапуск pod-а не видаляє дані Loki, а збережені LogQL-запити швидко працюють на реальному часовому діапазоні. Додайте алерти на відсутність логів від критичного застосунку, помилки ingestion, заповнення сховища та недоступність datasource.
Почніть із невеликого набору стабільних міток, виміряйте фактичний потік і лише після цього змінюйте retention або масштабуйте компоненти. У результаті Grafana стане єдиною точкою для метрик і логів, а пошук причини інциденту скоротиться від ручного перегляду окремих pod-ів до одного точного запиту LogQL.