Download PDF

Configuring VKS Cluster Logging with Fluent Bit and VCF Operations for Logs

Julius M. Nicolescu

June 2026

Overview

This document describes how to deploy and configure Fluent Bit as the log forwarding agent on a VKS guest cluster, shipping logs to VCF Operations for Logs over HTTPS.

Unlike the Supervisor cluster — which ships a managed Fluent Bit DaemonSet that operators can only partially configure — a VKS guest cluster gives full control over the logging stack. Fluent Bit is installed as a package from the VKS Standard Packages bundle using the VCF CLI package manager. This approach is consistent with how other platform add-ons (Cilium, Prometheus, cert-manager) are deployed on VKS, and it supports the full Fluent Bit configuration surface: inputs, parsers, filters, and outputs are all defined in a data values file before installation.

Four log streams are collected from the cluster:

Stream Source Tag Description
Container logs /var/log/containers/*.log kube.* All pod stdout/stderr across every namespace
Systemd daemon logs /var/log/journal kube_systemd.* kubelet and containerd service logs from the systemd journal
API server audit logs /var/log/kubernetes/kube-apiserver.log apiserver_audit.* Kubernetes API audit trail in audit.k8s.io/v1 JSON format
Linux auth logs /var/log/audit/audit.log auth.* Node-level authentication and authorisation events from the Linux audit daemon

All four streams are forwarded in a single HTTP output to VCF Operations for Logs, enriched with structured metadata fields for filtering and search.

Prerequisite: The VKS Standard Packages bundle must already be accessible — either from the public Broadcom registry or from a local Harbor mirror. Follow the air-gapped setup guide before proceeding if the cluster has no direct internet access.


Reference Environment

The procedures and configurations in this document were validated against the following platform versions:

Component Version
VMware Cloud Foundation 9.0.2.0
Supervisor v1.32.9+vmware.2-fips.vsc9.0.2.0100-25262241
vSphere Kubernetes Service 3.6.0+v1.35
Kubernetes Release v1.35.2+vmware.1-vkr.3
Fluent Bit Package 4.2.3+vmware.1-vks.1
VCF Operations for Logs 8.x (API v2)

Architecture

Fluent Bit runs as a DaemonSet — one pod per cluster node — and reads log files directly from the node’s filesystem via hostPath mounts. All pods write to the same VCF Operations for Logs HTTPS endpoint.

┌────────────────────────────────────────────────────────────────────┐
│  VKS Guest Cluster: dev-cluster-04                                 │
│                                                                    │
│  Node 1..N                                                         │
│  /var/log/containers/*.log          ◄── pod stdout / stderr        │
│  /var/log/journal                   ◄── kubelet, containerd        │
│  /var/log/kubernetes/kube-apiserver.log  ◄── API audit trail       │
│  /var/log/audit/audit.log           ◄── Linux audit daemon         │
│             │                                                      │
│             ▼                                                      │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │  vks-system-logging                                          │  │
│  │                                                              │  │
│  │  fluent-bit (DaemonSet, one pod per node)                    │  │
│  │    │                                                         │  │
│  │    ├─ INPUT  tail      kube.*            (CRI parser)        │  │
│  │    ├─ INPUT  systemd   kube_systemd.*    (kubelet+containerd)│  │
│  │    ├─ INPUT  tail      apiserver_audit.* (JSON parser)       │  │
│  │    ├─ INPUT  tail      auth.*            (authlog parser)    │  │
│  │    │                                                         │  │
│  │    ├─ FILTER record_modifier  (add vks_cluster, environment) │  │
│  │    ├─ FILTER kubernetes       (enrich kube.* with K8s meta)  │  │
│  │    ├─ FILTER nest/lift        (flatten kubernetes object)    │  │
│  │    ├─ FILTER modify           (add per-stream text label)    │  │
│  │    │                                                         │  │
│  │    └─ OUTPUT http             (TLS, JSON, match *)           │  │
│  └──────────────────────────────────────────────────────────────┘  │
│             │                                                      │
└─────────────┼──────────────────────────────────────────────────────┘
              │  HTTPS POST  :9543/api/v2/events
              ▼
┌─────────────────────────────────────────┐
│  VCF Operations for Logs                │
│  192.168.200.40:9543                    │
└─────────────────────────────────────────┘

Prerequisites

Set the following environment variables before running any commands:

export CLUSTER_NAMESPACE='lab-poc-namespace-dev'
export CLUSTER_NAME='dev-cluster-04'
export SUPERVISOR_IP='10.77.68.3'
export VCF_CLI_VSPHERE_USERNAME='administrator@vsphere.local'
export VCF_CLI_VSPHERE_PASSWORD='<password>'

Step 1 — Connect to the VKS Cluster

Create a VCF CLI context that points directly to the VKS guest cluster. This context connects through the Supervisor API endpoint and targets the specific workload cluster by namespace and name.

vcf context delete ${CLUSTER_NAME} -y

vcf context create ${CLUSTER_NAME} \
  --endpoint ${SUPERVISOR_IP} \
  --username ${VCF_CLI_VSPHERE_USERNAME} \
  --workload-cluster-namespace ${CLUSTER_NAMESPACE} \
  --workload-cluster-name ${CLUSTER_NAME} \
  --insecure-skip-tls-verify

vcf context list
vcf context use ${CLUSTER_NAME}:${CLUSTER_NAME}

Verify connectivity to the guest cluster:

kubectl get nodes

Step 2 — Add the VKS Standard Packages Repository

The Fluent Bit package is distributed as part of the VKS Standard Packages bundle. Add the repository to the tkg-system namespace, which is the package management namespace that Carvel/kapp-controller monitors on every VKS cluster.

2.1 Install the Package Plugin

If the VCF CLI package plugin is not yet installed:

vcf plugin install package

2.2 Add the Standard Packages Repository

vcf package repository add standard-repo \
  --url projects.packages.broadcom.com/vsphere/supervisor/vks-standard-packages/3.6.0-20260416/vks-standard-packages:3.6.0-20260416 \
  -n tkg-system

2.3 Verify the Repository

vcf package repository list -n tkg-system

Expected output:

  NAME           SOURCE                                                                                                                       STATUS
  standard-repo  (imgpkg)                                                                                                                     Reconcile succeeded
                 projects.packages.broadcom.com/vsphere/supervisor/vks-standard-packages/3.6.0-20260416/vks-standard-packages:3.6.0-20260416

The Reconcile succeeded status confirms that kapp-controller on the cluster has successfully pulled and indexed the package metadata. You can also verify at the Kubernetes level:

kubectl get pkgr -n tkg-system

Expected output:

NAME           AGE     DESCRIPTION           PAUSED
standard-repo  2m45s   Reconcile succeeded

Step 3 — Inspect the Available Fluent Bit Package

List all available versions of the Fluent Bit package from the repository:

vcf package available list fluent-bit.kubernetes.vmware.com -n tkg-system

Expected output:

  NAME                              VERSION               RELEASED-AT
  fluent-bit.kubernetes.vmware.com  4.0.8+vmware.1-vks.1  2025-10-22 14:00:00 -0400 EDT
  fluent-bit.kubernetes.vmware.com  4.0.8+vmware.2-vks.1  2025-12-18 13:00:00 -0500 EST
  fluent-bit.kubernetes.vmware.com  4.1.1+vmware.1-vks.1  2025-12-18 13:00:00 -0500 EST
  fluent-bit.kubernetes.vmware.com  4.2.2+vmware.1-vks.1  2026-02-11 13:00:00 -0500 EST
  fluent-bit.kubernetes.vmware.com  4.2.3+vmware.1-vks.1  2026-04-16 14:00:00 -0400 EDT

Extract the default data values schema for the target version. This generates a YAML template with all configurable fields and their defaults:

vcf package available get fluent-bit.kubernetes.vmware.com/4.2.3+vmware.1-vks.1 \
  --default-values-file-output fluent-bit-data-values.yaml \
  -n tkg-system

Review the generated file to understand the full configuration surface before customising it in the next step.


Step 4 — Prepare the Data Values File

The data values file controls the complete Fluent Bit configuration: the pipeline (inputs, parsers, filters, outputs) as well as the DaemonSet resource requests and the target namespace. Each configuration section is described below before the complete manifest is shown.

4.1 Service

The [SERVICE] block sets global Fluent Bit behaviour:

Parameter Value Notes
Flush 1 Flush buffered records to outputs every second
Log_Level info Set to debug temporarily when troubleshooting
Daemon off Fluent Bit runs as a foreground process inside the container
HTTP_Server On Enables the built-in metrics endpoint at :2020 for Prometheus scraping
HTTP_Port 2020 Default port for /api/v1/metrics and /api/v1/health

4.2 Inputs

Four input sources are configured.

Input 1 — Container logs (kube.*)

Tails all container log files written by the CRI (containerd) runtime. Each file corresponds to one running container; the filename encodes the pod name, namespace, and container name.

Parameter Value Notes
Tag kube.* Fluent Bit replaces * with the file path, producing tags like kube.var.log.containers.etcd-dev-cluster-04_kube-system_etcd-<hash>.log
Parser cri CRI log format: <timestamp> <stream> <flags> <message> — defined in the custom parsers section
DB /var/log/flb_kube.db SQLite file persisting the read position; prevents re-shipping historical logs after a pod restart
Mem_Buf_Limit 50MB Maximum in-memory buffer per input before backpressure is applied

Input 2 — Systemd daemon logs (kube_systemd.*)

Reads structured log entries from the systemd journal for the two core Kubernetes node services. The systemd input reads from the binary journal (not text files), which preserves the original log priority, unit, and PID fields.

Parameter Value Notes
Systemd_Filter _SYSTEMD_UNIT=kubelet.service Restricts collection to kubelet; excludes unrelated system services
Systemd_Filter _SYSTEMD_UNIT=containerd.service Adds containerd runtime logs to the same stream
Read_From_Tail On Only new journal entries are read on startup
Strip_Underscores On Removes leading _ from systemd field names (e.g., _PID becomes PID) for cleaner output

Input 3 — API server audit logs (apiserver_audit.*)

Collects the Kubernetes API audit log from the VKS control plane node. Each line is a self-contained JSON object in audit.k8s.io/v1 format containing the requesting user, target resource, HTTP verb, and response.

Parameter Value Notes
Path /var/log/kubernetes/kube-apiserver.log Standard audit log location on VKS Ubuntu nodes
Parser json Each audit line is a complete JSON document
Mem_Buf_Limit 50MB Verbose RequestResponse level audit events can be large

Input 4 — Linux auth logs (auth.*)

Collects the Linux audit daemon log from cluster nodes. This stream captures node-level security events: PAM authentication, sudo usage, file permission changes, and kernel audit rules. It is independent of the Kubernetes audit log.

Parameter Value Notes
Path /var/log/audit/audit.log Standard Linux audit daemon log path
Parser authlog Custom syslog-style regex parser defined in the parsers section

4.3 Parsers

Three custom parsers are defined.

cri — Parses container runtime log lines. CRI-O and containerd both write logs in the format <RFC3339Nano> <stream> <flags> <message>:

2026-06-05T17:19:50.764323889Z stderr F I0605 17:19:50 controller.go:109] message text

authlog — Parses traditional syslog-formatted Linux auth log lines. The regex captures the timestamp, hostname, process name, optional PID, and message body. Time_Keep On preserves the original log timestamp as a field alongside the ingestion timestamp.

json — Parses JSON audit log lines. Time_Key time maps the time field in the JSON object to the Fluent Bit record timestamp.

4.4 Filters

The filter pipeline runs in declaration order. Each filter is applied to events whose tag matches the Match pattern.

Stage 1 — Global metadata (record_modifier, match *)

Applied to every event regardless of source. Adds three fields that identify the log’s origin environment:

Field Value Purpose
log_type kubernetes Top-level classification for all logs from this cluster
vks_cluster dev-cluster-04 Identifies the specific VKS cluster; essential when multiple clusters forward to the same Operations for Logs instance
environment vcf902 Identifies the VCF environment

Stage 2 — Kubernetes metadata enrichment (kubernetes, match kube.*)

This filter contacts the Kubernetes API server from within the pod to look up metadata for the pod that produced each log line. It parses the tag (which encodes the container filename path) to extract the pod name, namespace, and container name, then fetches the corresponding pod object.

Metadata fields added include: pod_name, namespace_name, container_name, container_image, pod_id, docker_id, labels, and annotations.

Key parameters:

Parameter Value Notes
Merge_Log On If the message field contains JSON, it is parsed and merged into the top-level record as log_processed
Merge_Log_Key log_processed Nested key under which the parsed JSON message is stored
K8S-Logging.Parser On Allows per-pod parser selection via the fluentbit.io/parser pod annotation
K8S-Logging.Exclude On Allows per-pod log exclusion via the fluentbit.io/exclude: "true" pod annotation

Stage 3 — Flatten Kubernetes metadata (modify + nest, match kube.*)

VCF Operations for Logs indexes top-level fields as searchable facets but treats nested JSON objects as opaque strings. To make Kubernetes metadata fields (pod name, namespace, labels) individually searchable, the kubernetes nested object is lifted to the top level:

modify:  Copy kubernetes → k8s    (preserve original nested copy)
nest:    lift fields from kubernetes object to top level

After this stage, pod_name, namespace_name, and container_name are top-level fields on the event.

Stage 4 — Text labels (modify, per-stream)

Each stream receives a text field whose value identifies the stream by name. VCF Operations for Logs full-text search operates on the text field, so these labels enable targeted searches without parsing nested JSON or audit record structures:

Match pattern text value
kube.* Kubernetes Container Logs
kube_systemd.* Linux Daemon Logs
auth.* Linux Auth Logs
apiserver_audit.* Kubernetes API Server Audit Logs

4.5 Output

A single HTTP output with Match * forwards all four streams to VCF Operations for Logs. Sending all streams through one output simplifies configuration and ensures consistent delivery semantics across all log types.

Parameter Value Notes
Format json VCF Operations for Logs API v2 accepts JSON event arrays
tls on Traffic is encrypted in transit
tls.verify off Server certificate is not validated — see the security note in Step 4.5 below
Retry_Limit False Events are retried indefinitely on delivery failure; no log data is silently dropped during connectivity issues
json_date_key timestamp Maps the record timestamp to the timestamp field required by the Operations for Logs API

Security note — TLS without certificate verification: tls.verify off encrypts traffic but does not validate the VCF Operations for Logs server certificate. For production, mount the Operations for Logs CA certificate into the Fluent Bit pods and configure tls.verify on with tls.ca_file <path>. The CA certificate can be distributed via a Kubernetes Secret and referenced in the DaemonSet volume mounts.

4.6 Complete Data Values Manifest

cat << 'EOF' > ${CLUSTER_NAME}-fluentbit-data-values.yaml
fluent_bit:
  config:
    service: |
      [SERVICE]
        Flush         1
        Log_Level     info
        Daemon        off
        Parsers_File  parsers.conf
        HTTP_Server   On
        HTTP_Listen   0.0.0.0
        HTTP_Port     2020

    inputs: |
      ###########################################################################
      # Container logs — all pod stdout/stderr across every namespace
      ###########################################################################
      [INPUT]
        Name              tail
        Tag               kube.*
        Path              /var/log/containers/*.log
        Parser            cri
        DB                /var/log/flb_kube.db
        Mem_Buf_Limit     50MB
        Skip_Long_Lines   On
        Refresh_Interval  10

      ###########################################################################
      # Systemd daemon logs — kubelet and containerd services
      ###########################################################################
      [INPUT]
        Name                systemd
        Tag                 kube_systemd.*
        Path                /var/log/journal
        DB                  /var/log/flb_kube_systemd.db
        Systemd_Filter      _SYSTEMD_UNIT=kubelet.service
        Systemd_Filter      _SYSTEMD_UNIT=containerd.service
        Read_From_Tail      On
        Strip_Underscores   On

      ###########################################################################
      # Kubernetes API server audit logs
      ###########################################################################
      [INPUT]
        Name              tail
        Tag               apiserver_audit.*
        Parser            json
        Path              /var/log/kubernetes/kube-apiserver.log
        DB                /var/log/flb_kube_audit.db
        Mem_Buf_Limit     50MB
        Refresh_Interval  10
        Skip_Long_Lines   On

      ###########################################################################
      # Linux auth logs — PAM, sudo, node-level authentication events
      ###########################################################################
      [INPUT]
        Name              tail
        Tag               auth.*
        Path              /var/log/audit/audit.log
        Parser            authlog
        DB                /var/log/flb_system_auth.db
        Mem_Buf_Limit     50MB
        Refresh_Interval  10
        Skip_Long_Lines   On

    filters: |
      ###########################################################################
      # Global metadata — applied to all streams
      ###########################################################################
      [FILTER]
        Name                record_modifier
        Match               *
        Record log_type     kubernetes
        Record vks_cluster  dev-cluster-04
        Record environment  vcf902

      ###########################################################################
      # Kubernetes metadata enrichment — container logs only
      ###########################################################################
      [FILTER]
        Name                kubernetes
        Match               kube.*
        Kube_URL            https://kubernetes.default.svc:443
        Kube_CA_File        /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
        Kube_Token_File     /var/run/secrets/kubernetes.io/serviceaccount/token
        Kube_Tag_Prefix     kube.var.log.containers.
        Merge_Log           On
        Merge_Log_Key       log_processed
        K8S-Logging.Parser  On
        K8S-Logging.Exclude On

      ###########################################################################
      # Flatten Kubernetes metadata to top-level fields
      ###########################################################################
      [FILTER]
        Name                  modify
        Match                 kube.*
        Copy                  kubernetes k8s

      [FILTER]
        Name                  nest
        Match                 kube.*
        Operation             lift
        Nested_Under          kubernetes

      ###########################################################################
      # Per-stream text labels for VCF Operations for Logs full-text search
      ###########################################################################
      [FILTER]
        Name                  modify
        Match                 kube.*
        Add                   text "Kubernetes Container Logs"

      [FILTER]
        Name                  modify
        Match                 kube_systemd.*
        Add                   text "Linux Daemon Logs"

      [FILTER]
        Name                  modify
        Match                 auth.*
        Add                   text "Linux Auth Logs"

      [FILTER]
        Name                  modify
        Match                 apiserver_audit.*
        Add                   text "Kubernetes API Server Audit Logs"

    outputs: |
      ###########################################################################
      # Output — all streams to VCF Operations for Logs
      ###########################################################################
      [OUTPUT]
        Name          http
        Match         *
        Host          192.168.200.40
        Port          9543
        URI           /api/v2/events
        Format        json
        tls           on
        tls.verify    off
        Retry_Limit   False
        json_date_key timestamp

    parsers: |
      ###########################################################################
      # CRI — container runtime log format (containerd / CRI-O)
      ###########################################################################
      [PARSER]
        Name        cri
        Format      regex
        Regex       ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<message>.*)$
        Time_Key    time
        Time_Format %Y-%m-%dT%H:%M:%S.%L%z

      ###########################################################################
      # authlog — traditional syslog format for Linux auth/audit logs
      ###########################################################################
      [PARSER]
        Name        authlog
        Format      regex
        Regex       ^(?<time>[A-Za-z]+ {1,2}\d+ \d+:\d+:\d+) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$
        Time_Key    time
        Time_Format %b %e %H:%M:%S
        Time_Keep   On

      ###########################################################################
      # json — Kubernetes API audit log (audit.k8s.io/v1 JSON objects)
      ###########################################################################
      [PARSER]
        Name        json
        Format      json
        Time_Key    time
        Time_Format %Y-%m-%dT%H:%M:%S.%LZ

    streams: ""
    plugins: ""

  daemonset:
    env: []
    podAnnotations: {}
    priorityClassName: ""
    resources:
      limits:
        cpu: ""
        memory: ""
      requests:
        cpu: 200m
        memory: 256Mi

  ipv6Primary: false

namespace: vks-system-logging
nsLimitRange:
  defaultLimits:
    cpu: ""
    memory: ""
  defaultRequests:
    cpu: 200m
    memory: 256Mi
EOF

Step 5 — Deploy Fluent Bit

Create the target namespace and install the package. The --verbose 9 flag produces detailed output from kapp-controller during reconciliation, which is useful for diagnosing image pull or RBAC issues on first install.

kubectl create ns vks-system-logging

vcf package install fluent-bit \
  -p fluent-bit.kubernetes.vmware.com \
  --version 4.2.3+vmware.1-vks.1 \
  --values-file ${CLUSTER_NAME}-fluentbit-data-values.yaml \
  -n vks-system-logging \
  --verbose 9

Package installation is managed by kapp-controller, which reconciles the Helm chart defined by the package. Installation typically completes within 2–3 minutes.


Step 6 — Verify the Installation

6.1 Package and App Status

Verify that the package installation has reconciled successfully:

kubectl get packageinstall fluent-bit -n vks-system-logging

Expected output:

NAME         PACKAGE NAME                       PACKAGE VERSION        DESCRIPTION           AGE   PAUSED
fluent-bit   fluent-bit.kubernetes.vmware.com   4.2.3+vmware.1-vks.1   Reconcile succeeded   13h

The underlying kapp App resource shows the same status:

kubectl get apps fluent-bit -n vks-system-logging

Expected output:

NAME         DESCRIPTION           SINCE-DEPLOY   AGE   PAUSED
fluent-bit   Reconcile succeeded   8m54s          13h

6.2 DaemonSet and Pod Status

Confirm that one Fluent Bit pod is running on every node:

kubectl get all -n vks-system-logging

Expected output (six-node cluster — 3 control plane + 3 workers):

NAME                   READY   STATUS    RESTARTS   AGE
pod/fluent-bit-9whdv   1/1     Running   0          4m42s
pod/fluent-bit-h5hdn   1/1     Running   0          4m42s
pod/fluent-bit-hf4n9   1/1     Running   0          4m42s
pod/fluent-bit-lm5qd   1/1     Running   0          4m42s
pod/fluent-bit-pznvs   1/1     Running   0          4m42s
pod/fluent-bit-t96d2   1/1     Running   0          4m42s

NAME                        DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR
daemonset.apps/fluent-bit   6         6         6       6            6           kubernetes.io/os=linux

DESIRED must equal READY. A pod that is not Running indicates an image pull failure, a missing volume, or a configuration parse error.

6.3 Inspect Fluent Bit Logs

Check the Fluent Bit output across all pods for successful input initialisation and output connectivity:

kubectl -n vks-system-logging logs -l app=fluent-bit \
  --all-containers=true \
  --tail=200

Look for lines confirming each input has opened its source successfully:

[info] [input:tail:tail.0] inotify_fs_add(): inode=... filename=/var/log/containers/...log
[info] [input:systemd:systemd.1] seeking to tail of journal
[info] [output:http:http.0] worker #0 started

To stream live logs:

kubectl -n vks-system-logging logs -l app=fluent-bit -f

Step 7 — Query VCF Operations for Logs

VCF Operations for Logs exposes a REST API for searching ingested events. Authentication uses short-lived session tokens.

7.1 Obtain a Session Token

LOGS_HOST='192.168.200.40'
LOGS_USER='admin'
LOGS_PASS='<password>'

SESSION_ID=$(curl -sk \
  -H "Content-Type: application/json" \
  -X POST "https://${LOGS_HOST}:9543/api/v2/sessions" \
  -d "{
    \"username\":\"${LOGS_USER}\",
    \"password\":\"${LOGS_PASS}\",
    \"provider\":\"Local\"
  }" | jq -r '.sessionId')

echo "Session ID: ${SESSION_ID}"

7.2 Search for Container Log Events

SEARCH="Kubernetes Container Logs"

curl -sk \
  -H "Authorization: Bearer ${SESSION_ID}" \
  "https://${LOGS_HOST}:9543/api/v1/events/text/CONTAINS%20$(python3 -c "import urllib.parse; print(urllib.parse.quote('${SEARCH}'))")/timestamp/LAST%203600000" \
| jq .

Example event returned. Note the Kubernetes metadata fields lifted to the top level — pod_name, namespace_name, container_name, container_image — making them individually searchable in the Operations for Logs UI:

{
  "text": "Kubernetes Container Logs",
  "timestamp": 1780674175933,
  "timestampString": "2026-06-05 15:42:55.933 GMT+00:00",
  "fields": [
    { "name": "message",         "content": "{\"level\":\"info\",\"ts\":\"2026-06-05T15:42:55.273296Z\",\"caller\":\"mvcc/index.go:214\",\"msg\":\"compact tree index\",\"revision\":123094}" },
    { "name": "pod_name",        "content": "etcd-dev-cluster-04-jfjss-4q796" },
    { "name": "namespace_name",  "content": "kube-system" },
    { "name": "container_name",  "content": "etcd" },
    { "name": "container_image", "content": "localhost:5000/vmware.io/etcd:v3.5.27_vmware.1-fips" },
    { "name": "pod_id",          "content": "d8a868ae-e8d5-43e6-b106-9a1ff8541d5e" },
    { "name": "stream",          "content": "stderr" },
    { "name": "host",            "content": "dev-cluster-04-jfjss-4q796" },
    { "name": "vks_cluster",     "content": "dev-cluster-04" },
    { "name": "log_type",        "content": "kubernetes" },
    { "name": "environment",     "content": "vcf902" },
    { "name": "source",          "content": "10.88.36.2" }
  ]
}

The screenshot below shows the event as it appears in the VCF Operations for Logs event viewer. Each Kubernetes metadata field — pod_name, namespace_name, container_name, container_image — is indexed as a discrete, searchable facet rather than a nested JSON property. This is the direct result of the nest/lift filter stage in the pipeline: without it, the entire kubernetes object would arrive as an opaque string and none of its subfields would be individually queryable.

The vks_cluster and environment fields appended by the global record_modifier filter make it possible to scope queries to a specific cluster when multiple VKS clusters forward logs to the same Operations for Logs instance. The text field value Kubernetes Container Logs serves as the primary stream discriminator in the field query builder — selecting text CONTAINS Kubernetes Container Logs on the interactive timeline isolates container log events from all other ingested streams without requiring full-text search.

Kubernetes container log events in VCF Operations for Logs — pod, namespace, and container metadata indexed as top-level searchable fields

7.3 Search for API Audit Log Events

SEARCH="Kubernetes API Server Audit Logs"

curl -sk \
  -H "Authorization: Bearer ${SESSION_ID}" \
  "https://${LOGS_HOST}:9543/api/v1/events/text/CONTAINS%20$(python3 -c "import urllib.parse; print(urllib.parse.quote('${SEARCH}'))")/timestamp/LAST%203600000" \
| jq .

Example event returned. Audit log fields (auditID, verb, requestURI, level, stage) are top-level fields because the JSON audit record was parsed by the json input parser and its fields were flattened directly into the event:

{
  "text": "Kubernetes API Server Audit Logs",
  "timestamp": 1780674338933,
  "timestampString": "2026-06-05 15:45:38.933 GMT+00:00",
  "fields": [
    { "name": "apiVersion",               "content": "audit.k8s.io/v1" },
    { "name": "kind",                     "content": "Event" },
    { "name": "level",                    "content": "Metadata" },
    { "name": "stage",                    "content": "ResponseComplete" },
    { "name": "auditID",                  "content": "5714b0a3-c78b-452b-866a-7fe43e021aff" },
    { "name": "verb",                     "content": "get" },
    { "name": "requestURI",               "content": "/readyz" },
    { "name": "userAgent",                "content": "kube-probe/1.35" },
    { "name": "requestReceivedTimestamp", "content": "2026-06-05T15:45:38.382182Z" },
    { "name": "stageTimestamp",           "content": "2026-06-05T15:45:38.382612Z" },
    { "name": "vks_cluster",              "content": "dev-cluster-04" },
    { "name": "log_type",                 "content": "kubernetes" },
    { "name": "environment",              "content": "vcf902" },
    { "name": "source",                   "content": "10.88.36.2" }
  ]
}

The screenshot below shows a Kubernetes API server audit event in VCF Operations for Logs. Because the Fluent Bit json input parser processes the full audit.k8s.io/v1 record before it enters the filter pipeline, each audit field is promoted directly to a top-level indexed field. Fields such as verb, requestURI, level, stage, auditID, and userAgent are individually queryable without nested path syntax or post-ingestion transformation.

This structure enables precise compliance and security queries. For example, filtering on verb = delete and requestURI CONTAINS secrets and namespace_name = kube-system surfaces all destructive operations against cluster secrets in a single view. Combined with the vks_cluster field, the same Operations for Logs instance can enforce consistent audit retention policies across every VKS cluster in the environment, differentiating events per cluster without separate ingestion pipelines.

Kubernetes API server audit log events in VCF Operations for Logs — audit.k8s.io/v1 fields indexed as top-level searchable facets

Updating the Configuration

To modify the Fluent Bit configuration after initial deployment — for example, to add a new input, change a filter, or update the output endpoint — edit the data values file and apply the update:

vcf package installed update fluent-bit \
  -n vks-system-logging \
  --values-file ${CLUSTER_NAME}-fluentbit-data-values.yaml

kapp-controller reconciles the change and rolls out an updated DaemonSet. The pods are restarted rolling to apply the new configuration.


Removing Fluent Bit

To uninstall the Fluent Bit package:

vcf package installed delete fluent-bit -n vks-system-logging

If the deletion stalls — this can occur when kapp-controller finalizers are not cleared automatically — remove the finalizers manually:

kubectl patch packageinstall fluent-bit -n vks-system-logging \
  --type=merge --patch '{"metadata":{"finalizers":[]}}'

kubectl patch app fluent-bit -n vks-system-logging \
  --type=merge --patch '{"metadata":{"finalizers":[]}}'

Verify that all resources have been removed:

kubectl get all -n vks-system-logging
kubectl get packageinstall -A
kubectl get app -A

Troubleshooting

Symptom Likely Cause Resolution
Reconcile failed in kubectl get packageinstall Image pull failure or kapp-controller RBAC error Check kapp-controller logs: kubectl logs -n tkg-system -l app=kapp-controller --tail=50; verify the package repository is reachable
Fluent Bit pods in CrashLoopBackOff Configuration parse error in the data values file Check pod logs: kubectl -n vks-system-logging logs <pod> --previous; look for [error] [config] lines
No events in VCF Operations for Logs Output not connecting, or wrong host/port Run kubectl -n vks-system-logging logs -l app=fluent-bit --tail=50 and look for HTTP error codes; verify port 9543 is reachable from cluster nodes
kube.* events missing Kubernetes metadata fields kubernetes filter API call failing Check that the Fluent Bit ServiceAccount has permissions to read pods; look for [error] [filter:kubernetes] in pod logs
API audit log input collecting nothing Audit log file does not exist at the configured path Verify /var/log/kubernetes/kube-apiserver.log exists on a control plane node; audit logging may be disabled or path may differ
DESIRED does not equal READY in DaemonSet Pod scheduling failure on a specific node Run kubectl describe pod -n vks-system-logging <pod> on the non-ready pod for scheduling or image pull errors
Package deletion stalls kapp-controller finalizers not cleared Patch out finalizers on both the packageinstall and app resources as shown in the Removing Fluent Bit section
Mem_Buf_Limit reached warnings in logs Log volume exceeds buffer allocation Increase Mem_Buf_Limit for the affected input, or reduce log verbosity at the source

Reference

Name URL
Broadcom — VKS Standard Packages Release Notes https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vsphere-supervisor-services-and-standalone-components/latest/release-notes/vks-standard-packages-release-notes.html
Fluent Bit — tail Input Plugin https://docs.fluentbit.io/manual/pipeline/inputs/tail
Fluent Bit — systemd Input Plugin https://docs.fluentbit.io/manual/pipeline/inputs/systemd
Fluent Bit — Kubernetes Filter https://docs.fluentbit.io/manual/pipeline/filters/kubernetes
Fluent Bit — HTTP Output Plugin https://docs.fluentbit.io/manual/pipeline/outputs/http
VCF Operations for Logs — API Reference https://developer.broadcom.com/xapis/aria-operations-for-logs/latest/