Стадия жизненного цикла модуля: Общедоступная версия
У модуля есть требования для установки
Чтение логов из всех подов кластера и направление их в Loki
apiVersion: deckhouse.io/v1alpha2
kind: ClusterLoggingConfig
metadata:
name: all-logs
spec:
type: KubernetesPods
destinationRefs:
- loki-storage
---
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: loki-storage
spec:
type: Loki
loki:
endpoint: http://loki.loki:3100Чтобы направить логи в кластерный модуль loki, укажите d8-loki в параметре destinationRefs ClusterLoggingConfig. Дополнительные примеры можно найти в документации.
Чтение логов подов из указанного неймспейса с указанным label и перенаправление одновременно в Loki и Elasticsearch
Чтение логов подов из неймспейса whispers только с label app=booking и перенаправление одновременно в Loki и Elasticsearch:
apiVersion: deckhouse.io/v1alpha2
kind: ClusterLoggingConfig
metadata:
name: whispers-booking-logs
spec:
type: KubernetesPods
kubernetesPods:
namespaceSelector:
labelSelector:
matchExpressions:
- key: "kubernetes.io/metadata.name"
operator: In
values: [whispers]
labelSelector:
matchLabels:
app: booking
destinationRefs:
- loki-storage
- es-storage
---
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: loki-storage
spec:
type: Loki
loki:
endpoint: http://loki.loki:3100
---
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: es-storage
spec:
type: Elasticsearch
elasticsearch:
endpoint: http://192.168.1.1:9200
index: logs-%F
auth:
strategy: Basic
user: elastic
password: c2VjcmV0IC1uCg==Создание source в неймспейсе и чтение логов всех подов в этом неймспейсе с направлением их в Loki
Следующий pipeline создает source в неймспейсе test-whispers, читает логи всех подов в этом неймспейсе и пишет их в Loki:
apiVersion: deckhouse.io/v1alpha1
kind: PodLoggingConfig
metadata:
name: whispers-logs
namespace: tests-whispers
spec:
clusterDestinationRefs:
- loki-storage
---
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: loki-storage
spec:
type: Loki
loki:
endpoint: http://loki.loki:3100Чтение только подов в указанном неймспейсе и с определенным label
Пример чтения только подов, имеющих label app=booking, в неймспейсе test-whispers:
apiVersion: deckhouse.io/v1alpha1
kind: PodLoggingConfig
metadata:
name: whispers-logs
namespace: tests-whispers
spec:
labelSelector:
matchLabels:
app: booking
clusterDestinationRefs:
- loki-storage
---
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: loki-storage
spec:
type: Loki
loki:
endpoint: http://loki.loki:3100Переход с Promtail на Log-Shipper
В ранее используемом URL Loki требуется убрать путь /loki/api/v1/push.
Vector сам добавит этот путь при работе с Loki.
Работа с Grafana Cloud
Данная документация подразумевает, что у Вас уже создан ключ API.
Для начала Вам потребуется закодировать в base64 Ваш токен доступа к Grafana Cloud.

echo -n "<YOUR-GRAFANACLOUD-TOKEN>" | base64 -w0Затем нужно создать ClusterLogDestination
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: loki-storage
spec:
loki:
auth:
password: PFlPVVItR1JBRkFOQUNMT1VELVRPS0VOPg==
strategy: Basic
user: "<YOUR-GRAFANACLOUD-USER>"
endpoint: <YOUR-GRAFANACLOUD-URL> # Например https://logs-prod-us-central1.grafana.net или https://logs-prod-eu-west-0.grafana.net
type: LokiТеперь можно создать PodLogginConfig или ClusterPodLoggingConfig и отправлять логи в Grafana Cloud.
Добавление Loki в Deckhouse Grafana
Вы можете работать с Loki из встроенной в Deckhouse Grafana. Достаточно добавить GrafanaAdditionalDatasource.
apiVersion: deckhouse.io/v1
kind: GrafanaAdditionalDatasource
metadata:
name: loki
spec:
access: Proxy
basicAuth: false
jsonData:
maxLines: 5000
timeInterval: 30s
type: loki
url: http://loki.loki:3100Поддержка Elasticsearch < 6.X
Для Elasticsearch < 6.0 нужно включить поддержку doc_type индексов. Сделать это можно следующим образом:
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: es-storage
spec:
type: Elasticsearch
elasticsearch:
endpoint: http://192.168.1.1:9200
docType: "myDocType" # Укажите значение здесь. Оно не должно начинаться с '_'.
auth:
strategy: Basic
user: elastic
password: c2VjcmV0IC1uCg==Шаблон индекса для Elasticsearch
Существует возможность отправлять сообщения в определенные индексы на основе метаданных с помощью шаблонов индексов:
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: es-storage
spec:
type: Elasticsearch
elasticsearch:
endpoint: http://192.168.1.1:9200
index: "k8s-{{ namespace }}-%F"В приведенном выше примере для каждого неймспейса Kubernetes будет создан свой индекс в Elasticsearch.
Эта функция также хорошо работает в комбинации с extraLabels:
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: es-storage
spec:
type: Elasticsearch
elasticsearch:
endpoint: http://192.168.1.1:9200
index: "k8s-{{ service }}-{{ namespace }}-%F"
extraLabels:
service: "{{ service_name }}"В результате выполняются следующие изменения:
- Если сообщение имеет формат JSON, поле
service_nameэтого документа JSON перемещается на уровень метаданных. - Новое поле метаданных
serviceиспользуется в шаблоне индекса.
Пример интеграции со Splunk
Существует возможность отсылать события из Deckhouse в Splunk. Для настройки Splunk выполните следующие действия:
- Endpoint должен быть таким же, как имя Вашего экземпляра Splunk с портом
8088и без указания пути, напримерhttps://prd-p-xxxxxx.splunkcloud.com:8088. - Чтобы добавить token для доступа, откройте пункт меню
Setting->Data inputs, добавьте новыйHTTP Event Collectorи скопируйте token. - Укажите индекс Splunk для хранения логов, например
logs.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: splunk
spec:
type: Splunk
splunk:
endpoint: https://prd-p-xxxxxx.splunkcloud.com:8088
token: xxxx-xxxx-xxxx
index: logs
tls:
verifyCertificate: false
verifyHostname: falsedestination не поддерживает лейблы пода для индексирования. Рассмотрите возможность добавления нужных лейблов с помощью опции extraLabels.
extraLabels:
pod_label_app: '{{ pod_labels.app }}'Простой пример Logstash
Чтобы отправлять логи в Logstash, на стороне Logstash должен быть настроен входящий поток tcp и его кодек должен быть json.
Пример минимальной конфигурации Logstash:
input {
tcp {
port => 12345
codec => json
}
}
output {
stdout { codec => json }
}Пример манифеста ClusterLogDestination:
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: logstash
spec:
type: Logstash
logstash:
endpoint: logstash.default:12345Syslog
Следующий пример показывает, как отправлять сообщения через сокет по протоколу TCP в формате syslog:
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: rsyslog
spec:
type: Socket
socket:
mode: TCP
address: 192.168.0.1:3000
encoding:
codec: Syslog
extraLabels:
syslog.severity: "alert"
# Поле request_id должно присутствовать в сообщении.
syslog.message_id: "{{ request_id }}"Пример интеграции с Graylog
Убедитесь, что в Graylog настроен входящий поток для приема сообщений по протоколу TCP на указанном порту. Пример манифеста для интеграции с Graylog:
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: test-socket2-dest
spec:
type: Socket
socket:
address: graylog.svc.cluster.local:9200
mode: TCP
encoding:
codec: GELFЛоги в CEF формате
Существует способ формировать логи в формате CEF, используя codec: CEF, с переопределением cef.name и cef.severity по значениям из поля message (лога приложения) в формате JSON.
В примере ниже app и log_level это ключи содержащие значения для переопределения:
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: siem-kafka
spec:
extraLabels:
cef.name: '{{ app }}'
cef.severity: '{{ log_level }}'
type: Kafka
kafka:
bootstrapServers:
- my-cluster-kafka-brokers.kafka:9092
encoding:
codec: CEF
tls:
verifyCertificate: false
verifyHostname: true
topic: logsТак же можно вручную задать свои значения:
extraLabels:
cef.name: 'TestName'
cef.severity: '1'Сбор событий Kubernetes
События Kubernetes могут быть собраны log-shipper’ом, если events-exporter включен в настройках модуля extended-monitoring.
Включите events-exporter, изменив параметры модуля extended-monitoring:
apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
name: extended-monitoring
spec:
version: 1
settings:
events:
exporterEnabled: trueВыложите в кластер следующий ClusterLoggingConfig, чтобы собирать сообщения с пода events-exporter:
apiVersion: deckhouse.io/v1alpha2
kind: ClusterLoggingConfig
metadata:
name: kubernetes-events
spec:
type: KubernetesPods
kubernetesPods:
labelSelector:
matchLabels:
app: events-exporter
namespaceSelector:
labelSelector:
matchExpressions:
- key: "kubernetes.io/metadata.name"
operator: In
values: [d8-monitoring]
destinationRefs:
- loki-storageФильтрация логов
Логи можно фильтровать с помощью следующих фильтров:
labelFilter— применяется к метаданным, например имени контейнера (container), неймспейсу (namespace) или имени пода (pod_name);logFilter— применяется к полям самого сообщения, если оно в JSON-формате.
Сборка логов только для контейнера nginx
apiVersion: deckhouse.io/v1alpha2
kind: ClusterLoggingConfig
metadata:
name: nginx-logs
spec:
type: KubernetesPods
labelFilter:
- field: container
operator: In
values: [nginx]
destinationRefs:
- loki-storageСборка логов без строки, содержащей GET /status" 200
apiVersion: deckhouse.io/v1alpha2
kind: ClusterLoggingConfig
metadata:
name: all-logs
spec:
type: KubernetesPods
destinationRefs:
- loki-storage
labelFilter:
- field: message
operator: NotRegex
values:
- .*GET /status" 200$Аудит событий kubelet’а
apiVersion: deckhouse.io/v1alpha2
kind: ClusterLoggingConfig
metadata:
name: kubelet-audit-logs
spec:
type: File
file:
include:
- /var/log/kube-audit/audit.log
logFilter:
- field: userAgent
operator: Regex
values: ["kubelet.*"]
destinationRefs:
- loki-storageСистемные логи Deckhouse
apiVersion: deckhouse.io/v1alpha2
kind: ClusterLoggingConfig
metadata:
name: system-logs
spec:
type: File
file:
include:
- /var/log/syslog
labelFilter:
- field: message
operator: Regex
values:
- .*d8-kubelet-forker.*
- .*containerd.*
- .*bashible.*
- .*kernel.*
destinationRefs:
- loki-storageЕсли Вам нужны только логи одного пода или малой группы подов, постарайтесь использовать настройки kubernetesPods, чтобы сузить количество читаемых файлов. Фильтры необходимы только для высокогранулярной настройки.
Настройка равномерности чтения при множестве активно растущих файлов
apiVersion: deckhouse.io/v1alpha2
kind: ClusterLoggingConfig
metadata:
name: many-growing-files
spec:
type: File
file:
include:
- /var/log/myapp/*.log
maxReadBytes: 65536
destinationRefs:
- loki-storageПараметр maxReadBytes ограничивает количество байт, считываемых из одного файла за один проход, прежде чем Vector перейдёт к следующему подходящему файлу. Уменьшите значение, если несколько файлов растут быстро одновременно и чтение нужно распределить между ними равномернее. Большие значения ускоряют вычитывание накопившегося отставания, но увеличивают потребление памяти. Если параметр не задан, применяется встроенное значение Vector (2048 байт).
Тот же параметр доступен для источника kubernetesPods (spec.kubernetesPods.maxReadBytes в ClusterLoggingConfig) и для PodLoggingConfig (spec.maxReadBytes). Для логов подов oldestFirst по умолчанию равен true: более новые файлы не читаются, пока не дочитаны более старые, и maxReadBytes задаёт только размер одной порции чтения. Чтобы распределить чтение между подами, задайте также oldestFirst: false:
apiVersion: deckhouse.io/v1alpha1
kind: PodLoggingConfig
metadata:
name: many-growing-pods
spec:
labelSelector:
matchLabels:
app: chatty-app
maxReadBytes: 65536
oldestFirst: false
clusterDestinationRefs:
- loki-storageПриоритетное чтение более старых файлов логов
apiVersion: deckhouse.io/v1alpha2
kind: ClusterLoggingConfig
metadata:
name: drain-old-files-first
spec:
type: File
file:
include:
- /var/log/myapp/*.log
oldestFirst: true
destinationRefs:
- loki-storageПараметр oldestFirst заставляет Vector в первую очередь вычитывать самые старые из подходящих файлов, прежде чем переходить к более новым, вместо равномерного распределения пропускной способности чтения между всеми файлами. Это полезно для файлов логов с временными метками в имени, когда старые файлы должны быть полностью обработаны (и затем удалены при ротации), прежде чем начнётся чтение новых. Для источника file по умолчанию (если параметр не задан) используется значение false.
Тот же параметр доступен для источника kubernetesPods (spec.kubernetesPods.oldestFirst в ClusterLoggingConfig) и для PodLoggingConfig (spec.oldestFirst) — там по умолчанию (если параметр не задан) используется значение true, как и во встроенном источнике Vector kubernetes_logs. Установите false, чтобы вернуться к равномерному чтению по всем отслеживаемым подам:
apiVersion: deckhouse.io/v1alpha1
kind: PodLoggingConfig
metadata:
name: many-growing-pods
spec:
labelSelector:
matchLabels:
app: chatty-app
oldestFirst: false
clusterDestinationRefs:
- loki-storageПреобразование логов
В ресурсе ClusterLogDestination можно задать цепочку трансформаций по порядку. Поддерживаются следующие действия: ParseMessage, ReplaceKeys, ReplaceValue, AddLabels, DropLabels, DropEvent.
Преобразование логов в структурированный объект
Вы можете использовать трансформацию ParseMessage,
чтобы преобразовать строку в поле message в структурированный объект.
Для формата String задаётся регулярное выражение с именованными группами и карта setLabels. Ключи результата сопоставляются с группами через шаблоны {{ имя_группы }}.
При использовании нескольких трансформаций ParseMessage, преобразование строки должно выполняться последним.
В parseMessage.targetLabel нельзя задать путь .parsed_data.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: string-to-json
spec:
# ...
transformations:
- action: ParseMessage
parseMessage:
sourceFormat: String
string:
regex: "^(?P<msg>.*)$"
setLabels:
msg: "{{ msg }}"Пример изначальной записи в логе:
/docker-entrypoint.sh: Configuration complete; ready for start upРезультат преобразования:
{... "message": {
"msg": "/docker-entrypoint.sh: Configuration complete; ready for start up"
}
}Преобразование логов в формате Klog в структурированный объект
Вы можете использовать трансформацию ParseMessage,
чтобы распарсить логи в формате Klog и преобразовать их в структурированный объект.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: klog-to-json
spec:
# ...
transformations:
- action: ParseMessage
parseMessage:
sourceFormat: KlogПример изначальной записи в логе:
I0505 17:59:40.692994 28133 klog.go:70] hello from klogРезультат преобразования:
{... "message": {
"file":"klog.go",
"id":28133,
"level":"info",
"line":70,
"message":"hello from klog",
"timestamp":"2025-05-05T17:59:40.692994Z"
}
}Преобразование логов в формате Syslog в структурированный объект
Вы можете использовать трансформацию ParseMessage,
чтобы распарсить логи в формате Syslog и преобразовать их в структурированный объект.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: syslog-to-json
spec:
# ...
transformations:
- action: ParseMessage
parseMessage:
sourceFormat: SysLogПример изначальной записи в логе:
<13>1 2020-03-13T20:45:38.119Z dynamicwireless.name non 2426 ID931 [exampleSDID@32473 iut="3" eventSource= "Application" eventID="1011"] Try to override the THX port, maybe it will reboot the neural interface!Результат преобразования:
{... "message": {
"appname": "non",
"exampleSDID@32473": {
"eventID": "1011",
"eventSource": "Application",
"iut": "3"
},
"facility": "user",
"hostname": "dynamicwireless.name",
"message": "Try to override the THX port, maybe it will reboot the neural interface!",
"msgid": "ID931",
"procid": 2426,
"severity": "notice",
"timestamp": "2020-03-13T20:45:38.119Z",
"version": 1
}}Преобразование логов в формате CLF в структурированный объект
Вы можете использовать трансформацию ParseMessage,
чтобы распарсить логи в формате CLF и преобразовать их в структурированный объект.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: clf-to-json
spec:
# ...
transformations:
- action: ParseMessage
parseMessage:
sourceFormat: CLFПример изначальной записи в логе:
127.0.0.1 bob frank [10/Oct/2000:13:55:36 -0700] \"GET /apache_pb.gif HTTP/1.0\" 200 2326Результат преобразования:
{... "message": {
"host": "127.0.0.1",
"identity": "bob",
"message": "GET /apache_pb.gif HTTP/1.0",
"method": "GET",
"path": "/apache_pb.gif",
"protocol": "HTTP/1.0",
"size": 2326,
"status": 200,
"timestamp": "2000-10-10T20:55:36Z",
"user": "frank"
}}Преобразование логов в формате logfmt в структурированный объект
Вы можете использовать трансформацию ParseMessage,
чтобы распарсить логи в формате logfmt и преобразовать их в структурированный объект.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: logfmt-to-json
spec:
# ...
transformations:
- action: ParseMessage
parseMessage:
sourceFormat: LogfmtПример изначальной записи в логе:
@timestamp=\"Sun Jan 10 16:47:39 EST 2021\" level=info msg=\"Stopping all fetchers\" tag#production=stopping_fetchers id=ConsumerFetcherManager-1382721708341 module=kafka.consumer.ConsumerFetcherManagerРезультат преобразования:
{... "message": {
"@timestamp": "Sun Jan 10 16:47:39 EST 2021",
"id": "ConsumerFetcherManager-1382721708341",
"level": "info",
"module": "kafka.consumer.ConsumerFetcherManager",
"msg": "Stopping all fetchers",
"tag#production": "stopping_fetchers"
}}Парсинг JSON и уменьшение вложенности
Вы можете использовать трансформацию ParseMessage, чтобы парсить записи в логах в формате JSON.
С помощью параметра depth можно контролировать глубину вложенности.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: parse-json
spec:
# ...
transformations:
- action: ParseMessage
parseMessage:
sourceFormat: JSON
json:
depth: 1Пример изначальной записи в логе:
{"level" : { "severity": "info" },"msg" : "fetching.module.release"}Результат преобразования:
{... "message": {
"level" : "{ \"severity\": \"info\" }",
"msg" : "fetching.module.release"
}
}Пример парсинга записей смешанных форматов в объект
При указании нескольких трансформаций ParseMessage они применяются к каждой входящей записи по порядку сверху вниз. Сначала запись проверяется первой трансформацией: если парсинг не удался, применяется следующая трансформация. При успешном парсинге содержимое поля message становится структурированным объектом, и следующие трансформации к этой записи уже не применяются. Поэтому сначала следует указывать преобразования для конкретных форматов, например JSON, а универсальное преобразование строки — последним. Если поставить преобразование строки выше, оно может успешно обработать запись, предназначенную для JSON или другого формата.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: parse-json
spec:
# ...
transformations:
- action: ParseMessage
parseMessage:
sourceFormat: JSON
- action: ParseMessage
parseMessage:
sourceFormat: Klog
- action: ParseMessage
parseMessage:
sourceFormat: String
string:
regex: "^(?P<text>.*)$"
setLabels:
text: "{{ text }}"Пример изначальной записи в логе:
/docker-entrypoint.sh: Configuration complete; ready for start up
{"level" : { "severity": "info" },"msg" : "fetching.module.release"}
I0505 17:59:40.692994 28133 klog.go:70] hello from klogРезультат преобразования:
{... "message": {
"text": "/docker-entrypoint.sh: Configuration complete; ready for start up"
}
}
{... "message": {
"level" : "{ "severity": "info" }",
"msg" : "fetching.module.release"
}
}
{... "message": {
"file":"klog.go",
"id":28133,
"level":"info",
"line":70,
"message":"hello from klog",
"timestamp":"2025-05-05T17:59:40.692994Z"
}
}Замена лейблов
Вы можете использовать трансформацию ReplaceKeys, чтобы заменить source на target в заданных ключах лейблов.
Перед применением трансформации ReplaceKeys к полю message или его вложенным полям необходимо преобразовать запись лога в структурированный объект с помощью трансформации ParseMessage.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: replace-dot
spec:
# ...
transformations:
- action: ReplaceKeys
replaceKeys:
source: "."
target: "_"
labels:
- .pod_labelsПример изначальной записи в логе:
{"msg" : "fetching.module.release"} # Лейбл пода pod.app=testРезультат преобразования:
{... "message": {
"msg" : "fetching.module.release"
},
"pod_labels": {
"pod_app": "test"
}
}Замена подстрок в строковых полях
Трансформация ReplaceValue заменяет вхождения регулярного выражения source в скалярных строковых полях. В target можно задать литерал или шаблон с именованными группами {{ имя }} из source.
Если замена нужна для поля внутри структурированного message, сначала примените ParseMessage.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: redact-digits
spec:
# ...
transformations:
- action: ReplaceValue
replaceValue:
source: \d+
target: REDACTED
labels:
- .messageПример изначальной записи в логе:
user id 12345 connected from 10.0.0.1Результат преобразования:
{... "message": "user id REDACTED connected from REDACTED"
}Добавление лейблов из литералов и шаблонов
Трансформация AddLabels добавляет поля со статическими значениями или шаблонами вида {{ .pod_labels.app }}. Трансформации выполняются после применения extraLabels. Если имена лейблов совпадают, у значения из AddLabels будет приоритет.
Поле when содержит необязательный список условий, объединяемых логическим «И». Слева в условии указывается путь к полю записи лога — строка с ведущей точкой и сегментами через точку (например .namespace, .pod_labels.app, .message.level). Каждый элемент списка может быть одним из следующих типов:
- сравнение значения —
.namespace == "production". Поддерживаются операторы==,!=,=~и!=~; - проверка наличия поля — в строке условия указывается только путь без оператора, например,
.pod_labels.team(поле должно существовать); - проверка отсутствия поля —
!.pod_labels.legacy.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: add-env-from-pod
spec:
# ...
transformations:
- action: AddLabels
addLabels:
when:
- '.namespace == "production"'
setLabels:
.env: prod
.source_app: "{{ .pod_labels.app }}"Результат преобразования для события в неймспейсе production с лейблом пода app=api:
{..."namespace": "production", "pod_labels": { "app": "api" } "env": "prod", "source_app": "api", ...
}Удаление событий
Трансформация DropEvent удаляет событие лога, если истинны все условия из when. Поле when имеет тот же синтаксис, что и в AddLabels, условия объединяются логическим «И». Условие на отсутствующем поле ложно, поэтому событие остаётся.
Трансформация выполняется на своей позиции в списке и видит поля, добавленные предыдущими трансформациями. В отличие от logFilter и labelFilter в ClusterLoggingConfig, которые фильтруют на источнике для всех хранилищ, DropEvent действует только для того хранилища, где задан.
apiVersion: deckhouse.io/v1alpha2
kind: ClusterLogDestination
metadata:
name: drop-user-events
spec:
# ...
transformations:
- action: AddLabels
addLabels:
when:
- ".message =~ 'AddUser'"
setLabels:
.action: adduser
- action: AddLabels
addLabels:
when:
- ".message =~ 'DelUser'"
setLabels:
.action: deluser
- action: DropEvent
dropEvent:
when:
- ".action"События, в message которых есть AddUser или DelUser, получают лейбл action и удаляются; остальные события отправляются без изменений.
Удаление лейблов
Вы можете использовать трансформацию DropLabels, чтобы удалить заданные лейблы из записей логов. У каждого элемента списка dropLabels.labels есть поле label (путь) и опционально keepKeys. Если для элемента задан keepKeys, поле label должно указывать на объект; внутри него удаляются все вложенные ключи, кроме перечисленных в keepKeys (имена без ведущей точки). Если keepKeys у элемента не задан — путь из label удаляется целиком.
Перед применением трансформации DropLabels к полю message или его вложенным полям необходимо преобразовать запись лога в структурированный объект с помощью трансформации ParseMessage.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: drop-label
spec:
# ...
transformations:
- action: DropLabels
dropLabels:
labels:
- label: .exampleПример удаления заданного лейбла из структурированного сообщения
В этом примере показано, как Вы можете удалить лейбл из структурированного JSON-сообщения.
Сначала применяется трансформация ParseMessage для парсинга сообщения,
после чего применяется DropLabels для удаления указанного лейбла.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: drop-label
spec:
# ...
transformations:
- action: ParseMessage
parseMessage:
sourceFormat: JSON
- action: DropLabels
dropLabels:
labels:
- label: .message.exampleПример изначальной записи в логе:
{"msg" : "fetching.module.release", "example": "test"}Результат преобразования:
{... "message": {
"msg" : "fetching.module.release"
}
}Отправка логов в Elasticsearch с трансформациями
Ниже приведён пример ресурса ClusterLogDestination для отправки логов в Elasticsearch.
В этом примере:
- JSON из поля
messageразбирается и переносится в корень события (targetLabel: "."); - в именах ключей в
pod_labelsточки заменяются на подчёркивания; - исходное поле
messageудаляется.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: es-storage
spec:
type: Elasticsearch
elasticsearch:
endpoint: http://elasticsearch:9200
index: logs-%F
transformations:
- action: ParseMessage
parseMessage:
sourceFormat: JSON
targetLabel: "."
- action: ReplaceKeys
replaceKeys:
source: "."
target: "_"
labels:
- .pod_labels
- action: DropLabels
dropLabels:
labels:
- label: .messageПример исходной записи: приложение на Java пишет структурированный JSON в stdout, поэтому в поле message события попадает JSON-строка. Поле msg внутри этой строки содержит текст программного лога.
{... "namespace": "prod", "pod_labels": {"app.kubernetes.io/name": "orders", "app": "api"}, "message": "{\"@timestamp\":\"2025-03-25T10:15:00.123Z\",\"level\":\"INFO\",\"logger\":\"com.example.OrderService\",\"msg\":\"Order id=42 created; user=1001\"}"}Результат после преобразований:
- поля из JSON перенесены в корень события;
- в
pod_labelsточки в именах ключей заменены на подчёркивания; - поле
messageудалено.
{... "namespace": "prod",
"pod_labels": {
"app_kubernetes_io/name": "orders",
"app": "api"
},
"@timestamp": "2025-03-25T10:15:00.123Z",
"level": "INFO",
"logger": "com.example.OrderService",
"msg": "Order id=42 created; user=1001"
}Настройка сборки логов с продуктовых неймспейсов с помощью селектора меток неймспейса
apiVersion: deckhouse.io/v1alpha2
kind: ClusterLoggingConfig
metadata:
name: production-logs
spec:
type: KubernetesPods
kubernetesPods:
namespaceSelector:
labelSelector:
matchLabels:
environment: production
destinationRefs:
- loki-storageИсключение подов и неймспейсов, используя label
Существует преднастроенный label для исключения определенных подов и неймспейсов: log-shipper.deckhouse.io/exclude=true.
Он помогает остановить сбор логов с подов и неймспейсов без изменения глобальной конфигурации.
---
apiVersion: v1
kind: Namespace
metadata:
name: test-namespace
labels:
log-shipper.deckhouse.io/exclude: "true"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
spec:
# ...
template:
metadata:
labels:
log-shipper.deckhouse.io/exclude: "true"Включение буферизации
Настройка буферизации логов необходима для улучшения надежности и производительности системы сбора логов. Буферизация может быть полезна в следующих случаях:
-
Временные перебои с подключением. Если есть временные перебои или нестабильность соединения с системой хранения логов (например, с Elasticsearch), буфер позволяет временно сохранять логи и отправить их, когда соединение восстановится.
-
Сглаживание пиков нагрузки. При внезапных всплесках объёма логов буфер позволяет сгладить пиковую нагрузку на систему хранения логов, предотвращая её перегрузку и потенциальную потерю данных.
-
Оптимизация производительности. Буферизация помогает оптимизировать производительность системы сбора логов за счёт накопления логов и отправки их группами, что снижает количество сетевых запросов и улучшает общую пропускную способность.
Пример включения буферизации в оперативной памяти
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: loki-storage
spec:
buffer:
memory:
maxEvents: 4096
type: Memory
type: Loki
loki:
endpoint: http://loki.loki:3100Пример включения буферизации на диске
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: loki-storage
spec:
buffer:
disk:
maxSize: 1Gi
type: Disk
type: Loki
loki:
endpoint: http://loki.loki:3100Пример определения поведения при переполнении буфера
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
name: loki-storage
spec:
buffer:
disk:
maxSize: 1Gi
type: Disk
whenFull: DropNewest
type: Loki
loki:
endpoint: http://loki.loki:3100Более подробное описание параметров доступно в ресурсе ClusterLogDestination.