Configuring logging


Red Hat OpenShift Logging 6.4

Configuring log forwarding and LokiStack

Red Hat OpenShift Documentation Team

Abstract

This document provides an overview of configuring OpenShift logging features including log forwarding and LokiStack.

Chapter 1. Advanced collector configuration

This section covers advanced collector configuration options, including input sources and receivers, pod rollout strategy, and network policies. For basic collector setup, see "Configuring log forwarding."

1.1. Configuring input receivers

The Red Hat OpenShift Logging Operator deploys a service for each configured input receiver so that clients can write to the collector. This service exposes the port specified for the input receiver. For log forwarder ClusterLogForwarder CR deployments, the service name is in the <clusterlogforwarder_resource_name>-<input_name> format.

Important

Receiver inputs are only supported when logs originate from a Red Hat-supported product that is installed on the same cluster as the Red Hat OpenShift Logging Operator, or when logging is installed on hosted control planes.

The collector supports two types of receiver inputs:

HTTP receiver

Receives and parses audit logs. Use this receiver when:

  • Logging is installed on hosted control planes.
  • Logs originate from a Red Hat-supported product that is installed on the same cluster as the Red Hat OpenShift Logging Operator. For example, OpenShift Virtualization.
Syslog receiver

Receives and parses infrastructure logs in journal format. Use this receiver when:

  • Logs originate from a Red Hat-supported product that is installed on the same cluster as the Red Hat OpenShift Logging Operator. For example:

    • Red Hat OpenStack Services on OpenShift (RHOSO)
    • OpenShift Virtualization

You can configure your log collector to listen for HTTP connections to only receive audit logs by specifying http as a receiver input in the ClusterLogForwarder custom resource (CR).

Important

HTTP receiver input is only supported for the following scenarios:

  • Logging is installed on hosted control planes.
  • When logs originate from a Red Hat-supported product that is installed on the same cluster as the Red Hat OpenShift Logging Operator. For example:

    • OpenShift Virtualization

Prerequisites

  • You have administrator permissions.
  • You have installed the OpenShift CLI (oc).
  • You have installed the Red Hat OpenShift Logging Operator.

Procedure

  1. Modify the ClusterLogForwarder CR to add configuration for the http receiver input:

    Example ClusterLogForwarder CR

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <clusterlogforwarder_name> 
    1
    
      namespace: <namespace>
    # ...
    spec:
      serviceAccount:
        name: <service_account_name>
      inputs:
      - name: http-receiver 
    2
    
        type: receiver
        receiver:
          type: http 
    3
    
          port: 8443 
    4
    
          http:
            format: kubeAPIAudit 
    5
    
      outputs:
      - name: <output_name>
        type: http
        http:
          url: <url>
      pipelines: 
    6
    
        - name: http-pipeline
          inputRefs:
            - http-receiver
          outputRefs:
            - <output_name>
    # ...

    1
    Specify a name for the ClusterLogForwarder CR.
    2
    Specify a name for your input receiver.
    3
    Specify the input receiver type as http.
    4
    Optional: Specify the port that the input receiver listens on. This must be a value between 1024 and 65535. The default value is 8443 if this is not specified.
    5
    Currently, only the kube-apiserver webhook format is supported for http input receivers.
    6
    Configure a pipeline for your input receiver.
  2. Apply the changes to the ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml
  3. Verify that the collector is listening on the service that has a name in the <clusterlogforwarder_resource_name>-<input_name> format by running the following command:

    $ oc get svc

    Example output

    NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)            AGE
    collector                 ClusterIP   172.30.85.239    <none>        24231/TCP          3m6s
    collector-http-receiver   ClusterIP   172.30.205.160   <none>        8443/TCP           3m6s

    In the example, the service name is collector-http-receiver.

Verification

  1. Extract the certificate authority (CA) certificate file by running the following command:

    $ oc extract cm/openshift-service-ca.crt -n <namespace>
    Note

    If the CA in the cluster where the collectors are running changes, you must extract the CA certificate file again.

  2. As an example, use the curl command to send logs by running the following command:

    $ curl --cacert <openshift_service_ca.crt> https://collector-http-receiver.<namespace>.svc:8443 -XPOST -d '{"<prefix>":"<message>"}'

    Replace <openshift_service_ca.crt> with the extracted CA certificate file.

You can configure your log collector to collect journal format infrastructure logs by specifying syslog as a receiver input in the ClusterLogForwarder custom resource (CR).

Important

Syslog receiver input is only supported for the following scenarios:

  • Logging is installed on hosted control planes.
  • When logs originate from a Red Hat-supported product that is installed on the same cluster as the Red Hat OpenShift Logging Operator. For example:

    • Red Hat OpenStack Services on OpenShift (RHOSO)
    • OpenShift Virtualization

Prerequisites

  • You have administrator permissions.
  • You have installed the OpenShift CLI (oc).
  • You have installed the Red Hat OpenShift Logging Operator.

Procedure

  1. Grant the collect-infrastructure-logs cluster role to the service account by running the following command:

    Example binding command

    $ oc adm policy add-cluster-role-to-user collect-infrastructure-logs -z logcollector

  2. Modify the ClusterLogForwarder CR to add configuration for the syslog receiver input:

    Example ClusterLogForwarder CR

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <clusterlogforwarder_name> 
    1
    
      namespace: <namespace>
    # ...
    spec:
      serviceAccount:
        name: <service_account_name> 
    2
    
      inputs:
        - name: syslog-receiver 
    3
    
          type: receiver
          receiver:
            type: syslog 
    4
    
            port: 10514 
    5
    
      outputs:
      - name: <output_name>
        lokiStack:
          authentication:
            token:
              from: serviceAccount
          target:
            name: logging-loki
            namespace: openshift-logging
        tls: 
    6
    
          ca:
            key: service-ca.crt
            configMapName: openshift-service-ca.crt
        type: lokiStack
    # ...
      pipelines: 
    7
    
        - name: syslog-pipeline
          inputRefs:
            - syslog-receiver
          outputRefs:
            - <output_name>
    # ...

    1 2
    Use the service account that you granted the collect-infrastructure-logs permission in the previous step.
    3
    Specify a name for your input receiver.
    4
    Specify the input receiver type as syslog.
    5
    Optional: Specify the port that the input receiver listens on. This must be a value between 1024 and 65535.
    6
    If TLS configuration is not set, the default certificates will be used. For more information, run the command oc explain clusterlogforwarders.spec.inputs.receiver.tls.
    7
    Configure a pipeline for your input receiver.
  3. Apply the changes to the ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml
  4. Verify that the collector is listening on the service that has a name in the <clusterlogforwarder_resource_name>-<input_name> format by running the following command:

    $ oc get svc

    Example output

    NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)            AGE
    collector                   ClusterIP   172.30.85.239    <none>        24231/TCP          33m
    collector-syslog-receiver   ClusterIP   172.30.216.142   <none>        10514/TCP          2m20s

    In this example output, the service name is collector-syslog-receiver.

Verification

  1. Extract the certificate authority (CA) certificate file by running the following command:

    $ oc extract cm/openshift-service-ca.crt -n <namespace>
    Note

    If the CA in the cluster where the collectors are running changes, you must extract the CA certificate file again.

  2. As an example, use the curl command to send logs by running the following command:

    $ curl --cacert <openshift_service_ca.crt> collector-syslog-receiver.<namespace>.svc:10514  “test message”

    Replace <openshift_service_ca.crt> with the extracted CA certificate file.

1.2. Configuring pod rollout strategy

You can configure the collector pods rollout strategy so that the requests to the API server are minimized during upgrades and restarts.

Note

Unlike in previous releases, API server kube-api caching is always enabled.

Prerequisites

  • You have administrator permissions.
  • You installed the OpenShift CLI (oc).
  • You installed and configured Red Hat OpenShift Logging Operator.
  • You have created a ClusterLogForwarder custom resource (CR).

Procedure

  1. Update the ClusterLogForwarder CR:

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: my-forwarder
      namespace: openshift-logging
    spec:
      collector:
        maxUnavailable: <value>

    Where <value> can be a number or percentage. If you do not specify a value, the default value of 100% is used for the maxUnavailable field.

  2. Apply the ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml

1.3. Configure log collector CPU and memory limits

You can adjust both the CPU and memory limits for the log collector by editing the ClusterLogForwarder custom resource (CR).

Procedure

  • Edit the ClusterLogForwarder CR in the openshift-logging project:

    $ oc -n openshift-logging edit clusterlogforwarder.observability.openshift.io <clf_name>
    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <clf_name> 
    1
    
      namespace: openshift-logging
    spec:
      collector:
        resources: 
    2
    
          requests:
            memory: 736Mi
          limits:
            cpu: 100m
            memory: 736Mi
    # ...
    1
    Specify a name for the ClusterLogForwarder CR.
    2
    Specify the CPU and memory limits and requests as needed. The values shown are the default values.

Red Hat OpenShift Logging Operator optionally provides permissive NetworkPolicy resources to override any restrictive network policies present in an OpenShift Container Platform cluster.

The NetworkPolicy resource ensures that all ingress and egress traffic is allowed even when the following restrictions are in place:

  • Restrictive default NetworkPolicies resource has been defined in the cluster.
  • AdminNetworkPolicy configuration that limits pod communications is applied.
  • Namespace-level network restrictions are defined.

Red Hat OpenShift Logging Operator provides permissive NetworkPolicy resources for the collector and the LogFileMetricExporter.

1.4.1. Collector network policy

Red Hat OpenShift Logging Operator creates a NetworkPolicy resource for the collector pods when a ClusterLogForwarder resource is deployed if you specify a network policy rule set in the ClusterLogForwarder custom resource (CR). NetworkPolicy resources are automatically created, updated, and removed along with the component deployment lifecycle.

You can specify the network policy rule set by defining the networkPolicy.ruleSet field in the collector specification. The collector supports the following network policy rule set types:

AllowAllIngressEgress
Allows all ingress and egress traffic.
RestrictIngressEgress
Restricts traffic to specific ports based on the configured inputs, outputs, and the metrics port.

If you do not define a spec.collector.networkPolicy field, the Operator will not create a NetworkPolicy resource for the collector. Without a NetworkPolicy resource, logging components might not function if a cluster-wide AdminNetworkPolicy restricts traffic or other restrictive network policies are in place.

Define a network policy rule set so that Red Hat OpenShift Logging Operator creates a NetworkPolicy resource for the collector pods when the ClusterLogForwarder resource is deployed. The NetworkPolicy resource overrides network restrictions to ensure that the permitted ingress and egress traffic for the collector pods is allowed to flow.

Prerequisites

  • You have administrator permissions.
  • You have installed the OpenShift CLI (oc).
  • You have installed the Red Hat OpenShift Logging Operator.
  • You have created a ClusterLogForwarder custom resource (CR).

Procedure

  1. Update the ClusterLogForwarder CR:

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: my-forwarder
      namespace: openshift-logging
    spec:
      collector:
        networkPolicy:
          ruleSet: <RestrictIngressEgress_or_AllowAllIngressEgress>
      # ...

    Where the value for the ruleSet field can be either RestrictIngressEgress or AllowAllIngressEgress.

  2. Apply the configuration by running the following command:

    $ oc apply -f <filename>.yaml

1.4.3. LogFileMetricExporter network policy

Red Hat OpenShift Logging Operator creates a NetworkPolicy resource for the metric exporter pods when a LogFileMetricExporter resource is deployed if you specify a network policy rule set in the LogFileMetricExporter custom resource (CR). NetworkPolicy resources are automatically created, updated, and removed along with the component deployment lifecycle.

The LogFileMetricExporter resource supports the following network policy rule set types:

AllowIngressMetrics
Allows ingress traffic only on the metrics port, denies all egress traffic.
AllowAllIngressEgress
Allows all ingress and egress traffic.

If you do not define a spec.networkPolicy field, the Operator will not create a NetworkPolicy resource for the LogFileMetricExporter. Without a NetworkPolicy resource, logging components might not function if a cluster-wide AdminNetworkPolicy restricts traffic or other restrictive network policies are in place.

Define a network policy rule set so that Red Hat OpenShift Logging Operator creates a NetworkPolicy resource for the LogFileMetricExporter pods when the LogFileMetricExporter resource is deployed. The NetworkPolicy resource overrides network restrictions to ensure that the permitted ingress and egress traffic for the LogFileMetricExporter pods is allowed to flow.

Prerequisites

  • You have administrator permissions.
  • You have installed the OpenShift CLI (oc).
  • You have installed the Red Hat OpenShift Logging Operator.
  • You have created a LogFileMetricExporter CR.

Procedure

  1. Update the LogFileMetricExporter CR:

    apiVersion: logging.openshift.io/v1alpha1
    kind: LogFileMetricExporter
    metadata:
      name: my-lfme
      namespace: openshift-logging
    spec:
      networkPolicy:
        ruleSet: <AllowAllIngressEgress_or_AllowIngressMetrics>
    #...

    Where the value for the ruleSet field can be either AllowAllIngressEgress or AllowIngressMetrics.

  2. Apply the configuration by running the following command:

    $ oc apply -f <filename>.yaml

To ensure that the pods running resources managed by Red Hat OpenShift Logging Operator can communicate when an AdminNetworkPolicy configuration is blocking traffic, create an AdminNetworkPolicy rule that delegates to a NetworkPolicy definition.

OpenShift Container Platform network policy precedence:

  • AdminNetworkPolicy: Cluster-admin controlled, highest priority.
  • BaselineAdminNetworkPolicy: Default fallback rules.
  • NetworkPolicy: Namespace-level policies. This is where collector policies reside.

Prerequisites

  • You have administrator permissions.
  • You installed the OpenShift CLI (oc).

Procedure

  1. Create an AdminNetworkPolicy rule:

    apiVersion: policy.networking.k8s.io/v1alpha1
    kind: AdminNetworkPolicy
    metadata:
      name: allow-logging-collector-delegation
    spec:
      priority: 50 # Adjust based on your cluster's ANP priority scheme. Lower number means higher priority
      subject:
        pods: # Target the pods in openshift-logging namespace
          namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: openshift-logging
          podSelector:
            matchLabels:
              app.kubernetes.io/name: <name>
              app.kubernetes.io/instance: <instance>
              app.kubernetes.io/managed-by: cluster-logging-operator
              app.kubernetes.io/part-of: cluster-logging
              app.kubernetes.io/component: <component>
      ingress:
        - name: "delegate-to-collector-ingress"
          action: "Pass"
          from:
            # Select all pods in all namespaces as the source.
            - pods:
                namespaceSelector: {}
                podSelector: {}
      egress:
        - name: "delegate-to-collector-egress"
          action: "Pass"
          to:
            # Select all pods in all namespaces for internal traffic.
            - pods:
                namespaceSelector: {}
                podSelector: {}
            # Select all external destinations for egress traffic.
            - networks:
              - "0.0.0.0/0"
              - "::/0"

    To apply this network policy to all the resources in a namespace, remove app.kubernetes.io/name, app.kubernetes.io/instance, and app.kubernetes.io/component fields. To apply the admin network policy to specific resources, define the fields as follows:

    • Replace <name> with the name of the collector or the LogFileMetricExporter resource.
    • Replace <instance> with the instance name of the collector or the LogFileMetricExporter resource.
    • Replace <component> with the value collector or logfilesmetricexporter.
  2. Apply the AdminNetworkPolicy rule by running the following command:

    $ oc apply -f <filename>.yaml

Chapter 2. Configuring log forwarding

Implement a tailored log routing pipeline to deliver the right data to the right stakeholders. By configuring log forwarding, you can bridge the gap between raw cluster telemetry and the specific needs of site reliability engineers (SREs), security officers, and developers, ensuring high-signal logs reach your external destinations while managing storage costs and compliance requirements.

2.1. About log forwarding

You can design a log routing pipeline that connects raw cluster telemetry to the specific needs of your organization. A managed data service can help you balance deep operational visibility for site reliability engineers (SREs) with strict long-term retention requirements for security and compliance officers.

In a complex OpenShift Container Platform environment, a one-size-fits-all approach to logging is often too expensive or legally insufficient. Log forwarding helps you do the following:

  • Reduce costs: Use filters to drop "noisy" debug logs or rate-limit high-volume applications before they hit expensive storage.
  • Ensure compliance: Isolate sensitive audit trails and route them to immutable "cold storage" for long-term legal retention.
  • Empower teams: Deliver application-specific logs directly to tools such as LokiStack, Splunk, or Datadog, allowing developers to use familiar platforms they already know.

By orchestrating multiple log routing pipelines, you can resolve the natural tensions between different log consumers:

  • Cost versus visibility: Provide SREs with high-volume logs for short-term troubleshooting without incurring the costs of long-term storage on high-performance systems.
  • Compliance versus accessibility: Create a dedicated audit log routing pipeline that bypasses standard developer tools to ship raw data directly to an immutable security archive.
  • Data sovereignty: Ensure that filters prune specific fields or logs from sensitive namespaces before they leave the cluster for a third-party SaaS provider.

2.2. How log forwarding works

Log forwarding is powered by a collector that runs as a DaemonSet on every node in your cluster. To manage how this collector handles data, you define a ClusterLogForwarder custom resource (CR) that routes logs through three distinct functional areas:

Inputs

Inputs define the source of your telemetry. The collector recognizes three reserved, high-level input types:

  • Application: Application logs provide telemetry for user-deployed workloads.
  • Infrastructure: Infrastructure logs provide telemetry for the node operating system and OpenShift Container Platform components.
  • Audit: Audit logs provide telemetry for sensitive security and API server records.

    In addition to these default input types, you can configure receiver inputs that allow the collector to listen for incoming log data from external sources. Receiver inputs enable the collector to act as a server that accepts logs over HTTP or syslog protocols. This is useful when logs originate from Red Hat-supported products installed on the same cluster, such as Red Hat OpenStack Services on OpenShift (RHOSO) or OpenShift Virtualization, or when logging is installed on hosted control planes.

    Tip

    You can also define custom inputs to target specific namespaces or pods using label selectors, which can isolate data for specific application teams.

Filters
Filters serve as the logic gates where you enforce data policies. You use filters to refine the stream before it leaves the cluster. This includes using a prune filter to remove specific metadata or JSON fields containing personally identifiable information (PII), and a drop filter to discard records based on regular expressions or severity levels. The collector also supports rate limiting to prevent a single high-volume application from overwhelming your storage infrastructure.
Outputs
Outputs specify the final destination for the telemetry. You can configure multiple outputs to satisfy different consumers simultaneously. Supported destinations include internal stores like LokiStack, external providers like Splunk, Datadog, or Amazon CloudWatch, and standard protocols like Kafka, Syslog, or S3-compatible object storage.

Log routing pipelines act as the central orchestrator of the entire log routing process. A pipeline is not a step in the sequence, but the configuration logic that binds inputs and filters to specific outputs. By defining multiple pipelines within a single ClusterLogForwarder CR, you can split a single source into different paths. For example, one log routing pipeline can send raw audit logs to an S3 bucket for compliance, while a second pipeline filters those same logs for errors and sends them to a site reliability engineer (SRE) alerting dashboard.

Service account permissions ensure the collector has the necessary authority to gather logs. The collector uses a specific service account, identified in the spec.serviceAccount.name field of the CR. You must provide this service account with the appropriate ClusterRoleBinding permissions for each log type that you intend to collect.

2.3. About collector permissions and identity

The Red Hat OpenShift Logging Operator uses a collector to gather logs from across your cluster. For the collector to access these logs, it must have a distinct role and explicit permission to read specific types of log data from the nodes and the API.

Service account
When you configure log forwarding, you must first create a ServiceAccount in the openshift-logging namespace. This service account acts as the identity for the collector pods. You must reference this account by name when you create your ClusterLogForwarder custom resource (CR).
Log types and cluster roles

OpenShift Container Platform protects log data using role-based access control (RBAC). To allow the collector to "see" logs, you must create ClusterRoleBindings that connect your service account to the following predefined roles:

  • collect-application-logs: Grants access to logs from user-defined projects.
  • collect-infrastructure-logs: Grants access to logs from the nodes and system projects such as openshift-* and kube-*.
  • collect-audit-logs: Grants access to the sensitive audit logs that the API server and OAuth server generate.
Important

Sequence is critical. You must grant these permissions before you include the corresponding log types in your ClusterLogForwarder configuration.

If the ClusterLogForwarder CR requests a log type that the collector’s service account is not authorized to access, the Operator enters a protective failure state. To prevent an insecure or partial configuration, the Operator removes the entire collector DaemonSet, which stops all log collection for the cluster.

2.4. Granting collector permissions

You must grant explicit permissions to the collector service account before the ClusterLogForwarder can collect logs. Each log type requires a separate ClusterRoleBinding.

Warning

Avoid a service outage: Always create the required ClusterRoleBinding before you add a new log type to the ClusterLogForwarder custom resource (CR).

If you add a log type to your pipeline without the corresponding permissions, the Operator removes the entire collector DaemonSet. This stops all log collection for the entire cluster.

Prerequisites

  • You have installed the Red Hat OpenShift Logging Operator.
  • You have cluster-admin permissions.

Procedure

  1. Create a service account for the collector. This example creates the service account in the openshift-logging namespace, but you can deploy the collector in any namespace by running the following command:

    $ oc create sa collector -n openshift-logging
  2. Grant the service account permission to collect application logs by running the following command:

    $ oc adm policy add-cluster-role-to-user collect-application-logs \
      system:serviceaccount:openshift-logging:collector
  3. Grant the service account permission to collect infrastructure logs by running the following command:

    $ oc adm policy add-cluster-role-to-user collect-infrastructure-logs \
      system:serviceaccount:openshift-logging:collector
  4. Optional: Grant the service account permission to collect audit logs by running the following command:

    $ oc adm policy add-cluster-role-to-user collect-audit-logs \
      system:serviceaccount:openshift-logging:collector
    Note

    You can add audit log collection later. If you do, grant this ClusterRoleBinding before you add audit to the inputRefs list in your ClusterLogForwarder CR.

    Considerations for audit logs:

    • Volume and Cost: Audit logs are significantly more voluminous than application or infrastructure logs. In cloud environments, this can lead to unexpected storage and data transfer costs.
    • Sensitivity: Audit logs contain a detailed record of API activity. To protect sensitive metadata and manage data volume, consider implementing prune filters to remove specific fields before the logs are forwarded to their destination.

Verification

  • Verify that the ClusterRoleBindings exist for your service account by running the following command:

    $ oc get clusterrolebinding -o wide | grep collect

    The output shows a binding for each log type that you granted:

    Example output

    collect-application-logs     ClusterRole/collect-application-logs     11m   system:serviceaccount:openshift-logging:collector
    collect-infrastructure-logs  ClusterRole/collect-infrastructure-logs  11m   system:serviceaccount:openshift-logging:collector

2.5. Creating the log forwarder

Create a ClusterLogForwarder custom resource (CR) to define your log forwarding pipeline. This CR links the collector’s service account to specific log sources, optional filters, and your chosen destination.

Prerequisites

  • You have cluster-admin permissions.
  • You have installed the Red Hat OpenShift Logging Operator in the openshift-logging namespace.
  • You have created a collector service account and granted the required ClusterRoleBindings. See "Granting collector permissions for log collection."
  • You have installed the Loki Operator and a LokiStack instance named logging-loki exists in the openshift-logging namespace if you are forwarding logs to LokiStack.
Warning

Prerequisite Check: You must have already created the collector service account and granted it the required permissions. If you reference a service account or log source without the proper ClusterRoleBinding, the Operator will shut down all log collection for the cluster.

Procedure

  1. Define the ClusterLogForwarder CR. Use the following example to forward application and infrastructure logs to an in-cluster LokiStack.

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: instance
      namespace: openshift-logging
    spec:
      serviceAccount:
        name: collector
      outputs:
      - name: default-lokistack
        type: lokiStack
        lokiStack:
          authentication:
            token:
              from: serviceAccount
          target:
            name: logging-loki
            namespace: openshift-logging
        tls:
          ca:
            configMapName: logging-loki-gateway-ca-bundle
            key: service-ca.crt
      pipelines:
      - name: default-logstore
        inputRefs:
        - application
        - infrastructure
        outputRefs:
        - default-lokistack
    metadata.name
    The name must be instance. It is a singleton.
    spec.serviceAccount.name
    The service account that the collector uses to authenticate. This service account must have ClusterRoleBindings for each log type listed in inputRefs.
    spec.outputs[].type
    Set to lokiStack for the in-cluster LokiStack. This type uses the LokiStack gateway for authentication and multi-tenancy.
    spec.outputs[].lokiStack.target.name
    The name of your LokiStack CR. This value must strictly match the name of the LokiStack you want to forward logs to, and is not bound to a specific default.
    spec.outputs[].tls.ca.configMapName
    The ConfigMap that has the certificate authority (CA) bundle for the LokiStack gateway. Use logging-loki-gateway-ca-bundle.
    spec.outputs[].tls.ca.key

    The key in the ConfigMap that has the CA certificate. For the service-signed certificate, use service-ca.crt.

    Note

    You must include the tls.ca block in the output configuration when forwarding to LokiStack. Without it, the collector cannot verify the LokiStack gateway certificate. The ClusterLogForwarder reports Ready, but the collector fails silently and no logs reach LokiStack.

    spec.pipelines[].inputRefs
    The log types to collect. Add only log types for which the service account has ClusterRoleBindings.
  2. Apply the ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml
  3. Verify that the ClusterLogForwarder status shows Ready by running the following command:

    $ oc get clusterlogforwarder instance -n openshift-logging \
      -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}'

    The output should show True. If the output shows False, check the status.conditions for error messages:

    $ oc get clusterlogforwarder instance -n openshift-logging \
      -o jsonpath='{.status.conditions}' | python3 -m json.tool

2.5.1. Checking status conditions

You can view the ClusterLogForwarder status conditions to verify that the CR is valid and the collector is running.

Procedure

  • View the ClusterLogForwarder status by running the following command:

    $ oc get clusterlogforwarder instance -n openshift-logging \
      -o jsonpath='{.status.conditions}' | python3 -m json.tool

    Example output

    [
        {
            "type": "observability.openshift.io/Authorized",
            "status": "True",
            "message": "permitted to collect log types: [application audit infrastructure]"
        },
        {
            "type": "observability.openshift.io/Valid",
            "status": "True",
            "message": ""
        },
        {
            "type": "Ready",
            "status": "True",
            "message": ""
        }
    ]

2.5.2. About status conditions

The ClusterLogForwarder reports its state through status.conditions. Use these conditions to verify that the CR is valid and the collector is running:

Expand
Table 2.1. ClusterLogForwarder status conditions
ConditionExpectedDescription

observability.openshift.io/Authorized

True

The collector service account has ClusterRoleBindings for all log types in inputRefs. The message lists the authorized log types.

observability.openshift.io/Valid

True

The CR passes schema and semantic validation.

Ready

True

The Operator reconciled the CR without error or validation failures, and can create resources to support a collector deployment.

If Authorized shows False, the collector service account lacks a required ClusterRoleBinding. The Operator removes the collector DaemonSet until you grant the missing binding.

If Valid shows False, the CR has a structural or semantic error. Check the message field for details.

2.5.3. Verifying that log collection is working

After you create the ClusterLogForwarder custom resource (CR), verify that the collector is running and that logs are flowing to your destination. This verification step is critical for all stakeholders: developers need to confirm that their application logs are accessible, site reliability engineers need operational visibility, and security officers must ensure that audit logs are being captured for compliance.

Prerequisites

  • You have created a ClusterLogForwarder CR.
  • You have access to the OpenShift Container Platform web console.

Procedure

  1. Verify that the ClusterLogForwarder status conditions all show True by running the following command:

    $ oc get clusterlogforwarder instance -n openshift-logging \
      -o jsonpath='{.status.conditions}' | python3 -m json.tool

    Confirm the following conditions:

    • observability.openshift.io/Authorized is True and the message lists the log types that the collector can collect.
    • observability.openshift.io/Valid is True.
    • Ready is True.

    If Authorized shows False, the collector service account lacks a required ClusterRoleBinding. See "Granting collector permissions for log collection."

  2. Verify that a collector pod is running by running the following command:

    $ oc get pods -n openshift-logging -l app.kubernetes.io/component=collector

    Example output

    NAME               READY   STATUS    RESTARTS   AGE
    instance-jlhjw     1/1     Running   0          5m

  3. In the OpenShift Container Platform web console, go to Observe > Logs.
  4. Select a log type from the drop-down menu, such as infrastructure, and verify that log entries appear.
  5. Optional: Check the collector logs for errors by running the following command:

    $ oc logs -n openshift-logging -l app.kubernetes.io/component=collector --tail=20

Troubleshooting

  • 429 Too Many Requests: This status code can occur during initial log collection. The collector flushes a backlog of accumulated logs to the LokiStack. The error typically resolves within several minutes.
  • certificate verify failed: self-signed certificate in certificate chain: The tls.ca block is missing or incorrect in the ClusterLogForwarder output configuration. The ClusterLogForwarder still reports Ready, but the collector cannot deliver logs. See "Creating a ClusterLogForwarder for LokiStack`" for the required `tls.ca configuration.
  • Collector pod not found: If no collector pod exists, check the ClusterLogForwarder status conditions. A common cause is a missing ClusterRoleBinding for one of the log types in inputRefs. See "Granting collector permissions for log collection."

2.6. Configuring inputs

2.6.1. ClusterLogForwarder input types

Input types define the source of log data for the collector to gather and forward. You can configure inputs to select specific log streams from different parts of your cluster.

application

Selects logs from user-deployed application containers. This input type excludes logs from infrastructure namespaces. You can further customize which application logs to collect by specifying namespace and pod label selectors.

Use case: Developers need access to their application logs for debugging and troubleshooting. Use custom inputs with label selectors to route logs from specific applications to dedicated outputs that development teams can access.

The application input type can be configured with the following:

  • selector: A label selector to collect logs only from pods with matching labels
  • includes: A list of namespaces and container patterns to include
  • excludes: A list of namespaces and container patterns to exclude
  • tuning: Configuration for rate limiting per container and maximum message size
infrastructure

Selects logs from infrastructure components and system services. This includes logs from two sources:

  • container: Container logs from workloads deployed in namespaces with the default, kube*, or openshift* prefix
  • node: Journal logs from the cluster nodes

If you do not specify sources, the collector gathers logs from both container and node sources.

Use case: Site reliability engineers need infrastructure logs for troubleshooting cluster issues, analyzing node performance, and monitoring Red Hat OpenShift Logging component health.

audit

Selects audit logs that track security-relevant events in the cluster. Audit logs are sourced from multiple components:

  • kubeAPI: Kubernetes API server audit logs
  • openshiftAPI: Red Hat OpenShift Logging API server audit logs
  • auditd: Node audit daemon logs
  • ovn: Open Virtual Network audit logs

If you do not specify sources, the collector gathers logs from all audit sources.

Use case: Security officers require audit logs for compliance, security investigations, and maintaining an immutable record of API activity. Audit logs are typically more voluminous and require careful consideration of storage costs and retention policies.

receiver

Creates a network listener that receives logs from sources outside the cluster. This input type can accept logs from remote systems or applications that cannot use the standard collector deployment.

Supported receiver types include:

  • http: Receives logs over HTTP (currently supports Kubernetes audit logs only)
  • syslog: Receives logs using the syslog protocol (currently supports infrastructure logs only)

Each receiver requires a port number between 1024 and 65535. The operator can request TLS certificates from the cluster certificate signing service or you can provide your own certificates.

You can include or exclude the application logs based on the namespace and container name by using the input selector.

Procedure

  1. Add a configuration to include or exclude the namespace and container names in the ClusterLogForwarder CR.

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    # ...
    spec:
      serviceAccount:
        name: <service_account_name>
      inputs:
        - name: mylogs
          application:
            includes:
              - namespace: "my-project"
                container: "my-container"
            excludes:
              - container: "other-container*"
                namespace: "other-namespace"
          type: application
    # ...
    includes.namespace
    Specifies that the logs are only collected from these namespaces.
    includes.container
    Specifies that the logs are only collected from these containers.
    excludes.namespace
    Specifies the pattern of namespaces to ignore when collecting the logs.
    excludes.container

    Specifies the set of containers to ignore when collecting the logs.

    Note

    The excludes field takes precedence over the includes field.

  2. Apply the ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml

You can include the application logs based on the label expressions or a matching label key and its values by using the input selector.

Procedure

  1. Add a configuration for a filter to the input spec in the ClusterLogForwarder CR.

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    # ...
    spec:
      serviceAccount:
        name: <service_account_name>
      inputs:
        - name: mylogs
          application:
            selector:
              matchExpressions:
              - key: env
                operator: In
                values: ["prod", "qa"]
              - key: zone
                operator: NotIn
                values: ["east", "west"]
              matchLabels:
                app: one
                name: app1
          type: application
    # ...
    matchExpressions.key
    Specifies the label key to match.
    matchExpressions.operator
    Specifies the operator. Valid values include: In, NotIn, Exists, and DoesNotExist.
    matchExpressions.values
    Specifies an array of string values. If the operator value is either Exists or DoesNotExist, the value array must be empty.
    matchLabels
    Specifies an exact key and value mapping.
  2. Apply the ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml

You can define the list of audit and infrastructure sources to collect the logs by using the input selector.

Procedure

  1. Add a configuration to define the audit and infrastructure sources in the ClusterLogForwarder CR.

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    # ...
    spec:
      serviceAccount:
        name: <service_account_name>
      inputs:
        - name: mylogs1
          type: infrastructure
          infrastructure:
            sources:
              - node
        - name: mylogs2
          type: audit
          audit:
            sources:
              - kubeAPI
              - openshiftAPI
              - ovn
    # ...
    infrastructure.sources

    Specifies the list of infrastructure sources to collect. The valid sources include:

    • node: Journal log from the node
    • container: Logs from the workloads deployed in the namespaces
    audit.sources

    Specifies the list of audit sources to collect. The valid sources include:

    • kubeAPI: Logs from the Kubernetes API servers
    • openshiftAPI: Logs from the OpenShift API servers
    • auditd: Logs from a node auditd service
    • ovn: Logs from an open virtual network service
  2. Apply the ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml

2.6.5. Adding audit log collection

To add audit log collection to an existing pipeline, you must explicitly grant the collect-audit-logs permission to the collector service account. You must complete this step before updating your ClusterLogForwarder custom resource (CR). Failure to grant this permission before adding the audit log type will trigger a protective shutdown of the entire collector DaemonSet, stopping all log collection across the cluster.

Warning

If you add audit to the inputRefs list of the ClusterLogForwarder`CR without first granting the `collect-audit-logs permission to the ClusterRoleBinding, the Operator removes the entire collector DaemonSet. All log collection stops until you grant the missing permission.

Note

Logging is not a Security Information and Event Monitoring (SIEM) system and does not provide secure storage for audit logs. Audit logs are not stored by default. You must configure a ClusterLogForwarder CR to forward audit logs to a storage solution. For more information about Logging capabilities and limitations, see "OpenShift Logging support".

Procedure

  1. Grant the collector service account permission to collect audit logs:

    $ oc adm policy add-cluster-role-to-user collect-audit-logs \
      system:serviceaccount:<namespace>:<service_account_name>

    Replace <namespace> with the namespace where your ClusterLogForwarder CR is deployed and <service_account_name> with the name you specified in the ClusterLogForwarder CR spec.serviceAccount.name field.

  2. Add audit to the inputRefs list in your ClusterLogForwarder pipeline by editing the CR:

    $ oc edit clusterlogforwarder <clusterlogforwarder_name> -n <namespace>

    Replace <clusterlogforwarder_name> with the name of your ClusterLogForwarder CR and <namespace> with the namespace where it is deployed.

    Note

    In Logging versions before 5.9, the ClusterLogForwarder CR was a singleton named instance in the openshift-logging namespace. Starting in Logging 5.9, you can create multiple ClusterLogForwarder CRs with different names in different namespaces.

    Example configuration

    spec:
      # ... other configuration
      outputs:
      - name: default-loki
        # ... output configuration
      pipelines:
      - name: my-pipeline
        inputRefs:
        - application
        - infrastructure
        - audit
        outputRefs:
        - default-loki

  3. Verify that the ClusterLogForwarder still shows Ready by running the following command:

    $ oc get clusterlogforwarder <clusterlogforwarder_name> -n <namespace> \
      -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}'

    Replace <clusterlogforwarder_name> with the name of your ClusterLogForwarder CR and <namespace> with the namespace where it is deployed.

    The output should show True.

  4. Verify that the Authorized condition lists audit by running the following command:

    $ oc get clusterlogforwarder <clusterlogforwarder_name> -n <namespace> \
      -o jsonpath='{.status.conditions[?(@.type=~"Authorized")].message}'

    Example output

    permitted to collect log types: [application audit infrastructure]

2.7. Configuring filters

2.7.1. ClusterLogForwarder filter types

Filter types transform or drop log records as they flow through a pipeline. Filters are applied sequentially in the order specified in the pipeline configuration. A log record dropped by an earlier filter does not reach subsequent filters.

detectMultilineException
Enables multi-line error detection for container logs. This filter recognizes stack traces and exception messages that span multiple lines and combines them into a single log record. No additional configuration is required.
drop

Drops entire log records based on conditional tests. A drop filter contains one or more tests, where each test contains multiple conditions. If all conditions in a test are true, the log record is dropped. This filter is useful for reducing log volume by excluding known noisy or irrelevant messages.

Use case: Site reliability engineers can reduce storage costs by dropping debug-level logs or messages from non-critical namespaces before they reach expensive long-term storage.

Each condition specifies:

  • A field path in the log record (for example, .kubernetes.namespace_name)
  • A regular expression that the field value either matches or does not match

The collector applies tests in sequence and drops the record if any test passes.

kubeAPIAudit

Removes unwanted Kubernetes API audit events and reduces event size to create a manageable audit trail. This filter allows you to exclude audit events based on omit stages, omit response codes, and other criteria. Configure this filter to reduce storage costs while maintaining compliance requirements for audit log retention.

Use case: Security officers can filter out low-value audit events while retaining critical security-relevant records, balancing compliance requirements with storage costs.

openshiftLabels
Adds custom labels to log records passing through the pipeline. These labels appear in the openshift.labels map in the log record and can be used for routing decisions in downstream systems. Use this filter to tag logs with environment identifiers, team ownership, or compliance classifications.
parse
Parses log entries into structured log records. This filter attempts to parse the message field as JSON and adds the parsed message to the top level structured field of the log record. No additional configuration is required. Parsing is best-effort; if the message cannot be parsed, it is left unchanged.
prune

Removes specific fields from log records to reduce the size of logs flowing into the log store. This filter is essential for managing storage costs and ensuring compliance with data privacy requirements.

The prune filter supports two modes:

  • in: Specifies field paths to remove from the log record
  • notIn: Specifies field paths to keep (all other fields are removed)

Use case: Security officers must prune personally identifiable information (PII) from logs before forwarding them to third-party SaaS providers to ensure data sovereignty and compliance with privacy regulations.

Important

You cannot prune the following required fields: .log_type, .log_source, .message, .kubernetes.namespace_name, .kubernetes.pod_name, .kubernetes.container_name, and .level. If you try to prune these required fields, the Operator accepts the CR but sets the validation condition to False.

Additional pruning restrictions apply for specific output types:

  • For googleCloudLogging output: .hostname cannot be pruned.
  • For lokiStack output: See the LokiStack output documentation for additional fields that cannot be pruned.

2.7.2. API audit filter overview

OpenShift API servers generate audit events for every API call. These events include details about the request, the response, and the identity of the requester. This can lead to large volumes of data.

The API audit filter helps manage the audit trail by using rules to exclude non-essential events and to reduce the event size. Rules are checked in order, and checking stops at the first match. The amount of data in an event depends on the value of the level field:

  • None: The event is dropped.
  • Metadata: The event includes audit metadata and excludes request and response bodies.
  • Request: The event includes audit metadata and the request body, and excludes the response body.
  • RequestResponse: The event includes all data: metadata, request body and response body. The response body can be very large. For example, oc get pods -A generates a response body containing the YAML description of every pod in the cluster.
Note

You can only use the API audit filter feature if the Vector collector is set up in your logging deployment.

The ClusterLogForwarder custom resource (CR) uses the same format as the standard Kubernetes audit policy. The ClusterLogForwarder CR provides the following additional functions:

Wildcards
Names of users, groups, namespaces, and resources can have a leading or trailing * asterisk character. For example, the openshift-\* namespace matches openshift-apiserver or openshift-authentication namespaces. The \*/status resource matches Pod/status or Deployment/status resources.
Default Rules

Events that do not match any rule in the policy are filtered as follows:

  • Read-only system events such as get, list, and watch are dropped.
  • Service account write events that occur within the same namespace as the service account are dropped.
  • All other events are forwarded, subject to any configured rate limits.

To disable these defaults, either end your rules list with a rule that has only a level field or add an empty rule.

Omit Response Codes
A list of integer status codes to omit. You can drop events based on the HTTP status code in the response by using the OmitResponseCodes field, which lists HTTP status codes for which no events are created. The default value is [404, 409, 422, 429]. If the value is an empty list, [], no status codes are omitted.

The ClusterLogForwarder CR audit policy acts in addition to the OpenShift Container Platform audit policy. The ClusterLogForwarder CR audit filter changes what the log collector forwards, and provides the ability to filter by verb, user, group, namespace, or resource. You can create multiple filters to send different summaries of the same audit stream to different places. For example, you can send a detailed stream to the local cluster log store, and a less detailed stream to a remote site.

Important
  • You must have the collect-audit-logs cluster role to collect the audit logs.
  • The following example provided is intended to illustrate the range of rules possible in an audit policy and is not a recommended configuration.

Example audit policy

apiVersion: observability.openshift.io/v1
kind: ClusterLogForwarder
metadata:
  name: instance
  namespace: openshift-logging
spec:
  serviceAccount:
    name: example-service-account
  pipelines:
    - name: my-pipeline
      inputRefs:
        - audit
      filterRefs:
        - my-policy
      outputRefs:
        - my-output
  filters:
    - name: my-policy
      type: kubeAPIAudit
      kubeAPIAudit:
        # Don't generate audit events for all requests in RequestReceived stage.
        omitStages:
          - "RequestReceived"

        rules:
          # Log pod changes at RequestResponse level
          - level: RequestResponse
            resources:
            - group: ""
              resources: ["pods"]

          # Log "pods/log", "pods/status" at Metadata level
          - level: Metadata
            resources:
            - group: ""
              resources: ["pods/log", "pods/status"]

          # Don't log requests to a configmap called "controller-leader"
          - level: None
            resources:
            - group: ""
              resources: ["configmaps"]
              resourceNames: ["controller-leader"]

          # Don't log watch requests by the "system:kube-proxy" on endpoints or services
          - level: None
            users: ["system:kube-proxy"]
            verbs: ["watch"]
            resources:
            - group: "" # core API group
              resources: ["endpoints", "services"]

          # Don't log authenticated requests to certain non-resource URL paths.
          - level: None
            userGroups: ["system:authenticated"]
            nonResourceURLs:
            - "/api*" # Wildcard matching.
            - "/version"

          # Log the request body of configmap changes in kube-system.
          - level: Request
            resources:
            - group: "" # core API group
              resources: ["configmaps"]
            # This rule only applies to resources in the "kube-system" namespace.
            # The empty string "" can be used to select non-namespaced resources.
            namespaces: ["kube-system"]

          # Log configmap and secret changes in all other namespaces at the Metadata level.
          - level: Metadata
            resources:
            - group: "" # core API group
              resources: ["secrets", "configmaps"]

          # Log all other resources in core and extensions at the Request level.
          - level: Request
            resources:
            - group: "" # core API group
            - group: "extensions" # Version of group should NOT be included.

          # A catch-all rule to log all other requests at the Metadata level.
          - level: Metadata

+ inputRefs:: The collected log types. The value for this field can be audit for audit logs, application for application logs, infrastructure for infrastructure logs, or a named input that is defined for your application.

+ filterRefs:: The name of your audit policy.

2.7.3. Filtering collected logs

You can add filters to a ClusterLogForwarder pipeline to drop, prune, or label log records before the collector sends them to an output. Filters reduce storage costs and remove noise from your log data.

For complete information about all available filter types and their capabilities, see "ClusterLogForwarder filter types" in the Additional resources section.

The following table shows the filter type to use for common tasks:

Expand
Table 2.2. Choosing a filter type
GoalFilter typeExample

Drop all logs from a specific namespace

drop

Drop logs where .kubernetes.namespace_name matches openshift-marketplace

Drop logs that match a field value

drop

Drop logs where .message matches a regex pattern

Remove specific fields from log records

prune

Remove .kubernetes.annotations from all logs

Keep only specific fields in log records

prune

Keep only .message, .kubernetes.namespace_name, and @timestamp

Note

To collect application logs only from certain namespaces, use a custom input instead of a filter. For more information, see "Filtering application logs at input by including or excluding the namespace or container name" in the Additional resources section.

2.7.3.1. Adding a drop filter

Use a drop filter to exclude entire log records based on field values. The filter uses tests that evaluate log fields. Site reliability engineers use drop filters to reduce storage costs by excluding debug-level logs or noisy messages from non-critical namespaces before they reach long-term storage.

Procedure

  1. Add a filter to the spec.filters array and reference it from a pipeline:

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: instance
      namespace: openshift-logging
    spec:
      serviceAccount:
        name: collector
      filters:
      - name: drop-marketplace
        type: drop
        drop:
        - test:
          - field: .kubernetes.namespace_name
            matches: openshift-marketplace
      outputs:
      # ... your output configuration
      pipelines:
      - name: default-logstore
        inputRefs:
        - application
        - infrastructure
        outputRefs:
        - <output_name>
        filterRefs:
        - drop-marketplace
    spec.filters[].name
    A unique name for the filter. Reference this name in a pipeline filterRefs list.
    spec.filters[].type
    Set to drop to exclude matching records.
    spec.filters[].drop[].test[]
    An array of field tests. All tests within a single test array must match for the collector to drop the record (AND logic). If you specify several test arrays in the drop list, the collector drops the record when any test array matches (OR logic).
    spec.filters[].drop[].test[].field
    The dot-delimited path to a field in the log record. Each path segment can contain alphanumeric characters and underscores, a-z, A-Z, 0-9, _, for example, .kubernetes.namespace_name. If segments contain different characters, the segment must be in quotes, for example, .kubernetes.labels."app.version-1.2/beta".
    spec.filters[].drop[].test[].matches
    The value to match against. Supports exact strings and regular expressions. If the field value matches this regular expression, the condition evaluates to True.
    spec.filters[].drop[].test[].notMatches

    The value to not match against. Supports exact strings and regular expressions. If the field value does not match this regular expression, the condition evaluates to True.

    Note

    You can set either matches or notMatches for a single field, but not both. If a field referenced in a test does not exist in the log record, that condition evaluates to False.

    Example: Keep only high-priority log records

    +

    spec:
      filters:
      - name: important
        type: drop
        drop:
        - test:
          - field: .message
            notMatches: "(?i)critical|error"
          - field: .level
            matches: "info|warning"

    + This filter drops records where the message does not contain "critical" or "error" and the level is "info" or "warning".

    + Example: Multiple test conditions (OR logic)

    +

    spec:
      filters:
      - name: drop-noisy-logs
        type: drop
        drop:
        - test:
          - field: .kubernetes.namespace_name
            matches: "openshift.*"
        - test:
          - field: .log_type
            matches: "application"
          - field: .kubernetes.pod_name
            notMatches: "my-pod"

    + This filter drops logs that either come from a namespace starting with openshift (first test), or are application logs that do not have my-pod in the pod name (second test).

  2. Apply the updated ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml

Verification

  • Verify that the collector pods restarted by running the following command:

    $ oc get pods -n <namespace> -l app.kubernetes.io/component=collector

    Replace <namespace> with the namespace where your ClusterLogForwarder CR is deployed. The pod age should show a recent restart.

    Note

    If multiple ClusterLogForwarder CRs exist in the same namespace, this command lists all collector pods. To list only the pods for a specific ClusterLogForwarder CR, add the label -l app.kubernetes.io/instance=<clusterlogforwarder_name> to the command.

2.7.3.2. Adding a prune filter

Use a prune filter to remove or keep specific fields in log records. This reduces the size of each record and hides sensitive metadata without dropping the entire log record. This is particularly useful for managing the high volume and sensitivity of audit logs. Security officers commonly use prune filters to remove personally identifiable information (PII) from logs before forwarding them to third-party systems, ensuring data sovereignty and compliance with privacy regulations.

Procedure

  1. Add a prune filter to the spec.filters array:

    spec:
      filters:
      - name: prune-audit-logs
        type: prune
        prune:
          in: [.audit.requestObject, .audit.responseObject, .audit.managedFields]
    prune.in
    Fields to remove from the log record. The collector keeps all other fields. Use dot notation to specify fields for removal. For audit logs, requestObject and responseObject often contain the most data and sensitive information.
    prune.notIn

    Fields to keep. The collector removes all other fields.

    Important

    You cannot prune the following required fields: .log_type, .log_source, .message, .kubernetes.namespace_name, .kubernetes.pod_name, .kubernetes.container_name, and .level. If you try to prune these required fields, the Operator accepts the CR but sets the validation condition to False.

    Additional pruning restrictions:

    • If you specify both in and notIn, the notIn array takes precedence over in during pruning. The collector processes notIn first to find the fields to keep, and then processes in to remove additional fields from the remaining set.
    • If you use the googleCloudLogging output, you cannot prune .hostname, otherwise the collector cannot forward logs to Google Cloud Logging.
    • If you use the lokiStack output, see the LokiStack output documentation for additional fields that cannot be pruned.
  2. Reference the filter in a pipeline:

    spec:
      pipelines:
      - name: default-logstore
        filterRefs:
        - prune-audit-logs
  3. Apply the updated ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml

Verification

  • Verify that the collector pods restarted by running the following command:

    $ oc get pods -n <namespace> -l app.kubernetes.io/component=collector

    Replace <namespace> with the namespace where your ClusterLogForwarder CR is deployed. The pod age should show a recent restart.

    Note

    If multiple ClusterLogForwarder CRs exist in the same namespace, this command lists all collector pods. To list only the pods for a specific ClusterLogForwarder CR, add the label -l app.kubernetes.io/instance=<clusterlogforwarder_name> to the command.

2.7.4. About multi-line exception detection

When log messages appear as a consecutive sequence forming an exception stack trace, the collector combines them into a single, unified log record. The collector replaces the first log message’s content with the concatenated content of all the message fields in the sequence.

The collector supports the following languages:

  • Java
  • JS
  • Ruby
  • Python
  • Golang
  • PHP
  • Dart

Example java exception

java.lang.NullPointerException: Cannot invoke "String.toString()" because "<param1>" is null
    at testjava.Main.handle(Main.java:47)
    at testjava.Main.printMe(Main.java:19)
    at testjava.Main.main(Main.java:10)

2.7.5. Enabling multi-line exception detection

You can enable multi-line error detection of container logs to combine exception stack traces into a single log record.

Warning

Enabling this feature could have performance implications and might require additional computing resources or alternate logging solutions.

Procedure

  1. To enable logging to detect multi-line exceptions and reassemble them into a single log entry, ensure that the ClusterLogForwarder Custom Resource (CR) has a detectMultilineErrors field under the .spec.filters.

    Example ClusterLogForwarder CR

    apiVersion: "observability.openshift.io/v1"
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
      namespace: <log_forwarder_namespace>
    spec:
      serviceAccount:
        name: <service_account_name>
      filters:
      - name: <name>
        type: detectMultilineException
      pipelines:
        - inputRefs:
            - <input_name>
          name: <pipeline_name>
          filterRefs:
            - <filter_name>
          outputRefs:
            - <output_name>

2.8. Configuring outputs

2.8.1. ClusterLogForwarder output types

Output types define the destination where the collector forwards log records. Each output type has specific configuration requirements for authentication, connection parameters, and data formatting.

azureMonitor

Forwards logs to Azure Monitor Logs service. This output requires a customer ID and shared key for authentication. You can specify a custom log type and associate logs with a specific Azure resource ID.

Warning

The azureMonitor output type is deprecated and will be removed in a future release. This output type will become obsolete in September 2026.

cloudwatch
Forwards logs to Amazon CloudWatch. This output supports two authentication methods: AWS access keys or IAM roles with Security Token Service (STS). You must specify the AWS region and a group name pattern for organizing log streams. CloudWatch outputs support cross-account log forwarding using the AssumeRole feature.
elasticsearch
Forwards logs to an external Elasticsearch cluster. This output is tested with Elasticsearch versions 6, 7, and 8. You must specify the cluster URL, version, and index pattern. Elasticsearch outputs support Basic authentication with username and password, and custom headers for advanced configurations.
googleCloudLogging
Forwards logs to Google Cloud Logging (formerly Stackdriver). This output requires a service account credentials file and supports organization, folder, project, or billing account scopes. You must specify a log ID pattern to identify the log stream.
http
Forwards logs to a generic HTTP endpoint. This output sends logs as JSON or newline-delimited JSON (NDJSON) to any HTTP or HTTPS URL. It supports bearer token and Basic authentication, custom headers, and configurable HTTP methods. Use this output for custom log aggregators or webhook-based integrations.
kafka
Forwards logs to Apache Kafka topics. This output supports Kafka protocol version 0.11 and later. You can specify multiple broker endpoints and configure SASL authentication. The topic name supports template syntax for dynamic per-event routing.
loki
Forwards logs to a Loki aggregation system. This output is suitable for external Loki deployments outside of Red Hat OpenShift Logging. It supports custom label keys for stream identification and tenant keys for multitenant Loki deployments.
lokiStack

Forwards logs to a Red Hat managed LokiStack deployment by using the Red Hat OpenShift Logging tenancy model. This output integrates with Red Hat OpenShift Logging authentication and enforces multitenancy through the LokiStack gateway proxy. The collector automatically discovers the LokiStack service based on the namespace and name you specify.

Use case: Site reliability engineers and developers benefit from LokiStack for short-term troubleshooting and performance analysis. The built-in multitenancy ensures that developers can only access logs from their own namespaces.

Important

The following fields are required as default stream labels for LokiStack and cannot be pruned:

  • .kubernetes.container_name
  • .kubernetes.namespace_name
  • .kubernetes.pod_name

If these fields are not present in the log record, they will be set to the empty string.

otlp

Forwards logs by using the OpenTelemetry Protocol (OTLP) with Red Hat OpenShift Logging semantic conventions. This output sends logs in OTLP format over HTTP or HTTPS to OpenTelemetry collectors and observability backends that support OTLP ingestion.

Use case: Platform teams can forward logs to any observability platform that supports the OTLP protocol. Organizations can also use OpenTelemetry Collector as a central gateway to aggregate logs from multiple clusters before routing to final destinations. This approach provides vendor-neutral log forwarding and simplified multi-destination routing.

Note

The otlp output uses the OpenTelemetry data model, which differs from the ViaQ data model used by other output types. Field names and structure vary between these models.

s3

Forwards logs to Amazon S3 or S3-compatible object storage. This output supports the same authentication methods as CloudWatch (AWS access keys or IAM roles). You must specify the AWS region, bucket name, and key prefix pattern for organizing log objects. Use this output for long-term archival, compliance retention, or integration with data lake pipelines.

Use case: Security officers use S3 for immutable long-term retention of audit logs to meet compliance requirements. S3 bucket lifecycle policies can automatically move logs to cheaper storage tiers while maintaining the required retention period.

splunk

Forwards logs to Splunk HTTP Event Collector (HEC). This output requires a Splunk HEC token for authentication. You can configure custom index, source, and indexed fields to optimize Splunk search performance.

Use case: Developers and site reliability engineers often prefer Splunk because it is a familiar platform with powerful search and visualization capabilities. Organizations can route application and infrastructure logs to Splunk for operational analysis.

syslog
Forwards logs to an external syslog receiver by using RFC3164 or RFC5424 format. This output supports TCP, TLS, and UDP transports. You can customize facility, severity, application name, process ID, and message ID fields by using template syntax.

2.9. Configuring pipelines

2.9.1. ClusterLogForwarder pipelines

Pipelines define the routing logic that connects log sources to destinations. A pipeline binds one or more inputs to one or more outputs, with optional filters applied in between. Pipelines are the central orchestration mechanism that determines which logs flow where and how they are transformed along the way.

name
A unique identifier for the pipeline. Use descriptive names that indicate the pipeline’s purpose, such as app-logs-to-splunk or audit-to-s3.
inputRefs

A list of input names to include in this pipeline. You can reference the built-in inputs (application, infrastructure, audit) or custom inputs you have defined in the spec.inputs section. The collector gathers logs from all referenced inputs and sends them through this pipeline.

Important

You can only reference inputs for log types that the collector service account is authorized to access through ClusterRoleBindings. If you reference an unauthorized log type, the Operator removes the collector DaemonSet and stops all log collection.

outputRefs

A list of output names where the pipeline sends logs. You can send logs to multiple destinations simultaneously by listing multiple outputs. The collector duplicates the log stream and forwards a copy to each output.

Note

If you send the same log record to multiple outputs and one output fails, the collector continues forwarding to other outputs. Each output operates independently.

filterRefs

An optional list of filter names to apply to log records passing through this pipeline. Filters are applied sequentially in the order you specify. If a filter drops a log record, subsequent filters in the list do not process that record.

Common filter ordering patterns:

  • Drop before prune: Apply drop filters first to remove unwanted log records, then apply prune filters to remove fields from the remaining records. This reduces processing work.
  • Parse before filter: Apply parse filters early to convert JSON strings into structured fields, then apply drop or prune filters that operate on those structured fields.
  • Label last: Apply openshiftLabels filters after other transformations to add routing metadata that downstream systems can use.
2.9.1.1. Pipeline examples

The following examples demonstrate common pipeline patterns tailored to the needs of different stakeholders: developers who need application-specific log access, site reliability engineers (SREs) who need operational visibility, and security officers who need compliance and audit trails.

Developer use case - Application logs to familiar tools

Developers need quick access to their application logs in tools they already know. This pipeline forwards application logs to a Splunk instance where development teams can troubleshoot issues:

pipelines:
- name: apps-to-splunk
  inputRefs:
  - application
  outputRefs:
  - splunk-prod
SRE use case - Operational visibility

Site reliability engineers need comprehensive operational visibility across application and infrastructure components. This pipeline forwards both log types to a single LokiStack for short-term troubleshooting and performance monitoring:

pipelines:
- name: all-logs-to-loki
  inputRefs:
  - application
  - infrastructure
  outputRefs:
  - default-lokistack
Security officer use case - Compliance and real-time monitoring

Security officers must balance compliance requirements with operational needs. This pipeline sends audit logs to both an S3 bucket for long-term immutable retention and CloudWatch for real-time security alerting:

pipelines:
- name: audit-to-archive-and-monitor
  inputRefs:
  - audit
  outputRefs:
  - s3-compliance
  - cloudwatch-alerts
Security officer use case - Data sovereignty and PII protection

Security officers must ensure personally identifiable information (PII) does not leave the cluster for third-party SaaS providers. This pipeline drops noisy logs and prunes sensitive fields before forwarding to an external system:

pipelines:
- name: filtered-apps
  inputRefs:
  - application
  filterRefs:
  - drop-marketplace-logs
  - prune-annotations
  outputRefs:
  - external-aggregator
Multi-stakeholder use case - Serving developers, SREs, and security officers

Organizations typically need to serve all three stakeholders simultaneously. This configuration defines separate pipelines for each persona’s needs: developers get application logs in LokiStack, SREs get infrastructure logs in Elasticsearch for performance analysis, and security officers get audit logs with sensitive fields pruned for compliance archival:

pipelines:
- name: apps-to-loki
  inputRefs:
  - application
  outputRefs:
  - lokistack
- name: infrastructure-to-elasticsearch
  inputRefs:
  - infrastructure
  outputRefs:
  - elasticsearch-infra
- name: audit-to-s3
  inputRefs:
  - audit
  filterRefs:
  - prune-sensitive-fields
  outputRefs:
  - s3-compliance
Important

If you do not define a pipeline for a log type, the collector drops logs of that type. For example, if you create pipelines for application and audit logs but not for infrastructure logs, the collector does not collect infrastructure logs.

2.9.1.2. Complete example

This example shows a complete ClusterLogForwarder CR with inputs, filters, outputs, and pipelines:

apiVersion: observability.openshift.io/v1
kind: ClusterLogForwarder
metadata:
  name: instance
  namespace: openshift-logging
spec:
  serviceAccount:
    name: collector
  inputs:
  - name: high-priority-apps
    type: application
    application:
      selector:
        matchLabels:
          priority: high
  filters:
  - name: drop-debug-logs
    type: drop
    drop:
    - test:
      - field: .level
        matches: debug
  - name: remove-annotations
    type: prune
    prune:
      in:
      - .kubernetes.annotations
  outputs:
  - name: lokistack
    type: lokiStack
    lokiStack:
      authentication:
        token:
          from: serviceAccount
      target:
        name: logging-loki
        namespace: openshift-logging
    tls:
      ca:
        configMapName: logging-loki-gateway-ca-bundle
        key: service-ca.crt
  - name: splunk-prod
    type: splunk
    splunk:
      authentication:
        token:
          secretName: splunk-token
      url: https://splunk.example.com:8088
  pipelines:
  - name: priority-apps-to-splunk
    inputRefs:
    - high-priority-apps
    filterRefs:
    - drop-debug-logs
    outputRefs:
    - splunk-prod
  - name: all-apps-to-loki
    inputRefs:
    - application
    filterRefs:
    - remove-annotations
    outputRefs:
    - lokistack
  - name: infrastructure-to-loki
    inputRefs:
    - infrastructure
    outputRefs:
    - lokistack

2.10. Advanced configuration

2.10.1. Configuring rate limits

You can configure rate limits on inputs and outputs to control log forwarding volume and prevent resource exhaustion. Rate limits specify the maximum number of log records per second that the collector can process. When the rate limit is exceeded, the collector drops excess log records.

Prerequisites

  • You have a working ClusterLogForwarder custom resource (CR).
  • You have cluster-admin permissions.

Procedure

  1. Configure rate limits on inputs, outputs, or both.

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: instance
      namespace: openshift-logging
    spec:
      serviceAccount:
        name: collector
      inputs:
      - name: limited-app-logs
        type: application
        application:
          tuning:
            rateLimitPerContainer:
              maxRecordsPerSecond: 100
      outputs:
      - name: limited-splunk
        type: splunk
        splunk:
          url: https://splunk.example.com:8088
          authentication:
            token:
              key: token
              secretName: splunk-secret
        rateLimit:
          maxRecordsPerSecond: 1000
      pipelines:
      - name: app-to-splunk
        inputRefs:
        - limited-app-logs
        outputRefs:
        - limited-splunk
    Input rate limit (inputs[].application.tuning.rateLimitPerContainer)

    Limits the number of log records per second from each container that matches this input. This is a per-container limit. For example, if you set maxRecordsPerSecond: 100 and 10 containers match the input selector, the total input rate could be up to 1000 records per second (100 per container × 10 containers).

    Use case: Site reliability engineers can use input rate limits to prevent noisy applications from overwhelming the log collector and consuming excessive cluster resources.

    Output rate limit (outputs[].rateLimit)

    Limits the total number of log records per second that the collector forwards to this output from a single collector pod. This is an aggregate limit across all pipelines that reference this output. Generally, one collector pod runs per cluster node.

    Use case: Developers can use output rate limits to stay within the ingestion quotas imposed by third-party log aggregation services, preventing overage charges or throttling.

    Important

    When rate limits are exceeded, the collector drops log records. The collector increments the observability_log_forwarder_output_rate_limited_total metric for each dropped record. Monitor this metric to determine if your rate limits are too restrictive.

    Rate limit only on output

    spec:
      outputs:
      - name: rate-limited-kafka
        type: kafka
        kafka:
          brokers:
          - kafka.example.com:9092
          topic: logs
        rateLimit:
          maxRecordsPerSecond: 5000
      pipelines:
      - name: all-logs-to-kafka
        inputRefs:
        - application
        - infrastructure
        outputRefs:
        - rate-limited-kafka

    Rate limit only on input

    spec:
      inputs:
      - name: high-volume-namespace
        type: application
        application:
          includes:
          - namespace: "production"
          tuning:
            rateLimitPerContainer:
              maxRecordsPerSecond: 500
      pipelines:
      - name: production-to-loki
        inputRefs:
        - high-volume-namespace
        outputRefs:
        - default-lokistack

    Different rate limits for different outputs

    spec:
      outputs:
      - name: expensive-splunk
        type: splunk
        splunk:
          url: https://splunk.example.com:8088
          authentication:
            token:
              key: token
              secretName: splunk-secret
        rateLimit:
          maxRecordsPerSecond: 500
      - name: cheap-s3
        type: s3
        s3:
          url: https://s3.us-east-1.amazonaws.com
          bucket: log-archive
        rateLimit:
          maxRecordsPerSecond: 10000
      pipelines:
      - name: critical-to-splunk
        inputRefs:
        - audit
        outputRefs:
        - expensive-splunk
      - name: bulk-to-s3
        inputRefs:
        - application
        - infrastructure
        outputRefs:
        - cheap-s3
  2. Apply the updated ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml

Verification

  • Verify that the collector pods restarted by running the following command:

    $ oc get pods -n openshift-logging -l app.kubernetes.io/component=collector

2.10.2. Tuning log payloads and delivery

The tuning spec in the ClusterLogForwarder custom resource (CR) provides a means of configuring your deployment to prioritize either throughput or durability of logs.

For example, if you need to reduce the possibility of log loss when the collector restarts, or you require collected log messages to survive a collector restart to support regulatory mandates, you can tune your deployment to prioritize log durability. If you use outputs that have hard limitations on the size of batches they can receive, you might want to tune your deployment to prioritize log throughput.

You can tune both inputs and outputs in the ClusterLogForwarder CR.

2.10.2.1. Tuning inputs

You can tune application and infrastructure inputs to control message size limits and rate limiting. These settings apply to container log collection and help prevent resource exhaustion from high-volume logging workloads.

The following example shows the ClusterLogForwarder CR options that you can change to tune log forwarder inputs:

Example ClusterLogForwarder CR input tuning options

apiVersion: observability.openshift.io/v1
kind: ClusterLogForwarder
metadata:
# ...
spec:
  # ...
  inputs:
  - name: application
    type: application
    application:
      tuning:
        container:
          maxMessageSize: 16Ki
          rateLimitPerContainer:
            maxRecordsPerSecond: 1000
  - name: infrastructure
    type: infrastructure
    infrastructure:
      tuning:
        container:
          maxMessageSize: 16Ki
          rateLimitPerContainer:
            maxRecordsPerSecond: 1000

maxMessageSize
Specifies the maximum message length in bytes that a single log event can be when all partial log lines are merged. Messages exceeding this limit are dropped. You can specify this value as an integer or as a string with units such as Ki (kibibytes) or Mi (mebibytes).
rateLimitPerContainer.maxRecordsPerSecond
Specifies the maximum number of log records allowed per second for each container. This limit is applied per collector deployment. When a container exceeds this rate, the collector drops excess log records until the rate falls below the limit.
2.10.2.2. Tuning outputs

The following example shows the ClusterLogForwarder CR options that you can change to tune log forwarder outputs:

Example ClusterLogForwarder CR tuning options

apiVersion: observability.openshift.io/v1
kind: ClusterLogForwarder
metadata:
# ...
spec:
  # ...
  outputs:
  - name: default-lokistack
    type: lokiStack
    lokiStack:
      tuning:
        deliveryMode: AtLeastOnce
        compression: none
        maxWrite: <integer>
        minRetryDuration: 1s
        maxRetryDuration: 1s

deliveryMode

Specify the delivery mode for log forwarding. When left unset, the system defaults to using an in-memory buffer, which offers the highest performance due to low latency but does not provide durability. Buffered data is lost on process termination or failure.

  • AtLeastOnce delivery means that if the log forwarder crashes or restarts, the collector re-sends any logs it read before the crash but did not send to their destination. The collector might duplicate some logs after a crash.
  • AtMostOnce delivery means that the log forwarder makes no effort to recover logs lost during a crash. This mode gives better throughput, but might result in greater log loss.
compression
Specifying a compression configuration causes the collector to compress data before sending it over the network. Note that not all output types support compression, and if the specified compression type is not supported by the output, this results in an error. For more information, see "Supported compression types for tuning outputs".
maxWrite
Specifies a limit for the maximum payload of a single send operation to the output.
minRetryDuration
Specifies a minimum duration to wait between attempts before retrying delivery after a failure. This value is a string, and you can specify it as milliseconds (ms), seconds (s), or minutes (m).
maxRetryDuration
Specifies a maximum duration to wait between attempts before retrying delivery after a failure. This value is a string, and you can specify it as milliseconds (ms), seconds (s), or minutes (m).
Expand
Table 2.3. Supported compression types for tuning outputs
Compression algorithmSplunkAmazon CloudWatchElasticsearch 8LokiStackApache KafkaHTTPSyslogGoogle CloudMicrosoft Azure MonitoringAmazon S3

gzip

X

X

X

X

 

X

   

X

snappy

 

X

 

X

X

X

    

zlib

 

X

X

  

X

    

zstd

 

X

  

X

X

    

lz4

    

X

     

2.10.3. Setting the collector log level

Set the collector log level by adding the observability.openshift.io/log-level annotation to the ClusterLogForwarder custom resource (CR).

Prerequisites

  • You have a working ClusterLogForwarder CR.
  • You have cluster-admin permissions.

Procedure

  1. Set the log level by running the following command:

    $ oc annotate clusterlogforwarder instance -n openshift-logging \
      observability.openshift.io/log-level=debug --overwrite

    The supported log levels are trace, debug, info, warn, error, and off. The default level is info.

  2. Verify that the collector pod restarted with the new log level by running the following command:

    $ oc logs -n openshift-logging -l app.kubernetes.io/component=collector --tail=5

    At the debug level, entries begin with DEBUG.

    Note

    Use debug or trace only for troubleshooting. These levels increase log volume significantly and can affect collector performance. Reset the level to info after troubleshooting.

2.10.4. Setting collector resource limits

Set CPU and memory resource limits by modifying the spec.collector.resources stanza in the ClusterLogForwarder custom resource (CR).

Prerequisites

  • You have a working ClusterLogForwarder CR.
  • You have cluster-admin permissions.

Procedure

  1. Patch the ClusterLogForwarder CR by running the following command:

    $ oc patch clusterlogforwarder instance -n openshift-logging \
      --type=merge \
      -p '{"spec":{"collector":{"resources":{"requests":{"cpu":"100m","memory":"256Mi"},"limits":{"cpu":"500m","memory":"512Mi"}}}}}'
  2. Verify that the collector pod restarted with the updated resources by running the following command:

    $ oc get pods -n openshift-logging -l app.kubernetes.io/component=collector

    The pod age should show a recent restart.

    Note

    If you do not set resource limits explicitly, the collector applies default limits: 500m CPU and 64Mi memory for requests, and 6000m CPU and 2048Mi memory for limits. Setting explicit limits prevents the collector from consuming more resources than expected on nodes with high log volume.

2.10.5. Creating the log file metric exporter

Create a LogFileMetricExporter custom resource (CR) to generate metrics about the logs produced by running containers. The Operator does not deploy the exporter by default, so you must create it manually.

Note

If you do not create the LogFileMetricExporter CR, the Produced Logs field in the OpenShift Container Platform web console dashboard shows No datapoints found.

Prerequisites

  • You have administrator permissions.
  • Ensure that you installed the Red Hat OpenShift Logging Operator.
  • You have installed the OpenShift CLI (oc).

Procedure

  1. Create a LogFileMetricExporter CR as a YAML file:

    apiVersion: logging.openshift.io/v1alpha1
    kind: LogFileMetricExporter
    metadata:
      name: instance
      namespace: openshift-logging
    spec:
      nodeSelector: {}
      resources:
        limits:
          cpu: 500m
          memory: 256Mi
        requests:
          cpu: 200m
          memory: 128Mi
      tolerations: []
    spec.nodeSelector
    Optional: Define the nodes that the exporter pods run on.
    spec.resources
    Optional: Define CPU and memory resource limits and requests for the exporter.
    spec.tolerations

    Optional: Define tolerations that the exporter pods accept.

    Note

    The LogFileMetricExporter is a singleton. The Operator only honors openshift-logging/instance for the namespace and name.

  2. Apply the LogFileMetricExporter CR by running the following command:

    $ oc apply -f <filename>.yaml

Verification

  • Verify that the logfilesmetricexporter pods are running by running the following command:

    $ oc get pods -l app.kubernetes.io/component=logfilesmetricexporter \
      -n openshift-logging

    Example output

    NAME                           READY   STATUS    RESTARTS   AGE
    logfilesmetricexporter-9qbjj   1/1     Running   0          2m46s
    logfilesmetricexporter-cbc4v   1/1     Running   0          2m46s

    A logfilesmetricexporter pod runs concurrently with a collector pod on each node.

2.11. Troubleshooting log collection

Use this reference to diagnose common problems when log collection does not work as expected.

2.11.1. TLS certificate errors

Symptom: The ClusterLogForwarder custom resource (CR) reports Ready: True, but no logs appear in the LokiStack or other HTTP-based sink. The collector logs show the following error:

Example error output

error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:2123:: self-signed certificate in certificate chain

Cause: The tls.ca block is missing or incorrect in the ClusterLogForwarder output configuration. The collector cannot verify the LokiStack gateway or destination sink certificate.

Resolution: Add the tls.ca block to the output:

spec:
  outputs:
  - name: default-lokistack
    type: lokiStack
    # ... other configuration
    tls:
      ca:
        configMapName: logging-loki-gateway-ca-bundle
        key: service-ca.crt

The Loki Operator creates the logging-loki-gateway-ca-bundle ConfigMap automatically.

2.11.2. Rate limiting (429 Too Many Requests)

Symptom: The collector logs show 429 Too Many Requests responses and the collector retries requests.

Cause: The collector is sending logs faster than the LokiStack or destination sink can process them. This is common in two situations:

  • During initial deployment, when the collector flushes a backlog of accumulated logs.
  • After restoring connectivity to a LokiStack that was temporarily unavailable.

Resolution: This condition resolves automatically. The collector automatically retries with exponential back-off. On a 1x.demo LokiStack, the backlog typically clears within several minutes. On larger LokiStack sizes, clearing takes less time.

2.11.3. Collector not running

Symptom: No collector pod exists.

$ oc get pods -n openshift-logging -l app.kubernetes.io/component=collector
No resources found in openshift-logging namespace.

Cause: The ClusterLogForwarder has an authorization or validation error. When the ClusterLogForwarder is invalid or unauthorized, the Operator removes the collector DaemonSet.

Resolution:

  1. Check the ClusterLogForwarder status by running the following command:

    $ oc get clusterlogforwarder instance -n openshift-logging \
      -o jsonpath='{.status.conditions}' | python3 -m json.tool
  2. If Authorized shows False, grant the missing ClusterRoleBinding. See "Granting collector permissions for log collection."
  3. If Valid shows False, review the message for details about the validation error.

The Operator recreates the collector DaemonSet within about 45 seconds after you fix the error.

2.11.4. Enabling debug logging

To enable debug logging for the collector, set the observability.openshift.io/log-level annotation:

$ oc annotate clusterlogforwarder instance -n openshift-logging \
  observability.openshift.io/log-level=debug --overwrite

Review the collector logs:

$ oc logs -n openshift-logging -l app.kubernetes.io/component=collector --tail=50

Reset the log level to info after troubleshooting to reduce log volume:

$ oc annotate clusterlogforwarder instance -n openshift-logging \
  observability.openshift.io/log-level=info --overwrite

2.12. Forwarding to third-party destinations

The following table lists external log forwarding destinations tested and validated with Red Hat OpenShift Logging.

Expand
Table 2.4. Tested and validated external log forwarding destinations
Output typeProtocolTested versionsLogging versions

Elasticsearch v6

HTTP 1.1

6.8.1

6.0+

Elasticsearch v7

HTTP 1.1

7.12.2

6.0+

Elasticsearch v8

HTTP 1.1

8.6.1

6.0+

Elasticsearch v9

HTTP 1.1

9.3.3

6.0+

Google Cloud Logging

REST over HTTPS

Latest

6.0+

HTTP (Generic)

HTTP 1.1

Vector 0.28-1, 0.34-1

6.0+

Kafka

Kafka 0.11

2.4.1, 2.7.0

6.0+

Loki (External)

REST over HTTP/HTTPS

2.3.0

6.0+

OTLP

HTTP/HTTPS

OpenTelemetry Collector 0.88+

6.1+

Splunk

HEC

9.0.0

6.0+

Syslog

RFC3164, RFC5424

rsyslog 8.39.0

6.0+

Amazon CloudWatch

REST over HTTPS

Latest

6.0+

Amazon S3

REST over HTTPS

Latest

6.0+

Azure Monitor Logs

REST over HTTPS

Latest

6.0+

Note

This table lists versions that Red Hat has tested. Other versions might work but Red Hat has not validated them. For Red Hat OpenShift Logging managed destinations (LokiStack), version compatibility is managed automatically.

To send logs to specific endpoints inside and outside your OpenShift Container Platform cluster, you specify a combination of outputs and pipelines in a ClusterLogForwarder custom resource (CR). You can also use inputs to forward the application logs associated with a specific project to an endpoint. A Kubernetes Secret object provides authentication.

pipeline

Defines simple routing from one log type to one or more outputs, or the logs to send. The log types are one of the following:

  • application. Container logs generated by user applications running in the cluster, except infrastructure container applications.
  • infrastructure. Container logs from pods that run in the openshift*, kube*, or default projects and journal logs sourced from node file system.
  • audit. Audit logs generated by the node audit system, auditd, Kubernetes API server, OpenShift API server, and OVN network.

You can add labels to outbound log messages by using key:value pairs in the pipeline. For example, you might add a label to messages that the collector forwards to other data centers or label the logs by type. The collector also forwards labels added to objects with the log message.

input

Forwards the application logs associated with a specific project to a pipeline.

In the pipeline, you define the input sources to forward using an inputRef parameter and where to forward the logs to using an outputRef parameter.

Secret
A key:value map that has confidential data such as user credentials.

Note the following:

  • You can use many types of outputs in the ClusterLogForwarder custom resource (CR) to send logs to servers that support different protocols.

The following example forwards the audit logs to a secure external Elasticsearch instance.

Sample log forwarding outputs and pipelines

kind: ClusterLogForwarder
apiVersion: observability.openshift.io/v1
metadata:
  name: instance
  namespace: openshift-logging
spec:
  serviceAccount:
    name: logging-admin
  outputs:
    - name: external-es
      type: elasticsearch
      elasticsearch:
        url: <elasticsearch_url>
        version: 8
        index: '{.log_type||"undefined"}'
        authentication:
          username:
            key: username
            secretName: es-secret
          password:
            key: password
            secretName: es-secret
      tls:
        ca:
          key: ca-bundle.crt
          secretName: es-secret
        certificate:
          key: tls.crt
          secretName: es-secret
        key:
          key: tls.key
          secretName: es-secret
  pipelines:
    - name: my-logs
      inputRefs:
        - application
        - infrastructure
      outputRefs:
        - external-es

version
Forwarding to an external Elasticsearch of version 8.x or greater requires you to specify the version field.
index
The index field reads the .log_type field value and falls back to "unknown" if not found.
secretName
Use username and password to authenticate to the server
ca
Enable Mutual Transport Layer Security (mTLS) between collector and Elasticsearch. The spec identifies the keys and secret for the certificates that they represent.
2.12.2.1. Creating a Secret

You can create a secret in the directory that has your certificate and key files by using the following command:

$ oc create secret generic -n <namespace> <secret_name> \
  --from-file=ca-bundle.crt=<your_bundle_file> \
  --from-literal=username=<your_username> \
  --from-literal=password=<your_password>
Note

Red Hat recommends generic or opaque secrets for best results.

You can forward logs to Google Cloud Logging.

Important

Forwarding logs to GCP is not supported on Red Hat OpenShift on AWS.

Prerequisites

  • Ensure that you installed the Red Hat OpenShift Logging Operator.

Procedure

  1. Create a secret using your Google service account key.

    $ oc -n openshift-logging create secret generic gcp-secret --from-file google-application-credentials.json=<your_service_account_key_file.json>
  2. Create a ClusterLogForwarder Custom Resource YAML using the template below:

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
      namespace: openshift-logging
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
        - name: gcp-1
          type: googleCloudLogging
          googleCloudLogging:
            authentication:
              credentials:
                secretName: gcp-secret
                key: google-application-credentials.json
            id:
              type : project
              value: openshift-gce-devel
            logId : app-gcp
      pipelines:
        - name: test-app
          inputRefs:
            - application
          outputRefs:
            - gcp-1
    serviceAccount.name
    Specify the name of your service account.
    value
    Set a project, folder, organization, or billingAccount field and its corresponding value, depending on where you want to store your logs in the GCP resource hierarchy.
    logId
    Set the value to add to the logName field of the log entry. The value can be a combination of static and dynamic values consisting of field paths followed by ||, followed by another field path or a static value. You must encase a dynamic value in single curly brackets {} and follow it with a static fallback value separated with ||. Static values can only contain alphanumeric characters along with dashes, underscores, dots and forward slashes.
    inputRefs
    Specify the names of inputs defined in the input.name field for this pipeline. You can also use the built-in values application, infrastructure, audit.

2.12.4. Configuring OTLP output

Cluster administrators can use the OpenTelemetry Protocol (OTLP) output to collect and forward logs to OTLP receivers. The OTLP output uses the specification defined by the OpenTelemetry Observability framework to send data over HTTP with JSON encoding.

Important

The OpenTelemetry Protocol (OTLP) output log forwarder is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

Procedure

  1. Create or edit a ClusterLogForwarder custom resource (CR) to enable forwarding using OTLP.

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      annotations:
        observability.openshift.io/tech-preview-otlp-output: "enabled" 
    1
    
      name: clf-otlp
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
      - name: otlp
        type: otlp
        otlp:
          tuning:
            compression: gzip
            deliveryMode: AtLeastOnce
            maxRetryDuration: 20
            maxWrite: 10M
            minRetryDuration: 5
          url: <otlp_url>
      pipelines:
      - inputRefs:
        - application
        - infrastructure
        - audit
        name: otlp-logs
        outputRefs:
        - otlp
    url
    This URL must be absolute and is a placeholder for the OTLP endpoint where logs are sent.
    tuning.compression
    Compression algorithm to use. Valid values are gzip, snappy, or none.
    tuning.deliveryMode
    Delivery mode for log forwarding. Valid values are AtLeastOnce or AtMostOnce.
    tuning.maxRetryDuration
    Maximum time in seconds to retry failed deliveries.
    tuning.maxWrite
    Maximum size of a single write request.
    tuning.minRetryDuration

    Minimum time in seconds between retries.

    Note

    The OTLP output uses the OpenTelemetry data model, which is different from the ViaQ data model that is used by other output types. For more information, see OpenTelemetry Semantic Conventions.

  2. Apply the ClusterLogForwarder custom resource:

    $ oc apply -f <filename>.yaml

Verification

  1. Verify that the ClusterLogForwarder status shows Ready:

    $ oc get clusterlogforwarder clf-otlp -n openshift-logging \
      -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}'

    The output should show True.

  2. Verify that OTLP is functioning correctly by checking the LokiStack metrics dashboard:

    1. In the OpenShift Container Platform web console, navigate to ObserveDashboards.
    2. From the Dashboard dropdown, select OpenShift Logging / LokiStack / Writes.
    3. Check the Distributor - structured metadata panel for incoming OTLP log records.

2.12.5. Forwarding logs to Splunk

You can forward logs to the Splunk HTTP Event Collector (HEC).

Prerequisites

  • Ensure that you installed the Red Hat OpenShift Logging Operator
  • You have obtained a Base64 encoded Splunk HEC token.

Procedure

  1. Create a secret using your Base64 encoded Splunk HEC token.

    $ oc -n openshift-logging create secret generic vector-splunk-secret --from-literal hecToken=<HEC_Token>
  2. Create or edit the ClusterLogForwarder Custom Resource (CR) using the template below:

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
      namespace: openshift-logging
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
        - name: splunk-receiver
          type: splunk
          splunk:
            url: '<http://your.splunk.hec.url:8088>'
            authentication:
              token:
                secretName: splunk-secret
                key: hecToken
            index: '{.log_type||"undefined"}'
            source: '{.log_source||"undefined"}'
            indexedFields: ['.log_type', '.log_source']
            payloadKey: '.kubernetes'
            tuning:
                compression: gzip
      pipelines:
        - name: my-logs
          inputRefs:
            - application
            - infrastructure
          outputRefs:
            - splunk-receiver
    serviceAccount.name
    The name of your service account.
    outputs.name
    Specify a name for the output.
    type
    Specify the output type as splunk.
    key
    Specify the name of the secret that has your HEC token.
    url
    Specify the URL, including port, of your Splunk HEC.
    index
    Specify the name of the index to send events to. If you do not specify an index, the Splunk server uses its default index. This is an optional field.
    source
    Specify the source of events to send to this sink. You can configure dynamic per-event values. This field is optional. If you do not specify a value, the log_type and log_source values determine the value of the field. For example, see Default Splunk metadata key values.
    indexedFields
    Specify the fields to add to the Splunk index. This field is optional. The index stores the values directly alongside the raw event data, allowing for faster search performance on those fields. However, indexed_fields fields increase storage use. Use them only for high-value fields that give significant search benefits, for example, large datasets with frequent queries on specific fields. You can use complex and nested fields as indexed fields. These are automatically transformed to meet Splunk’s requirements.
    payloadKey
    Specify the record field to use as the payload. By default, the payloadKey field is not set, which means the collector forwards the complete log record as the payload. Use the payloadKey field carefully. Selecting a single field as the payload might drop other important information in the log, potentially leading to inconsistent or incomplete log events.
    compression
    Specify the compression configuration, which can be either gzip or none. The default value is none. This field is optional.
    inputRefs
    Specify the input names.
    receiver
    Specify the name of the output to use when forwarding logs with this pipeline.
2.12.5.2. Default Splunk metadata key values

Red Hat OpenShift Logging Operator sets default values for some Splunk metadata keys if you do not configure them in the spec.output.splunk.source field of the ClusterLogForwarder Custom Resource (CR).

The following table describes the default value that the collector uses for Splunk metadata, depending on log_type and log_source attributes.

Expand
Table 2.5. Default metadata key values

Key

Infrastructure Journal

  • log_type: infrastructure
  • log_source: node

Infrastructure or application container

  • log_type: infrastructure, application
  • log_source: container

Audit

  • log_type: audit
  • log_source: auditd, ovn, openshiftAPI, kubeAPI

Note

index

   

Not configured by default.

source

SYSLOG_IDENTIFIER

ns_name_podName_containerName

.log_source

 

indexedFields

   

Not configured by default.

sourceType

_json or generic_single_line

_json or generic_single_line

_json or generic_single_line

Determined automatically based on the type of the final event payload.

host

.hostname

.hostname

.hostname

Not configurable.

payloadKey

   

Not configured by default.

2.12.6. Forwarding logs over HTTP

To enable forwarding logs over HTTP, specify http as the output type in the ClusterLogForwarder custom resource (CR).

Procedure

  • Create or edit the ClusterLogForwarder CR using the template below:

    Example ClusterLogForwarder CR

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
      namespace: <log_forwarder_namespace>
    spec:
      managementState: Managed
      outputs:
      - name: <output_name>
        type: http
        http:
          headers:
              h1: v1
              h2: v2
          authentication:
            username:
              key: username
              secretName: <http_auth_secret>
            password:
              key: password
              secretName: <http_auth_secret>
          timeout: 300
          proxyURL: <proxy_url>
          url: <url>
        tls:
          insecureSkipVerify:
          ca:
            key: <ca_certificate>
            secretName: <secret_name>
      pipelines:
        - inputRefs:
            - application
          name: pipe1
          outputRefs:
            - <output_name>
      serviceAccount:
        name: <service_account_name>

    headers
    Optional: Additional headers to send with each log record.
    authentication.username
    Optional: Username for HTTP Basic authentication. Specify the secret name and key containing the username.
    authentication.password
    Optional: Password for HTTP Basic authentication. Specify the secret name and key containing the password.
    timeout
    Optional: Timeout in seconds for HTTP requests. Default is 300 seconds (5 minutes).
    proxyURL
    Optional: URL of the HTTP/HTTPS proxy to forward logs over http or https from this output. This setting overrides any default proxy settings for the cluster or the node.
    url
    Destination address for logs.
    tls.insecureSkipVerify

    Optional: When set to true, the collector skips verification of the server’s certificate. When set to false (the default), the collector verifies the server’s certificate against the CA specified in tls.ca. If insecureSkipVerify is set to true, the tls.ca field is not required.

    Warning

    Setting insecureSkipVerify to true is not recommended for production environments because it disables certificate validation and makes the connection vulnerable to man-in-the-middle attacks. Use this setting only for testing purposes or when connecting to trusted internal endpoints.

    tls.ca.secretName
    Secret name containing the certificate authority (CA) certificate for validating the server’s TLS certificate. Required when insecureSkipVerify is false or not set.
    tls.ca.key
    The key name in the secret that contains the CA certificate.
    <output_name>
    This value should be the same as the output name.
    serviceAccount.name

    The name of your service account.

    Note

    The tls configuration shown in this example applies to HTTP outputs, but similar TLS settings are available for other output types that support TLS encryption, including Kafka, Syslog, Elasticsearch, and Splunk. For information about configuring TLS for other output types, run the command oc explain clusterlogforwarders.spec.outputs.<output_type>.tls.

To configure log forwarding to Loki, you must create a ClusterLogForwarder custom resource (CR) with an output to Loki, and a pipeline that uses the output. The output to Loki can use the HTTP (insecure) or HTTPS (secure HTTP) connection.

Prerequisites

  • You have installed Red Hat OpenShift Logging Operator.
  • You have administrator access to OpenShift Container Platform.
  • You have installed OpenShift CLI (oc).
  • You have a Loki logging system running at the URL specified in the url field.

Procedure

  1. Create or edit a YAML file that defines the ClusterLogForwarder CR object:

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
      namespace: <log_forwarder_namespace>
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
      - name: loki-output
        type: loki
        loki:
          authentication:
            username:
              key: username
              secretName: to-loki-secret
            password:
              key: password
              secretName: to-loki-secret
            token:
              from: secret
              secret:
                key: ca-bundle.crt
                name: to-loki-secret
          labelKeys:
            - <label_keys>
          tenantKey: '{.kubernetes.namespace_name||"application"}'
          url: https://loki.secure.com:3100
      pipelines:
      - name:  my-pipeline
        inputRefs:
        - application
        - audit
        outputRefs:
        - loki-output
    serviceAccount.name
    Specify the name of your service account.
    outputs.name
    Specify a name for the output.
    type
    Specify the type as loki.
    authentication
    Specify the authentication information.
    labelKeys
    Specify the log record keys to map to Loki stream labels. If you do not set the labelKeys field, the ClusterLogForwarder CR uses these default keys: log_type, kubernetes.container_name, kubernetes.namespace_name, kubernetes.pod_name.
    tenantKey
    Specify the tenant for the logs. The value can be a combination of static and dynamic values consisting of field paths separated by ||. Encase dynamic values inside single curly brackets {}. Follow dynamic values with a static fallback value.
    url
    Specify the URL for Loki.
    inputRefs
    Specify the names of inputs defined in the input.name field for this pipeline. You can also use the built-in values application, infrastructure, audit.
    outputRefs

    Specify the names of outputs defined in the outputs.name field for this pipeline.

    Note

    Because Loki requires log streams to be correctly ordered by timestamp, labelKeys always includes the kubernetes_host label set, even if you do not specify it. This inclusion ensures that each stream originates from a single host, which prevents timestamps from becoming disordered due to clock differences on different hosts.

  2. Apply the ClusterLogForwarder CR object by running the following command:

    $ oc apply -f <filename>.yaml

2.12.8. Forwarding logs to a Kafka broker

To configure log forwarding to an external Kafka instance, you must create a ClusterLogForwarder custom resource (CR) with an output to that instance, and a pipeline that uses the output. You can include a specific Kafka topic in the output or use the default. The Kafka output can use a TCP (insecure) or TLS (secure TCP) connection.

Procedure

  1. Create or edit a YAML file that defines the ClusterLogForwarder CR object:

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
      namespace: <log_forwarder_namespace>
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
       - name: kafka-output
         type: kafka
         kafka:
           authentication:
             sasl:
               username:
                 key: <key>
                 secretName: kafka-secret
               password:
                key: <key>
                secretName:  kafka-secret
               mechanism: <sasl_mechanism>
           url: tls://kafka.example.devlab.com:9093/app-topic
           brokers:
             - tls://kafka-broker1.example.com:9093
             - tls://kafka-broker2.example.com:9093
           topic:
      pipelines:
        - name: app-topic
          inputRefs:
            - application
          outputRefs:
            - kafka-output
    serviceAccount.name
    Specify the name of your service account.
    outputs.name
    Specify a name for the output.
    type
    Specify the kafka type.
    secretName
    If you use a tls prefix in the URL, you must specify the name of the secret required by the endpoint for TLS communication.
    mechanism
    Specify the Simple Authentication and Security Layer (SASL) mechanism to use. For example, SCRAM-SHA-256,SCRAM-SHA-512, or PLAIN. The default value is PLAIN.
    url
    Optional: Specify the URL and port of the Kafka broker as a valid absolute URL, optionally with a specific topic. You can use the tcp (insecure) or tls (secure TCP) protocol. If you enable the cluster-wide proxy by using the CIDR annotation, the output must be a server name or FQDN, and not an IP address. You must specify either the URL or Kafka brokers.
    brokers
    Optional: Specify a list of broker endpoints of a Kafka cluster.
    topic
    Specify the target topic. By default, the value for the field is topic. The topic name can be a combination of static and dynamic values consisting of field paths separated by "||". Encase dynamic values in single curly brackets "{}". Follow dynamic values with a static fallback value. The topic specified here overrides the topic defined in the url field.
  2. Apply the ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml

2.12.9. Forwarding to Azure Monitor Logs

You can forward logs to Azure Monitor Logs. The Vector Azure Monitor Logs sink provides this functionality.

Warning

The azureMonitor output type is deprecated and will be removed in a future release. This output type will become obsolete in September 2026.

Prerequisites

  • You have basic familiarity with Azure services.
  • You have an Azure account configured for Azure Portal or Azure CLI access.
  • You have obtained your Azure Monitor Logs primary or the secondary security key.
  • You have determined which log types to forward.
  • You installed the OpenShift CLI (oc).
  • You have installed Red Hat OpenShift Logging Operator.
  • You have administrator permissions.

Procedure

  1. Create a secret with your shared key:

    apiVersion: v1
    kind: Secret
    metadata:
      name: my-secret
      namespace: openshift-logging
    type: Opaque
    data:
      shared_key: <your_shared_key>
    shared_key
    Must contain a primary or secondary key for the Log Analytics workspace making the request.
  2. Obtain a shared key by running the following command in the Azure CLI:

    Get-AzOperationalInsightsWorkspaceSharedKey -ResourceGroupName "<resource_name>" -Name "<workspace_name>”
  3. Create or edit your ClusterLogForwarder CR using the template matching your log selection.

    Forward all logs

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
      namespace: openshift-logging
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
      - name: azure-monitor
        type: azureMonitor
        azureMonitor:
          customerId: my-customer-id
          logType: my_log_type
          authentication:
            sharedKey:
              secretName: my-secret
              key: shared_key
      pipelines:
        - name: app-pipeline
          inputRefs:
          - application
          outputRefs:
          - azure-monitor

    serviceAccount.name
    The name of your service account.
    customerId
    Unique identifier for the Log Analytics workspace. Required field.
    logType
    Record type of the submitted data. Can only contain letters, numbers, and underscores (_), and cannot exceed 100 characters. For more information, see Azure record type in the Microsoft Azure documentation.

You can forward a copy of the application logs from specific projects to an external log aggregator, in addition to, or instead of, using the internal log store. You must also configure the external log aggregator to receive log data from OpenShift Container Platform.

To configure forwarding application logs from a project, you must create a ClusterLogForwarder custom resource (CR) with at least one input from a project, optional outputs for other log aggregators, and pipelines that use those inputs and outputs.

Prerequisites

  • You must configure a logging server to receive the logging data using the specified protocol or format.

Procedure

  1. Create or edit a YAML file that defines the ClusterLogForwarder CR:

    Example ClusterLogForwarder CR

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
      namespace: <log_forwarder_namespace>
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
      - name: <output_name>
        type: <output_type>
      inputs:
      - name: my-app-logs
        type: application
        application:
          includes:
          - namespace: my-project
      filters:
      - name: my-project-labels
        type: openshiftLabels
        openshiftLabels:
          project: my-project
      - name: cluster-labels
        type: openshiftLabels
        openshiftLabels:
          clusterId: C1234
      pipelines:
      - name: <pipeline_name>
        inputRefs:
        - my-app-logs
        outputRefs:
        - <output_name>
        filterRefs:
        - my-project-labels
        - cluster-labels

    inputs.name
    Specify the name for the input.
    type
    Specify the type as application to collect logs from applications.
    includes
    Specify the set of namespaces and containers to include when collecting logs.
    openshiftLabels
    Specify the labels to apply to log records passing through this pipeline. These labels appear in the openshift.labels map in the log record.
    pipelines.name
    Specify a name for the pipeline.
  2. Apply the ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml

As a cluster administrator, you can use Kubernetes pod labels to gather log data from specific pods and forward it to a log collector.

Suppose that you have an application composed of pods running alongside other pods in various namespaces. If those pods have labels that identify the application, you can gather and output their log data to a specific log collector.

To specify the pod labels, you use one or more matchLabels key-value pairs. If you specify many key-value pairs, the collector selects only pods that match all of them.

Procedure

  1. Create or edit a YAML file that defines the ClusterLogForwarder CR object. In the file, specify the pod labels using simple equality-based selectors under inputs[].name.application.selector.matchLabels, as shown in the following example.

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
      namespace: <log_forwarder_namespace>
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
        - <output_name>
        # ...
      inputs:
      - name: exampleAppLogData
        type: application
        application:
          includes:
          - namespace: app1
          - namespace: app2
          selector:
            matchLabels:
              environment: production
              app: nginx
      pipelines:
      - inputRefs:
        - exampleAppLogData
        outputRefs:
        # ...
    serviceAccount.name
    Specify the service account name.
    inputs.name
    Specify a name for the input.
    type
    Specify the type as application to collect logs from applications.
    includes
    Specify the set of namespaces to include when collecting logs.
    matchLabels
    Specify the key-value pairs of pod labels whose log data you want to gather. You must specify both a key and value, not just a key. The collector selects only pods that match all the key-value pairs.
  2. Optional: You can send log data from additional applications that have different pod labels to the same pipeline.

    1. For each unique combination of pod labels, create an additional inputs[].name section similar to the one shown.
    2. Update the selectors to match the pod labels of this application.
    3. Add the new inputs[].name value to inputRefs. For example:

      - inputRefs: [ myAppLogData, myOtherAppLogData ]
  3. Create the CR object:

    $ oc create -f <file_name>.yaml

You can use the syslog RFC3164 or RFC5424 protocol to send a copy of your logs to an external log aggregator. You are responsible for configuring the external log aggregator, such as a syslog server, to receive the logs from OpenShift Container Platform.

To configure log forwarding using the syslog protocol, you must create a ClusterLogForwarder custom resource (CR) with one or more outputs to the syslog servers, and pipelines that use those outputs. The syslog output can use a UDP, TCP, or TLS connection.

Prerequisites

  • You must configure a logging server to receive the logging data using the specified protocol or format.

Procedure

  1. Create or edit a YAML file that defines the ClusterLogForwarder CR object:

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: collector
    spec:
      managementState: Managed
      outputs:
      - name: rsyslog-east
        syslog:
          appName: <app_name>
          enrichment: KubernetesMinimal
          facility: <facility_value>
          msgId: <message_ID>
          payloadKey: <record_field>
          procId: <process_ID>
          rfc: <RFC3164_or_RFC5424>
          severity: informational
          tuning:
            deliveryMode: <AtLeastOnce_or_AtMostOnce>
          url: <url>
        tls:
          ca:
            key: ca-bundle.crt
            secretName: syslog-secret
        type: syslog
      pipelines:
      - inputRefs:
        - application
        name: syslog-east
        outputRefs:
        - rsyslog-east
      serviceAccount:
        name: logcollector
    outputs.name
    Specify a name for the output.
    appName
    Optional: Specify the value for the APP-NAME part of the syslog message header. The value must conform with The Syslog Protocol. The value can be a combination of static and dynamic values consisting of field paths followed by ||, and then followed by another field path or a static value. The collector truncates the final values to a maximum length of 48 characters. You must encase a dynamic value in curly brackets and follow the value with a static fallback value separated with ||. Static values can only contain alphanumeric characters along with dashes, underscores, dots and forward slashes. Example value: <value1>-{.<value2>||"none"}.
    enrichment
    Optional: Specify the enrichment level for Kubernetes metadata fields added to log records. The value can be KubernetesMinimal to add minimal Kubernetes fields such as namespace, pod name, and container name. This parameter replaces the addLogSource parameter that was removed in Logging 6.0.
    facility
    Optional: Specify the value for Facility part of the syslog-msg header.
    msgId
    Optional: Specify the value for MSGID part of the syslog-msg header. The value can be a combination of static and dynamic values consisting of field paths followed by ||, and then followed by another field path or a static value. The collector truncates the final values to a maximum length of 32 characters. You must encase a dynamic value in curly brackets and follow the value with a static fallback value separated with ||. Static values can only contain alphanumeric characters along with dashes, underscores, dots and forward slashes. Example value: <value1>-{.<value2>||"none"}.
    payloadKey
    Optional: Specify the record field to use as the payload. The payloadKey value must be a single field path encased in single curly brackets {}. Example: {.<value>}.
    procId
    Optional: Specify the value for the PROCID part of the syslog message header. The value must conform with The Syslog Protocol. The value can be a combination of static and dynamic values consisting of field paths followed by ||, and then followed by another field path or a static value. The collector truncates the final values to a maximum length of 48 characters. You must encase a dynamic value in curly brackets and follow the value with a static fallback value separated with ||. Static values can only contain alphanumeric characters along with dashes, underscores, dots and forward slashes. Example value: <value1>-{.<value2>||"none"}.
    rfc
    Optional: Set the RFC that the generated messages conform to. The value can be RFC3164 or RFC5424.
    severity
    Optional: Set the severity level for the message. For more information, see The Syslog Protocol.
    deliveryMode
    Optional: Set the delivery mode for log forwarding. The value can be either AtLeastOnce, or AtMostOnce.
    url
    Specify the absolute URL with a scheme. Valid schemes are: tcp, tls, and udp. For example: tls://syslog-receiver.example.com:6514.
    tls
    Specify the settings for controlling options of the transport layer security (TLS) client connections.
    inputRefs
    Specify which log types to forward by using the pipeline: application, infrastructure, or audit.
    pipelines.name
    Specify a name for the pipeline.
    serviceAccount
    The name of your service account.
  2. Create the CR object:

    $ oc create -f <filename>.yaml

You can add namespace_name, pod_name, and container_name elements to the message field of the record by adding the enrichment field to your ClusterLogForwarder custom resource (CR).

# ...
  spec:
    outputs:
    - name: syslogout
      syslog:
        enrichment: KubernetesMinimal
        facility: user
        payloadKey: message
        rfc: RFC3164
        severity: debug
      type: syslog
      url: tls://syslog-receiver.example.com:6514
    pipelines:
    - inputRefs:
      - application
      name: test-app
      outputRefs:
      - syslogout
# ...
Note

This configuration is compatible with both RFC3164 and RFC5424.

Example syslog message output with enrichment: None

 2025-03-03T11:48:01+00:00  example-worker-x  syslogsyslogserverd846bb9b: {...}

Example syslog message output with enrichment: KubernetesMinimal

2025-03-03T11:48:01+00:00  example-worker-x  syslogsyslogserverd846bb9b: namespace_name=cakephp-project container_name=mysql pod_name=mysql-1-wr96h,message: {...}

2.12.12. Forwarding logs to Amazon CloudWatch

To configure log forwarding to CloudWatch, create a ClusterLogForwarder custom resource (CR) with an output for CloudWatch and a pipeline that uses the output.

Prerequisites

  • You have installed Red Hat OpenShift Logging Operator.
  • You have administrator access to OpenShift Container Platform.
  • You have installed OpenShift CLI (oc).

Procedure

  1. Create a Secret YAML file that uses the aws_access_key_id and aws_secret_access_key fields to specify your base64-encoded AWS credentials. For example:

    apiVersion: v1
    kind: Secret
    metadata:
      name: aws-secret
      namespace: <namespace_name>
    data:
      aws_access_key_id: QUtJQUlPU0ZPRE5ON0VYQU1QTEUK
      aws_secret_access_key: d0phbHJYVXRuRkVNSS9LN01ERU5HL2JQeFJmaUNZRVhBTVBMRUtFWQo=
    namespace
    Specify the namespace where your ClusterLogForwarder CR is deployed. The secret must be in the same namespace as the ClusterLogForwarder CR.
  2. Create the secret. For example:

    $ oc apply -f aws-secret.yaml
  3. Create or edit a YAML file that defines the ClusterLogForwarder CR object. In the file, specify the name of the secret. For example:

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
      namespace: <log_forwarder_namespace>
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
       - name: cw-output
         type: cloudwatch
         cloudwatch:
           authentication:
             type: awsAccessKey
             awsAccessKey:
               keyId:
                 key: <key>
                 secretName: cw-secret
               keySecret:
                 key: <key>
                 secretName: cw-secret
           groupName: <prefix-{.dynamic_value||"none"}>
           region: us-east-2
      pipelines:
        - name: infra-logs
          inputRefs:
            - infrastructure
            - audit
            - application
          outputRefs:
            - cw-output
    serviceAccount.name
    Specify the name of your service account.
    outputs.name
    Specify a name for the output.
    type
    Specify the cloudwatch type.
    secretName
    Specify the name of the secret that has your AWS credentials.
    groupName
    Specify the strategy for grouping log streams. The value can be a combination of static and dynamic values consisting of field paths separated by "||". Encase dynamic values in single curly brackets "{}". Follow dynamic values with a static fallback value.
    region
    Specify the AWS region.
    pipelines.name
    Specify a name for the pipeline.
    inputRefs
    Specify the names of inputs defined in the input.name field for this pipeline. You can also use the built-in values application, infrastructure, audit.
    output
    Specify the names of outputs defined in the outputs.name field for this pipeline.
  4. Apply the CR object:

    $ oc apply -f <file_name>.yaml

2.12.13. Forwarding logs to Amazon S3 endpoint

To configure log forwarding to an Amazon S3 endpoint, create a ClusterLogForwarder custom resource (CR) with an S3 output and a pipeline that uses it.

Prerequisites

  • You have installed Red Hat OpenShift Logging Operator.
  • You have administrator access to OpenShift Container Platform.
  • You have installed OpenShift CLI (oc).

Procedure

  1. Create a Secret YAML file that uses the aws_access_key_id and aws_secret_access_key fields to specify your base64-encoded AWS credentials. For example:

    apiVersion: v1
    kind: Secret
    metadata:
      name: aws-secret
      namespace: <namespace_name>
    data:
      aws_access_key_id: QUtJQUlPU0ZPRE5ON0VYQU1QTEUK
      aws_secret_access_key: d0phbHJYVXRuRkVNSS9LN01ERU5HL2JQeFJmaUNZRVhBTVBMRUtFWQo=
    namespace
    Specify the namespace where your ClusterLogForwarder CR is deployed. The secret must be in the same namespace as the ClusterLogForwarder CR.
  2. Create the secret. For example:

    $ oc apply -f aws-secret.yaml
  3. Create or edit a YAML file that defines the ClusterLogForwarder CR object and specify the secret name. For example:

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
      - name: s3bucket
        type: s3
        s3:
          authentication:
            type: awsAccessKey
            awsAccessKey:
              keyId:
                key: aws_access_key_id
                secretName: aws-secret
              keySecret:
                key: aws_secret_access_key
                secretName: aws-secret
          bucket: <bucket_name>
          keyPrefix: 's3{.log_type||"missing"}'
          region: us-east-1
          url: 'https://s3.us-east-1.amazonaws.com'
      pipelines:
      - name: pipe1
        inputRefs:
        - application
        outputRefs:
        - s3bucket
    serviceAccount.name
    Specify the name of your service account.
    outputs.name
    Specify a name for the output.
    type
    Specify the s3 type.
    secretName
    Specify the name of the secret that has your AWS credentials.
    bucket
    Specify the Amazon S3 bucket name for log storage.
    keyPrefix
    Specify the S3 key prefix for log objects. The value can be a combination of static and dynamic values consisting of field paths separated by "||". Encase dynamic values in single curly brackets "{}". You must follow dynamic values with a static fallback value.
    url
    Optional: Specify the S3 endpoint URL. If you do not specify this, the system uses the default AWS S3 endpoint https://s3.<region>.amazonaws.com based on the region. Use this field for S3-compatible storage endpoints or custom endpoints.
  4. Apply the CR object:

    $ oc apply -f <file_name>.yaml
2.12.14.1. Creating an AWS IAM role

Create an Amazon Web Services (AWS) IAM role that your service account can assume to securely access AWS resources.

The following procedure demonstrates creating an AWS IAM role by using the AWS CLI. You can also use the Cloud Credential Operator (CCO) utility ccoctl. Using the ccoctl utility creates many fields in the IAM role policy that are not required by the ClusterLogForwarder custom resource (CR). The CR ignores these extra fields. However, the ccoctl utility provides a convenient way for configuring IAM roles. For more information see Manual mode with short-term credentials for components.

Prerequisites

  • You have access to an Red Hat OpenShift Logging cluster with Security Token Service (STS) enabled and configured for AWS.
  • You have administrator access to the AWS account.
  • AWS CLI installed.

Procedure

  1. Create an IAM policy that grants permissions to write logs to CloudWatch.

    1. Create a file, for example cw-iam-role-policy.json, with the following content:

      {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "logs:PutLogEvents",
                      "logs:CreateLogGroup",
                      "logs:PutRetentionPolicy",
                      "logs:CreateLogStream",
                      "logs:DescribeLogGroups",
                      "logs:DescribeLogStreams"
                  ],
                  "Resource": "arn:aws:logs:*:*:*"
              }
          ]
      }
    2. Create the IAM policy based on the earlier policy definition by running the following command:

      $ aws iam create-policy \
          --policy-name cluster-logging-allow \
          --policy-document file://cw-iam-role-policy.json

      Note the Arn value of the created policy.

  2. Create a trust policy to allow the logging service account to assume an IAM role:

    1. Create a file, for example cw-trust-policy.json, with the following content:

      {
      "Version": "2012-10-17",
      "Statement": [
          {
              "Effect": "Allow",
              "Principal": {
                  "Federated": "arn:aws:iam::123456789012:oidc-provider/<OPENSHIFT_OIDC_PROVIDER_URL>"
              },
              "Action": "sts:AssumeRoleWithWebIdentity",
              "Condition": {
                  "StringEquals": {
                      "<OPENSHIFT_OIDC_PROVIDER_URL>:sub": "system:serviceaccount:openshift-logging:logcollector"
                  }
              }
          }
      ]
      }
  3. Create an IAM role based on the trust policy defined earlier by running the following command:

    $ aws iam create-role --role-name openshift-logger --assume-role-policy-document file://cw-trust-policy.json

    Note the Arn value of the created role.

  4. Attach the policy to the role by running the following command:

    $ aws iam put-role-policy \
          --role-name openshift-logger --policy-name cluster-logging-allow \
          --policy-document file://cw-role-policy.json

Verification

  • Verify the role and the permissions policy by running the following command:

    $ aws iam get-role --role-name openshift-logger

    Example output

    ROLE	arn:aws:iam::123456789012:role/openshift-logger
    ASSUMEROLEPOLICYDOCUMENT	2012-10-17
    STATEMENT	sts:AssumeRoleWithWebIdentity	Allow
    STRINGEQUALS	system:serviceaccount:openshift-logging:openshift-logger
    PRINCIPAL	arn:aws:iam::123456789012:oidc-provider/<OPENSHIFT_OIDC_PROVIDER_URL>

Create a secret for Amazon Web Services (AWS) Security Token Service (STS) from the configured AWS IAM role by using the oc create secret --from-literal command.

Prerequisites

  • You have created an AWS IAM role.
  • You have administrator access to Red Hat OpenShift Logging.

Procedure

  • In the CLI, enter the following to generate a secret for AWS:

    $ oc create secret generic sts-secret -n openshift-logging --from-literal=role_arn=arn:aws:iam::123456789012:role/openshift-logger

    Example Secret

    apiVersion: v1
    kind: Secret
    metadata:
      namespace: openshift-logging
      name: sts-secret
    stringData:
      role_arn: arn:aws:iam::123456789012:role/openshift-logger

You can forward logs from logging for Red Hat OpenShift deployed on clusters with Amazon Web Services (AWS) Security Token Service (STS)-enabled to Amazon CloudWatch. Amazon CloudWatch is a service that helps administrators observe and monitor resources and applications on AWS.

Prerequisites

  • Ensure that you installed the Red Hat OpenShift Logging Operator.
  • You have configured a credential secret.
  • You have administrator access to Red Hat OpenShift Logging.

Procedure

  • Create or update a ClusterLogForwarder custom resource (CR):

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
      namespace: openshift-logging
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
       - name: cw-output
         type: cloudwatch
         cloudwatch:
           groupName: 'prefix-{.log_type||"none"}'
           region: us-east-2
           authentication:
               type: iamRole
             iamRole:
                 roleARN:
                 key: role_arn               secretName: sts-secret
               token:
                 from: serviceAccount
      pipelines:
        - name: to-cloudwatch
          inputRefs:
            - infrastructure
            - audit
            - application
          outputRefs:
            - cw-output
    serviceAccount.name
    Specify the name of your service account.
    outputs.name
    Specify a name for the output.
    type
    Specify the cloudwatch type.
    groupName
    Specify the group name for the log stream.
    region
    Specify the AWS region.
    iamRole
    Specify iamRole as the authentication type for STS.
    roleARN
    Specify the name of the secret and the key where you store the role_arn resource.
    token
    Specify the service account token to use for authentication. To use the projected service account token, use from: serviceAccount.
    inputRefs
    Specify which log types to forward by using the pipeline: application, infrastructure, or audit.
    outputRefs
    Specify the names of the output to use when forwarding logs with this pipeline.

You can forward logs from logging for Red Hat OpenShift deployed on Amazon Web Services (AWS) Security Token Service (STS)-enabled clusters to an S3 configured endpoint.

Prerequisites

  • You have installed Red Hat OpenShift Logging Operator.
  • You have configured a credential secret.
  • You have administrator access to OpenShift Container Platform.
  • You have installed OpenShift CLI (oc).

Procedure

  1. Create or update a ClusterLogForwarder custom resource (CR):

    apiVersion: observability.openshift.io/v1
    kind: ClusterLogForwarder
    metadata:
      name: <log_forwarder_name>
    spec:
      serviceAccount:
        name: <service_account_name>
      outputs:
       - name: s3-output
         type: s3
         s3:
           keyPrefix: 's3{.log_type||"missing"}'
           bucket: <bucket_name>
           region: us-east-2
           authentication:
             type: iamRole
             iamRole:
               roleARN:
                 key: role_arn
                 secretName: sts-secret
               token:
                 from: serviceAccount
      pipelines:
        - name: to-s3
          inputRefs:
            - infrastructure
            - audit
            - application
          outputRefs:
            - s3-output
    • keyPrefix: The S3 key prefix for log objects. You can use static or dynamic values consisting of field paths separated by || and ending with a static fallback value.
    • bucket: The S3 bucket name for log storage.
  2. Apply the ClusterLogForwarder CR by running the following command:

    $ oc apply -f <filename>.yaml

You can forward logs to external AWS accounts by using the AWS Security Token Service (STS) AssumeRole functionality. Cross-account log forwarding enables centralized logging across many AWS accounts while maintaining security boundaries.

Cross-account log forwarding works as follows:

  1. Initial Authentication: The collector authenticates to the AWS account of your cluster using Identity and Access Management (IAM) roles or access keys.
  2. Role Assumption: After initial authentication, the collector assumes a role in the target AWS account.
  3. Log Forwarding: The collector forwards logs to CloudWatch or S3 bucket in the target account using credentials of the assumed role.

When using cross-account log forwarding, keep these security considerations in mind :

  • Use external IDs for cross-account role assumptions.

    External ID serves as an additional identifier.

    Note

    External IDs appear in CloudTrail logs and API responses. Therefore, they are not considered secrets.

    Take the following measures when creating external IDs:

    • They should be unique for each trust relationship.
    • They should be unpredictable and not based on public information.
  • Grant only the minimum required permissions to assumed roles.
  • Protect secrets containing role Amazon Resource Names (ARN) and tokens.
  • Monitor CloudTrail for AssumeRole activity.

You can configure AWS Identity Access Management (IAM) for cross-account access.

Prerequisites

  • You have administrator permissions.
  • You have created the target role and the target role has permissions to send data to CloudWatch or S3 outputs.
  • You have permissions to update the policy for the initial and the target role.

Procedure

  1. Create an initial account in your cluster account to assume the target role with the required permissions.

    The initial account can either be a user or an IAM role. This account assumes the target role.

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": "sts:AssumeRole",
                "Resource": "arn:aws:iam::<target_aws_account_id>:role/target-logging-role"
            }
        ]
    }
  2. In your target role, create a trust policy and specify the initial cluster role, and optionally an external id.

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam:::<role_or_user>/<role_name_or_user_name>"
                },
                "Action": "sts:AssumeRole",
                "Condition": {
                    "StringEquals": {
                        "sts:ExternalId": "<your_unique_external_id>"
                    }
                }
            }
        ]
    }

    Set the Principal.AWS field as follows:

    • If the initial account is a user, use the format:

      arn:aws:iam::<aws_account_id>:user/<user_name>

    • If the initial account is an IAM role, use the format:

      arn:aws:iam::<aws_account_id>:role/<role_name>

  3. Configure CloudWatch or S3 permissions in the target role depending on whether you want to forward logs to the CloudWatch or S3 output:

    CloudWatch permissions

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents",
                    "logs:DescribeLogGroups",
                    "logs:DescribeLogStreams"
                ],
                "Resource": "*"
            }
        ]
    }

    S3 permissions

    {
        "Version": "2012-10-17",
        "Statement": [
            {
            "Sid": "AllowRoleToPutObjects",
            "Effect": "Allow",
            "Principal": {
                "AWS": "<assumerole_arn>"
            },
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:<aws_partition>:s3:::<s3_bucket>",
                "arn:<aws_partition>:s3:::<s3_bucket>/*"
            ]
            }
        ]
    }

The following example illustrates using cross-account AssumeRole field configuration when forwarding logs to CloudWatch.

ClusterLogForwarder resource with AssumeRole authentication

apiVersion: observability.openshift.io/v1
kind: ClusterLogForwarder
metadata:
  name: cross-account-example
  namespace: openshift-logging
spec:
  serviceAccount:
    name: my-sa
  outputs:
    - name: cw-cross-account
      type: cloudwatch
      cloudwatch:
        groupName: my-logs-{.log_type||"unknown"}
        region: us-east-1
        authentication:
          type: iamRole
          iamRole:
            roleARN:
              secretName: initial-role-secret
              key: role_arn
            token:
              from: serviceAccount
          # Cross-account assume role configuration
          assumeRole:
            roleARN:
              secretName: cross-account-secret
              key: assume_role_arn
            externalID: "my-unique-id-1234"
  pipelines:
    - name: cross-account-logs
      inputRefs:
        - application
      outputRefs:
        - cw-cross-account

  • authentication.assumeRole.roleARN: Reference to a secret containing the Amazon Resource Name (ARN) of the role to assume in the target account.
  • authentication.assumeRole.externalID: A string containing the external ID to enforce for assuming the role. This can add additional security by ensuring only entities with knowledge of the external ID can assume the role.

Session names for assumed role sessions are automatically generated by the Red Hat OpenShift Logging Operator to give meaningful identification in AWS CloudTrail logs for auditing purposes. The Operator generates session names by using cluster metadata as follows:

  • Primary format: {clusterId}-{clfName}-{outputName}.
  • Fallback format (if cluster metadata unavailable): output-{outputName}.
  • Always truncated to 64 characters maximum (AWS requirement).
  • Uses first 8 characters of cluster ID for uniqueness.

The following table describes issues that you might experience with cross-account log forwarding and the steps that you can take to resolve the issues.

Expand
Table 2.6. Cross-account log forwarding issue and resolution
IssueTroubleshooting steps

Role Assumption Fails

  • Verify the trust relationship in the target account.
  • Verify that the external ID in the trust policy is an exact match with the one used in the ClusterLogForwarder Custom Resource (CR).
  • Ensure that the initial role has the sts:AssumeRole permission.

Permission Denied

  • Verify that the assumed role has the CloudWatch or S3 permissions.
  • Check the CloudWatch or s3 bucket resource policies.
  • Verify that region configuration matches in the initial and the target role.

Invalid role or user Amazon Resource Name (ARN)

  • Ensure that the role Amazon Resource Name (ARN) in the format:

    • arn:<aws_partition>:iam::<aws_account_id>:role/<role_name>
    • arn:<aws_partition>:iam::<aws_account_id>:user/<user_name>
  • Verify the role exists in the target account.

Chapter 3. Configuring the log store

You can configure a LokiStack custom resource (CR) to store application, audit, and infrastructure-related logs.

Loki is a horizontally scalable, highly available, multi-tenant log aggregation system offered as a GA log store for logging for Red Hat OpenShift that can be visualized with the OpenShift Observability UI. The Loki configuration provided by OpenShift Logging is a short-term log store designed to enable users to perform fast troubleshooting with the collected logs. For that purpose, the logging for Red Hat OpenShift configuration of Loki has short-term storage, and is optimized for very recent queries.

Important

For long-term storage or queries over a long time period, users should look to log stores external to their cluster. Loki sizing is only tested and supported for short term storage, for a maximum of 30 days.

3.1. Loki deployment sizing

Sizing for Loki follows the format of 1x.<size> where the value 1x is number of instances and <size> specifies performance capabilities.

The 1x.pico configuration defines a single Loki deployment with minimal resource and limit requirements, offering high availability (HA) support for all Loki components. This configuration is suited for deployments that do not require a single replication factor or auto-compaction.

Disk requests are similar across size configurations, allowing customers to test different sizes to determine the best fit for their deployment needs.

Important

It is not possible to change the number 1x for the deployment size.

Expand
Table 3.1. Loki sizing
 1x.demo1x.pico [6.1+ only]1x.extra-small1x.small1x.medium

Data transfer

Demo use only

50GB/day

100GB/day

500GB/day

2TB/day

Queries per second (QPS)

Demo use only

1-25 QPS at 200ms

1-25 QPS at 200ms

25-50 QPS at 200ms

25-75 QPS at 200ms

Replication factor

None

2

2

2

2

Total CPU requests

None

7 vCPUs

14 vCPUs

34 vCPUs

54 vCPUs

Total CPU requests if using the ruler

None

8 vCPUs

16 vCPUs

42 vCPUs

70 vCPUs

Total memory requests

None

17Gi

31Gi

67Gi

139Gi

Total memory requests if using the ruler

None

18Gi

35Gi

83Gi

171Gi

Total disk requests

40Gi

590Gi

430Gi

430Gi

590Gi

Total disk requests if using the ruler

60Gi

910Gi

750Gi

750Gi

910Gi

3.2. Loki object storage

The Loki Operator supports AWS S3, as well as other S3 compatible object stores such as Minio and OpenShift Data Foundation. Azure, GCS, and Swift are also supported.

The recommended nomenclature for Loki storage is logging-loki-<your_storage_provider>.

The following table shows the type values within the LokiStack custom resource (CR) for each storage provider. For more information, see the section on your storage provider.

Expand
Table 3.2. Secret type quick reference
Storage providerSecret type value

AWS

s3

Azure

azure

Google Cloud

gcs

Minio

s3

OpenShift Data Foundation

s3

Swift

swift

3.2.1. AWS object storage

You can use Amazon Web Services (AWS) object storage to store logs.

Prerequisites

Procedure

  • Create an object storage secret with the name logging-loki-aws by running the following command:

    $ oc create secret generic logging-loki-aws \ 
    1
    
      --from-literal=bucketnames="<bucket_name>" \
      --from-literal=endpoint="<aws_bucket_endpoint>" \
      --from-literal=access_key_id="<aws_access_key_id>" \
      --from-literal=access_key_secret="<aws_access_key_secret>" \
      --from-literal=region="<aws_region_of_your_bucket>" \
      --from-literal=forcepathstyle="true" 
    2
    1 1
    logging-loki-aws is the name of the secret.
    2
    AWS endpoints (those ending in .amazonaws.com) use a virtual-hosted style by default, which is equivalent to setting the forcepathstyle attribute to false. Conversely, non-AWS endpoints use a path style, equivalent to setting forcepathstyle attribute to true. If you need to use a virtual-hosted style with non-AWS S3 services, you must explicitly set forcepathstyle to false.
3.2.1.1. AWS storage for STS enabled clusters

If your cluster has STS enabled, the Cloud Credential Operator (CCO) supports short-term authentication by using AWS tokens.

You can create the Loki object storage secret manually by running the following command:

$ oc -n openshift-logging create secret generic "logging-loki-aws" \
  --from-literal=bucketnames="<s3_bucket_name>" \
  --from-literal=region="<bucket_region>" \
  --from-literal=audience="<oidc_audience>" 
1
1
Optional annotation, default value is openshift.

3.2.2. Azure storage

Prerequisites

  • You installed the Loki Operator.
  • You installed the OpenShift CLI (oc).
  • You created a bucket on Azure.

Procedure

  • Create an object storage secret with the name logging-loki-azure by running the following command:

    $ oc create secret generic logging-loki-azure \
      --from-literal=container="<azure_container_name>" \
      --from-literal=environment="<azure_environment>" \ 
    1
    
      --from-literal=account_name="<azure_account_name>" \
      --from-literal=account_key="<azure_account_key>"
    1
    Supported environment values are AzureGlobal, AzureChinaCloud, AzureGermanCloud, or AzureUSGovernment.

If your cluster has Microsoft Entra Workload ID enabled, the Cloud Credential Operator (CCO) supports short-term authentication using Workload ID.

You can create the Loki object storage secret manually by running the following command:

$ oc -n openshift-logging create secret generic logging-loki-azure \
  --from-literal=environment="<azure_environment>" \
  --from-literal=account_name="<storage_account_name>" \
  --from-literal=container="<container_name>"

3.2.3. Google Cloud Platform storage

Prerequisites

  • You installed the Loki Operator.
  • You installed the OpenShift CLI (oc).
  • You created a project on Google Cloud Platform (GCP).
  • You created a bucket in the same project.
  • You created a service account in the same project for GCP authentication.

Procedure

  1. Copy the service account credentials received from GCP into a file called key.json.
  2. Create an object storage secret with the name logging-loki-gcs by running the following command:

    $ oc create secret generic logging-loki-gcs \
      --from-literal=bucketname="<bucket_name>" \
      --from-file=key.json="<path/to/key.json>"

3.2.4. Minio storage

You can create an object storage in Minio to store logs.

Prerequisites

  • You installed the Loki Operator.
  • You installed the OpenShift CLI (oc).
  • You have Minio deployed on your cluster.
  • You created a bucket on Minio.

Procedure

  • Create an object storage secret with the name logging-loki-minio by running the following command:

    $ oc create secret generic logging-loki-minio \ 
    1
    
      --from-literal=bucketnames="<bucket_name>" \
      --from-literal=endpoint="<minio_bucket_endpoint>" \
      --from-literal=access_key_id="<minio_access_key_id>" \
      --from-literal=access_key_secret="<minio_access_key_secret>" \
      --from-literal=forcepathstyle="true" 
    2
    1
    logging-loki-minio is the name of the secret.
    2
    AWS endpoints (those ending in .amazonaws.com) use a virtual-hosted style by default, which is equivalent to setting the forcepathstyle attribute to false. Conversely, non-AWS endpoints use a path style, equivalent to setting forcepathstyle attribute to true. If you need to use a virtual-hosted style with non-AWS S3 services, you must explicitly set forcepathstyle to false.

3.2.5. OpenShift Data Foundation storage

You can create an object storage in OpenShift Data Foundation storage to store logs.

Prerequisites

Procedure

  1. Create an ObjectBucketClaim custom resource in the openshift-logging namespace:

    apiVersion: objectbucket.io/v1alpha1
    kind: ObjectBucketClaim
    metadata:
      name: loki-bucket-odf
      namespace: openshift-logging
    spec:
      generateBucketName: loki-bucket-odf
      storageClassName: openshift-storage.noobaa.io
  2. Get bucket properties from the associated ConfigMap object by running the following command:

    BUCKET_HOST=$(oc get -n openshift-logging configmap loki-bucket-odf -o jsonpath='{.data.BUCKET_HOST}')
    BUCKET_NAME=$(oc get -n openshift-logging configmap loki-bucket-odf -o jsonpath='{.data.BUCKET_NAME}')
    BUCKET_PORT=$(oc get -n openshift-logging configmap loki-bucket-odf -o jsonpath='{.data.BUCKET_PORT}')
  3. Get bucket access key from the associated secret by running the following command:

    ACCESS_KEY_ID=$(oc get -n openshift-logging secret loki-bucket-odf -o jsonpath='{.data.AWS_ACCESS_KEY_ID}' | base64 -d)
    SECRET_ACCESS_KEY=$(oc get -n openshift-logging secret loki-bucket-odf -o jsonpath='{.data.AWS_SECRET_ACCESS_KEY}' | base64 -d)
  4. Create an object storage secret with the name logging-loki-odf by running the following command:

    $ oc create -n openshift-logging secret generic logging-loki-odf \ 
    1
    
      --from-literal=access_key_id="<access_key_id>" \
      --from-literal=access_key_secret="<secret_access_key>" \
      --from-literal=bucketnames="<bucket_name>" \
      --from-literal=endpoint="https://<bucket_host>:<bucket_port>" \
      --from-literal=forcepathstyle="true" 
    2
    1
    logging-loki-odf is the name of the secret.
    2
    AWS endpoints (those ending in .amazonaws.com) use a virtual-hosted style by default, which is equivalent to setting the forcepathstyle attribute to false. Conversely, non-AWS endpoints use a path style, equivalent to setting forcepathstyle attribute to true. If you need to use a virtual-hosted style with non-AWS S3 services, you must explicitly set forcepathstyle to false.

3.2.6. Swift storage

Prerequisites

  • You installed the Loki Operator.
  • You installed the OpenShift CLI (oc).
  • You created a bucket on Swift.

Procedure

  • Create an object storage secret with the name logging-loki-swift by running the following command:

    $ oc create secret generic logging-loki-swift \
      --from-literal=auth_url="<swift_auth_url>" \
      --from-literal=username="<swift_usernameclaim>" \
      --from-literal=user_domain_name="<swift_user_domain_name>" \
      --from-literal=user_domain_id="<swift_user_domain_id>" \
      --from-literal=user_id="<swift_user_id>" \
      --from-literal=password="<swift_password>" \
      --from-literal=domain_id="<swift_domain_id>" \
      --from-literal=domain_name="<swift_domain_name>" \
      --from-literal=container_name="<swift_container_name>"
  • You can optionally provide project-specific data, region, or both by running the following command:

    $ oc create secret generic logging-loki-swift \
      --from-literal=auth_url="<swift_auth_url>" \
      --from-literal=username="<swift_usernameclaim>" \
      --from-literal=user_domain_name="<swift_user_domain_name>" \
      --from-literal=user_domain_id="<swift_user_domain_id>" \
      --from-literal=user_id="<swift_user_id>" \
      --from-literal=password="<swift_password>" \
      --from-literal=domain_id="<swift_domain_id>" \
      --from-literal=domain_name="<swift_domain_name>" \
      --from-literal=container_name="<swift_container_name>" \
      --from-literal=project_id="<swift_project_id>" \
      --from-literal=project_name="<swift_project_name>" \
      --from-literal=project_domain_id="<swift_project_domain_id>" \
      --from-literal=project_domain_name="<swift_project_domain_name>" \
      --from-literal=region="<swift_region>"

For some storage providers, you can use the Cloud Credential Operator utility (ccoctl) during installation to implement short-term credentials. These credentials are created and managed outside the OpenShift Container Platform cluster. For more information, see Manual mode with short-term credentials for components.

Note

Short-term credential authentication must be configured during a new installation of Loki Operator, on a cluster that uses this credentials strategy. You cannot configure an existing cluster that uses a different credentials strategy to use this feature.

You can use workload identity federation with short-lived tokens to authenticate to cloud-based log stores. With workload identity federation, you do not have to store long-lived credentials in your cluster, which reduces the risk of credential leaks and simplifies secret management.

Prerequisites

  • You have administrator permissions.

Procedure

  • Use one of the following options to enable authentication:

    • If you used the OpenShift Container Platform web console to install the Loki Operator, the system automatically detects clusters that use short-lived tokens. You are prompted to create roles and supply the data required for the Loki Operator to create a CredentialsRequest object, which populates a secret.
    • If you used the OpenShift CLI (oc) to install the Loki Operator, you must manually create a Subscription object. Use the appropriate template for your storage provider, as shown in the following samples. This authentication strategy supports only the storage providers indicated within the samples.

      Microsoft Azure sample subscription

      apiVersion: operators.coreos.com/v1alpha1
      kind: Subscription
      metadata:
        name: loki-operator
        namespace: openshift-operators-redhat
      spec:
        channel: "stable-6.3"
        installPlanApproval: Manual
        name: loki-operator
        source: redhat-operators
        sourceNamespace: openshift-marketplace
        config:
          env:
            - name: CLIENTID
              value: <your_client_id>
            - name: TENANTID
              value: <your_tenant_id>
            - name: SUBSCRIPTIONID
              value: <your_subscription_id>
            - name: REGION
              value: <your_region>

      Amazon Web Services (AWS) sample subscription

      apiVersion: operators.coreos.com/v1alpha1
      kind: Subscription
      metadata:
        name: loki-operator
        namespace: openshift-operators-redhat
      spec:
        channel: "stable-6.3"
        installPlanApproval: Manual
        name: loki-operator
        source: redhat-operators
        sourceNamespace: openshift-marketplace
        config:
          env:
          - name: ROLEARN
            value: <role_ARN>

      Google Cloud Platform (GCP) sample subscription

      apiVersion: operators.coreos.com/v1alpha1
      kind: Subscription
      metadata:
        name: loki-operator
        namespace: openshift-operators-redhat
      spec:
        channel: "stable-6.3"
        installPlanApproval: Manual
        name: loki-operator
        source:  redhat-operators
        sourceNamespace: openshift-marketplace
        config:
          env:
          - name: PROJECT_NUMBER
            value: <your_project_number>
          - name: POOL_ID
            value: <your_pool_id>
          - name: PROVIDER_ID
            value: <your_provider_id>
          - name: SERVICE_ACCOUNT_EMAIL
            value: example@mydomain.iam.gserviceaccount.com

You can create a LokiStack custom resource (CR) by using the OpenShift Container Platform web console.

Prerequisites

  • You have administrator permissions.
  • You have access to the OpenShift Container Platform web console.
  • You installed the Loki Operator.

Procedure

  1. Go to the OperatorsInstalled Operators page. Click the All instances tab.
  2. From the Create new drop-down list, select LokiStack.
  3. Select YAML view, and then use the following template to create a LokiStack CR:

    apiVersion: loki.grafana.com/v1
    kind: LokiStack
    metadata:
      name: logging-loki 
    1
    
      namespace: openshift-logging
    spec:
      size: 1x.small 
    2
    
      storage:
        schemas:
          - effectiveDate: '2023-10-15'
            version: v13
        secret:
          name: logging-loki-s3 
    3
    
          type: s3 
    4
    
          credentialMode: 
    5
    
      storageClassName: <storage_class_name> 
    6
    
      tenants:
        mode: openshift-logging
    1
    Use the name logging-loki.
    2
    Specify the deployment size. In the logging 5.8 and later versions, the supported size options for production instances of Loki are 1x.extra-small, 1x.small, or 1x.medium.
    3
    Specify the secret used for your log storage.
    4
    Specify the corresponding storage type.
    5
    Optional field, logging 5.9 and later. Supported user configured values are as follows: static is the default authentication mode available for all supported object storage types using credentials stored in a Secret. token for short-lived tokens retrieved from a credential source. In this mode the static configuration does not contain credentials needed for the object storage. Instead, they are generated during runtime using a service, which allows for shorter-lived credentials and much more granular control. This authentication mode is not supported for all object storage types. token-cco is the default value when Loki is running on managed STS mode and using CCO on STS/WIF clusters.
    6
    Enter the name of a storage class for temporary storage. For best performance, specify a storage class that allocates block storage. Available storage classes for your cluster can be listed by using the oc get storageclasses command.

To configure Loki object storage, you must create a secret. You can do this by using the OpenShift CLI (oc).

Prerequisites

  • You have administrator permissions.
  • You installed the Loki Operator.
  • You installed the OpenShift CLI (oc).

Procedure

  • Create a secret in the directory that contains your certificate and key files by running the following command:

    $ oc create secret generic -n openshift-logging <your_secret_name> \
      --from-file=tls.key=<your_key_file> \
      --from-file=tls.crt=<your_crt_file> \
      --from-file=ca-bundle.crt=<your_bundle_file> \
      --from-literal=username=<your_username> \
      --from-literal=password=<your_password>
Note

Use generic or opaque secrets for best results.

Verification

  • Verify that a secret was created by running the following command:

    $ oc get secret -n openshift-logging

3.2.8. Fine grained access for Loki logs

The Red Hat OpenShift Logging Operator does not grant all users access to logs by default. As an administrator, you must configure your users' access unless the Operator was upgraded and prior configurations are in place. Depending on your configuration and need, you can configure fine grain access to logs using the following:

  • Cluster wide policies
  • Namespace scoped policies
  • Creation of custom admin groups

As an administrator, you need to create the role bindings and cluster role bindings appropriate for your deployment. The Red Hat OpenShift Logging Operator provides the following cluster roles:

  • cluster-logging-application-view grants permission to read application logs.
  • cluster-logging-infrastructure-view grants permission to read infrastructure logs.
  • cluster-logging-audit-view grants permission to read audit logs.

If you have upgraded from a prior version, an additional cluster role logging-application-logs-reader and associated cluster role binding logging-all-authenticated-application-logs-reader provide backward compatibility, allowing any authenticated user read access in their namespaces.

Note

Users with access by namespace must provide a namespace when querying application logs.

3.2.8.1. Cluster wide access

Cluster role binding resources reference cluster roles, and set permissions cluster wide.

Example ClusterRoleBinding

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: logging-all-application-logs-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-logging-application-view 
1

subjects: 
2

- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io

1
Additional ClusterRoles are cluster-logging-infrastructure-view, and cluster-logging-audit-view.
2
Specifies the users or groups this object applies to.
3.2.8.2. Namespaced access

RoleBinding resources can be used with ClusterRole objects to define the namespace a user or group has access to logs for.

Example RoleBinding

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: allow-read-logs
  namespace: log-test-0 
1

roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-logging-application-view
subjects:
- kind: User
  apiGroup: rbac.authorization.k8s.io
  name: testuser-0

1
Specifies the namespace this RoleBinding applies to.
3.2.8.3. Custom admin group access

If you have a large deployment with several users who require broader permissions, you can create a custom group using the adminGroup field. Users who are members of any group specified in the adminGroups field of the LokiStack CR are considered administrators.

Administrator users have access to all application logs in all namespaces, if they also get assigned the cluster-logging-application-view role.

Example LokiStack CR

apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
  name: logging-loki
  namespace: openshift-logging
spec:
  tenants:
    mode: openshift-logging 
1

    openshift:
      adminGroups: 
2

      - cluster-admin
      - custom-admin-group 
3

1
Custom admin groups are only available in this mode.
2
Entering an empty list [] value for this field disables admin groups.
3
Overrides the default groups (system:cluster-admins, cluster-admin, dedicated-admin)
Important

Querying application logs for multiple namespaces as a cluster-admin user, where the sum total of characters of all of the namespaces in the cluster is greater than 5120, results in the error Parse error: input size too long (XXXX > 5120). For better control over access to logs in LokiStack, make the cluster-admin user a member of the cluster-admin group. If the cluster-admin group does not exist, create it and add the desired users to it.

Use the following procedure to create a new group for users with cluster-admin permissions.

Procedure

  1. Enter the following command to create a new group:

    $ oc adm groups new cluster-admin
  2. Enter the following command to add the desired user to the cluster-admin group:

    $ oc adm groups add-users cluster-admin <username>
  3. Enter the following command to add cluster-admin user role to the group:

    $ oc adm policy add-cluster-role-to-group cluster-admin cluster-admin

3.3. Enhanced reliability and performance for Loki

Use the following configurations to ensure reliability and efficiency of Loki in production.

3.3.1. Loki pod placement

You can control which nodes the Loki pods run on, and prevent other workloads from using those nodes, by using tolerations or node selectors on the pods.

You can apply tolerations to the log store pods with the LokiStack custom resource (CR) and apply taints to a node with the node specification. A taint on a node is a key:value pair that instructs the node to repel all pods that do not allow the taint. Using a specific key:value pair that is not on other pods ensures that only the log store pods can run on that node.

Example LokiStack with node selectors

apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
  name: logging-loki
  namespace: openshift-logging
spec:
# ...
  template:
    compactor: 
1

      nodeSelector:
        node-role.kubernetes.io/infra: "" 
2

    distributor:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    gateway:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    indexGateway:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    ingester:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    querier:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    queryFrontend:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
    ruler:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
# ...

1
Specifies the component pod type that applies to the node selector.
2
Specifies the pods that are moved to nodes containing the defined label.

Example LokiStack CR with node selectors and tolerations

apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
  name: logging-loki
  namespace: openshift-logging
spec:
# ...
  template:
    compactor:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/infra
        value: reserved
      - effect: NoExecute
        key: node-role.kubernetes.io/infra
        value: reserved
    distributor:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/infra
        value: reserved
      - effect: NoExecute
        key: node-role.kubernetes.io/infra
        value: reserved
    indexGateway:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/infra
        value: reserved
      - effect: NoExecute
        key: node-role.kubernetes.io/infra
        value: reserved
    ingester:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/infra
        value: reserved
      - effect: NoExecute
        key: node-role.kubernetes.io/infra
        value: reserved
    querier:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/infra
        value: reserved
      - effect: NoExecute
        key: node-role.kubernetes.io/infra
        value: reserved
    queryFrontend:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/infra
        value: reserved
      - effect: NoExecute
        key: node-role.kubernetes.io/infra
        value: reserved
    ruler:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/infra
        value: reserved
      - effect: NoExecute
        key: node-role.kubernetes.io/infra
        value: reserved
    gateway:
      nodeSelector:
        node-role.kubernetes.io/infra: ""
      tolerations:
      - effect: NoSchedule
        key: node-role.kubernetes.io/infra
        value: reserved
      - effect: NoExecute
        key: node-role.kubernetes.io/infra
        value: reserved
# ...

To configure the nodeSelector and tolerations fields of the LokiStack (CR), you can use the oc explain command to view the description and fields for a particular resource:

$ oc explain lokistack.spec.template

Example output

KIND:     LokiStack
VERSION:  loki.grafana.com/v1

RESOURCE: template <Object>

DESCRIPTION:
     Template defines the resource/limits/tolerations/nodeselectors per
     component

FIELDS:
   compactor	<Object>
     Compactor defines the compaction component spec.

   distributor	<Object>
     Distributor defines the distributor component spec.
...

For more detailed information, you can add a specific field:

$ oc explain lokistack.spec.template.compactor

Example output

KIND:     LokiStack
VERSION:  loki.grafana.com/v1

RESOURCE: compactor <Object>

DESCRIPTION:
     Compactor defines the compaction component spec.

FIELDS:
   nodeSelector	<map[string]string>
     NodeSelector defines the labels required by a node to schedule the
     component onto it.
...

3.3.2. Configuring Loki to tolerate node failure

In the logging 5.8 and later versions, the Loki Operator supports setting pod anti-affinity rules to request that pods of the same component are scheduled on different available nodes in the cluster.

Affinity is a property of pods that controls the nodes on which they prefer to be scheduled. Anti-affinity is a property of pods that prevents a pod from being scheduled on a node.

In OpenShift Container Platform, pod affinity and pod anti-affinity allow you to constrain which nodes your pod is eligible to be scheduled on based on the key-value labels on other pods.

The Operator sets default, preferred podAntiAffinity rules for all Loki components, which includes the compactor, distributor, gateway, indexGateway, ingester, querier, queryFrontend, and ruler components.

You can override the preferred podAntiAffinity settings for Loki components by configuring required settings in the requiredDuringSchedulingIgnoredDuringExecution field:

Example user settings for the ingester component

apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
  name: logging-loki
  namespace: openshift-logging
spec:
# ...
  template:
    ingester:
      podAntiAffinity:
      # ...
        requiredDuringSchedulingIgnoredDuringExecution: 
1

        - labelSelector:
            matchLabels: 
2

              app.kubernetes.io/component: ingester
          topologyKey: kubernetes.io/hostname
# ...

1
The stanza to define a required rule.
2
The key-value pair (label) that must be matched to apply the rule.

3.3.3. Enabling stream-based retention with Loki

You can configure retention policies based on log streams. You can set retention rules globally, per-tenant, or both. If you configure both, tenant rules apply before global rules.

Important

If there is no retention period defined on the s3 bucket or in the LokiStack custom resource (CR), then the logs are not pruned and they stay in the s3 bucket forever, which might fill up the s3 storage.

Note
  • Although logging version 5.9 and later supports schema v12, schema v13 is recommended for future compatibility.
  • For cost-effective log pruning, configure retention policies directly on the object storage provider. Use the lifecycle management features of the storage provider to ensure automatic deletion of old logs. This also avoids extra processing from Loki and delete requests to S3.

    If the object storage does not support lifecycle policies, you must configure LokiStack to enforce retention internally. The supported retention period is up to 30 days.

Prerequisites

  • You have administrator permissions.
  • You have installed the Loki Operator.
  • You have installed the OpenShift CLI (oc).

Procedure

  1. To enable stream-based retention, create a LokiStack CR and save it as a YAML file. In the following example, it is called lokistack.yaml.

    Example global stream-based retention for S3

    apiVersion: loki.grafana.com/v1
    kind: LokiStack
    metadata:
      name: logging-loki
      namespace: openshift-logging
    spec:
      limits:
       global: 
    1
    
          retention: 
    2
    
            days: 20
            streams:
            - days: 4
              priority: 1
              selector: '{kubernetes_namespace_name=~"test.+"}' 
    3
    
            - days: 1
              priority: 1
              selector: '{log_type="infrastructure"}'
      managementState: Managed
      replicationFactor: 1
      size: 1x.small
      storage:
        schemas:
        - effectiveDate: "2020-10-11"
          version: v13
        secret:
          name: logging-loki-s3
          type: s3
      storageClassName: gp3-csi
      tenants:
        mode: openshift-logging

    1
    Set the retention policy for all log streams. This policy does not impact the retention period for stored logs in object storage.
    2
    Enable retention in the cluster by adding the retention block to the CR.
    3
    Specify the LogQL query to match log streams to the retention rule.

    Example per-tenant stream-based retention for S3

    apiVersion: loki.grafana.com/v1
    kind: LokiStack
    metadata:
      name: logging-loki
      namespace: openshift-logging
    spec:
      limits:
        global:
          retention:
            days: 20
        tenants: 
    1
    
          application:
            retention:
              days: 1
              streams:
                - days: 4
                  selector: '{kubernetes_namespace_name=~"test.+"}' 
    2
    
          infrastructure:
            retention:
              days: 5
              streams:
                - days: 1
                  selector: '{kubernetes_namespace_name=~"openshift-cluster.+"}'
      managementState: Managed
      replicationFactor: 1
      size: 1x.small
      storage:
        schemas:
        - effectiveDate: "2020-10-11"
          version: v13
        secret:
          name: logging-loki-s3
          type: s3
      storageClassName: gp3-csi
      tenants:
        mode: openshift-logging

    1
    Set the retention policy per-tenant. Valid tenant types are application, audit, and infrastructure.
    2
    Specify the LogQL query to match log streams to the retention rule.
  2. Apply the LokiStack CR:

    $ oc apply -f lokistack.yaml

In an OpenShift Container Platform cluster, administrators generally use a non-private IP network range. As a result, the LokiStack memberlist configuration fails because, by default, it only uses private IP networks.

As an administrator, you can select the pod network for the memberlist configuration. You can modify the LokiStack custom resource (CR) to use the podIP address in the hashRing spec. To configure the LokiStack CR, use the following command:

$ oc patch LokiStack logging-loki -n openshift-logging  --type=merge -p '{"spec": {"hashRing":{"memberlist":{"instanceAddrType":"podIP"},"type":"memberlist"}}}'

Example LokiStack to include podIP

apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
  name: logging-loki
  namespace: openshift-logging
spec:
# ...
  hashRing:
    type: memberlist
    memberlist:
      instanceAddrType: podIP
# ...

3.3.5. LokiStack behavior during cluster restarts

When an OpenShift Container Platform cluster is restarted, LokiStack ingestion and the query path continue to operate within the available CPU and memory resources available for the node. This means that there is no downtime for the LokiStack during OpenShift Container Platform cluster updates. This behavior is achieved by using PodDisruptionBudget resources. The Loki Operator provisions PodDisruptionBudget resources for Loki, which determine the minimum number of pods that must be available per component to ensure normal operations under certain conditions.

3.4. Advanced deployment and scalability for Loki

You can configure high availability, scalability, and error handling for Loki.

3.4.1. Zone aware data replication

The Loki Operator offers support for zone-aware data replication through pod topology spread constraints. Enabling this feature enhances reliability and safeguards against log loss in the event of a single zone failure. When configuring the deployment size as 1x.extra-small, 1x.small, or 1x.medium, the replication.factor field is automatically set to 2.

To ensure proper replication, you need to have at least as many availability zones as the replication factor specifies. While it is possible to have more availability zones than the replication factor, having fewer zones can lead to write failures. Each zone should host an equal number of instances for optimal operation.

Example LokiStack CR with zone replication enabled

apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
 name: logging-loki
 namespace: openshift-logging
spec:
 replicationFactor: 2 
1

 replication:
   factor: 2 
2

   zones:
   -  maxSkew: 1 
3

      topologyKey: topology.kubernetes.io/zone 
4

1
Deprecated field, values entered are overwritten by replication.factor.
2
This value is automatically set when deployment size is selected at setup.
3
The maximum difference in number of pods between any two topology domains. The default is 1, and you cannot specify a value of 0.
4
Defines zones in the form of a topology key that corresponds to a node label.

3.4.2. Recovering Loki pods from failed zones

In OpenShift Container Platform a zone failure happens when specific availability zone resources become inaccessible. Availability zones are isolated areas within a cloud provider’s data center, aimed at enhancing redundancy and fault tolerance. If your OpenShift Container Platform cluster is not configured to handle this, a zone failure can lead to service or data loss.

Loki pods are part of a StatefulSet, and they come with Persistent Volume Claims (PVCs) provisioned by a StorageClass object. Each Loki pod and its PVCs reside in the same zone. When a zone failure occurs in a cluster, the StatefulSet controller automatically attempts to recover the affected pods in the failed zone.

Warning

The following procedure will delete the PVCs in the failed zone, and all data contained therein. To avoid complete data loss the replication factor field of the LokiStack CR should always be set to a value greater than 1 to ensure that Loki is replicating.

Prerequisites

  • Verify your LokiStack CR has a replication factor greater than 1.
  • Zone failure detected by the control plane, and nodes in the failed zone are marked by cloud provider integration.

The StatefulSet controller automatically attempts to reschedule pods in a failed zone. Because the associated PVCs are also in the failed zone, automatic rescheduling to a different zone does not work. You must manually delete the PVCs in the failed zone to allow successful re-creation of the stateful Loki Pod and its provisioned PVC in the new zone.

Procedure

  1. List the pods in Pending status by running the following command:

    $ oc get pods --field-selector status.phase==Pending -n openshift-logging

    Example oc get pods output

    NAME                           READY   STATUS    RESTARTS   AGE 
    1
    
    logging-loki-index-gateway-1   0/1     Pending   0          17m
    logging-loki-ingester-1        0/1     Pending   0          16m
    logging-loki-ruler-1           0/1     Pending   0          16m

    1
    These pods are in Pending status because their corresponding PVCs are in the failed zone.
  2. List the PVCs in Pending status by running the following command:

    $ oc get pvc -o=json -n openshift-logging | jq '.items[] | select(.status.phase == "Pending") | .metadata.name' -r

    Example oc get pvc output

    storage-logging-loki-index-gateway-1
    storage-logging-loki-ingester-1
    wal-logging-loki-ingester-1
    storage-logging-loki-ruler-1
    wal-logging-loki-ruler-1

  3. Delete the PVC(s) for a pod by running the following command:

    $ oc delete pvc <pvc_name> -n openshift-logging
  4. Delete the pod(s) by running the following command:

    $ oc delete pod <pod_name> -n openshift-logging

    Once these objects have been successfully deleted, they should automatically be rescheduled in an available zone.

The PVCs might hang in the terminating state without being deleted, if PVC metadata finalizers are set to kubernetes.io/pv-protection. Removing the finalizers should allow the PVCs to delete successfully.

  • Remove the finalizer for each PVC by running the command below, then retry deletion.

    $ oc patch pvc <pvc_name> -p '{"metadata":{"finalizers":null}}' -n openshift-logging

3.4.3. Troubleshooting Loki rate limit errors

If the Log Forwarder API forwards a large block of messages that exceeds the rate limit to Loki, Loki generates rate limit (429) errors.

These errors can occur during normal operation. For example, when adding the logging to a cluster that already has some logs, rate limit errors might occur while the logging tries to ingest all of the existing log entries. In this case, if the rate of addition of new logs is less than the total rate limit, the historical data is eventually ingested, and the rate limit errors are resolved without requiring user intervention.

In cases where the rate limit errors continue to occur, you can fix the issue by modifying the LokiStack custom resource (CR).

Important

The LokiStack CR is not available on Grafana-hosted Loki. This topic does not apply to Grafana-hosted Loki servers.

Conditions

  • The Log Forwarder API is configured to forward logs to Loki.
  • Your system sends a block of messages that is larger than 2 MB to Loki. For example:

    "values":[["1630410392689800468","{\"kind\":\"Event\",\"apiVersion\":\
    .......
    ......
    ......
    ......
    \"received_at\":\"2021-08-31T11:46:32.800278+00:00\",\"version\":\"1.7.4 1.6.0\"}},\"@timestamp\":\"2021-08-31T11:46:32.799692+00:00\",\"viaq_index_name\":\"audit-write\",\"viaq_msg_id\":\"MzFjYjJkZjItNjY0MC00YWU4LWIwMTEtNGNmM2E5ZmViMGU4\",\"log_type\":\"audit\"}"]]}]}
  • After you enter oc logs -n openshift-logging -l component=collector, the collector logs in your cluster show a line containing one of the following error messages:

    429 Too Many Requests Ingestion rate limit exceeded

    Example Vector error message

    2023-08-25T16:08:49.301780Z  WARN sink{component_kind="sink" component_id=default_loki_infra component_type=loki component_name=default_loki_infra}: vector::sinks::util::retries: Retrying after error. error=Server responded with an error: 429 Too Many Requests internal_log_rate_limit=true

    The error is also visible on the receiving end. For example, in the LokiStack ingester pod:

    Example Loki ingester error message

    level=warn ts=2023-08-30T14:57:34.155592243Z caller=grpc_logging.go:43 duration=1.434942ms method=/logproto.Pusher/Push err="rpc error: code = Code(429) desc = entry with timestamp 2023-08-30 14:57:32.012778399 +0000 UTC ignored, reason: 'Per stream rate limit exceeded (limit: 3MB/sec) while attempting to ingest for stream

Procedure

  • Update the ingestionBurstSize and ingestionRate fields in the LokiStack CR:

    apiVersion: loki.grafana.com/v1
    kind: LokiStack
    metadata:
      name: logging-loki
      namespace: openshift-logging
    spec:
      limits:
        global:
          ingestion:
            ingestionBurstSize: 16 
    1
    
            ingestionRate: 8 
    2
    
    # ...
    1
    The ingestionBurstSize field defines the maximum local rate-limited sample size per distributor replica in MB. This value is a hard limit. Set this value to at least the maximum logs size expected in a single push request. Single requests that are larger than the ingestionBurstSize value are not permitted.
    2
    The ingestionRate field is a soft limit on the maximum amount of ingested samples per second in MB. Rate limit errors occur if the rate of logs exceeds the limit, but the collector retries sending the logs. As long as the total average is lower than the limit, the system recovers and errors are resolved without user intervention.

3.5. Loki network policies for added security

Loki Operator can deploy and manage a set of network policies that restrict the communications to and from the Loki components to enhance security.

3.5.1. Loki network policies

You can enable the Loki Operator to automatically create a NetworkPolicy resource that implements a "default deny" security model with explicit allow rules for required communications. Network policies provide network segmentation for your LokiStack deployment by controlling ingress and egress traffic between Loki components and external services. The network policies in Loki Operator are designed to be secure by default while maintaining compatibility across diverse environments.

Network policies for Loki on OpenShift Container Platform include the following additional integrations:

  • Monitoring: Automatic integration with the OpenShift Container Platform monitoring stack.
  • DNS: Support for both standard and OpenShift Container Platform DNS services (port 5353).

3.5.2. Configuring a network policy for Loki

Enable or disable the deployment of NetworkPolicies per LokiStack by setting the networkPolicies field.

Prerequisites

  • You have administrator permissions.
  • You have installed the OpenShift CLI (oc).
  • You have installed the Loki Operator.
  • You have created a LokiStack custom resource (CR).

Procedure

  1. Update the LokiStack CR:

    apiVersion: loki.grafana.com/v1
    kind: LokiStack
    metadata:
      name: logging-loki
      namespace: openshift-logging
    spec:
      size: 1x.small
      storage:
        schemas:
        - version: v13
          effectiveDate: "<yyyy>-<mm>-<dd>"
        secret:
          name: logging-loki-s3
          type: s3
      storageClassName: <storage_class_name>
      tenants:
        mode: openshift-logging
      networkPolicies:
        ruleSet: RestrictIngressEgress

    You can set one of the following values for the spec.networkPolicies.ruleSet field:

    None
    Loki Operator will not deploy any network policy.
    RestrictIngressEgress

    Loki Operator will deploy a set of network policies that restrict the communications to and from the Loki components.

    If you do not define a spec.networkPolicies.ruleSet value, the platform and operator default values are inherited and full network access is allowed.

  2. Apply the LokiStack CR object by running the following command:

    $ oc apply -f <filename>.yaml

3.5.3. Loki NetworkPolicy resources

When network policies are enabled, the Loki Operator creates several NetworkPolicy resources to secure different aspects of your LokiStack deployment.

Expand

Policy name

Purpose

Components affected

{name}-default-deny

A baseline deny-all policy

All LokiStack pods

{name}-loki-allow

Inter-component communication allowed

All Loki components

{name}-loki-allow-metrics

Allow metric scraping on the prometheus endpoint

All Loki components

{name}-loki-allow-bucket-egress

Policy for object storage access

ingester, querier, index-gateway, compactor, ruler

{name}-loki-allow-gateway-ingress

Allow gateway access to Loki components

distributor, query-frontend, ruler

{name}-gateway-allow

Gateway external and monitoring access

LokiStack-gateway

{name}-gateway-allow-metrics

Allow metric scraping on the prometheus endpoint

LokiStack-gateway

{name}-ruler-allow-alert-egress

Allow ruler egress to AlertManager

ruler

{name}-loki-allow-query-frontend

Query frontend external access

query-frontend (OpenShift network mode)

To integrate Loki with external systems such as custom dashboards, or external alerting, create additional network policies. You can select specific components by using the label app.kubernetes.io/component. Always include the labels app.kubernetes.io/name=lokistack and app.kubernetes.io/instance={name} to avoid collision with other pods deployed in the namespace.

Prerequisites

  • You have administrator permissions.
  • You have installed the OpenShift CLI (oc).
  • You have installed the Loki Operator.
  • You have created a LokiStack custom resource (CR).

Procedure

  1. Create a network policy:

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: <name>
    spec:
      podSelector:
        matchLabels:
          app.kubernetes.io/name: lokistack
          app.kubernetes.io/instance: <instance_name>
          app.kubernetes.io/component: <loki_component>
      policyTypes:
      - Egress
      egress:
      - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: <namespace_name>
        ports:
        - protocol: TCP
          port: <port_number>

    Replace <component_name> with the component you want to integrate with.

  2. Apply the network policy:

    $ oc apply -f <file_name>.yaml

3.6. Log-based alerts for Loki

You can configure log-based alerts for Loki by creating an AlertingRule custom resource (CR).

Administrators bind cluster roles to users to enable them to create and manage alerting and recording rules. A cluster role is defined as a ClusterRole object that has the required role-based access control (RBAC) permissions.

The following cluster roles for alerting and recording rules are available for LokiStack:

Expand
Rule nameDescription

alertingrules.loki.grafana.com-v1-admin

Users with this role have administrative-level access to manage alerting rules. This cluster role grants permissions to create, read, update, delete, list, and watch AlertingRule resources within the loki.grafana.com/v1 API group.

alertingrules.loki.grafana.com-v1-crdview

Users with this role can view the definitions of Custom Resource Definitions (CRDs) related to AlertingRule resources within the loki.grafana.com/v1 API group, but do not have permissions for modifying or managing these resources.

alertingrules.loki.grafana.com-v1-edit

Users with this role have permission to create, update, and delete AlertingRule resources.

alertingrules.loki.grafana.com-v1-view

Users with this role can read AlertingRule resources within the loki.grafana.com/v1 API group. They can inspect configurations, labels, and annotations for existing alerting rules but cannot make any modifications to them.

recordingrules.loki.grafana.com-v1-admin

Users with this role have administrative-level access to manage recording rules. This cluster role grants permissions to create, read, update, delete, list, and watch RecordingRule resources within the loki.grafana.com/v1 API group.

recordingrules.loki.grafana.com-v1-crdview

Users with this role can view the definitions of Custom Resource Definitions (CRDs) related to RecordingRule resources within the loki.grafana.com/v1 API group, but do not have permissions for modifying or managing these resources.

recordingrules.loki.grafana.com-v1-edit

Users with this role have permission to create, update, and delete RecordingRule resources.

recordingrules.loki.grafana.com-v1-view

Users with this role can read RecordingRule resources within the loki.grafana.com/v1 API group. They can inspect configurations, labels, and annotations for existing alerting rules but cannot make any modifications to them.

3.6.1.1. Examples

To apply cluster roles for a user, you must bind an existing cluster role to a specific username.

Cluster roles can be cluster or namespace scoped, depending on which type of role binding you use. When a RoleBinding object is used, as when using the oc adm policy add-role-to-user command, the cluster role only applies to the specified namespace. When a ClusterRoleBinding object is used, as when using the oc adm policy add-cluster-role-to-user command, the cluster role applies to all namespaces in the cluster.

The following example command gives the specified user create, read, update and delete (CRUD) permissions for alerting rules in a specific namespace in the cluster:

The following example displays cluster role binding command for alerting rule CRUD permissions in a specific namespace:

$ oc adm policy add-role-to-user alertingrules.loki.grafana.com-v1-admin -n <namespace> <username>

The following command gives the specified user administrator permissions for alerting rules in all namespaces:

$ oc adm policy add-cluster-role-to-user alertingrules.loki.grafana.com-v1-admin <username>

The AlertingRule CR contains a set of specifications and webhook validation definitions to declare groups of alerting rules for a single LokiStack instance. In addition, the webhook validation definition provides support for rule validation conditions:

  • If an AlertingRule CR includes an invalid interval period, it is an invalid alerting rule
  • If an AlertingRule CR includes an invalid for period, it is an invalid alerting rule.
  • If an AlertingRule CR includes an invalid LogQL expr, it is an invalid alerting rule.
  • If an AlertingRule CR includes two groups with the same name, it is an invalid alerting rule.
  • If none of the above applies, an alerting rule is considered valid.
Expand
Table 3.3. AlertingRule definitions
Tenant typeValid namespaces for AlertingRule CRs

application

<your_application_namespace>

audit

openshift-logging

infrastructure

openshift-/*, kube-/\*, default

Procedure

  1. Create an AlertingRule custom resource (CR):

    Example infrastructure AlertingRule CR

      apiVersion: loki.grafana.com/v1
      kind: AlertingRule
      metadata:
        name: loki-operator-alerts
        namespace: openshift-operators-redhat 
    1
    
        labels: 
    2
    
          openshift.io/<label_name>: "true"
      spec:
        tenantID: "infrastructure" 
    3
    
        groups:
          - name: LokiOperatorHighReconciliationError
            rules:
              - alert: HighPercentageError
                expr: | 
    4
    
                  sum(rate({kubernetes_namespace_name="openshift-operators-redhat", kubernetes_pod_name=~"loki-operator-controller-manager.*"} |= "error" [1m])) by (job)
                    /
                  sum(rate({kubernetes_namespace_name="openshift-operators-redhat", kubernetes_pod_name=~"loki-operator-controller-manager.*"}[1m])) by (job)
                    > 0.01
                for: 10s
                labels:
                  severity: critical 
    5
    
                annotations:
                  summary: High Loki Operator Reconciliation Errors 
    6
    
                  description: High Loki Operator Reconciliation Errors 
    7

    1
    The namespace where this AlertingRule CR is created must have a label matching the LokiStack spec.rules.namespaceSelector definition.
    2
    The labels block must match the LokiStack spec.rules.selector definition.
    3
    AlertingRule CRs for infrastructure tenants are only supported in the openshift-*, kube-\*, or default namespaces.
    4
    The value for kubernetes_namespace_name: must match the value for metadata.namespace.
    5
    The value of this mandatory field must be critical, warning, or info.
    6
    This field is mandatory.
    7
    This field is mandatory.

    Example application AlertingRule CR

      apiVersion: loki.grafana.com/v1
      kind: AlertingRule
      metadata:
        name: app-user-workload
        namespace: app-ns 
    1
    
        labels: 
    2
    
          openshift.io/<label_name>: "true"
      spec:
        tenantID: "application"
        groups:
          - name: AppUserWorkloadHighError
            rules:
              - alert:
                expr: | 
    3
    
                  sum(rate({kubernetes_namespace_name="app-ns", kubernetes_pod_name=~"podName.*"} |= "error" [1m])) by (job)
                for: 10s
                labels:
                  severity: critical 
    4
    
                annotations:
                  summary:  
    5
    
                  description:  
    6

    1
    The namespace where this AlertingRule CR is created must have a label matching the LokiStack spec.rules.namespaceSelector definition.
    2
    The labels block must match the LokiStack spec.rules.selector definition.
    3
    Value for kubernetes_namespace_name: must match the value for metadata.namespace.
    4
    The value of this mandatory field must be critical, warning, or info.
    5
    The value of this mandatory field is a summary of the rule.
    6
    The value of this mandatory field is a detailed description of the rule.
  2. Apply the AlertingRule CR:

    $ oc apply -f <filename>.yaml

Chapter 4. OTLP data ingestion in Loki

You can use an API endpoint by using the OpenTelemetry Protocol (OTLP) with Logging. As OTLP is a standardized format not specifically designed for Loki, OTLP requires an additional Loki configuration to map data format of OpenTelemetry to data model of Loki. OTLP lacks concepts such as stream labels or structured metadata. Instead, OTLP provides metadata about log entries as attributes, grouped into the following three categories:

  • Resource
  • Scope
  • Log

You can set metadata for multiple entries simultaneously or individually as needed.

4.1. Configuring LokiStack for OTLP data ingestion

Important

The OpenTelemetry Protocol (OTLP) output log forwarder is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

To configure a LokiStack custom resource (CR) for OTLP ingestion, follow these steps:

Prerequisites

  • Ensure that your Loki setup supports structured metadata, introduced in schema version 13 to enable OTLP log ingestion.

Procedure

  1. Set the schema version:

    • When creating a new LokiStack CR, set version: v13 in the storage schema configuration.

      Note

      For existing configurations, add a new schema entry with version: v13 and an effectiveDate in the future. For more information on updating schema versions, see Upgrading Schemas (Grafana documentation).

  2. Configure the storage schema as follows:

    Example configure storage schema

    # ...
    spec:
      storage:
        schemas:
        - version: v13
          effectiveDate: 2024-10-25

    Once the effectiveDate has passed, the v13 schema takes effect, enabling your LokiStack to store structured metadata.

4.2. Attribute mapping

When you set the Loki Operator to the openshift-logging mode, Loki Operator automatically applies a default set of attribute mappings. These mappings align specific OTLP attributes with stream labels and structured metadata of Loki.

For typical setups, these default mappings are sufficient. However, you might need to customize attribute mapping in the following cases:

  • Using a custom collector: If your setup includes a custom collector that generates additional attributes that you do not want to store, consider customizing the mapping to ensure these attributes are dropped by Loki.
  • Adjusting attribute detail levels: If the default attribute set is more detailed than necessary, you can reduce it to essential attributes only. This can avoid excessive data storage and streamline the logging process.

4.2.1. Custom attribute mapping for OpenShift

When using the Loki Operator in openshift-logging mode, attribute mapping follow OpenShift default values, but you can configure custom mappings to adjust default values. In the openshift-logging mode, you can configure custom attribute mappings globally for all tenants or for individual tenants as needed. When you define custom mappings, they are appended to the OpenShift default values. If you do not need default labels, you can disable them in the tenant configuration.

Note

A major difference between the Loki Operator and Loki lies in inheritance handling. Loki copies only default_resource_attributes_as_index_labels to tenants by default, while the Loki Operator applies the entire global configuration to each tenant in the openshift-logging mode.

Within LokiStack, attribute mapping configuration is managed through the limits setting. See the following example LokiStack configuration:

# ...
spec:
  limits:
    global:
      otlp: {} 
1

    tenants:
      application:
        otlp: {} 
2
1
Defines global OTLP attribute configuration.
2
Defines the OTLP attribute configuration for the application tenant within the openshift-logging mode. You can also configure infrastructure and audit tenants in addition to application tenants.
Note

You can use both global and per-tenant OTLP configurations for mapping attributes to stream labels.

Stream labels derive only from resource-level attributes, which the LokiStack resource structure reflects. See the following LokiStack example configuration:

spec:
  limits:
    global:
      otlp:
        streamLabels:
          resourceAttributes:
          - name: "k8s.namespace.name"
          - name: "k8s.pod.name"
          - name: "k8s.container.name"

You can drop attributes of type resource, scope, or log from the log entry.

# ...
spec:
  limits:
    global:
      otlp:
        streamLabels:
# ...
        drop:
          resourceAttributes:
          - name: "process.command_line"
          - name: "k8s\\.pod\\.labels\\..+"
            regex: true
          scopeAttributes:
          - name: "service.name"
          logAttributes:
          - name: "http.route"

You can use regular expressions by setting regex: true to apply a configuration for attributes with similar names.

Important

Avoid using regular expressions for stream labels, as this can increase data volume.

Attributes that are not explicitly set as stream labels or dropped from the entry are saved as structured metadata by default.

4.2.2. Customizing OpenShift defaults

In the openshift-logging mode, certain attributes are required and cannot be removed from the configuration due to their role in OpenShift functions. Other attributes, labeled recommended, might be dropped if performance is impacted. For information about the attributes, see OpenTelemetry data model attributes.

When using the openshift-logging mode without custom attributes, you can achieve immediate compatibility with OpenShift tools. If additional attributes are needed as stream labels or some attributes need to be dropped, use custom configuration. Custom configurations can merge with default configurations.

Chapter 5. OpenTelemetry data model

This document outlines the protocol and semantic conventions for Red Hat OpenShift Logging’s OpenTelemetry support with Logging.

Important

The OpenTelemetry Protocol (OTLP) output log forwarder is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

5.1. Forwarding and ingestion protocol

Red Hat OpenShift Logging collects and forwards logs to OpenTelemetry endpoints using OTLP Specification. OTLP encodes, transports, and delivers telemetry data. You can also deploy Loki storage, which provides an OTLP endpont to ingest log streams. This document defines the semantic conventions for the logs collected from various OpenShift cluster sources.

5.2. Semantic conventions

The log collector in this solution gathers the following log streams:

  • Container logs
  • Cluster node journal logs
  • Cluster node auditd logs
  • Kubernetes and OpenShift API server logs
  • OpenShift Virtual Network (OVN) logs

You can forward these streams according to the semantic conventions defined by OpenTelemetry semantic attributes. The semantic conventions in OpenTelemetry define a resource as an immutable representation of the entity producing telemetry, identified by attributes. For example, a process running in a container includes attributes such as container_name, cluster_id, pod_name, namespace, and possibly deployment or app_name. These attributes are grouped under the resource object, which helps reduce repetition and optimizes log transmission as telemetry data.

In addition to resource attributes, logs might also contain scope attributes specific to instrumentation libraries and log attributes specific to each log entry. These attributes provide greater detail about each log entry and enhance filtering capabilities when querying logs in storage.

The following sections define the attributes that are generally forwarded.

5.2.1. Log entry structure

All log streams include the following log data fields:

The Applicable Sources column indicates which log sources each field applies to:

  • all: This field is present in all logs.
  • container: This field is present in Kubernetes container logs, both application and infrastructure.
  • audit: This field is present in Kubernetes, OpenShift API, and OVN logs.
  • auditd: This field is present in node auditd logs.
  • journal: This field is present in node journal logs.
Expand
NameApplicable SourcesComment

body

all

 

observedTimeUnixNano

all

 

timeUnixNano

all

 

severityText

container, journal

 

attributes

all

(Optional) Present when forwarding stream specific attributes

5.2.2. Attributes

Log entries include a set of resource, scope, and log attributes based on their source, as described in the following table.

The Location column specifies the type of attribute:

  • resource: Indicates a resource attribute
  • scope: Indicates a scope attribute
  • log: Indicates a log attribute

The Storage column indicates whether the attribute is stored in a LokiStack using the default openshift-logging mode and specifies where the attribute is stored:

  • stream label:

    • Enables efficient filtering and querying based on specific labels.
    • Can be labeled as required if the Loki Operator enforces this attribute in the configuration.
  • structured metadata:

    • Allows for detailed filtering and storage of key-value pairs.
    • Enables users to use direct labels for streamlined queries without requiring JSON parsing.

With OTLP, users can filter queries directly by labels rather than using JSON parsing, improving the speed and efficiency of queries.

Expand
NameLocationApplicable SourcesStorage (LokiStack)Comment

log_source

resource

all

required stream label

(DEPRECATED) Compatibility attribute, contains same information as openshift.log.source

log_type

resource

all

required stream label

(DEPRECATED) Compatibility attribute, contains same information as openshift.log.type

kubernetes.container_name

resource

container

stream label

(DEPRECATED) Compatibility attribute, contains same information as k8s.container.name

kubernetes.host

resource

all

stream label

(DEPRECATED) Compatibility attribute, contains same information as k8s.node.name

kubernetes.namespace_name

resource

container

required stream label

(DEPRECATED) Compatibility attribute, contains same information as k8s.namespace.name

kubernetes.pod_name

resource

container

stream label

(DEPRECATED) Compatibility attribute, contains same information as k8s.pod.name

openshift.cluster_id

resource

all

 

(DEPRECATED) Compatibility attribute, contains same information as openshift.cluster.uid

level

log

container, journal

 

(DEPRECATED) Compatibility attribute, contains same information as severityText

openshift.cluster.uid

resource

all

required stream label

 

openshift.log.source

resource

all

required stream label

 

openshift.log.type

resource

all

required stream label

 

openshift.labels.*

resource

all

structured metadata

 

k8s.node.name

resource

all

stream label

 

k8s.namespace.name

resource

container

required stream label

 

k8s.container.name

resource

container

stream label

 

k8s.pod.labels.*

resource

container

structured metadata

 

k8s.pod.name

resource

container

stream label

 

k8s.pod.uid

resource

container

structured metadata

 

k8s.cronjob.name

resource

container

stream label

Conditionally forwarded based on creator of pod

k8s.daemonset.name

resource

container

stream label

Conditionally forwarded based on creator of pod

k8s.deployment.name

resource

container

stream label

Conditionally forwarded based on creator of pod

k8s.job.name

resource

container

stream label

Conditionally forwarded based on creator of pod

k8s.replicaset.name

resource

container

structured metadata

Conditionally forwarded based on creator of pod

k8s.statefulset.name

resource

container

stream label

Conditionally forwarded based on creator of pod

log.iostream

log

container

structured metadata

 

k8s.audit.event.level

log

audit

structured metadata

 

k8s.audit.event.stage

log

audit

structured metadata

 

k8s.audit.event.user_agent

log

audit

structured metadata

 

k8s.audit.event.request.uri

log

audit

structured metadata

 

k8s.audit.event.response.code

log

audit

structured metadata

 

k8s.audit.event.annotation.*

log

audit

structured metadata

 

k8s.audit.event.object_ref.resource

log

audit

structured metadata

 

k8s.audit.event.object_ref.name

log

audit

structured metadata

 

k8s.audit.event.object_ref.namespace

log

audit

structured metadata

 

k8s.audit.event.object_ref.api_group

log

audit

structured metadata

 

k8s.audit.event.object_ref.api_version

log

audit

structured metadata

 

k8s.user.username

log

audit

structured metadata

 

k8s.user.groups

log

audit

structured metadata

 

process.executable.name

resource

journal

structured metadata

 

process.executable.path

resource

journal

structured metadata

 

process.command_line

resource

journal

structured metadata

 

process.pid

resource

journal

structured metadata

 

service.name

resource

journal

stream label

 

systemd.t.*

log

journal

structured metadata

 

systemd.u.*

log

journal

structured metadata

 
Note

Attributes marked as Compatibility attribute support minimal backward compatibility with the ViaQ data model. These attributes are deprecated and function as a compatibility layer to ensure continued UI functionality. These attributes will remain supported until the Logging UI fully supports the OpenTelemetry counterparts in future releases.

Loki changes the attribute names when persisting them to storage. The names will be lowercased, and all characters in the set: (.,/,-) will be replaced by underscores (_). For example, k8s.namespace.name will become k8s_namespace_name.

Chapter 6. Loki query performance troubleshooting

This documentation details methods for optimizing your Logging stack to improve query performance and provides steps for troubleshooting.

6.1. Best practices for Loki query performance

You can take the following steps to improve Loki query performance:

  • Ensure that you are running the latest version of the Loki Operator.
  • Ensure that you have migrated LokiStack schema to the v13 version.
  • Ensure that you use reliable and fast object storage. Loki places significant demands on object storage. If you are not using an object store solution from a cloud provider, use solid-state drive (SSD) for your object storage. By using SSDs you can benefit from the high parallelization capabilities of Loki.

    To better understand the utilization of object storage by Loki, you can use the following query in the Metrics dashboard in the OpenShift Container Platform web console:

    sum by(status, container, operation) (label_replace(rate(loki_s3_request_duration_seconds_count{namespace="openshift-logging"}[5m]), "status", "${1}xx", "status_code", "([0-9]).."))
  • Loki Operator enables automatic stream sharding by default. The default automatic stream sharding mechanism should be adequate in most cases and users should not need to configure perStream* attributes.
  • If you use the OpenTelemetry Protocol (OTLP) data model, you can configure additional stream labels in LokiStack. For more information, see Best practices for Loki labels.
  • Different types of queries have different performance characteristics. Use simple filter queries instead of regular expressions for better performance.

6.2. Best practices for Loki labels

Labels in Loki are the keyspace on which Loki shards incoming data. They are also the index used for finding logs at query-time. You can optimize query performance by properly using labels.

Consider the following criteria when creating labels:

  • Labels should describe infrastructure. This could include regions, clusters, servers, applications, namespaces, or environments.
  • Labels are long-lived. Label values should generate logs perpetually, or at least for several hours.
  • Labels are intuitive for querying.

Configuring which labels the Loki Operator will use as stream labels depends on the data model you are using: ViaQ or OpenTelemetry Protocol (OTLP).

Both models come with a predefined set of stream labels, for more information, see OpenTelemetry data model.

ViaQ model

ViaQ does not support structured metadata. To configure stream labels for the ViaQ model, add the configuration in the ClusterLogForwarder resource. For example:

apiVersion: observability.openshift.io/v1
kind: ClusterLogForwarder
metadata:
  name: instance
  namespace: openshift-logging
spec:
  serviceAccount:
    name: logging-collector
  outputs:
    - name: lokistack-out
      type: lokiStack
      lokiStack:
        target:
          name: logging-loki
          namespace: openshift-logging
        labelKeys:
          application:
            ignoreGlobal: <true_or_false>
            labelKeys: []
          audit:
            ignoreGlobal: <true_or_false>
            labelKeys: []
          infrastructure:
            ignoreGlobal: <true_or_false>
            labelKeys: []
          global: []

lokiStack.labelKeys field contains the configuration that maps log record keys to Loki labels used to identify streams.

OTLP model
In the OTLP model all labels that are not specified as stream labels are attached as structured metadata.

The following are the best practices for creating stream labels:

  • have a low cardinality with at most tens of values.
  • The values are long lived. For example, the first level of an HTTP path: /load, /save, and /update.
  • The labels can be used in queries to improve query performance.

6.4. Analyzing Loki query performance

Every query and subquery in Loki generates a metrics.go log line with performance statistics. Subqueries emit the log line in the queriers. Every query has an associated single summary metrics.go line emitted by the query-front end. Use these statistics to calculate the query performance metrics.

Prerequisites

  • You have administrator permissions.
  • You have access to the OpenShift Container Platform web console.
  • You installed and configured Loki Operator.

Procedure

  1. In the OpenShift Container Platform web console, navigate to the MetricsObserve tab.
  2. Note the following values:

    • duration: Denotes the amount of time a query took to run.
    • queue_time: Denotes the time a query spent in the queue before being processed.
    • chunk_refs_fetch_time: Denotes the amount of time spent in getting chunk information from the index.
    • store_chunks_download_time: Denotes the amount of time in getting chunks from cache or storage.
  3. Calculate the following performance metrics:

    • total query time as total_duration:

      total_duration = duration + queue_time
    • Percentage of the total duration that a query spent in the queue as Queue Time:

      Queue Time = queue_time / total_duration * 100
    • Calculate the percentage of the total duration that was spent in getting chunk information from the index as Chunk Refs Fetch Time:

      Chunk Refs Fetch Time = chunk_refs_fetch_time / total_duration * 100
    • Calculate the percentage of the total duration that was spent in getting chunks from cache or storage:

      Chunks Download Time = store_chunks_download_time / total_duration * 100
    • Calculate the percentage of the total duration that was spent in executing the query:

      Execution Time = (duration - chunk_refs_fetch_time - store_chunks_download_time) / total_duration * 100
  4. Refer to Query performance analysis to understand the reason for each metric and how each metric affects query performance.

6.5. Query performance analysis

For best query performance, you want to see as much time as possible spent in execution time, denoted by the Execution Time metric. See the table below for the reason other performance metrics might be higher and the steps you can take to improve them. You can also reduce the execution time by modifying your queries, thereby improving the overall performance.

Expand
IssueReasonFix

High Execution Time

Queries might be doing many CPU-intensive operations such as regular expression processing.

You can make the following changes:

  • Change your queries to reduce or remove regular expressions.
  • Add more CPU resources.

Your queries have many small log lines.

If your queries have many small lines, execution becomes dependent on how fast Loki can iterate the lines themselves. This becomes a CPU clock frequency bottleneck. To make things faster you need a faster CPU.

High Queue Time

You do not have enough queriers running.

The only fix is to increase the number of queriers replicas in the LokiStack spec.

High Chunk Refs Fetch Time

Insufficient number of index-gateway replicas in the LokiStack spec.

Increase the number of index-gateway replicas or ensure they have enough CPU resources.

High Chunks Download Time

The chunks might be too small

Check the average chunk size by dividing total_bytes value by cache_chunk_req value. The average represents the average uncompressed bytes per chunk. The value for best performance should be in the order of magnitude of megabytes. If the chunks are only a few hundred bytes or kilobytes in size, revisit labels to ensure that you are not splitting your data into very small chunks.

Query timing out

Query timeout value might be too low

Increase the queryTimeout value in the LokiStack spec.

Legal Notice

Copyright © Red Hat.
Except as otherwise noted below, the text of and illustrations in this documentation are licensed by Red Hat under the Creative Commons Attribution–Share Alike 3.0 Unported license . If you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, the Red Hat logo, JBoss, Hibernate, and RHCE are trademarks or registered trademarks of Red Hat, LLC. or its subsidiaries in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
XFS is a trademark or registered trademark of Hewlett Packard Enterprise Development LP or its subsidiaries in the United States and other countries.
The OpenStack® Word Mark and OpenStack logo are trademarks or registered trademarks of the Linux Foundation, used under license.
All other trademarks are the property of their respective owners.
Red Hat logoGithubredditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat Documentation

Legal Notice

Theme

© 2026 Red Hat
Back to top