> ## Documentation Index
> Fetch the complete documentation index at: https://otel.fyi/llms.txt
> Use this file to discover all available pages before exploring further.

# K8sobjects

> OpenTelemetry receiver for K8sobjects

# K8sobjects Receiver

![Status](https://img.shields.io/badge/status-beta-yellow)

**Available in:** `contrib`, `k8s`

**Maintainers:** [@dmitryax](https://github.com/dmitryax), [@TylerHelmuth](https://github.com/TylerHelmuth), [@ChrsMark](https://github.com/ChrsMark), [@krisztianfekete](https://github.com/krisztianfekete)

**Source:** [opentelemetry-collector-contrib](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/k8sobjectsreceiver)

## Supported Telemetry

![Logs](https://img.shields.io/badge/logs-beta-blue)

## Overview

Currently this receiver supports authentication via service accounts only.
See [example](#example) for more information.

## Getting Started

The following is example configuration

```yaml theme={null}
  k8s_objects:
    auth_type: serviceAccount
    storage: file_storage
    k8s_leader_elector: k8s_leader_elector
    interval: 30m
    objects:
      - name: pods
        mode: pull
        label_selector: environment in (production),tier in (frontend)
        field_selector: status.phase=Running
        interval: 15m
        initial_delay: 5m
        exclude_namespaces:
          - regexp: namespace-to-ignore
      - name: events
        mode: watch
        group: events.k8s.io
        namespaces: [default]
```

Brief description of configuration properties:

* `auth_type` (default = `serviceAccount`): Determines how to authenticate to
  the K8s API server. This can be one of `none` (for no auth), `serviceAccount`
  (to use the standard service account token provided to the agent pod), or
  `kubeConfig` to use credentials from `~/.kube/config`.
* `error_mode` (default = `propagate`): Determines how to handle errors when the receiver is unable to pull or watch objects due to missing resources. This can be one of `propagate`, `ignore`, or `silent`.
  * `propagate` will propagate the error to the collector as an Error.
  * `ignore` will log and ignore the error and continue.
  * `silent` will ignore the error and continue without logging.
* `interval`: Top level pull interval applied to all pull-mode objects that do not set their own `interval`. Falls back to `1h` when neither this field nor the per-resource `objects[*].interval` is set. Has no effect on watch-mode objects.
* `name`: Name of the resource object to collect
* `mode`: define in which way it collects this type of object, either "pull" or "watch".
  * `pull` mode will read all objects of this type use the list API at an interval.
  * `watch` mode will do setup a long connection using the watch API to just get updates.
* `include_initial_state` (default = `false`): When set to `true` (watch-mode only) the receiver sends a one-time snapshot of the current objects before it starts processing watch events.
* `label_selector`: select objects by label(s)
* `field_selector`: select objects by field(s)
* `objects[*].interval`: per-resource pull interval override. When set, takes precedence over the top-level `interval`. Only applies to `pull` mode objects.
* `initial_delay`: exact delay applied before the first pull for an object. Use this to stagger large pull workloads while preserving the configured `interval` cadence afterward. Non-positive values behave like `0`. Must be less than the resolved pull interval when set. Only useful for `pull` mode.
* `exclude_watch_type`: allows excluding specific watch types. Valid values are `ADDED`, `MODIFIED`, `DELETED`, `BOOKMARK`, and `ERROR`. Only usable in `watch` mode.
* `resource_version`: allows watching resources starting from a specific version (default = `1`). Only available for `watch` mode. If not specified, the receiver will do an initial list to get the resourceVersion before starting the watch. See [Efficient Detection of Change](https://kubernetes.io/docs/reference/using-api/api-concepts/#efficient-detection-of-changes) for details on why this is necessary.
* `namespaces`: An array of `namespaces` to collect events from. (default = `all`)
* `exclude_namespaces`: allows excluding namespaces from being watched/pulled, (NOTE: if a new namespace that matches the regex is added, the collector will need to be restarted)
* `group`: API group name. It is an optional config. When given resource object is present in multiple groups,
  use this config to specify the group to select. By default, it will select the first group.
  For example, `events` resource is available in both `v1` and `events.k8s.io/v1` APIGroup. In
  this case, it will select `v1` by default.
* `kube_api_qps` (default = `5`): Maximum number of queries per second to the Kubernetes API. Increase this if you see `client-side throttling` warnings in the collector logs when watching or polling many resources simultaneously.
* `kube_api_burst` (default = `10`): Maximum burst size for requests to the Kubernetes API. Increase this alongside `kube_api_qps` if you see `client-side throttling` warnings.
* `k8s_leader_elector` (default: none): if specified, will enable Leader Election by using `k8sleaderelector` extension
* `storage` (default: none): specifies the storage extension to use for persisting resourceVersions. When configured, the receiver automatically persists the resourceVersion after processing each event for all watch-mode objects. On restart, each watch-mode object resumes from its persisted resourceVersion, preventing duplicate events. Pull-mode objects are unaffected.
  > **Important storage considerations:**
  >
  > * **Local or node-pinned volumes** (`hostPath`, local PV): the collector pod becomes tied to a specific node. If that node fails or the pod is rescheduled elsewhere, the persisted data will not be accessible and persistence will not work correctly.
  > * **Network-attached volumes** (`ReadWriteMany`): the volume is accessible from any node, so the collector pod can be freely rescheduled or fail over to a different node while still resuming from the correct resourceVersion. This is the recommended approach, especially when used with `k8s_leader_elector`.
  > * **Block volumes** (`ReadWriteOnce`): supported for single-replica deployments where restarts are graceful. Not recommended with leader election across multiple nodes, as Kubernetes may take 30–90 seconds to detach and reattach the volume after a node failure.

The full list of settings exposed for this receiver are documented in [config.go](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/k8sobjectsreceiver/config.go)
with detailed sample configurations in [testdata/config.yaml](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/k8sobjectsreceiver/testdata/config.yaml).

Follow the below sections to setup various Kubernetes resources required for the deployment.

### Supported Kubernetes objects

The `k8sobjectsreceiver` supports collecting a wide range of standard Kubernetes objects from the API server. For example, the mostly used supported objects
(in addition to other standard Kubernetes objects) are:

* `pods`
* `events`
* `nodes`
* `jobs`
* `cronjobs`
* `deployments`
* `services`
* `configmaps`
* `secrets`
* `statefulsets`
* `replicasets`
* `daemonsets`
* `namespaces`

This receiver supports both `pull` and `watch` modes, allowing for flexible and real-time monitoring of these objects. Please note that custom resources are supported only if their CRDs are available in the cluster.

### Configuration

Create a ConfigMap with the config for `otelcontribcol`. Replace `OTLP_ENDPOINT`
with valid value.

```bash theme={null}
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: otelcontribcol
  labels:
    app: otelcontribcol
data:
  config.yaml: |
    extensions:
      file_storage:
        directory: /var/lib/otelcol/storage

    receivers:
      k8s_objects:
        auth_type: serviceAccount
        storage: file_storage
        objects:
          - name: pods
            mode: pull
          - name: events
            mode: watch

    exporters:
      otlp_grpc:
        endpoint: <OTLP_ENDPOINT>
        tls:
          insecure: true

    service:
      extensions: [file_storage]
      pipelines:
        logs:
          receivers: [k8s_objects]
          exporters: [otlp_grpc]
EOF
```

### Service Account

Create a service account that the collector should use.

```bash theme={null}
<<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app: otelcontribcol
  name: otelcontribcol
EOF
```

### RBAC

Use the below commands to create a `ClusterRole` with required permissions and a
`ClusterRoleBinding` to grant the role to the service account created above.
Following config will work for collecting pods and events only. You need to add
appropriate rule for collecting other objects.

When using watch mode you must also specify `list` verb so that the receiver has permission to do its initial list if no
`resource_version` was supplied or a list to recover from [410 Gone scenarios](https://kubernetes.io/docs/reference/using-api/api-concepts/#410-gone-responses).

```bash theme={null}
<<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: otelcontribcol
  labels:
    app: otelcontribcol
rules:
- apiGroups:
  - ""
  resources:
  - events
  - pods
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - "events.k8s.io"
  resources:
  - events
  verbs:
  - watch
  - list
EOF
```

```bash theme={null}
<<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: otelcontribcol
  labels:
    app: otelcontribcol
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: otelcontribcol
subjects:
- kind: ServiceAccount
  name: otelcontribcol
  namespace: default
EOF
```

### Deployment

Create a [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) to deploy the collector.
Note: This receiver must be deployed as one replica, otherwise it'll be producing duplicated data.

```bash theme={null}
<<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: otelcontribcol-storage
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: otelcontribcol
  labels:
    app: otelcontribcol
spec:
  replicas: 1
  selector:
    matchLabels:
      app: otelcontribcol
  template:
    metadata:
      labels:
        app: otelcontribcol
    spec:
      serviceAccountName: otelcontribcol
      containers:
      - name: otelcontribcol
        # This image is created by running `make docker-otelcontribcol`.
        # If you are not building the collector locally, specify a published image: `otel/opentelemetry-collector-contrib`
        image: otelcontribcol:latest
        args: ["--config", "/etc/config/config.yaml"]
        volumeMounts:
        - name: config
          mountPath: /etc/config
        - name: storage
          mountPath: /var/lib/otelcol/storage
        imagePullPolicy: IfNotPresent
      volumes:
        - name: config
          configMap:
            name: otelcontribcol
        - name: storage
          persistentVolumeClaim:
            claimName: otelcontribcol-storage
EOF
```

## Compatibility

### Kubernetes Versions

This receiver is tested against the Kubernetes versions specified in the [e2e-tests.yml](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/.github/workflows/e2e-tests.yml#L97-L99)
workflow. These tested versions represent the officially supported Kubernetes versions for this component.

## Troubleshooting

If receiver returns error similar to below, make sure that resource is added to `ClusterRole`.

```
{"kind": "receiver", "name": "k8s_objects", "pipeline": "logs", "resource": "events.k8s.io/v1, Resource=events", "error": "unknown"}
```

## Configuration

### Example Configuration

```yaml theme={null}
k8s_objects:
  include_initial_state: false
  objects:
    - name: pods
      mode: pull
      interval: 1h
      initial_delay: 10m
      label_selector: environment in (production),tier in (frontend)
      field_selector: status.phase=Running
    - name: events
      mode: watch
      group: events.k8s.io
      namespaces: [default]
      exclude_watch_type: [DELETED]
k8s_objects/pull_with_resource:
  include_initial_state: false
  objects:
    - name: pods
      mode: pull
      interval: 1h
      initial_delay: 5m
      resource_version: "1"
    - name: events
      mode: pull
      interval: 1h
k8s_objects/watch_with_resource:
  objects:
    - name: events
      mode: watch
      group: events.k8s.io
      namespaces: [default]
    - name: events
      mode: watch
      group: events.k8s.io
      namespaces: [default]
      resource_version: "2"
k8s_objects/watch_with_initial_state:
  include_initial_state: true
  objects:
    - name: pods
      mode: watch
      namespaces: [default]
    - name: events
      mode: watch
      group: events.k8s.io
      namespaces: [default]
k8s_objects/watch_without_initial_state:
  include_initial_state: false
  objects:
    - name: events
      mode: watch
      group: events.k8s.io
      namespaces: [default]
k8s_objects/invalid_resource:
  objects:
    - name: fake_resource
      mode: watch
k8s_objects/exclude_deleted_with_pull:
  include_initial_state: false
  objects:
    - name: events
      mode: pull
      exclude_watch_type: [DELETED]
k8s_objects/invalid_mode:
  objects:
    - name: pods
      mode: invalid_mode
k8s_objects/exclude_namespaces:
  objects:
    - name: pods
      mode: watch
      exclude_namespaces:
        - regexp: default_ignore
k8s_objects/top_level_interval:
  auth_type: serviceAccount
  interval: 30m
  objects:
    - name: pods
      mode: pull
    - name: nodes
      mode: pull
      interval: 5m
```

***

*Last generated: 2026-07-06*
