Chapter 1. Enhanced reliability and performance for Loki
Configure reliability and high availability settings to ensure Loki operates efficiently in production environments.
1.1. Enhanced reliability and performance for Loki Copy linkLink copied to clipboard!
Use the following configurations to ensure reliability and efficiency of Loki in production environments. These settings help optimize pod placement, data retention, cluster hardening, and recovery behavior to minimize data loss and maintain consistent performance under load.
1.1.1. Loki pod placement Copy linkLink copied to clipboard!
Control which nodes Loki pods run on by using tolerations and node selectors.
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:
nodeSelector:
node-role.kubernetes.io/infra: ""
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: ""
# ...
- spec.template.compactor
- Specifies the component pod type that applies to the node selector.
- spec.template.compactor.nodeSelector
- 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.
...
1.1.2. Configure Loki to tolerate node failure Copy linkLink copied to clipboard!
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:
- labelSelector:
matchLabels:
app.kubernetes.io/component: ingester
topologyKey: kubernetes.io/hostname
# ...
- requiredDuringSchedulingIgnoredDuringExecution
- The stanza to define a required rule.
- labelSelector.matchLabels
- The key-value pair (label) that must be matched to apply the rule.
- topologyKey
-
The topology domain for the node. Use
kubernetes.io/hostnameto schedule pods on different nodes.
1.1.3. Enable stream-based retention with Loki Copy linkLink copied to clipboard!
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.
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.
-
Although logging version 5.9 and later supports schema
v12, schemav13is recommended for future compatibility. You can configure retention in Loki, in object storage, or both:
-
Loki retention (primary): Configure
spec.limitsto manage retention within Loki. The compactor removes index references and subsequently deletes the corresponding chunks from object storage. The maximum supported retention period is 30 days. Object storage lifecycle policies (safety net): Configure lifecycle deletion on your object storage provider as a safety net against orphaned chunks. Set the lifecycle expiration longer than your Loki retention period plus the compactor deletion delay to avoid deleting chunks that Loki still references. Lifecycle deletion is not index-aware and can cause data loss if it runs before the compactor has processed the chunks.
For guidance on setting lifecycle expiration relative to Loki retention, see the Grafana Loki documentation on compactor retention versus object store lifecycle policies.
-
Loki retention (primary): Configure
Prerequisites
- You have administrator permissions.
- You have installed the Loki Operator.
-
You have installed the OpenShift CLI (
oc).
Procedure
To enable stream-based retention, create a
LokiStackCR and save it as a YAML file. In the following example, it is calledlokistack.yaml.The following example shows global 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 streams: - days: 4 priority: 1 selector: '{kubernetes_namespace_name=~"test.+"}' - 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- spec.limits.global
- Set the retention policy for all log streams. The compactor enforces this policy by removing index references and deleting the corresponding chunks from object storage.
- spec.limits.global.retention
-
Enable retention in the cluster by adding the
retentionblock to the CR. - spec.limits.global.retention.streams.selector
- 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: application: retention: days: 1 streams: - days: 4 selector: '{kubernetes_namespace_name=~"test.+"}' 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- spec.limits.tenants
-
Set the retention policy per-tenant. Valid tenant types are
application,audit, andinfrastructure. - spec.limits.tenants.application.retention.streams.selector
- Specify the LogQL query to match log streams to the retention rule.
Apply the
LokiStackCR:$ oc apply -f lokistack.yaml
1.1.4. Configure Loki to tolerate memberlist creation failure Copy linkLink copied to clipboard!
Configure the LokiStack CR to use pod IP addresses for memberlist networking in non-private IP network ranges.
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
# ...
1.1.5. LokiStack behavior during cluster restarts Copy linkLink copied to clipboard!
LokiStack continues operating during cluster restarts by using PodDisruptionBudget resources to maintain availability.
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.