Configure Fluentd with Kubernetes DaemonSet and log routing for centralized collection

Intermediate 45 min Apr 21, 2026 640 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Deploy Fluentd as a DaemonSet on Kubernetes for centralized log collection with multi-format parsing, routing to multiple outputs, and RBAC security. Includes configuration for Elasticsearch, S3, and custom log sources.

Prerequisites

  • Kubernetes cluster with admin access
  • kubectl configured
  • Elasticsearch or log storage backend

What this solves

Fluentd provides centralized log collection for Kubernetes clusters, gathering container logs from all nodes and routing them to storage backends like Elasticsearch or S3. This tutorial shows you how to deploy Fluentd as a DaemonSet with proper RBAC permissions, configure multi-format log parsing, and set up routing to multiple output destinations for production-grade log management.

Step-by-step configuration

Create Fluentd namespace and RBAC configuration

Set up the namespace and service account with cluster-wide permissions to read container logs from all nodes.

apiVersion: v1
kind: Namespace
metadata:
  name: fluentd-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: fluentd
  namespace: fluentd-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: fluentd
rules:
- apiGroups: [""]
  resources:
    - pods
    - namespaces
  verbs:
    - get
    - list
    - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: fluentd
roleRef:
  kind: ClusterRole
  name: fluentd
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: fluentd
  namespace: fluentd-system
kubectl apply -f fluentd-rbac.yaml

Create Fluentd configuration with log routing

Configure Fluentd with input sources, filtering, parsing, and multiple output destinations including Elasticsearch and S3.

apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-config
  namespace: fluentd-system
data:
  fluent.conf: |
    
      @type tail
      @id in_tail_container_logs
      path /var/log/containers/*.log
      pos_file /var/log/fluentd-containers.log.pos
      tag kubernetes.*
      read_from_head true
      
    

    
      @type tail
      @id in_tail_minion
      path /var/log/salt/minion
      pos_file /var/log/fluentd-salt.log.pos
      tag salt
      
    

    
      @type tail
      @id in_tail_startupscript
      path /var/log/startupscript.log
      pos_file /var/log/fluentd-startupscript.log.pos
      tag startupscript
      
    

    
      @type tail
      @id in_tail_docker
      path /var/log/docker.log
      pos_file /var/log/fluentd-docker.log.pos
      tag docker
      
    

    
      @type tail
      @id in_tail_etcd
      path /var/log/etcd.log
      pos_file /var/log/fluentd-etcd.log.pos
      tag etcd
      
    

    
      @type tail
      @id in_tail_kubelet
      multiline_flush_interval 5s
      path /var/log/kubelet.log
      pos_file /var/log/fluentd-kubelet.log.pos
      tag kubelet
      
    

    
      @type tail
      @id in_tail_kube_proxy
      multiline_flush_interval 5s
      path /var/log/kube-proxy.log
      pos_file /var/log/fluentd-kube-proxy.log.pos
      tag kube-proxy
      
    

    
      @type tail
      @id in_tail_kube_apiserver
      multiline_flush_interval 5s
      path /var/log/kube-apiserver.log
      pos_file /var/log/fluentd-kube-apiserver.log.pos
      tag kube-apiserver
      
    

    
      @type tail
      @id in_tail_kube_controller_manager
      multiline_flush_interval 5s
      path /var/log/kube-controller-manager.log
      pos_file /var/log/fluentd-kube-controller-manager.log.pos
      tag kube-controller-manager
      
    

    
      @type tail
      @id in_tail_kube_scheduler
      multiline_flush_interval 5s
      path /var/log/kube-scheduler.log
      pos_file /var/log/fluentd-kube-scheduler.log.pos
      tag kube-scheduler
      
    

    

    

    

    

    

    
kubectl apply -f fluentd-configmap.yaml

Create secrets for external services

Configure authentication credentials for Elasticsearch and AWS S3 access.

kubectl create secret generic fluentd-secrets -n fluentd-system \
  --from-literal=FLUENT_ELASTICSEARCH_USER=elastic \
  --from-literal=FLUENT_ELASTICSEARCH_PASSWORD=your-elasticsearch-password \
  --from-literal=AWS_ACCESS_KEY_ID=your-aws-access-key \
  --from-literal=AWS_SECRET_ACCESS_KEY=your-aws-secret-key \
  --from-literal=S3_BUCKET_NAME=your-logs-bucket \
  --from-literal=AWS_REGION=us-west-2

Deploy Fluentd DaemonSet

Create the DaemonSet to run Fluentd on every node with proper resource limits and volume mounts.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: fluentd-system
  labels:
    k8s-app: fluentd-logging
    version: v1
spec:
  selector:
    matchLabels:
      k8s-app: fluentd-logging
      version: v1
  template:
    metadata:
      labels:
        k8s-app: fluentd-logging
        version: v1
    spec:
      serviceAccount: fluentd
      serviceAccountName: fluentd
      tolerations:
      - key: node-role.kubernetes.io/control-plane
        effect: NoSchedule
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1.16-debian-elasticsearch7-1
        env:
          - name: FLUENT_ELASTICSEARCH_HOST
            value: "elasticsearch.logging.svc.cluster.local"
          - name: FLUENT_ELASTICSEARCH_PORT
            value: "9200"
          - name: FLUENT_ELASTICSEARCH_SCHEME
            value: "http"
          - name: FLUENTD_SYSTEMD_CONF
            value: disable
          - name: FLUENT_CONTAINER_TAIL_EXCLUDE_PATH
            value: /var/log/containers/fluent*
          - name: FLUENT_ELASTICSEARCH_SSL_VERIFY
            value: "true"
          - name: FLUENT_ELASTICSEARCH_SSL_VERSION
            value: "TLSv1_2"
          - name: FLUENT_ELASTICSEARCH_USER
            valueFrom:
              secretKeyRef:
                name: fluentd-secrets
                key: FLUENT_ELASTICSEARCH_USER
          - name: FLUENT_ELASTICSEARCH_PASSWORD
            valueFrom:
              secretKeyRef:
                name: fluentd-secrets
                key: FLUENT_ELASTICSEARCH_PASSWORD
          - name: AWS_ACCESS_KEY_ID
            valueFrom:
              secretKeyRef:
                name: fluentd-secrets
                key: AWS_ACCESS_KEY_ID
          - name: AWS_SECRET_ACCESS_KEY
            valueFrom:
              secretKeyRef:
                name: fluentd-secrets
                key: AWS_SECRET_ACCESS_KEY
          - name: S3_BUCKET_NAME
            valueFrom:
              secretKeyRef:
                name: fluentd-secrets
                key: S3_BUCKET_NAME
          - name: AWS_REGION
            valueFrom:
              secretKeyRef:
                name: fluentd-secrets
                key: AWS_REGION
        resources:
          limits:
            memory: 512Mi
            cpu: 200m
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: fluentd-config
          mountPath: /fluentd/etc/fluent.conf
          subPath: fluent.conf
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
        - name: runlogjournal
          mountPath: /run/log/journal
          readOnly: true
        - name: dmesg
          mountPath: /var/log/dmesg
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: fluentd-config
        configMap:
          name: fluentd-config
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: runlogjournal
        hostPath:
          path: /run/log/journal
      - name: dmesg
        hostPath:
          path: /var/log/dmesg
kubectl apply -f fluentd-daemonset.yaml

Configure custom application log parsing

Add additional parsing rules for specific application formats like JSON logs and multiline stack traces.

apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-custom-parsing
  namespace: fluentd-system
data:
  custom-parsing.conf: |
    

    

    
kubectl apply -f fluentd-custom-parsing.yaml

Update DaemonSet to include custom parsing

Add the custom parsing configuration to the DaemonSet volume mounts.

kubectl patch daemonset fluentd -n fluentd-system --type='json' -p='[
  {
    "op": "add",
    "path": "/spec/template/spec/containers/0/volumeMounts/-",
    "value": {
      "name": "fluentd-custom-parsing",
      "mountPath": "/fluentd/etc/conf.d/custom-parsing.conf",
      "subPath": "custom-parsing.conf"
    }
  },
  {
    "op": "add",
    "path": "/spec/template/spec/volumes/-",
    "value": {
      "name": "fluentd-custom-parsing",
      "configMap": {
        "name": "fluentd-custom-parsing"
      }
    }
  }
]'

Configure log monitoring and alerting

Set up monitoring for Fluentd performance and log flow health.

apiVersion: v1
kind: Service
metadata:
  name: fluentd-metrics
  namespace: fluentd-system
  labels:
    k8s-app: fluentd-logging
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "24231"
spec:
  ports:
  - name: prometheus
    port: 24231
    protocol: TCP
    targetPort: 24231
  selector:
    k8s-app: fluentd-logging
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: fluentd-metrics
  namespace: fluentd-system
spec:
  selector:
    matchLabels:
      k8s-app: fluentd-logging
  endpoints:
  - port: prometheus
    interval: 30s
    path: /metrics
kubectl apply -f fluentd-monitoring.yaml

Configure output routing strategies

Set up log routing by namespace

Configure different output destinations based on Kubernetes namespace and application labels.

apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-routing
  namespace: fluentd-system
data:
  routing.conf: |
    

Automated install script

Run this to automate the entire setup

Prefere não gerir isto sozinho?

Gerimos a infraestrutura de empresas que dependem do tempo de atividade. Totalmente gerida, com um contacto fixo que conhece o seu ambiente.

Tem um contacto fixo que conhece o seu ambiente

Na secretária em Roterdão 15:00 · acessível por mensagem, sem formulário de tickets