Filbeat Kubernetes Процессор и фильтрация
Я пытаюсь отправить свои логи K8s в Elasticsearch с помощью Filebeat.
Я следую руководству онлайн здесь: https://www.elastic.co/guide/en/beats/filebeat/6.0/running-on-kubernetes.html
Все работает, как и ожидалось, однако я хочу отфильтровать события из системных модулей. Мой обновленный конфиг выглядит так:
apiVersion: v1
kind: ConfigMap
metadata:
name: filebeat-prospectors
namespace: kube-system
labels:
k8s-app: filebeat
kubernetes.io/cluster-service: "true"
data:
kubernetes.yml: |-
- type: log
paths:
- /var/lib/docker/containers/*/*.log
multiline.pattern: '^\s'
multiline.match: after
json.message_key: log
json.keys_under_root: true
processors:
- add_kubernetes_metadata:
in_cluster: true
namespace: ${POD_NAMESPACE}
- drop_event.when.regexp:
or:
kubernetes.pod.name: "weave-net.*"
kubernetes.pod.name: "external-dns.*"
kubernetes.pod.name: "nginx-ingress-controller.*"
kubernetes.pod.name: "filebeat.*"
Я пытаюсь игнорировать weave-net
, external-dns
, ingress-controller
а также filebeat
события через:
- drop_event.when.regexp:
or:
kubernetes.pod.name: "weave-net.*"
kubernetes.pod.name: "external-dns.*"
kubernetes.pod.name: "nginx-ingress-controller.*"
kubernetes.pod.name: "filebeat.*"
Однако они продолжают прибывать в Elasticsearch.
Заранее спасибо:)
3 ответа
Условия должны быть списком:
- drop_event.when.regexp:
or:
- kubernetes.pod.name: "weave-net.*"
- kubernetes.pod.name: "external-dns.*"
- kubernetes.pod.name: "nginx-ingress-controller.*"
- kubernetes.pod.name: "filebeat.*"
Я не уверен, что ваш порядок параметров работает. Один из моих рабочих примеров выглядит так:
- drop_event:
when:
or:
# Exclude traces from Zipkin
- contains.path: "/api/v"
# Exclude Jolokia calls
- contains.path: "/jolokia/?"
# Exclude pinging metrics
- equals.path: "/metrics"
# Exclude pinging health
- equals.path: "/health"
Это работало для меня в filebeat 6.1.3
- drop_event.when:
or:
- equals:
kubernetes.container.name: "filebeat"
- equals:
kubernetes.container.name: "prometheus-kube-state-metrics"
- equals:
kubernetes.container.name: "weave-npc"
- equals:
kubernetes.container.name: "nginx-ingress-controller"
- equals:
kubernetes.container.name: "weave"
Я использую другой подход, который менее эффективен с точки зрения количества журналов, которые проходят в конвейере журналов.
Аналогично тому, как вы это сделали, я развернул один экземпляр filebeat на своих узлах, используя набор демонов. Ничего особенного, вот конфигурация, которую я использую:
apiVersion: v1
data:
filebeat.yml: |-
filebeat.config:
prospectors:
# Mounted `filebeat-prospectors` configmap:
path: ${path.config}/prospectors.d/*.yml
# Reload prospectors configs as they change:
reload.enabled: false
modules:
path: ${path.config}/modules.d/*.yml
# Reload module configs as they change:
reload.enabled: false
processors:
- add_cloud_metadata:
output.logstash:
hosts: ['logstash.elk.svc.cluster.local:5044']
kind: ConfigMap
metadata:
labels:
k8s-app: filebeat
kubernetes.io/cluster-service: "true"
name: filebeat-config
И этот для разведчиков:
apiVersion: v1
data:
kubernetes.yml: |-
- type: log
paths:
- /var/lib/docker/containers/*/*.log
json.message_key: log
json.keys_under_root: true
processors:
- add_kubernetes_metadata:
in_cluster: true
namespace: ${POD_NAMESPACE}
kind: ConfigMap
metadata:
labels:
k8s-app: filebeat
kubernetes.io/cluster-service: "true"
name: filebeat-prospectors
Спецификация Daemonset:
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
labels:
k8s-app: filebeat
kubernetes.io/cluster-service: "true"
name: filebeat
spec:
selector:
matchLabels:
k8s-app: filebeat
kubernetes.io/cluster-service: "true"
template:
metadata:
labels:
k8s-app: filebeat
kubernetes.io/cluster-service: "true"
spec:
containers:
- args:
- -c
- /etc/filebeat.yml
- -e
command:
- /usr/share/filebeat/filebeat
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
image: docker.elastic.co/beats/filebeat:6.0.1
imagePullPolicy: IfNotPresent
name: filebeat
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
securityContext:
runAsUser: 0
volumeMounts:
- mountPath: /etc/filebeat.yml
name: config
readOnly: true
subPath: filebeat.yml
- mountPath: /usr/share/filebeat/prospectors.d
name: prospectors
readOnly: true
- mountPath: /usr/share/filebeat/data
name: data
- mountPath: /var/lib/docker/containers
name: varlibdockercontainers
readOnly: true
restartPolicy: Always
terminationGracePeriodSeconds: 30
volumes:
- configMap:
name: filebeat-config
name: config
- hostPath:
path: /var/lib/docker/containers
type: ""
name: varlibdockercontainers
- configMap:
defaultMode: 384
name: filebeat-prospectors
name: prospectors
- emptyDir: {}
name: data
По сути, все данные из всех журналов из всех контейнеров направляются в logstash, доступный в конечной точке службы: logstash.elk.svc.cluster.local:5044
(служба называется "logstash" в пространстве имен "elk").
Для краткости я дам вам только конфигурацию для logstash (если вам нужна более конкретная помощь с kubernetes, пожалуйста, спросите в комментариях):
Файл logstash.yml очень прост:
http.host: "0.0.0.0"
path.config: /usr/share/logstash/pipeline
Просто укажите точку монтирования каталога, куда я смонтировал файлы конфигурации конвейера, а именно:
10-beats.conf: объявляет ввод для filebeat (порт 5044 должен быть предоставлен сервисом, называемым logstash)
input {
beats {
port => 5044
ssl => false
}
}
49-filter-logs.conf: этот фильтр в основном удаляет журналы, поступающие из модулей, которые не имеют метки "elk". Для контейнеров, на которых есть метка "elk", хранятся журналы контейнеров, названных в метке "elk" модуля. Например, если у Pod есть два контейнера, называемые "nginx" и "python", то при добавлении метки "elk" со значением "nginx" будут сохраняться только журналы, поступающие из контейнера nginx, и удаляться из журналов python. Тип журнала устанавливается как пространство имен, в котором запущен модуль. Это может не подходить для всех (у вас будет один индекс в asticsearch для всех журналов, принадлежащих пространству имен), но это работает для меня потому что мои журналы гомологичны.
filter {
if ![kubernetes][labels][elk] {
drop {}
}
if [kubernetes][labels][elk] {
# check if kubernetes.labels.elk contains this container name
mutate {
split => { "kubernetes[labels][elk]" => "." }
}
if [kubernetes][container][name] not in [kubernetes][labels][elk] {
drop {}
}
mutate {
replace => { "@metadata[type]" => "%{kubernetes[namespace]}" }
remove_field => [ "beat", "host", "kubernetes[labels][elk]", "kubernetes[labels][pod-template-hash]", "kubernetes[namespace]", "kubernetes[pod][name]", "offset", "prospector[type]", "source", "stream", "time" ]
rename => { "kubernetes[container][name]" => "container" }
rename => { "kubernetes[labels][app]" => "app" }
}
}
}
Остальная часть конфигурации относится к разбору журналов и не относится к этому контексту. Единственной важной частью является вывод:
99-output.conf: отправка данных в asticsearch:
output {
elasticsearch {
hosts => ["http://elasticsearch.elk.svc.cluster.local:9200"]
manage_template => false
index => "%{[@metadata][type]}-%{+YYYY.MM.dd}"
document_type => "%{[@metadata][type]}"
}
}
Надеюсь, вы поняли это здесь.
Плюсы этого подхода
- После развертывания filebeat и logstash, если вам не нужно анализировать новый тип журнала, вам не нужно обновлять filebeat или logstash, чтобы получить новый журнал в kibana. Вам просто нужно добавить метку в шаблоне pod.
- Все файлы журналов по умолчанию удаляются, если вы явно не ставите метки.
Минусы этого подхода
- ВСЕ журналы от ВСЕХ модулей поступают через filebeat и logstash и удаляются только в logstash. Это большая работа для logstash и может потреблять много ресурсов в зависимости от количества модулей в вашем кластере.
Я уверен, что есть более подходящие подходы к этой проблеме, но я думаю, что это решение весьма удобно, по крайней мере, для моего случая использования.