Filebeat Kubernetes 处理器和过滤

Filebeat Kubernetes Processor and filtering

我正在尝试使用 Filebeat 将我的 K8s pod 日志发送到 Elasticsearch。

我正在按照此处的在线指南进行操作:https://www.elastic.co/guide/en/beats/filebeat/6.0/running-on-kubernetes.html

一切都按预期工作,但我想从系统 pods 中过滤掉事件。我的更新配置如下:

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-netexternal-dnsingress-controllerfilebeat 事件:

- 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。

我正在使用一种不同的方法,该方法在日志记录管道中传输的日志数量方面效率较低。

与您的做法类似,我使用守护程序集在我的节点上部署了一个 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(在 "elk" 命名空间中称为 "logstash" 的服务)。

为简洁起见,我将只为您提供 logstash 的配置(如果您需要更具体的 kubernetes 帮助,请在评论中提问):

logstash.yml 文件非常基础:

http.host: "0.0.0.0"
path.config: /usr/share/logstash/pipeline

只是表示我挂载管道配置文件的目录的挂载点,如下:

10-beats.conf: 为 filebeat 声明一个输入(必须使用名为 "logstash" 的服务公开端口 5044)

input {
  beats {
    port => 5044
    ssl => false
  }
}

49-过滤器-logs.conf: 此过滤器基本上会删除来自 pods 且没有 "elk" 标签的日志。对于确实具有 "elk" 标签的 pods,它保留来自 pod 的 "elk" 标签中命名的容器的日志。例如,如果一个 Pod 有两个容器,分别称为 "nginx" 和 "python",将标签 "elk" 的值为 "nginx" 将只保留来自 nginx 容器的日志并丢弃python 个。日志的类型设置为 pod 所在的命名空间 运行。 这可能不适合所有人(您将在 elasticsearch 中为属于命名空间的所有日志创建一个索引)但它对我有用,因为我的日志是同源的。

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: 向elasticsearch发送数据:

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中的新日志。您只需要在广告连播模板中添加标签即可。
  • 默认情况下会删除所有日志文件,只要您没有明确放置标签。

这种方法的缺点

  • 来自所有 pods 的所有日志都通过 filebeat 和 logstash,并且仅在 logstash 中被删除。这对 logstash 来说是很多工作,并且可能会消耗资源,具体取决于集群中 pods 的数量。

我确信这个问题有更好的方法,但我认为这个解决方案非常方便,至少对于我的用例而言。

条件需要是列表:

- 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"