Grafana Loki: алерты с Ruler и labels из логов

Thank you for reading this post, don't forget to subscribe!

Доку­мен­та­ция по алер­там в Loki – Rules and the Ruler.

  • созда­ём файл с алер­та­ми в Prometheus-like формате
  • под­клю­ча­ем его к ruler
  • ruler пар­сит логи по задан­ным в кон­фи­ге выра­же­ни­ям, и пушит Alertmanager, пере­да­вая ему алерт

Алер­ты будем опи­сы­вать в ConfigMap, кото­рый потом под­клю­чим к поду с Ruler.

Тестовый под для OOM-Killed

Поте­стим на сра­ба­ты­ва­ние OOM Killed, поэто­му созда­дим под с явно зани­жен­ны­ми лими­та­ми, кото­рый будет уби­вать­ся “на взлёте”:

В nodeSelector зада­ём имя ноды, что бы было про­ще искать в Локи.

При стар­те это­го пода Kubernetes будет его уби­вать из-за пре­вы­ше­ния лими­тов, а journald на WorkerNode будет запи­сы­вать собы­тие в систем­ный жур­нал, кото­рый соби­ра­ет­ся promtail:

Запус­ка­ем наш под:

kk apply -f test-oom.yaml
pod/oom-test created

 

И про­ве­ря­ем логи Локи:

теперь у нас есть oom-killed под для тестов – давай­те фор­ми­ро­вать запрос для буду­ще­го алерта.

Формирование запроса в Loki

В логах мы смот­ре­ли по {hostname="eks-node-dev_data_services-i-081719890438d467f"} |~ ".*OOM-killed.*" – исполь­зу­ем его же для тесто­во­го алерта.

Сна­ча­ла про­ве­рим что нам нари­су­ет сама Локи – исполь­зу­ем rate() и sum(), см. Log range aggregations:

Создание алерта для Loki Ruler

Созда­ём файл с ConfigMap:

Деп­ло­им его:

kk apply -f rule-cm.yaml
configmap/rules-alerts created

Ruler и ConfigMap volume

Далее, нам надо под­клю­чить этот ConfigMap в под с ruler в ката­лог, кото­рый ука­зан в кон­фи­ге Loki для ком­по­нен­та ruler:

Ruler у нас рабо­та­ет в loki-read подах – откры­ва­ем их StatefulSet:

kk -n monitoring edit sts loki-read

 

Опи­сы­ва­ем новый volume:


И его мап­пинг в под по пути /var/loki/rules/fake/rules.yaml, где fake – это tenant_id, если исполь­зу­ет­ся: (рас­ска­жу в посте про запуск Loki):

В subPath ука­зы­ва­ем key из ConfigMap, что бы под­клю­чить имен­но как файл.

Настройка Ruler alerting

Нахо­дим Alertmanager URL:

В ConfigMap Loki для ruler ука­зы­ва­ем этот адрес:


Все пара­мет­ры для ruler – тут>>>.

Откры­ва­ем себе доступ к Alertmanager, что бы про­ве­рять алерты:

kk -n monitoring port-forward svc/prometheus-kube-prometheus-alertmanager 9093:9093

Рестар­тим поды loki-read, мож­но про­сто через kubectl delete pod, и про­ве­ря­ем их логи:


Про­ве­ря­ем Алер­ты в Алерт­ме­не­дже­ре – http://localhost:9093:

Loki и дополнительные labels

В алер­тах хочет­ся выво­дить немно­го боль­ше инфор­ма­ции, чем про­сто сооб­ще­ние “Test Loki OOM Killer Alert”, к при­ме­ру – отоб­ра­зить имя пода, кото­рый был убит.

Добавление labels в Promtail

Пер­вый вари­ант – это созда­вать новые лейб­лы ещё на эта­пе сбо­ра логов, в самом Promtail через pipeline_stages,  напри­мер так:

Тут я для тестов созда­вал нове новые лейб­лы, кото­рые под­клю­ча­лись к логам – source и level.

Дру­гой вари­ант с Promtail – исполь­зуя static_labels.

Но тут есть про­бле­ма: так как Loki на каж­дый набор лей­бл созда­ёт отдель­ный стрим, для кото­ро­го созда­ют­ся отдель­ные индек­сы и бло­ки дан­ных, то в резуль­та­те полу­чим во-пер­вых про­бле­мы с про­из­во­ди­тель­но­стью, во-вто­рых – со сто­и­мо­стью, т.к. на каж­дый индекс и блок дан­ных будут выпол­нять­ся запро­сы чте­ния-запи­си в shared store, в кон­крет­но нашем слу­чае это AWS S3, где за каж­дый запрос при­хо­дит­ся пла­тить деньги.

Добавление labels из запросов в Loki

Вме­сто это­го, мы можем созда­вать новый лейб­лы пря­мо из запро­са с помо­щью самой Loki.

Возь­мём запись из лога, в кото­рой гово­рит­ся о сра­ба­ты­ва­нии OOM Killer:

Тут у нас есть поле pod с име­нем пода, кото­рый был убит – pod="default/oom-test".

Исполь­зу­ем regex в виде pod=".*/(?P<pod>[a-zA-Z].*)".*, что бы создать Named Capturing Group, про­ве­ря­ем напри­мер на https://regex101.com:

Допол­ня­ем выбор­ку в Loki:


И в логе полу­ча­ем лей­б­лу pod  со зна­че­ни­ем “oom-test“:

Про­ве­ря­ем запрос алер­та с sum() и rate():


Обнов­ля­ем алерт – доба­вим description в кото­ром исполь­зу­ем {{ $labels.pod }}:


Ждём его срабатывание:

И в Слаке:

Grafana Loki и ошибки 502 и 504

Сей­час не полу­ча­ет­ся заре­п­ро­дью­сить, но ино­гда Grafana не может дождать­ся отве­та от Loki, и выпол­не­ние запро­са пада­ет с ошиб­ка­ми 502 или 504.

Есть тред в Girthub, мне помог­ло уве­ли­че­ние тай­мау­тов HTTP в Loki ConfigMap: