How to add Kubernetes labels to Loki using FluentBit

March 02, 2024

How to add add Kubernetes metadata labels to Loki using FluentBit

So, after playing around with ElasticSearch for a while on my 3 node cluster for a few months I thought it was time for a lighter logging solution. Elastic was using 1GB per replica and most of the CPU, for a small cluster like mine this was simply too high – I needed Loki.

Loki, unlike Elastic, can be described as grep on steroids. You still have the normal inverted index à la Elastic but only the labels are indexed, the actual log message isn’t. Labels can be things like node, pod_name etc, this helps you to narrow down your search to avoid parsing hundreds of GBs of logs.

My cluster uses fluent-bit to read, filter and ship the logs to Loki. In fact, I use the CRDs provided by the Fluent Operator. The problem I was having was that the Kubernetes labels, such as namespace_name weren’t appearing as labels. Only the manually defined job=fluentbit label was being sent, this made it quite challenging to debug individual pods. I turned on autoKubernetesLabel and set-up my Kubernetes filter, like so:

apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterOutput
metadata:
  name: k8s-app-loki
  labels:
    fluentbit.fluent.io/enabled: "true"
    fluentbit.fluent.io/mode: "k8s"
spec:
  matchRegex: (?:kube|service)\.(.*)
  loki:
    host: loki-gateway.loki.svc.cluster.local
    port: 80
    labels:
      - job=fluentbit
    autoKubernetesLabels: "on"

But, nothing?

A picture of Grafana showing the Loki explore pane. A log message is visible, but with only the job=fluentbit2 label defined]

My filter was correct as well:

apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterFilter
metadata:
  name: kubernetes
  labels:
    fluentbit.fluent.io/enabled: "true"
    fluentbit.fluent.io/mode: "k8s"
spec:
  match: kube.*
  filters:
  - kubernetes:
      kubeURL: https://kubernetes.default.svc:443
      kubeCAFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      kubeTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
      labels: false
      annotations: false
      mergeLog: true
      mergeLogKey: "log_processed"
      keepLog: false
      k8sLoggingParser: true
      k8sLoggingExclude: false

Well, it seems the field autoKubernetesLabel doesn’t “automatically” add labels. You still need to

So, to finish the post off I used something like this (feel free to add additional labels):

apiVersion: fluentbit.fluent.io/v1alpha2
kind: ClusterOutput
metadata:
  name: k8s-app-loki
  labels:
    fluentbit.fluent.io/enabled: "true"
    fluentbit.fluent.io/mode: "k8s"
spec:
  matchRegex: (?:kube|service)\.(.*)
  loki:
    host: loki-gateway.loki.svc.cluster.local
    port: 80
    labels:
      - job=fluentbit
      - $kubernetes['pod_name']
      - $kubernetes['namespace_name']
      - $kubernetes['container_name']
    autoKubernetesLabels: "on"
Back to top