Cloud Native 11 min read

Designing Multi‑Tenant Loki Logging on Kubernetes: Centralized vs Partitioned

This article explores how to implement Loki’s multi‑tenant logging on Kubernetes, comparing centralized storage (Scheme A) and partitioned storage (Scheme B), detailing required configuration flags, runtime limits, client setups with Logging Operator, Fluentd/FluentBit, and gateway routing strategies.

Ops Development Stories
Ops Development Stories
Ops Development Stories
Designing Multi‑Tenant Loki Logging on Kubernetes: Centralized vs Partitioned

When looking at Loki's architecture docs, the community claims Loki supports multi‑tenant mode, but enabling it only requires two conditions: setting auth_enabled: true in the config file and sending the tenant ID in the X‑Scope‑OrgID request header.

In practice, building a multi‑tenant logging system on Kubernetes involves more considerations. Two architectural patterns are commonly used:

1. Centralized log storage (Scheme A)

Logs are written to a shared backend after validation and indexing, similar to native Loki.

2. Partitioned log storage (Scheme B)

Each tenant or project has an independent Loki instance and storage block.

Both approaches require configuring Loki’s per‑tenant limits. The main configuration blocks are query_frontend_config and limits_config.

query_frontend_config

The query frontend distributes and aggregates user queries; to prevent a single tenant from monopolising resources you can set max_outstanding_per_tenant (default 100).

[max_outstanding_per_tenant: <int> | default = 100]

limits_config

Controls global flow control and per‑tenant resource allocation. Runtime limits can be supplied via the -runtime-config flag and the runtimeConfigValues struct.

type runtimeConfigValues struct {
  TenantLimits map[string]*validation.Limits `yaml:"overrides"`
  Multi kv.MultiRuntimeConfig `yaml:"multi_kv_config"`
}

Example tenant overrides:

overrides:
  tenantA:
    ingestion_rate_mb: 10
    max_streams_per_user: 100000
    max_chunks_per_query: 100000
  tenantB:
    max_streams_per_user: 1000000
    max_chunks_per_query: 1000000

When using Scheme A, per‑tenant limits should be tuned according to log volume; Scheme B relies on the native limits_config because each tenant has a dedicated Loki instance.

Log client integration

In Kubernetes the log client must attach the tenant ID to each log stream. Two common approaches are the Logging Operator and Fluentd/Fluent Bit.

Logging Operator

The BanzaiCloud Logging Operator creates namespace‑scoped CRDs (Flow and Output) to control log collection and routing.

apiVersion: logging.banzaicloud.io/v1beta1
kind: Output
metadata:
  name: loki-output
  namespace: <tenantA-namespace>
spec:
  loki:
    url: http://loki:3100
    username: <tenantA>
    password: <tenantA>
    tenant: <tenantA>
apiVersion: logging.banzaicloud.io/v1beta1
kind: Flow
metadata:
  name: flow
  namespace: <tenantA-namespace>
spec:
  localOutputRefs:
    - loki-output
  match:
    - select:
        labels:
          app: nginx
  filters:
    - parser:
        remove_key_name_field: true
        reserve_data: true
        key_name: "log"

Fluentd / Fluent Bit

Both plugins support multi‑tenant configuration by extracting tenant information from Kubernetes metadata.

Fluentd example using a namespace label:

apiVersion: v1
kind: Namespace
metadata:
  labels:
    tenant: <tenantA>
  name: <tenant-namespace>
<match loki.**>
  @type loki
  @id loki.output
  url "http://loki:3100"
  # extract tenant from namespace labels
  tenant ${$.kubernetes.namespace_labels.tenant}
  username <username>
  password <password>
  <label>
    tenant ${$.kubernetes.namespace_labels.tenant}
  </label>
</match>

Fluent Bit extracts the tenant from pod labels:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
spec:
  template:
    metadata:
      labels:
        app: nginx
        tenant: <tenant-A>
[FILTER]
   Name           kubernetes
   Match          kube.*
   Kube_URL       https://kubernetes.default.svc:443
   Merge_Log      On
[FILTER]
   Name           rewrite_tag
   Match          kube.*
   Rule           $kubernetes['labels']['tenant'] ^(.*)$ tenant.$kubernetes['labels']['tenant'].$TAG false
   Emitter_Name   re_emitted
[Output]
   Name           grafana-loki
   Match          tenant.tenantA.*
   Url            http://loki:3100/api/prom/push
   TenantID       "tenantA"
[Output]
   Name           grafana-loki
   Match          tenant.tenantB.*
   Url            http://loki:3100/api/prom/push
   TenantID       "tenantB"

Log gateway

For Scheme A the gateway simply forwards requests with the tenant header to the shared Loki cluster. For Scheme B the gateway must route based on X‑Scope‑OrgID to the appropriate Loki instance.

# upstream addresses are rendered from CRD sidecars
upstream tenantA { server x.x.x.x:3100; }
upstream tenantB { server y.y.y.y:3100; }
server {
    location / {
        set $tenant $http_x_scope_orgid;
        proxy_pass http://$tenant;
        include proxy_params;
    }
}

Conclusion

The two multi‑tenant Loki architectures—centralized storage and partitioned storage—differ in Loki topology, client setup, and gateway complexity. Teams with Kubernetes operator expertise may prefer the partitioned approach, while operations‑focused teams might choose the simpler centralized storage.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ObservabilityKubernetesmulti-tenantLoki
Ops Development Stories
Written by

Ops Development Stories

Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.