<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Deploy Grafana Mimir with Jsonnet and Tanka on Grafana Labs</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/</link><description>Recent content in Deploy Grafana Mimir with Jsonnet and Tanka on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/mimir/v3.1.x/set-up/jsonnet/index.xml" rel="self" type="application/rss+xml"/><item><title>Deploy Grafana Mimir with Jsonnet and Tanka</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/deploy/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/deploy/</guid><content><![CDATA[&lt;h1 id=&#34;deploy-grafana-mimir-with-jsonnet-and-tanka&#34;&gt;Deploy Grafana Mimir with Jsonnet and Tanka&lt;/h1&gt;
&lt;p&gt;You can use &lt;a href=&#34;https://tanka.dev/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Tanka&lt;/a&gt; and &lt;a href=&#34;https://github.com/jsonnet-bundler/jsonnet-bundler&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;jsonnet-bundler&lt;/a&gt; to generate Kubernetes YAML manifests from the jsonnet files.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install &lt;code&gt;tanka&lt;/code&gt; and &lt;code&gt;jb&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;Follow the steps at &lt;a href=&#34;https://tanka.dev/install&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://tanka.dev/install&lt;/a&gt;. If you have &lt;code&gt;go&lt;/code&gt; installed locally you can also use:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;console&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-console&#34;&gt;# make sure to be outside of GOPATH or a go.mod project
go install github.com/grafana/tanka/cmd/tk@latest
go install github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb@latest&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set up a Jsonnet project, based on the example that follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Initialize Tanka&lt;/li&gt;
&lt;li&gt;Install Grafana Mimir and Kubernetes Jsonnet libraries&lt;/li&gt;
&lt;li&gt;Set up an environment&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- prettier-ignore-start --&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;#!/usr/bin/env bash
# SPDX-License-Identifier: AGPL-3.0-only

set -e

# Initialise the Tanka.
mkdir jsonnet-example &amp;amp;&amp;amp; cd jsonnet-example
tk init --k8s=1.30

# Install Mimir jsonnet.
jb install github.com/grafana/mimir/operations/mimir@main

# Use the provided example.
cp vendor/mimir/mimir-manifests.jsonnet.example environments/default/main.jsonnet

# Generate the YAML manifests.
export PAGER=cat
tk show environments/default&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;!-- prettier-ignore-end --&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generate the Kubernetes YAML manifests and store them in the &lt;code&gt;./manifests&lt;/code&gt; directory:&lt;/p&gt;
&lt;!-- prettier-ignore-start --&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;# Generate the YAML manifests:
export PAGER=cat
tk show environments/default
tk export manifests environments/default&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;!-- prettier-ignore-end --&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure the environment specification file at &lt;code&gt;environments/default/spec.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To learn about how to use Tanka and to configure the &lt;code&gt;spec.json&lt;/code&gt; file, see &lt;a href=&#34;https://tanka.dev/tutorial/jsonnet&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Using Jsonnet: Creating a new project&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Deploy the manifests to a Kubernetes cluster, in one of two ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use the &lt;code&gt;tk apply&lt;/code&gt; command&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Tanka supports commands to show the &lt;code&gt;diff&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; changes to a Kubernetes cluster:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;# Show the difference between your Jsonnet definition and your Kubernetes cluster:
tk diff environments/default

# Apply changes to your Kubernetes cluster:
tk apply environments/default&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use the &lt;code&gt;kubectl apply&lt;/code&gt; command&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;You generated the Kubernetes manifests and stored them in the &lt;code&gt;./manifests&lt;/code&gt; directory in the previous step.&lt;/p&gt;
&lt;p&gt;You can run the following command to directly apply these manifests to your Kubernetes cluster:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;sh&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-sh&#34;&gt;# Review the changes that will apply to your Kubernetes cluster:
kubectl apply --dry-run=client -k manifests/

# Apply the changes to your Kubernetes cluster:
kubectl apply -k manifests/&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;The generated Kubernetes manifests create resources in the &lt;code&gt;default&lt;/code&gt; namespace.
To use a different namespace, change the &lt;code&gt;namespace&lt;/code&gt; configuration option in the &lt;code&gt;environments/default/main.jsonnet&lt;/code&gt; file, and re-generate the Kubernetes manifests.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;



&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Starting from Mimir 3.0, a Jsonnet-based installation uses &lt;code&gt;memberlist&lt;/code&gt; for the HA tracker by default. No external dependencies are required. If you&amp;rsquo;re upgrading from a previous version that used etcd or Consul for the HA tracker, refer to the migration guide.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
]]></content><description>&lt;h1 id="deploy-grafana-mimir-with-jsonnet-and-tanka">Deploy Grafana Mimir with Jsonnet and Tanka&lt;/h1>
&lt;p>You can use &lt;a href="https://tanka.dev/" target="_blank" rel="noopener noreferrer">Tanka&lt;/a> and &lt;a href="https://github.com/jsonnet-bundler/jsonnet-bundler" target="_blank" rel="noopener noreferrer">jsonnet-bundler&lt;/a> to generate Kubernetes YAML manifests from the jsonnet files.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Install &lt;code>tanka&lt;/code> and &lt;code>jb&lt;/code>:&lt;/p></description></item><item><title>Configure Grafana Mimir to use low resources with Jsonnet</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/configure-low-resources/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/configure-low-resources/</guid><content><![CDATA[&lt;h1 id=&#34;configure-grafana-mimir-to-use-low-resources-with-jsonnet&#34;&gt;Configure Grafana Mimir to use low resources with Jsonnet&lt;/h1&gt;
&lt;p&gt;This page describes how to configure Jsonnet to deploy Grafana Mimir in a Kubernetes cluster with low CPU and memory resources available.&lt;/p&gt;
&lt;h2 id=&#34;anti-affinity&#34;&gt;Anti-affinity&lt;/h2&gt;
&lt;p&gt;Given the distributed nature of Mimir, both performance and reliability are improved when pods are spread across different nodes.
For example, losing multiple ingesters can cause data loss, so it&amp;rsquo;s better to distribute them across different nodes.&lt;/p&gt;
&lt;p&gt;For this reason, by default, anti-affinity rules are applied to some Kubernetes Deployments and StatefulSets.
These anti-affinity rules can become an issue when playing with Mimir in a single-node Kubernetes cluster.
You can disable anti-affinity by setting the configuration values &lt;code&gt;_config.&amp;lt;component&amp;gt;_allow_multiple_replicas_on_same_node&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;example-disable-anti-affinity&#34;&gt;Example: disable anti-affinity&lt;/h3&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;local mimir = import &amp;#39;mimir/mimir.libsonnet&amp;#39;;

mimir {
  _config&amp;#43;:: {
    ingester_allow_multiple_replicas_on_same_node: true,
    store_gateway_allow_multiple_replicas_on_same_node: true,
  },
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;resources&#34;&gt;Resources&lt;/h2&gt;
&lt;p&gt;Default scaling of Mimir components in the provided Jsonnet is opinionated and based on engineers’ years of experience running it at Grafana Labs.
The default resource requests and limits are also fine-tuned for the provided alerting rules.
For more information, see &lt;a href=&#34;../../../manage/monitor-grafana-mimir/&#34;&gt;Monitor Grafana Mimir&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, there are use cases where you might want to change the default resource requests, their limits, or both.
For example, if you are just testing Mimir and you want to run it on a small (possibly one-node) Kubernetes cluster, and you do not have tens of gigabytes of memory or multiple cores to schedule the components, consider overriding the scaling requirements as follows:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;local k = import &amp;#39;github.com/grafana/jsonnet-libs/ksonnet-util/kausal.libsonnet&amp;#39;,
      deployment = k.apps.v1.deployment,
      statefulSet = k.apps.v1.statefulSet;
local mimir = import &amp;#39;mimir/mimir.libsonnet&amp;#39;;

mimir {
  _config&amp;#43;:: {
    // ... configuration values
  },

  compactor_container&amp;#43;: k.util.resourcesRequests(&amp;#39;100m&amp;#39;, &amp;#39;128Mi&amp;#39;),
  compactor_statefulset&amp;#43;: statefulSet.mixin.spec.withReplicas(1),

  distributor_container&amp;#43;: k.util.resourcesRequests(&amp;#39;100m&amp;#39;, &amp;#39;128Mi&amp;#39;),
  distributor_deployment&amp;#43;: deployment.mixin.spec.withReplicas(2),

  ingester_container&amp;#43;: k.util.resourcesRequests(&amp;#39;100m&amp;#39;, &amp;#39;128Mi&amp;#39;),
  ingester_statefulset&amp;#43;: statefulSet.mixin.spec.withReplicas(3),

  querier_container&amp;#43;: k.util.resourcesRequests(&amp;#39;100m&amp;#39;, &amp;#39;128Mi&amp;#39;),
  querier_deployment&amp;#43;: deployment.mixin.spec.withReplicas(2),

  query_frontend_container&amp;#43;: k.util.resourcesRequests(&amp;#39;100m&amp;#39;, &amp;#39;128Mi&amp;#39;),
  query_frontend_deployment&amp;#43;: deployment.mixin.spec.withReplicas(2),

  store_gateway_container&amp;#43;: k.util.resourcesRequests(&amp;#39;100m&amp;#39;, &amp;#39;128Mi&amp;#39;),
  store_gateway_statefulset&amp;#43;: statefulSet.mixin.spec.withReplicas(1),

  local smallMemcached = {
    cpu_requests:: &amp;#39;100m&amp;#39;,
    memory_limit_mb:: 64,
    memory_request_overhead_mb:: 8,
    statefulSet&amp;#43;: statefulSet.mixin.spec.withReplicas(1),
  },

  memcached_chunks&amp;#43;: smallMemcached,
  memcached_frontend&amp;#43;: smallMemcached,
  memcached_index_queries&amp;#43;: smallMemcached,
  memcached_metadata&amp;#43;: smallMemcached,
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
]]></content><description>&lt;h1 id="configure-grafana-mimir-to-use-low-resources-with-jsonnet">Configure Grafana Mimir to use low resources with Jsonnet&lt;/h1>
&lt;p>This page describes how to configure Jsonnet to deploy Grafana Mimir in a Kubernetes cluster with low CPU and memory resources available.&lt;/p></description></item><item><title>Configure ingest storage architecture</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/configure-ingest-storage/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/configure-ingest-storage/</guid><content><![CDATA[&lt;h1 id=&#34;configure-ingest-storage-architecture&#34;&gt;Configure ingest storage architecture&lt;/h1&gt;
&lt;p&gt;The 
    &lt;a href=&#34;/docs/mimir/v3.1.x/get-started/about-grafana-mimir-architecture/&#34;&gt;ingest storage&lt;/a&gt; is the next generation architecture of Grafana Mimir. It decouples the Mimir read and write paths using Apache Kafka or a Kafka-compatible backend.&lt;/p&gt;
&lt;p&gt;To enable ingest storage, set the following Jsonnet:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    ingest_storage_enabled: true,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;The ingest storage architecture requires a production-grade Apache Kafka cluster or Kafka-compatible backend.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;



&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;p&gt;The ingest storage architecture requires the ruler remote evaluation to be enabled for the Mimir cluster.
Refer to the 
    &lt;a href=&#34;/docs/mimir/v3.1.x/set-up/jsonnet/configure-ruler/&#34;&gt;Configure the Grafana Mimir ruler with Jsonnet&lt;/a&gt; documentation for details about the ruler&amp;rsquo;s operational modes.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;kafka-connection-options&#34;&gt;Kafka connection options&lt;/h2&gt;
&lt;p&gt;The Jsonnet configures some Kafka connection parameters by default:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kafka topic&lt;/strong&gt;: &lt;code&gt;ingest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto-created partitions&lt;/strong&gt;: 1000 (when the topic doesn&amp;rsquo;t exist)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kafka addresses&lt;/strong&gt;: &lt;code&gt;kafka.&amp;lt;namespace&amp;gt;.svc.&amp;lt;cluster_domain&amp;gt;:9092&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To customize the Kafka connection configuration, override the default settings:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    ingest_storage_enabled: true,
  },

  // Override producer and consumer addresses for external Kafka
  ingest_storage_kafka_producer_address:: &amp;#39;kafka-broker-1:9092,kafka-broker-2:9092&amp;#39;,
  ingest_storage_kafka_consumer_address:: &amp;#39;kafka-broker-1:9092,kafka-broker-2:9092&amp;#39;,

  // Override Kafka client configuration
  ingest_storage_kafka_client_args&amp;#43;:: {
    &amp;#39;ingest-storage.kafka.topic&amp;#39;: &amp;#39;mimir-ingest&amp;#39;,
    &amp;#39;ingest-storage.kafka.auto-create-topic-default-partitions&amp;#39;: 500,
  },
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;kafka-partition-sizing&#34;&gt;Kafka partition sizing&lt;/h3&gt;
&lt;p&gt;The configured topic must have at least as many partitions as the number of ingesters in one zone.&lt;/p&gt;
&lt;p&gt;Refer to 
    &lt;a href=&#34;/docs/mimir/v3.1.x/configure/configure-kafka-backend/&#34;&gt;Configure the Grafana Mimir Kafka backend&lt;/a&gt; for more details about Kafka configurations.&lt;/p&gt;
]]></content><description>&lt;h1 id="configure-ingest-storage-architecture">Configure ingest storage architecture&lt;/h1>
&lt;p>The
&lt;a href="/docs/mimir/v3.1.x/get-started/about-grafana-mimir-architecture/">ingest storage&lt;/a> is the next generation architecture of Grafana Mimir. It decouples the Mimir read and write paths using Apache Kafka or a Kafka-compatible backend.&lt;/p></description></item><item><title>Configure the Grafana Mimir object storage backend with Jsonnet</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/configure-object-storage-backend/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/configure-object-storage-backend/</guid><content><![CDATA[&lt;h1 id=&#34;configure-the-grafana-mimir-object-storage-backend-with-jsonnet&#34;&gt;Configure the Grafana Mimir object storage backend with Jsonnet&lt;/h1&gt;
&lt;p&gt;You can configure the object storage backend for all Mimir components from a single place.
The minimum Jsonnet code required for this is:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    storage_backend: &amp;#39;gcs&amp;#39;,
    blocks_storage_bucket_name: &amp;#39;blocks-bucket&amp;#39;,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;storage_backend&lt;/code&gt; option must be one of either &lt;code&gt;azure&lt;/code&gt;, &lt;code&gt;gcs&lt;/code&gt;, or &lt;code&gt;s3&lt;/code&gt;.
Additional configuration options are available for each one of these providers.&lt;/p&gt;
&lt;h2 id=&#34;amazon-s3-s3-storage-configuration-options&#34;&gt;Amazon S3 (&lt;code&gt;s3&lt;/code&gt;) storage configuration options&lt;/h2&gt;
&lt;p&gt;Amazon S3 storage can be accessed without credentials when &lt;a href=&#34;https://aws.amazon.com/premiumsupport/knowledge-center/s3-private-connection-no-authentication/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;using Amazon VPC&lt;/a&gt;.
In this case, &lt;code&gt;storage_s3_secret_access_key&lt;/code&gt; and &lt;code&gt;storage_s3_access_key_id&lt;/code&gt; are optional and can be left null, as in the following example:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    storage_backend: &amp;#39;s3&amp;#39;,
    blocks_storage_bucket_name: &amp;#39;blocks-bucket&amp;#39;,
    aws_region: &amp;#39;af-south-1&amp;#39;,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If credentials are required, it is a good practice to keep them in secrets. In that case environment variable interpolation can be used:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    storage_backend: &amp;#39;s3&amp;#39;,
    storage_s3_access_key_id: &amp;#39;$(BLOCKS_STORAGE_S3_ACCESS_KEY_ID)&amp;#39;,
    storage_s3_secret_access_key: &amp;#39;$(BLOCKS_STORAGE_S3_SECRET_ACCESS_KEY)&amp;#39;,
    aws_region: &amp;#39;af-south-1&amp;#39;,
    blocks_storage_bucket_name: &amp;#39;blocks-bucket&amp;#39;,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;azure-azure-storage-configuration-options&#34;&gt;Azure (&lt;code&gt;azure&lt;/code&gt;) storage configuration options&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-namespace&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Hierarchical namespace&lt;/a&gt; must be disabled in Azure Blob Storage.
Otherwise, Grafana Mimir will leave empty directories behind after deleting blocks.&lt;/p&gt;
&lt;p&gt;The Azure storage client requires the &lt;code&gt;storage_azure_account_name&lt;/code&gt; and &lt;code&gt;storage_azure_account_key&lt;/code&gt; to be configured.
It is a good practice to keep them in secrets. In that case environment variable interpolation can be used:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    storage_backend: &amp;#39;azure&amp;#39;,
    storage_azure_account_name: &amp;#39;$(STORAGE_AZURE_ACCOUNT_NAME)&amp;#39;,
    storage_azure_account_key: &amp;#39;$(STORAGE_AZURE_ACCOUNT_KEY)&amp;#39;,
    blocks_storage_bucket_name: &amp;#39;blocks-bucket&amp;#39;,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&#34;google-cloud-storage-gcs-storage-configuration-options&#34;&gt;Google Cloud Storage (&lt;code&gt;gcs&lt;/code&gt;) storage configuration options&lt;/h2&gt;
&lt;p&gt;There are multiple &lt;a href=&#34;../../../configure/configuration-parameters/#gcs_storage_backend&#34;&gt;ways to configure Google Cloud Storage client&lt;/a&gt;.
If you run Mimir on Google Cloud Platform it is possible that &lt;a href=&#34;https://cloud.google.com/storage/docs/authentication#libauth&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;the environment already has the credentials configured&lt;/a&gt;,
in that case the minimum jsonnet configuration is valid:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    storage_backend: &amp;#39;gcs&amp;#39;,
    blocks_storage_bucket_name: &amp;#39;blocks-bucket&amp;#39;,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You can use the &lt;code&gt;storage_gcs_service_account&lt;/code&gt; configuration key to provide the service account when authentication is needed.
It is a good practice to keep credentials in secrets, so environment variable interpolation can be used:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    storage_backend: &amp;#39;gcs&amp;#39;,
    storage_gcs_service_account: &amp;#39;$(STORAGE_GCS_SERVICE_ACCOUNT)&amp;#39;,
    blocks_storage_bucket_name: &amp;#39;blocks-bucket&amp;#39;,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Alternatively, you can set the &lt;code&gt;GOOGLE_APPLICATION_CREDENTIALS&lt;/code&gt; environment variable to point to the service account file mounted from a secret.&lt;/p&gt;
]]></content><description>&lt;h1 id="configure-the-grafana-mimir-object-storage-backend-with-jsonnet">Configure the Grafana Mimir object storage backend with Jsonnet&lt;/h1>
&lt;p>You can configure the object storage backend for all Mimir components from a single place.
The minimum Jsonnet code required for this is:&lt;/p></description></item><item><title>Configure the Grafana Mimir ruler with Jsonnet</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/configure-ruler/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/configure-ruler/</guid><content><![CDATA[&lt;h1 id=&#34;configure-the-grafana-mimir-ruler-with-jsonnet&#34;&gt;Configure the Grafana Mimir ruler with Jsonnet&lt;/h1&gt;
&lt;p&gt;The ruler is an optional component and is therefore not deployed by default when using Jsonnet.
For more information about the ruler, see &lt;a href=&#34;../../../references/architecture/components/ruler/&#34;&gt;Grafana Mimir ruler&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To enable it, add the following Jsonnet code to the &lt;code&gt;_config&lt;/code&gt; section:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    ruler_enabled: true,
    ruler_storage_bucket_name: &amp;#39;ruler-bucket-name&amp;#39;,
  },
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;By default, the object storage backend used for the ruler will be the one set by the &lt;code&gt;$._config.storage_backend&lt;/code&gt; option.
If desired, you can override it by setting the &lt;code&gt;$._config.ruler_storage_backend&lt;/code&gt; option.
The &lt;code&gt;ruler_storage_backend&lt;/code&gt; option must be one of either &lt;code&gt;local&lt;/code&gt;, &lt;code&gt;azure&lt;/code&gt;, &lt;code&gt;gcs&lt;/code&gt;, or &lt;code&gt;s3&lt;/code&gt;.
For more information about the options available for storing ruler state, see &lt;a href=&#34;../../../references/architecture/components/ruler/#state&#34;&gt;Grafana Mimir ruler: State&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To get started, use the &lt;code&gt;local&lt;/code&gt; client type for initial testing:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    ruler_enabled: true,
    ruler_storage_backend: &amp;#39;local&amp;#39;,
    ruler_local_directory: &amp;#39;/path/to/local/directory&amp;#39;,
  },
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you are using object storage, you must set &lt;code&gt;ruler_storage_bucket_name&lt;/code&gt; to the name of the bucket that you want to use.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;If ruler object storage credentials differ from the ones defined in the common section, you need to manually provide them by using additional command line arguments.
For more information, refer to &lt;a href=&#34;../../../configure/configuration-parameters/#ruler_storage&#34;&gt;Grafana Mimir configuration parameters: ruler_storage&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;operational-modes&#34;&gt;Operational modes&lt;/h2&gt;
&lt;p&gt;The ruler has two operational modes: &lt;em&gt;internal&lt;/em&gt; and &lt;em&gt;remote&lt;/em&gt;. By default, the Jsonnet deploys the ruler by using the internal operational mode.
For more information about these modes, see &lt;a href=&#34;../../../references/architecture/components/ruler/#operational-modes&#34;&gt;Operational modes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To enable the remote operational mode, add the following code to the Jsonnet:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {n
    ruler_remote_evaluation_enabled: true,
  },
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;To support the &lt;em&gt;remote&lt;/em&gt; operational mode, the configuration includes three additional Kubernetes Deployments as a separate query path.&lt;/p&gt;
&lt;p&gt;These are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ruler-query-frontend&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ruler-query-scheduler&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ruler-querier&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h3 id=&#34;migrate-to-remote-evaluation&#34;&gt;Migrate to remote evaluation&lt;/h3&gt;
&lt;p&gt;To perform a zero downtime migration from internal to remote rule evaluation, follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Deploy the following changes to enable remote evaluation in migration mode.
Doing so causes the three new and previously listed Kubernetes deployments to start. However, they will not reconfigure the ruler to use them just yet.&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
 _config&amp;#43;:: {
   ruler_remote_evaluation_enabled: true,
   ruler_remote_evaluation_migration_enabled: true,
 },
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Check that all of pods for the following deployments have successfully started before moving to the next step:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ruler-query-frontend&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ruler-query-scheduler&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ruler-querier&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reconfigure the ruler pods to perform remote evaluation, by deploying the following changes:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    ruler_remote_evaluation_enabled: true,
  },
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
]]></content><description>&lt;h1 id="configure-the-grafana-mimir-ruler-with-jsonnet">Configure the Grafana Mimir ruler with Jsonnet&lt;/h1>
&lt;p>The ruler is an optional component and is therefore not deployed by default when using Jsonnet.
For more information about the ruler, see &lt;a href="../../../references/architecture/components/ruler/">Grafana Mimir ruler&lt;/a>.&lt;/p></description></item><item><title>Configure Grafana Mimir autoscaling with Jsonnet</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/configure-autoscaling/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/configure-autoscaling/</guid><content><![CDATA[&lt;h1 id=&#34;configure-grafana-mimir-autoscaling-with-jsonnet&#34;&gt;Configure Grafana Mimir autoscaling with Jsonnet&lt;/h1&gt;
&lt;p&gt;Mimir Jsonnet supports autoscaling for the following components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../../../references/architecture/components/ruler/&#34;&gt;Ruler Querier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../../references/architecture/components/querier/&#34;&gt;Querier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../../references/architecture/components/distributor/&#34;&gt;Distributor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Autoscaling, which is based on Prometheus metrics and &lt;a href=&#34;https://keda.sh&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Kubernetes-based Event Driven Autoscaler (KEDA)&lt;/a&gt;, uses Kubernetes&amp;rsquo; Horizontal Pod Autoscaler (HPA).&lt;/p&gt;
&lt;p&gt;HPA is not configured directly in Jsonnet but it&amp;rsquo;s created and updated by KEDA.
KEDA is an operator, running in the Kubernetes cluster, which is responsible to simplify the setup of HPA with custom metrics (Prometheus in our case).&lt;/p&gt;


&lt;div class=&#34;admonition admonition-warning&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Warning&lt;/p&gt;&lt;p&gt;Do not use the same Mimir or Grafana Enterprise Metrics cluster for storing and querying autoscaling metrics. Using the same cluster can create a dangerous feedback loop:&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t use the same Mimir or Grafana Enterprise Metrics cluster for storing and querying autoscaling metrics. Using the same cluster can create a dangerous feedback loop.&lt;/p&gt;
&lt;p&gt;For instance, if the Mimir or GEM cluster becomes unavailable, autoscaling stops working, because it cannot query the metrics. This prevents the cluster from automatically scaling up during high load or recovery. This inability to scale further exacerbates the cluster&amp;rsquo;s unavailability, which might, in turn, prevent the cluster from recovering.&lt;/p&gt;
&lt;p&gt;Instead, use a separate Prometheus instance or a different metrics backend for autoscaling metrics.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;how-keda-works&#34;&gt;How KEDA works&lt;/h2&gt;
&lt;p&gt;KEDA is a Kubernetes operator aiming to simplify the wiring between HPA and Prometheus.&lt;/p&gt;
&lt;p&gt;Kubernetes HPA, out of the box, is not capable of autoscaling based on metrics scraped by Prometheus, but it allows to configure a custom metrics API server which proxies metrics from a data source (e.g. Prometheus) to Kubernetes.
Setting up the custom metrics API server for Prometheus in a Kubernetes can be a tedious operation, so KEDA offers an operator to set it up automatically.
KEDA supports proxying metrics for a variety of sources, including Prometheus.&lt;/p&gt;
&lt;h3 id=&#34;keda-in-a-nutshell&#34;&gt;KEDA in a nutshell&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Runs an operator and an external metrics server.&lt;/li&gt;
&lt;li&gt;The metrics server supports proxying for many metric sources, including Prometheus.&lt;/li&gt;
&lt;li&gt;The operator watches for &lt;code&gt;ScaledObject&lt;/code&gt; custom resource definition (CRD), defining the minimum and maximum replicas, and scaling trigger metrics of a Deployment or StatefulSet, and then configures the related HPA resource. You don&amp;rsquo;t create the HPA resource in Kubernetes, but the operator creates it for you whenever a &lt;code&gt;ScaledObject&lt;/code&gt; CRD is created (and keeps it updated for its whole lifecycle).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Refers to &lt;a href=&#34;https://keda.sh&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;KEDA documentation&lt;/a&gt; for more information.&lt;/p&gt;
&lt;h3 id=&#34;what-happens-if-keda-is-unhealthy&#34;&gt;What happens if KEDA is unhealthy&lt;/h3&gt;
&lt;p&gt;The autoscaling of deployments is always managed by HPA, which is a native Kubernetes feature.
KEDA, as we use it, never changes the number of replicas of Mimir Deployments or StatefulSets.&lt;/p&gt;
&lt;p&gt;However, if KEDA is not running successfully, there are consequences for Mimir autoscaling too:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;keda-operator&lt;/code&gt; is down (critical): as the operator is the single point of truth, it will not request the metrics when &lt;code&gt;keda-operator-metrics-apiserver&lt;/code&gt; requests them. Changes to &lt;code&gt;ScaledObject&lt;/code&gt; CRD will not be reflected to the HPA until the operator is back online. The deployment (e.g. queriers) will keep working but, if there is a surge of traffic, HPA will not be able to detect it due to a lack of metrics and so will not scale up.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;keda-operator-metrics-apiserver&lt;/code&gt; is down (critical): HPA is not able to fetch updated metrics and it will stop scaling the deployment until metrics will be back. The deployment (e.g. queriers) will keep working but, if there is a surge of traffic, HPA will not be able to detect it due to a lack of metrics and so will not scale up.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;keda-admission-webhooks&lt;/code&gt; is down (not critical): CRD validation will not be executed. Based on KEDA&amp;rsquo;s configuration, this can block changes on CRDs until the service is restored. HPA functionality is not affected.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Use a &lt;a href=&#34;https://keda.sh/docs/latest/operate/cluster/#high-availability&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;high availability&lt;/a&gt; KEDA configuration if autoscaling is critical for your use case.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href=&#34;../../../manage/monitor-grafana-mimir/&#34;&gt;alert &lt;code&gt;MimirAutoscalerNotActive&lt;/code&gt;&lt;/a&gt; fires if HPA is unable to scale the deployment for any reason (e.g. unable to scrape metrics from KEDA metrics API server).&lt;/p&gt;
&lt;h2 id=&#34;how-kubernetes-hpa-works&#34;&gt;How Kubernetes HPA works&lt;/h2&gt;
&lt;p&gt;Refer to Kubernetes &lt;a href=&#34;https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Horizontal Pod Autoscaling&lt;/a&gt; documentation to have a full understanding of how HPA works.&lt;/p&gt;
&lt;h2 id=&#34;how-to-enable-autoscaling&#34;&gt;How to enable autoscaling&lt;/h2&gt;
&lt;p&gt;The following Jsonnet configuration snippet shows an example of how to enable Mimir autoscaling with Jsonnet:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;local mimir = import &amp;#39;mimir/mimir.libsonnet&amp;#39;;

mimir {
    _config&amp;#43;:: {
        autoscaling_prometheus_url: &amp;#39;http://prometheus.default:9090/prometheus&amp;#39;,
        // Enable queriers autoscaling.
        autoscaling_querier_enabled: true,
        autoscaling_querier_min_replicas: 10,
        autoscaling_querier_max_replicas: 40,
        // Enable ruler queriers autoscaling.
        autoscaling_ruler_querier_enabled: true,
        autoscaling_ruler_querier_min_replicas: 10,
        autoscaling_ruler_querier_max_replicas: 40,
        // Enable distributor autoscaling.
        autoscaling_distributor_enabled: true,
        autoscaling_distributor_min_replicas: 10,
        autoscaling_distributor_max_replicas: 40,
    }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;The Mimir Jsonet doesn&amp;rsquo;t install KEDA.&lt;/p&gt;
&lt;p&gt;To install KEDA, follow the instructions in &lt;a href=&#34;https://keda.sh/docs/latest/deploy/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Deploying KEDA&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;h2 id=&#34;how-to-disable-autoscaling&#34;&gt;How to disable autoscaling&lt;/h2&gt;
&lt;p&gt;There are two options to disable autoscaling in a Mimir cluster:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set minimum replicas = maximum replicas.&lt;/li&gt;
&lt;li&gt;Decommission HPA.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;set-minimum-replicas--maximum-replicas&#34;&gt;Set minimum replicas = maximum replicas&lt;/h3&gt;
&lt;p&gt;If KEDA and Kubernetes HPA work correctly but the HPA configuration (metric and threshold) are not giving the expected results (e.g. not scaling up when required), a simple solution to bypass the autoscaling algorithm is to set the minimum and maximum replicas to the same value. (e.g. &lt;code&gt;autoscaling_querier_min_replicas: 40&lt;/code&gt; and &lt;code&gt;autoscaling_querier_max_replicas: 40&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id=&#34;decommission-hpa&#34;&gt;Decommission HPA&lt;/h3&gt;
&lt;p&gt;To fully decommission HPA in a Mimir cluster you have to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Disable the relevant autoscaler (e.g. &lt;code&gt;autoscaling_querier_enabled: false&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Manually set the expected number of replicas for the given Mimir component.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The following example shows how to disable querier autoscaler and configure querier Deployment with 10 replicas:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;local k = import &amp;#39;github.com/grafana/jsonnet-libs/ksonnet-util/kausal.libsonnet&amp;#39;;
local deployment = k.apps.v1.deployment;

mimir {
    _config&amp;#43;:: {
        autoscaling_querier_enabled: false,
    },

    querier_deployment&amp;#43;: deployment.mixin.spec.withReplicas(10),
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
]]></content><description>&lt;h1 id="configure-grafana-mimir-autoscaling-with-jsonnet">Configure Grafana Mimir autoscaling with Jsonnet&lt;/h1>
&lt;p>Mimir Jsonnet supports autoscaling for the following components:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="../../../references/architecture/components/ruler/">Ruler Querier&lt;/a>&lt;/li>
&lt;li>&lt;a href="../../../references/architecture/components/querier/">Querier&lt;/a>&lt;/li>
&lt;li>&lt;a href="../../../references/architecture/components/distributor/">Distributor&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Autoscaling, which is based on Prometheus metrics and &lt;a href="https://keda.sh" target="_blank" rel="noopener noreferrer">Kubernetes-based Event Driven Autoscaler (KEDA)&lt;/a>, uses Kubernetes&amp;rsquo; Horizontal Pod Autoscaler (HPA).&lt;/p></description></item><item><title>Migrate from Consul to memberlist KV store for hash rings without downtime</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/migrate-from-consul-to-memberlist/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/migrate-from-consul-to-memberlist/</guid><content><![CDATA[&lt;h1 id=&#34;migrate-from-consul-to-memberlist-kv-store-for-hash-rings-without-downtime&#34;&gt;Migrate from Consul to memberlist KV store for hash rings without downtime&lt;/h1&gt;
&lt;p&gt;Mimir Jsonnet uses memberlist as KV store for hash rings since Mimir 2.2.0.&lt;/p&gt;
&lt;p&gt;Memberlist can be disabled by using the following configuration:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    memberlist_ring_enabled: false
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you are running Mimir hash rings with Consul and would like to migrate to memberlist without any downtime, you can follow instructions in this document.&lt;/p&gt;
&lt;h2 id=&#34;step-1-enable-memberlist-and-multi-kv-store&#34;&gt;Step 1: Enable memberlist and multi KV store.&lt;/h2&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    memberlist_ring_enabled: true,
    multikv_migration_enabled: true,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Step 1 configures components to use &lt;code&gt;multi&lt;/code&gt; KV store, with &lt;code&gt;consul&lt;/code&gt; as primary and memberlist as secondary stores.
This step requires rollout of all Mimir components.
After applying this step all Mimir components will expose &lt;a href=&#34;../../../references/http-api/#memberlist-cluster&#34;&gt;&lt;code&gt;/memberlist&lt;/code&gt;&lt;/a&gt; page on HTTP admin interface, which can be used to check health of memberlist cluster.&lt;/p&gt;
&lt;h2 id=&#34;step-2-enable-kv-store-mirroring&#34;&gt;Step 2: Enable KV store mirroring&lt;/h2&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    memberlist_ring_enabled: true,
    multikv_migration_enabled: true,
    multikv_mirror_enabled: true,  // Changed in this step.
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this step we enable writes to primary KV store (Consul) to be mirrored into secondary store (memberlist).
Applying this change will not cause restart of Mimir components.&lt;/p&gt;
&lt;p&gt;You can monitor following metrics to check if mirroring was enabled on all components and if it works correctly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cortex_multikv_mirror_enabled&lt;/code&gt; – shows which components have KV store mirroring enabled. All Mimir components should start mirroring to secondary KV store reloading runtime configuration.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rate(cortex_multikv_mirror_writes_total[1m])&lt;/code&gt; – shows rate of writes to secondary KV store in writes per second.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rate(cortex_multikv_mirror_write_errors_total[1m])&lt;/code&gt; – shows rate of write errors to secondary KV store, in errors per second.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After mirroring is enabled, you should see a key for each Mimir hash ring in the &lt;a href=&#34;../../../references/http-api/#memberlist-cluster&#34;&gt;Memberlist cluster information&lt;/a&gt; admin page.
See &lt;a href=&#34;../../../references/architecture/hash-ring/&#34;&gt;list of components that use hash ring&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;step-3-switch-primary-and-secondary-store&#34;&gt;Step 3: Switch Primary and Secondary store&lt;/h2&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    memberlist_ring_enabled: true,
    multikv_migration_enabled: true,
    multikv_mirror_enabled: true,
    multikv_switch_primary_secondary: true,  // Changed in this step.
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This change will switch primary and secondary stores as used by &lt;code&gt;multi&lt;/code&gt; KV.
From this point on Mimir components will use memberlist as primary KV store, and they will mirror updates to Consul.
This step does not require restart of Mimir components.&lt;/p&gt;
&lt;p&gt;To see if all components started to use memberlist as primary store, please watch &lt;code&gt;cortex_multikv_primary_store&lt;/code&gt; metric.&lt;/p&gt;
&lt;h2 id=&#34;step-4-disable-mirroring-to-consul&#34;&gt;Step 4: Disable mirroring to Consul&lt;/h2&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    memberlist_ring_enabled: true,
    multikv_migration_enabled: true,
    multikv_mirror_enabled: false,  // Changed in this step.
    multikv_switch_primary_secondary: true,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This step does not require restart of any Mimir component. After applying the change components will stop writing ring updates to Consul, and will only use memberlist.
You can watch &lt;code&gt;cortex_multikv_mirror_enabled&lt;/code&gt; metric to see if all components have picked up updated configuration.&lt;/p&gt;
&lt;h2 id=&#34;step-5-disable-multi-kv-store&#34;&gt;Step 5: Disable &lt;code&gt;multi&lt;/code&gt; KV Store&lt;/h2&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    memberlist_ring_enabled: true,
    multikv_migration_enabled: false,  // Changed in this step.
    multikv_mirror_enabled: false,
    multikv_switch_primary_secondary: true,
    multikv_migration_teardown: true,  // Added in this step.
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This configuration change will cause a new rollout of all components.
After the restart components will no longer use &lt;code&gt;multi&lt;/code&gt; KV store and will be configured to use memberlist only.
We use &lt;code&gt;multikv_migration_teardown&lt;/code&gt; to preserve runtime configuration for &lt;code&gt;multi&lt;/code&gt; KV store for components that haven&amp;rsquo;t restarted yet.&lt;/p&gt;
&lt;p&gt;All &lt;code&gt;cortex_multikv_*&lt;/code&gt; metrics are only exposed by components that use &lt;code&gt;multi&lt;/code&gt; KV store. As components restart, these metrics will disappear.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;Setting &lt;code&gt;multikv_migration_enabled: false&lt;/code&gt; while keeping &lt;code&gt;memberlist_ring_enabled: true&lt;/code&gt; removes the Consul workload.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s expected, since Consul isn&amp;rsquo;t used anymore—you disabled mirroring to it in step 4.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;p&gt;If you need to keep consul running, you can explicitly set &lt;code&gt;consul_enabled: true&lt;/code&gt; in &lt;code&gt;_config&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;step-6-cleanup&#34;&gt;Step 6: Cleanup&lt;/h2&gt;
&lt;p&gt;We have successfully migrated Mimir cluster from using Consul to memberlist without any downtime!
As a final step, we can remove all migration-related config options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;multikv_migration_enabled&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;multikv_mirror_enabled&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;multikv_switch_primary_secondary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;multikv_migration_teardown&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our final memberlist configuration will be:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    memberlist_ring_enabled: true,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will not trigger new restart of Mimir components. After applying this change, you are finished.&lt;/p&gt;
]]></content><description>&lt;h1 id="migrate-from-consul-to-memberlist-kv-store-for-hash-rings-without-downtime">Migrate from Consul to memberlist KV store for hash rings without downtime&lt;/h1>
&lt;p>Mimir Jsonnet uses memberlist as KV store for hash rings since Mimir 2.2.0.&lt;/p></description></item><item><title>Migrate query-scheduler from DNS-based to ring-based service discovery</title><link>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/migrate-query-scheduler-from-dns-to-ring-based-service-discovery/</link><pubDate>Wed, 03 Jun 2026 09:01:40 +0200</pubDate><guid>https://grafana.com/docs/mimir/v3.1.x/set-up/jsonnet/migrate-query-scheduler-from-dns-to-ring-based-service-discovery/</guid><content><![CDATA[&lt;h1 id=&#34;migrate-query-scheduler-from-dns-based-to-ring-based-service-discovery&#34;&gt;Migrate query-scheduler from DNS-based to ring-based service discovery&lt;/h1&gt;
&lt;p&gt;The query-scheduler supports two service discovery mechanisms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;../../../references/architecture/components/query-scheduler/#dns-based-service-discovery&#34;&gt;DNS-based service discovery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;../../../references/architecture/components/query-scheduler/#ring-based-service-discovery&#34;&gt;Ring-based service discovery&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To migrate the query-scheduler from DNS-based to ring-based service discovery when your Mimir cluster is deployed using Jsonnet:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Configure the query-scheduler instances to join a ring, but keep the querier and query-frontend instances discovering query-schedulers via DNS:

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    query_scheduler_service_discovery_mode: &amp;#39;ring&amp;#39;,
    query_scheduler_service_discovery_ring_read_path_enabled: false,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Wait until query-scheduler changes have been applied.&lt;/li&gt;
&lt;li&gt;Open the &lt;a href=&#34;../../../references/http-api/#query-scheduler-ring-status&#34;&gt;query-scheduler ring status&lt;/a&gt; page and ensure all query-scheduler instances are registered to the ring.&lt;/li&gt;
&lt;li&gt;Configure query-frontend and querier instances to discover query-schedulers via the ring:

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;jsonnet&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-jsonnet&#34;&gt;{
  _config&amp;#43;:: {
    query_scheduler_service_discovery_mode: &amp;#39;ring&amp;#39;,
    query_scheduler_service_discovery_ring_read_path_enabled: true,
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
]]></content><description>&lt;h1 id="migrate-query-scheduler-from-dns-based-to-ring-based-service-discovery">Migrate query-scheduler from DNS-based to ring-based service discovery&lt;/h1>
&lt;p>The query-scheduler supports two service discovery mechanisms:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="../../../references/architecture/components/query-scheduler/#dns-based-service-discovery">DNS-based service discovery&lt;/a>&lt;/li>
&lt;li>&lt;a href="../../../references/architecture/components/query-scheduler/#ring-based-service-discovery">Ring-based service discovery&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>To migrate the query-scheduler from DNS-based to ring-based service discovery when your Mimir cluster is deployed using Jsonnet:&lt;/p></description></item></channel></rss>