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 и может потреблять много ресурсов в зависимости от количества модулей в вашем кластере.

Я уверен, что есть более подходящие подходы к этой проблеме, но я думаю, что это решение весьма удобно, по крайней мере, для моего случая использования.

Другие вопросы по тегам