OpenShift Content Pack

The following content pack is available for use with a Graylog Illuminate license and Graylog Enterprise or Graylog Security. Contact sales to learn more about obtaining Illuminate.

Red Hat OpenShift is a Kubernetes-based application platform that runs across on-premises, cloud, and hybrid environments. This technology pack processes OpenShift/Kubernetes container log messages delivered as JSON. The pack normalizes the JSON envelope and OpenShift/Kubernetes metadata into Graylog schema-compatible fields. This metadata includes container name/ID, namespace, pod, worker node, container image, and cluster ID. It also promotes the human-readable application message to the stored message field and normalizes the log level to a standard event severity. The pack leaves application-specific message bodies (e.g., Spring Boot, Kafka, or Django logs) intact for parsing in a future release, except for Uvicorn HTTP access log lines, which this pack parses now.

This pack focuses on application logs (container stdout/stderr), identified by log_source value container. It does not process OpenShift audit logs (kube-apiserver, openshift-apiserver, OVN, or node auditd) or node and infrastructure logs. These records carry no container metadata, so the pack skips them.

Supported Versions

  • OpenShift 4.0 and later container logs in the OpenShift Logging (ViaQ) JSON data model, as emitted by a Fluentd or Vector collector.

    Important: You must configure the collector to forward the ViaQ JSON data model. The OpenTelemetry (OTEL) log data model introduced with OpenShift Logging 6.x (resource attributes, severityText, body) is not supported.

Requirements

  • A Red Hat OpenShift or Kubernetes cluster emitting container logs as JSON.

  • Graylog 7.1 or later.

  • A log collector (e.g. Fluentd or Vector) shipping container logs to Graylog.

Stream Configuration

This technology pack includes 1 stream:

  • Illuminate:OpenShift Messages

Hint: If this stream does not exist prior to the activation of this pack then it is created and configured to route messages to this stream and the associated index set. There should not be any stream rules configured for this stream.

Index Set Configuration

This technology pack includes 1 index set definition:

  • OpenShift Logs

Hint: If this index set is already defined, then nothing is changed. If this index set does not exist, then it is created with retention settings of a daily rotation and 90 days of retention. These settings can be adjusted as required after installation.

Log Collection

On each node, a log collector such as Fluentd or Vector gathers OpenShift container logs and ships them to Graylog as JSON, using the OpenShift Logging (ViaQ) data model. Graylog supports delivery over syslog.

OpenShift logs are identified by input rather than by payload. Either dedicate a Graylog input to OpenShift and map it to openshift in the core input_routing lookup table, or use a pipeline rule to set a static RoutedFrom field instead, as described in Input Routing Setup below. When the JSON arrives over syslog with a priority header, Graylog strips the header before parsing.

Each record includes:

  • cluster ID

  • metadata for the Kubernetes pod, namespace, container, and node

  • container stream (stdout or stderr)

  • log level

This information is included alongside the application log line.

Important: You must configure the collector to forward the ViaQ JSON data model. The OpenTelemetry (OTEL) log data model introduced with OpenShift Logging 6.x (resource attributes, severityText, body) is not supported.

Input Routing Setup

OpenShift logs are identified by the Graylog input they arrive on rather than by their payload. A dedicated input must be mapped to this pack in the core input_routing lookup table. Map the input ID to openshift so that every message on that input is processed as an OpenShift container log.

  1. Create a dedicated Syslog input in Graylog for your OpenShift logs.

  2. Select Show received messages to open a search window on the input.

  3. Copy the gl2_source_input value from a received message.

  4. Navigate to Enterprise > Illuminate, then select the Customization tab.

  5. Locate the lookup_adapter_input_routing title, then click Edit.

  6. For content_name (key), enter openshift and for input_id (value), enter the gl2_source_input ID copied earlier.

  7. Select Configure value.

All logs sent to the configured input are now identified as OpenShift container logs and processed by this pack. Repeat these steps for additional OpenShift inputs as needed.

Alternatively, use pipeline rules to set or create a static field RoutedFrom with the value Route - OpenShift Logs instead of using the input_routing lookup table.

Configure OpenShift Log Forwarding

This pack processes OpenShift/Kubernetes container logs delivered in the OpenShift Logging (ViaQ) JSON data model. These records have log_type set to application and log_source set to container, and carry the kubernetes metadata object and the openshift.cluster_id field.

Configure OpenShift Logging to forward these container (application) logs to the Graylog input you mapped under Input Routing Setup. This pack does not process audit logs (kube-apiserver, openshift-apiserver, OVN, node auditd) or node and infrastructure logs. These logs do not need to be forwarded.

Forward Container Logs from OpenShift Logging

Configure the OpenShift Logging collector to forward logs to Graylog. OpenShift Logging 6.x supports Vector as the only collector, while OpenShift Logging 5.x and earlier support Fluentd and Vector. Refer to Red Hat's OpenShift Logging documentation for the exact procedure for your OpenShift version.

  1. Install the Red Hat OpenShift Logging Operator and deploy the collector.

  2. Create a Graylog input for the OpenShift logs and map it to openshift as described in Input Routing Setup above.

  3. Create or edit a ClusterLogForwarder custom resource.

    Important: Only the ViaQ JSON data model is supported. If the collector forwards the OpenTelemetry (OTEL) data model (resource attributes, severityText, body), the logs will not be parsed by this pack.

  4. Define an input that selects the application log source, which is the container stream (stdout or stderr) this pack processes. Do not forward the audit or infrastructure sources.

  5. Define an output that points at your Graylog input, using a transport supported by that input.

  6. Add a pipeline in the ClusterLogForwarder that connects the application input to the Graylog output, then apply the resource.

  7. Verify that container log records arrive on the Graylog input and that event_source_product is set to openshift.

Log Format Examples

Representative OpenShift container log line (JSON).

{"hostname":"ocp-worker-0.example.com","kubernetes":{"container_name":"sample-app","namespace_name":"sample-app-dev","pod_name":"sample-app-7c9f8b6d5c-abcde","container_id":"cri-o://1111111111111111111111111111111111111111111111111111111111111111","container_image":"registry.example.com/sample-app/sample-app:1.0.0","labels":{"app":"sample-app"},"pod_owner":"ReplicaSet/sample-app-7c9f8b6d5c"},"level":"info","container_iostream":"stdout","log_type":"application","log_source":"container","openshift":{"cluster_id":"11111111-1111-1111-1111-111111111111"},"message":"2025-04-15T19:09:17.723Z INFO 1 --- [sample] [ main] com.example.app.SampleApplication : Started SampleApplication in 7.318 seconds"} {"@timestamp":"2025-03-24T14:39:04.750290671Z","hostname":"ocp-worker-0.example.com","kubernetes":{"annotations":{"openshift.io/scc":"confluent-operator"},"container_id":"cri-o://2222222222222222222222222222222222222222222222222222222222222222","container_image":"registry.example.com/sample-web/sample-web-ui:1.0.0","container_image_id":"registry.example.com/sample-web/sample-web-ui@sha256:2222222222222222222222222222222222222222222222222222222222222222","container_iostream":"stdout","container_name":"ui","labels":{"app":"ui","pod-template-hash":"7f784668b8"},"namespace_id":"44444444-4444-4444-4444-444444444444","namespace_labels":{"kubernetes_io_metadata_name":"sample-web-test"},"namespace_name":"sample-web-test","pod_id":"33333333-3333-3333-3333-333333333333","pod_ip":"10.128.2.43","pod_name":"ui-7f784668b8-njz49","pod_owner":"ReplicaSet/ui-7f784668b8"},"level":"default","log_source":"container","log_type":"application","message":"## CONTACT INFORMATION","openshift":{"cluster_id":"11111111-1111-1111-1111-111111111111","sequence":1744821243330547883},"timestamp":"2025-03-24T14:39:04.750290671Z"} {"@timestamp":"2025-04-15T19:09:06.556825292Z","hostname":"ocp-worker-0.example.com","kubernetes":{"annotations":{"dynakube.dynatrace.com/injected":"true","metadata.dynatrace.com/k8s.workload.kind":"deployment","metadata.dynatrace.com/k8s.workload.name":"sample-docs","oneagent.dynatrace.com/injected":"true","openshift.io/scc":"confluent-operator"},"container_iostream":"stdout","container_name":"dynatrace-operator","labels":{"app":"sample-docs","pod-template-hash":"86dc8c7755"},"namespace_id":"55555555-5555-5555-5555-555555555555","namespace_labels":{"kubernetes_io_metadata_name":"sample-docs-dev"},"namespace_name":"sample-docs-dev","pod_id":"66666666-6666-6666-6666-666666666666","pod_ip":"10.128.9.157","pod_name":"sample-docs-86dc8c7755-xq4rw","pod_owner":"ReplicaSet/sample-docs-86dc8c7755"},"level":"info","log_source":"container","log_type":"application","openshift":{"cluster_id":"11111111-1111-1111-1111-111111111111","sequence":1744821243545406784},"structured":{"content":{"apiUrl":"https://dynatrace.example.com/e/11111111-1111-1111-1111-111111111111/api","skipCertCheck":true,"tenantUUID":"11111111-1111-1111-1111-111111111111"},"level":"info","logger":"injection-startup","msg":"contents of secret config","ts":"2025-04-15T19:09:06.556Z"},"timestamp":"2025-04-15T19:09:06.556825292Z"} {"hostname":"ocp-worker-0.example.com","kubernetes":{"container_id":"cri-o://5555555555555555555555555555555555555555555555555555555555555555","container_image":"registry.example.com/model/model:1.0.0","container_iostream":"stdout","container_name":"model","labels":{"app":"model","pod-template-hash":"597bfcd89b"},"namespace_name":"sample-app-dev","pod_id":"6e15e0ed-a04a-4869-920f-69792a0cb6dd","pod_ip":"10.242.15.16","pod_name":"model-597bfcd89b-8cwlh","pod_owner":"ReplicaSet/model-597bfcd89b"},"level":"info","log_source":"container","log_type":"application","openshift":{"cluster_id":"11111111-1111-1111-1111-111111111111"},"message":"INFO: 10.242.16.2:52266 - \"GET /%5C..%5C..%5C..%5C..%5Cwinnt%5Cwin.ini HTTP/1.1\" 404 Not Found"}

What Is Provided

  • Input-based identification of OpenShift/Kubernetes container JSON logs.

  • Normalization of container and OpenShift/Kubernetes metadata into the container_* schema fields (name, id, namespace, image, iostream, pod name/uid/ip/owner, cluster id, app).

  • Worker node mapping to host_hostname.

  • Promotion of the application message to the stored message field, including containers that use structured JSON logging with no top-level message.

  • Log level normalized to event_severity and event_severity_level.

  • Parsing of Uvicorn HTTP access lines into http_ and source_ fields (source_ip, source_port, http_request_method, http_request_path, http_version, http_response_code).