Loki isolation problem: separate endpoints but shared logs

Hi everyone,

I have a multi-environment Kubernetes setup with separate environments:

  • dev
  • test
  • prod

Each environment contains multiple Kubernetes clusters.

On one cluster inside each environment I deployed a separate Loki instance, and on every cluster I deployed Grafana Alloy to collect and send logs to the Loki instance of that environment.

Example:

  • dev clusters → send logs to Loki in dev
  • test clusters → send logs to Loki in test
  • prod clusters → send logs to Loki in prod

Each Alloy instance has its own Loki endpoint configured correctly. However, I still see logs from other environments when querying Loki.

Important detail:
All Loki instances use the same S3 bucket, but I created separate folders/prefixes:

observability-dev/
observability-test/
observability-prod/

My expectation was:

  • dev Loki should only see dev logs
  • test Loki should only see test logs
  • prod Loki should only see prod logs

But currently the data appears mixed across environments.

My questions:

  1. Is using different “folders” inside the same S3 bucket enough for isolation in Loki?
  2. Do I need to configure explicit S3 prefixes/path_prefix somewhere in Loki configuration?
  3. Would labels like environment=dev help here, or are labels only for querying/filtering and not for real isolation?
  4. What is considered best practice for separating environments in Loki?

Thanks!

Antonio

In my opinion you should just use dedicated S3 bucket for each of your Loki cluster, and save yourself some headache. It’s not only easier, it’s also more secure in terms of data separation between environments.

I would suggest have single Loki for all environments and have multi-tenancy enabled. I have similar setup with a central Grafana LGTM stack. All components are multi-tenancy enabled. Each environment has its own tenant id.

For Grafana UI I have three Grafana UI deployments per each environment and they only can see their tenant (configured in Datasource definition)

This is, in my humble opinion, cost effective and easy to maintain. Single cluster for Grafana stack, single Loki, single S3 bucket set and proper isolation of data between environments.

For your case setup, if not recently changed, you can only define S3 bucket name to Loki for storage not a prefix/path_prefix..

if you want to go with three different Loki setup, then what @tonyswumac said is the way to go forward…

-Suleyman Kutlu (a.k.a. SNK)

What you’re seeing is usually caused by Loki instances sharing the same storage namespace/index, even if they point to different “folders” conceptually in S3.

A few important points:

  • Labels like environment=dev are only for querying/filtering. They do NOT provide storage isolation.
  • Real isolation in Loki comes from separate storage prefixes/buckets/tenants.
  • Using the same S3 bucket is fine, but only if each Loki instance is configured with a unique storage prefix for BOTH chunks and index data.

Just creating folders manually in S3 is not enough unless Loki is explicitly configured to use them.

For TSDB/Boltdb-shipper storage, you need separate prefixes such as:

  • observability-dev/
  • observability-test/
  • observability-prod/

configured in Loki itself.

For example, depending on your storage backend/version, look at settings like:

  • storage_config.aws.s3
  • storage_config.aws.bucketnames
  • storage_config.boltdb_shipper.shared_store
  • schema_config.configs[].index.prefix
  • common.path_prefix

The critical part is that each Loki instance must write/read from a distinct prefix namespace.

Right now, your Loki instances are most likely scanning the same index location, so queries return mixed data across environments.

Best practice is usually one of these:

  1. Separate S3 buckets per environment (simplest + safest)
  2. Same bucket but strict per-environment prefixes configured in Loki
  3. Multi-tenant Loki using X-Scope-OrgID isolation

For most setups, separate buckets or strict prefixes are easier to manage than multi-tenancy.

Also make sure:

  • Index prefixes are unique per environment
  • Compactor is not sharing the same working directory/storage namespace
  • Retention configs are separated if needed

Adding an environment label is still a good idea for querying/debugging, but it should not be relied on for isolation.