Skip to main content

Kubernetes

Enrich

Synopsis

Enriches events with pod metadata — namespace, pod name, deployment, and node — looked up from a live, in-cluster Kubernetes watcher, using the container ID or a pod name/namespace pair read from the event.

The watcher runs for the life of the process and answers lookups from its in-memory store, so a lookup never makes a network call.

Schema

- kubernetes:
container_id_field: <ident>
add_labels: <boolean>
api_server: <string>
ca_path: <string>
description: <text>
disabled: <boolean>
if: <script>
ignore_failure: <boolean>
ignore_missing: <boolean>
namespace_field: <ident>
node_name: <string>
on_failure: <processor[]>
on_success: <processor[]>
pod_name_field: <ident>
resync_interval: <integer>
tag: <string>
target_prefix: <ident>
token_path: <string>

Configuration

The following fields are used to define the processor:

FieldRequiredDefaultDescription
container_id_fieldNcontainer.idField containing the container ID to look up (checked first). Accepts values with or without a containerd://, docker://, or cri-o:// runtime prefix
add_labelsNfalseAlso write <target_prefix>.labels when the pod has labels
api_serverNin-cluster defaultKubernetes API server URL. Defaults to the value derived from KUBERNETES_SERVICE_HOST/KUBERNETES_SERVICE_PORT
ca_pathNin-cluster defaultPath to the CA certificate used to verify the API server
descriptionN-Documentation note
disabledNfalseDisable the processor
ifN-Conditional expression
ignore_failureNfalseContinue pipeline execution when the lookup fails
ignore_missingNfalseContinue pipeline execution on a lookup miss
namespace_fieldN*-Field containing the pod's namespace, used together with pod_name_field as the fallback identity
node_nameNall nodesRestricts the watcher to pods scheduled on this node
on_failureN-Error handling processors
on_successN-Success handling processors
pod_name_fieldN*-Field containing the pod name, used together with namespace_field as the fallback identity
resync_intervalN600 (10 minutes)Watch resync interval, in seconds. An explicit 0 falls back to the default rather than disabling resync
tagN-Identifier for logging
target_prefixNk8sPrefix for the output fields
token_pathNin-cluster defaultPath to the service account bearer token used to authenticate to the API server

* = namespace_field and pod_name_field only activate the fallback identity when both are set; setting only one has no effect.

Details

The processor resolves a pod's identity from the event in two steps. It first reads container_id_field (default container.id); if that field is absent or does not match any pod in the watcher's store, it falls back to the namespace_field/pod_name_field pair, when both are configured. The two sources are tried in order, not exclusively — a container ID that fails to match still falls through to the pod name/namespace pair.

A hit writes <target_prefix>.namespace, <target_prefix>.pod, <target_prefix>.deployment, and <target_prefix>.node, each only when the corresponding value is non-empty. <target_prefix>.deployment is derived from the pod's owning ReplicaSet name with its pod-template-hash suffix stripped, so it is only ever set for ReplicaSet-owned pods — a bare Pod or a DaemonSet-owned pod has no deployment and the field is omitted. <target_prefix>.labels is written only when add_labels is true and the pod has labels. The watcher's pod metadata also carries the pod's owner kind and annotations, but the processor does not expose either as an output field.

A watcher that has not completed its first list of the cluster is treated as a miss without consulting its store, even if the identity would otherwise match once it has synced. ignore_missing suppresses the error on a miss — no identity field present, no match in the store, or an unsynced watcher — but the miss is still treated as a no-op: on_success does not run for a suppressed miss.

api_server, token_path, and ca_path all default to the standard in-cluster service account mount paths and the KUBERNETES_SERVICE_HOST/KUBERNETES_SERVICE_PORT environment variables that a pod running inside the cluster receives automatically. Overriding them points the watcher at a different API server or credential set, which is what a Director running outside the cluster it enriches against needs.

One watcher is shared per distinct api_server/node_name pair, for the life of the process, across every pipeline that references it — it is built on first use and kept running afterward, including through transient API errors. A construction failure (an invalid or unreachable api_server) is not cached, so a misconfigured watcher retries on the next event rather than being nailed to a one-time mistake.

Examples

Basic

Looking up pod metadata by container ID, using the default identity field...

{
"container": {
"id": "containerd://abc123def456"
}
}
- kubernetes:
container_id_field: container.id

adds pod metadata under the default k8s prefix:

{
"container": {
"id": "containerd://abc123def456"
},
"k8s": {
"namespace": "prod",
"pod": "web-7f8b6d9c-x2k9p",
"deployment": "web",
"node": "node-1"
}
}

Pod Name Fallback

Looking up by namespace and pod name when no container ID is present...

{
"k8s_namespace": "prod",
"k8s_pod_name": "web-7f8b6d9c-x2k9p"
}
- kubernetes:
namespace_field: k8s_namespace
pod_name_field: k8s_pod_name

resolves the pod through the fallback identity:

{
"k8s_namespace": "prod",
"k8s_pod_name": "web-7f8b6d9c-x2k9p",
"k8s": {
"namespace": "prod",
"pod": "web-7f8b6d9c-x2k9p",
"node": "node-2"
}
}

Labels and Custom Prefix

Adding pod labels under a custom target prefix...

{
"container": {
"id": "abc123"
}
}
- kubernetes:
target_prefix: kube
add_labels: true

writes labels alongside the rest of the metadata:

{
"container": {
"id": "abc123"
},
"kube": {
"namespace": "prod",
"pod": "web-7f8b6d9c-x2k9p",
"labels": {
"app": "web",
"tier": "frontend"
}
}
}

Remote Cluster

Pointing the watcher at a specific cluster and node from outside it...

{
"container": {
"id": "abc123"
}
}
- kubernetes:
api_server: "https://10.0.0.1:6443"
token_path: "/etc/vmetric/k8s/token"
ca_path: "/etc/vmetric/k8s/ca.crt"
node_name: "node-1"

scopes the watcher to the specified cluster and node:

{
"container": {
"id": "abc123"
},
"k8s": {
"namespace": "prod",
"pod": "web-7f8b6d9c-x2k9p",
"node": "node-1"
}
}

Error Handling

Skipping unmatched events without stopping the pipeline...

{
"container": {
"id": "sidecar-not-yet-in-cluster"
}
}
- kubernetes:
ignore_missing: true
on_success:
- set:
field: k8s_enriched
value: true

the miss is skipped silently — on_success does not run, and no k8s field is added:

{
"container": {
"id": "sidecar-not-yet-in-cluster"
}
}