Skip to content
Configuration

Configuration

Korrel8r loads configuration from a file or URL specified by the --config option or the KORREL8R_CONFIG environment variable.

korrel8r --config <file_or_url>

Built-in configuration

The released korrel8r container image includes default configuration at /etc/korrel8r/, mirroring the etc/korrel8r/ directory in the source repository:

/etc/korrel8r/
├── openshift-route.yaml   # Out-of-cluster: connect to stores via OpenShift routes
├── openshift-svc.yaml     # In-cluster: connect to stores via service URLs
└── rules/
    └── all.yaml           #  Placeholder for additional rules

Korrel8r’s built-in correlation and status rules are compiled into the executable from pkg/rules/quickrules/; they do not need to be included from configuration.

openshift-route.yaml
Run korrel8r outside the cluster, connect to stores via routes.
openshift-svc.yaml
Run korrel8r as an in-cluster service, connect to stores via service URLs.

The default deployment uses --config=/etc/korrel8r/openshift-svc.yaml.

Custom configuration

Pass a local file or URL to --config, or set KORREL8R_CONFIG. For an in-cluster deployment, store custom configuration in a ConfigMap and mount it below /etc/korrel8r without replacing that directory. See Configuring Stores for a complete deployment example.

Custom rules can be defined directly or loaded with include. They supplement the compiled built-in rules; configuration does not select or disable built-in quickrules.

The configuration file supports the following sections:

include

Other configuration fragments to include:

include:
  - "path_or_url"

stores

Connections to data stores:

stores:
  - domain: "domain_name"    # 1. Domain name of the store (required)
    # Domain-specific fields # 2. See Domain Reference

Every entry in the stores section has a domain field to identify the domain. Other fields depend on the domain, see the Domain Reference.

Store fields may contain templates that expand to URLs.

Example: configuring a store URL from an OpenShift Route resource:

stores:
  - domain: log
    lokiStack: >-
      {{$r := query "k8s:Route.route.openshift.io/v1:{namespace: openshift-logging, name: logging-loki}" -}}
      https://{{ (first $r).Spec.Host -}}
  1. Get a list of routes in “openshift-logging” named “logging-loki”.
  2. Use the .Spec.Host field of the first route as the host for the store URL.

rules

Runtime correlation rules use Go templates to turn start objects into goal queries. See Configuration Rules for the complete schema, examples, and template behavior. Built-in rules are compiled into the executable; this section is for additional user-defined rules.

statusRules

Rules that generate status for objects in a correlation graph:

statusRules:
  - name: "rule_name"           # 1. Identifies the rule in log output
    start:                      # 2. Start objects must belong to one of these classes
      domain: "domain_name"
      classes:                  #    Optional — omit for all classes in the domain
        - "class_name"
    status: "status_template"   # 3. Go template that outputs labels, one per line

See Status for details and examples.

aliases

Short-hand alias names for groups of classes:

aliases:
  - name: "alias_name"       # 1. Can be used wherever a class name is allowed
    domain: "domain_name"    # 2. Domain for classes in this alias
    classes:                  # 3. Classes belonging to this alias
      - "class_name"

templates

Named templates that can be reused from rule, status, or store templates:

templates:
  - name: "template_name"       # 1. Name used to invoke the template
    template: "template_body"   # 2. Go template body

Named templates are invoked from rule or status templates using the standard Go template syntax:

{{template "template_name" <data>}}

The <data> expression becomes . inside the named template. Use the sprig dict function to pass named parameters:

templates:
  - name: myHelper
    template: 'k8s:{{.class}}:{"namespace":"{{index .labels "namespace"}}"}'

rules:
  - name: MyRule
    start: {domain: alert}
    goal: {domain: k8s, classes: [Pod]}
    result:
      query: '{{template "myHelper" (dict "labels" .Labels "class" "Pod")}}'

Named templates defined in any configuration file (including included files) are available to all rules across all files.

tuning

Limits and optimizations:

tuning:
  totalLimit: 10000        # 1. Unique result objects retained per traversal
  totalQueryLimit: 5000    # 2. Unique queries accepted per traversal
  # memoryLimit: 768Mi     # 3. Optional absolute memory-pressure override
  memoryPressureLimit: 80  # 4. Cancel searches at this percentage of available memory
  memoryPressureReset: 70  # 5. Clear memory pressure below this percentage
  requestTimeout: 1m       # Timeout for incoming and outgoing requests
  sessionTimeout: 5m       # Idle timeout for per-user sessions
  storeRetryInterval: 10s  # Minimum time between store re-creation attempts

Durations use Go duration syntax, for example 30s, 1m, 2h.

totalLimit
Maximum number of unique result objects retained across a traversal. This complements the per-query limit. A request may specify a lower totalLimit, but cannot raise this server limit. If omitted or 0, there is no traversal-wide object limit.
totalQueryLimit
Maximum number of unique queries accepted across a traversal. This complements the per-class queryLimit. A request may specify a lower totalQueryLimit, but cannot raise this server limit. If omitted or 0, there is no traversal-wide query limit.

When either total limit is exceeded, traversal stops and returns a successful partial graph. REST and MCP graph responses include truncation metadata naming the exhausted condition and its effective limit. REST responses also include X-Korrel8r-Truncated, X-Korrel8r-Truncated-By, and X-Korrel8r-Truncated-Limit headers.

requestTimeout
Cancels incoming or outgoing requests that take longer than this. Long-lived SSE subscriptions are exempt. If omitted or 0, requests never time out.
memoryPressureLimit
Cancels active searches when process cgroup or Go runtime memory reaches this percentage of its finite limit, whichever is under greater pressure. Searches are still admitted, but are canceled immediately while pressure remains high. Cancellation returns a successful partial graph with truncation condition memoryPressure. Defaults to 80.
memoryLimit
Overrides percentage-based detection with an absolute byte quantity such as 768Mi. The guard still uses cgroup usage when available and Go runtime usage otherwise. Set to -1 to disable the guard.
memoryPressureReset
Clears memory pressure at this lower percentage, providing hysteresis. It must be lower than memoryPressureLimit. If omitted, it defaults to 10 percentage points below the limit.

Memory is sampled every 200ms, with the first sample occurring immediately.

Set Go’s GOMEMLIMIT below the container memory limit as an additional safeguard. The guard monitors it when finite, but it remains a soft garbage-collection target rather than an OOM cap.

Library embedders can create the same guard with memory.NewFromTuning, run it with an application-lifetime context, and install it using engine.Builder.SearchGuard.

sessionTimeout
Idle timeout for sessions. In server mode each authenticated user gets a session with its own engine, configuration and state – see Security. If omitted or 0, sessions never time out.
storeRetryInterval
Minimum time between attempts to re-create a store after an error. Prevents a storm of expensive re-creation (DNS lookups, API discovery) on every failed query. Defaults to 10s if omitted or 0.
unsafeSharedSession
Skips authentication and uses a single shared session for all requests.
This disables per-user session isolation. Use only for development or testing.

Sizing the total limits for a memory limit

As a starting point, for a container memory limit M and at most N concurrent traversals:

totalLimit      = (0.8 × M - 95MiB) / (N × 11KiB)
totalQueryLimit = totalLimit / 10
Memory limit Concurrency totalLimit totalQueryLimit
256 MiB 1 10000 1000
512 MiB 1 29000 2900
512 MiB 2 14000 1400
1 GiB 1 67000 6700
2 GiB 1 143000 14000

The 95MiB term is the baseline server footprint before any traversal state, and the 11KiB term is the measured peak RSS per retained object; both come from OpenShift Kubernetes and log workloads with a single session. A server with many concurrent user sessions holds one engine per session, so measure your own baseline in that case. These are sizing heuristics, not memory guarantees: verify peak container memory with your own workloads and re-check after changing stores, rules, or payload sizes.

About Templates

Korrel8r rules and store configuration can include Go templates. Korrel8r provides additional template functions, domains may provide additional functions – see the Domain Reference