Grafana Mimir 快速上手指南:使用 Helm Chart 在 Kubernetes 上部署

原创2026-10-12 20:55:51381 阅读
文章标签:时序数据库后端数据存储可观测性云原生

Grafana Mimir 快速上手指南:使用 Helm Chart 在 Kubernetes 上部署

本指南完整讲解如何通过 mimir-distributed Helm Chart 在 Kubernetes 集群中快速部署一套可用的 Grafana Mimir,并用 Grafana Alloy 采集指标、用 Grafana 查询验证。读者将掌握从环境准备、Helm 安装、指标写入到可视化查询的完整链路,同时理解图表内置的 MinIO 对象存储、Kafka 写入架构与 nginx gateway 网关等关键组件的默认行为与配置要点。生产环境部署请参考同一文档目录下的 Run Grafana Mimir in production using the Helm chart 系列文档。

说明:本文内容以仓库文档 get-started-helm-charts/_index.md 为主体,并引用仓库中 operations/helm/charts/mimir-distributed/ 目录下的 Helm Chart 源码(values.yaml 与模板)作为佐证,所有命令均可直接复制执行。

准备工作(Before you begin)

本文的操作步骤适用于任意 Kubernetes 发行版(kind、minikube、云厂商托管集群等)。如果你没有现成的 Kubernetes 经验,可以先安装 kind 这类轻量级 Kubernetes 工具。建议(但非必需)具备以下基础:

  • Kubernetes 集群的通用使用知识;
  • 了解 kubectl 命令的作用;
  • 了解 helm 命令的作用。

Caution:本文流程主要面向本地或开发环境。生产环境的部署方式请阅读 Run Grafana Mimir in production using the Helm chart。

硬件要求

  • 单个 Kubernetes 节点至少需要 4 核 CPU 与 16 GiB 内存。这主要是为了容纳 Chart 默认部署的全部 Mimir 微服务、内置 MinIO 对象存储与 Kafka,见下文 Pod 清单。

软件要求

  • Kubernetes 1.32 或更高版本。Chart 的 Chart.yaml 中通过 kubeVersion: ^1.32.0-0 明确声明了最低版本约束;
  • kubectl 命令,版本与你的 Kubernetes 版本匹配。执行 kubectl version 可同时查看服务端(server)与客户端(client)版本,其中 server 指 Kubernetes 集群本身,client 指 kubectl;
  • helm 命令,版本 3.8 或更高。执行 helm version 可查看当前 Helm 版本。

安装前需要确认的事项

检查项 确认方式 说明
Kubernetes 集群访问权限 kubectl get ns 该命令会列出所有 namespace,能正常执行即代表有集群访问权限
持久化存储已启用 集群中存在默认 StorageClass 可以修改默认 StorageClass;如果使用 kind 或不确定,可默认视为已启用并继续
集群内 DNS 服务正常 — 如果使用 kind 或不确定,可默认视为可用并继续

注意:Chart 默认部署的 MinIO 与 Kafka 都是有状态组件,依赖 PVC 持久化(见下文 values.yaml 中的 persistence 配置),因此确认集群具备默认 StorageClass 是安装成功的前提。

安全策略说明(Security setup)

如果你使用 kind 或类似的本地 Kubernetes 环境且未配置安全策略,可以安全跳过本节。但要注意以下两个关键限制:

  1. 如果启用了 PodSecurityPolicy 准入控制器(admission controller),本安装将无法成功。原因是 Chart 内置了来自 minio/minio chart 的对象存储部署,该子 Chart 不兼容 Restricted 策略,也不兼容 mimir-distributed Chart 自带的 PodSecurityPolicy。
  2. 如果强制使用 Pod Security 准入控制器的 Restricted 策略,同样无法安装;但内置对象存储与 mimir-distributed Chart 可以在 baseline 级别的 Pod 安全等级下成功部署。

MinIO 镜像说明与私有镜像仓库适配

默认情况下,mimir-distributed 将 MinIO 子 Chart 的镜像覆盖为 pgsty/silo:RELEASE.2026-09-03T13-18-01Z,同时应用于 minio.image 与 minio.mcImage 两个配置项。Silo 是 PGSTY 维护的 MinIO fork,提供相同的 S3 API,且该镜像同时内置了服务端与 mc 客户端。Chart 之所以做此覆盖,是因为 MinIO 社区版镜像已不再发布到公共容器镜像仓库。

如果集群只从私有仓库拉取镜像,或强制启用了镜像策略(image policy),请自行允许或镜像该镜像,或通过以下 values 覆盖:

minio:
  image:
    repository: <YOUR_REGISTRY>/silo
    tag: RELEASE.2026-09-03T13-18-01Z
  mcImage:
    repository: <YOUR_REGISTRY>/silo
    tag: RELEASE.2026-09-03T13-18-01Z

将 <YOUR_REGISTRY> 替换为你的私有仓库主机与路径。仓库源码 values.yaml 中可以看到这些默认值,以及内置的 bucket 定义(mimir-tsdb 与 mimir-ruler,策略均为 none)、5Gi 的持久化卷、100m/128Mi 的资源请求等细节。

针对两类准入控制器的结论:

  • 使用 PodSecurityPolicy:无法连同内置对象存储一起部署 mimir-distributed Chart。请参考 Run Grafana Mimir in production using the Helm chart 配置外部对象存储,并在 Helm values 中通过 minio.enabled: false 禁用内置 MinIO 部署;
  • 使用 Pod Security 准入控制器:内置对象存储与 mimir-distributed Chart 可以在 baseline 级别的 Pod 安全等级下成功部署。

在自定义 namespace 中安装 Helm Chart

使用自定义 namespace 可以避免日后覆盖默认 namespace,减少后续运维冲突。

1. 创建专属 namespace

kubectl create namespace mimir-test

创建 namespace 的更多细节见 Kubernetes 官方文档 Creating a new namespace。

2. 添加 Helm 仓库

helm repo add grafana https://grafana.github.io/helm-charts
helm repo update

Note:https://grafana.github.io/helm-charts。

3. 安装 Grafana Mimir

helm -n mimir-test install mimir grafana/mimir-distributed

Note:命令输出中包含后续步骤所需的写入(write)与读取(read)URL。这些 URL 由 templates/NOTES.txt 模板生成——例如写入端为 http://<release>-gateway.<namespace>.svc:<port>/api/v1/push,读取端为 http://<release>-gateway.<namespace>.svc:<port>/prometheus。

4. 查看 Mimir Pod 状态

kubectl -n mimir-test get pods

输出结果大致如下:

NAME                                         READY   STATUS      RESTARTS       AGE
mimir-alertmanager-0                         1/1     Running     0              2m25s
mimir-compactor-0                            1/1     Running     0              2m25s
mimir-distributor-5c8f54fcf-t7f9m            1/1     Running     2 (2m1s ago)   2m25s
mimir-ingester-zone-a-0                      1/1     Running     2 (117s ago)   2m25s
mimir-ingester-zone-b-0                      1/1     Running     2 (118s ago)   2m25s
mimir-ingester-zone-c-0                      1/1     Running     2 (112s ago)   2m25s
mimir-kafka-0                                1/1     Running     0              2m25s
mimir-make-minio-buckets-5.4.0-d556m         0/1     Completed   0              2m25s
mimir-minio-5477c4c7b4-dwvsv                 1/1     Running     0              2m25s
mimir-gateway-5ddc75564-lcqlv                1/1     Running     0              2m25s
mimir-overrides-exporter-6db7cfd7c-c4ljk     1/1     Running     0              2m25s
mimir-querier-7fb9d8c875-x9jkd               1/1     Running     2 (119s ago)   2m25s
mimir-querier-7fb9d8c875-xf9hd               1/1     Running     2 (117s ago)   2m25s
mimir-query-frontend-6f56dc997f-lgd4j        1/1     Running     0              2m25s
mimir-query-scheduler-bf95f647-rm9cf         1/1     Running     0              2m25s
mimir-query-scheduler-bf95f647-swlzs         1/1     Running     0              2m25s
mimir-rollout-operator-569576c88c-xs2wz      1/1     Running     0              2m25s
mimir-ruler-67548666f-bmmn2                  1/1     Running     2 (2m ago)     2m25s
mimir-store-gateway-zone-a-0                 1/1     Running     0              2m25s
mimir-store-gateway-zone-b-0                 1/1     Running     0              2m25s
mimir-store-gateway-zone-c-0                 1/1     Running     0              2m25s

5. 等待全部 Pod 就绪

等待所有 Pod 的状态变为 Running 或 Completed,可能需要几分钟时间。

从 Pod 清单解读默认部署架构

从上述 Pod 列表可以清晰看到当前 Chart 默认部署的组件,对照 values.yaml 可理解其默认配置:

  • Mimir 微服务:alertmanager、compactor、distributor、ingester(zone-a/b/c 三个 zone 各 1 个)、overrides-exporter、querier(2 副本)、query-frontend、query-scheduler(2 副本)、ruler、store-gateway(zone-a/b/c 各 1 个)。其中 ingester 与 store-gateway 启用了 zoneAwareReplication(区域感知复制,对应 values 中的 ingester.zoneAwareReplication / store_gateway.zoneAwareReplication 配置块),因此默认会按 zone 命名;
  • mimir-kafka-0:Chart 默认启用了 Kafka(values.yaml 中 kafka.enabled: true),走的是 ingest storage(Kafka 写入)架构。对应 Mimir 配置中 values.yaml 的 ingest_storage 段:启用 Kafka、topic 为 mimir-ingest、自动建 topic 且默认分区数为 100,并将 ingester 的 gRPC Push 接口关闭(push_grpc_method_enabled: false),所有写入流量先进入 Kafka 再由 ingester 消费;
  • mimir-minio 与 mimir-make-minio-buckets:内置的 MinIO(S3 API 兼容)对象存储及创建 bucket 的初始化 Job。Job 模板见 templates/minio/create-bucket-job.yaml,它作为 helm install 的补充手段创建 mimir-tsdb 与 mimir-ruler 两个 bucket(因为 MinIO 自带 hook 在带 --wait 安装时不会执行,参考 grafana/mimir#2464 中 alertmanager_storage、blocks_storage.s3 的 insecure: true 端点配置;
  • mimir-gateway:一个 nginx 反向代理 Deployment,作为 Mimir 的统一流量入口(values.yaml 中 gateway.enabled: true)。它负责把 /api/v1/push、/prometheus 等路径分发到 distributor、query-frontend 等后端,同时保证 X-Scope-OrgID 请求头始终存在(默认 tenant 机制);
  • mimir-rollout-operator:用于在 zone-aware 架构下对 ingester、store-gateway、alertmanager 等有状态组件做滚动升级,默认启用(values.yaml)。

生成测试指标:用 Grafana Alloy 采集并写入

接下来安装 Grafana Alloy,预配置为抓取 Grafana Mimir Pod 的指标,并将这些指标写入同一个 Grafana Mimir 实例,从而验证写入链路。

1. 创建 Alloy 覆盖配置 alloy-values.yaml

alloy:
  clustering:
    enabled: false

  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      memory: 512Mi

  serviceAccount:
    create: true
    name: ""
  rbac:
    create: true

  configMap:
    content: |
      // Kubernetes service discovery for pods in test-mimir namespace
      discovery.kubernetes "pods" {
        role = "pod"
        namespaces {
          names = ["mimir-test"]
        }
      }
      // Relabel pods to extract metrics endpoints
      discovery.relabel "pod_relabel" {
        targets = discovery.kubernetes.pods.targets
        rule {
          source_labels = ["__meta_kubernetes_pod_label_name"]
          regex = ""
          action = "drop"
        }
        rule {
            source_labels = ["__meta_kubernetes_pod_container_port_name"]
            regex = ".*-metrics"
            action = "keep"
        }
        rule {
          source_labels = ["__meta_kubernetes_pod_phase"]
          regex = "Succeeded|Failed"
          action = "drop"
        }
        // Add pod metadata as labels
        rule {
          source_labels = ["__meta_kubernetes_namespace", "__meta_kubernetes_pod_label_name"]
          replacement = "$1"
          separator = "/"
          action = "replace"
          target_label = "job"
        }
        rule {
          source_labels = ["__meta_kubernetes_namespace"]
          action        = "replace"
          target_label  = "namespace"
        }
        rule {
          source_labels = ["__meta_kubernetes_pod_name"]
          action        = "replace"
          target_label  = "pod"
        }
        rule {
          source_labels = ["__meta_kubernetes_pod_container_name"]
          action        = "replace"
          target_label  = "container"
        }
      }
      // Scrape metrics from discovered targets
      prometheus.scrape "kubernetes_pods" {
        targets    = discovery.relabel.pod_relabel.output
        forward_to = [prometheus.remote_write.test_mimir.receiver]
        scrape_interval = "15s"
        scrape_timeout  = "10s"
      }
      // Remote write to Mimir
      prometheus.remote_write "test_mimir" {
        endpoint {
          url = "http://mimir-gateway.mimir-test.svc.cluster.local/api/v1/push"
          send_native_histograms = true
        }
      }
  securityContext:
    runAsNonRoot: true
    runAsUser: 472
    fsGroup: 472

  podSecurityContext:
    runAsNonRoot: true
    runAsUser: 472
    fsGroup: 472

# Disable ServiceMonitor for monitoring Alloy itself
serviceMonitor:
  enabled: false

逐段解读这份 Alloy 配置:

配置段 作用
discovery.kubernetes "pods" 基于 Kubernetes 服务发现,只发现 mimir-test namespace 中的 Pod
discovery.relabel "pod_relabel" 对发现的目标做重标记:丢弃没有 *-metrics 端口名的目标、丢弃 Succeeded/Failed 阶段的 Pod,并把 namespace、pod 名、容器名以及 namespace/pod名 组合成的 job 标签写入样本
prometheus.scrape "kubernetes_pods" 每 15s 抓取一次指标,超时 10s,转发给 remote write
prometheus.remote_write "test_mimir" 通过 http://mimir-gateway.mimir-test.svc.cluster.local/api/v1/push 写入 Mimir,并开启 send_native_histograms 发送原生直方图

Note:在生产环境中,prometheus.remote_write 块中的 url 参数应指向外部系统,而非你的 Grafana Mimir 实例本身,例如可以是 Grafana Cloud Metrics 实例。

mimir-gateway 这个名字与端口(80)在仓库中有据可查:网关 Service 由 templates/gateway/gateway-svc.yaml 渲染,默认 gateway.service.port: 80、类型 ClusterIP(见 values.yaml);集群内访问地址模板 http://<gateway-service>.<namespace>.svc:<port> 定义在 templates/_helpers.tpl 的 mimir.gatewayUrl helper 中。/api/v1/push 路径由 nginx 网关转发到 distributor,参考网关 nginx 配置 values.yaml 附近的 location = /api/v1/push 规则。

2. 安装 Grafana Alloy

helm install alloy grafana/alloy --namespace alloy-test --create-namespace -f alloy-values.yaml

注意这里用 --create-namespace 自动创建 alloy-test namespace,并将 alloy-values.yaml 作为覆盖文件传入。

在 Kubernetes 中启动 Grafana 并查询指标

1. 安装 Grafana

在同一个 Kubernetes 集群中安装 Grafana,安装方式参见 Grafana 官方文档 Deploy Grafana on Kubernetes。

2. 端口转发 Grafana 到本地

如果上一步没有完成,使用 kubectl 将 Grafana 端口转发到 localhost:

kubectl port-forward service/grafana 3000:3000

3. 打开 Grafana 并登录

在浏览器中访问 http://localhost:3000,使用默认用户名 admin、密码 admin 登录。

4. 配置 Prometheus 数据源

在左侧导航进入 Configuration > Data sources,新增一个 Prometheus 数据源,指向本地 Grafana Mimir 服务,设置如下:

字段 值
Name Mimir
URL http://mimir-gateway.mimir-test.svc:80/prometheus

添加数据源的详细步骤参见 Grafana 官方文档 Add a data source。

/prometheus 路径前缀来自 Chart 的 Prometheus HTTP 前缀约定:helper 函数 mimir.prometheusHttpPrefix(templates/_helpers.tpl)默认返回 /prometheus,除非 Mimir 配置中显式修改了 api.prometheus_http_prefix。Grafana 数据源 URL 使用 Mimir 的 Prometheus 兼容读接口,由网关 nginx 转发到 query-frontend。

5. 验证成功

现在你应该能够在 Grafana Explore 中查询指标,并使用新配置的 Mimir 数据源创建仪表盘面板。你可以尝试查询类似 mimir_ingester_memory_bytes 或 Mimir 自身的 up / *_metrics 相关指标来验证整条链路。

开启集群外部访问(可选)

如需从 Kubernetes 集群外部访问 Grafana Mimir 的写入与查询接口,请参阅同目录文档 Enable external access to Grafana Mimir。

其核心思路是配置 Ingress:在 custom.yaml 中启用 nginx.ingress,指定 ingressClassName 与 hosts,随后执行:

helm -n mimir-test upgrade mimir grafana/mimir-distributed -f custom.yaml

升级后命令输出会包含类似 From outside the cluster via ingress: http://myhost.mynetwork/prometheus 的外部访问地址。Chart 的 gateway.ingress 与顶层 ingress 配置项默认均关闭(见 values.yaml 与 values.yaml),启用时注意二者不要同时开启。

常见问题与排错提示

  • Pod 长时间处于 Pending:通常是 PVC 无法创建,确认集群存在默认 StorageClass;MinIO 与 Kafka 分别需要 5Gi 持久化卷(values.yaml、values.yaml);
  • MinIO 相关 Pod 镜像拉取失败:默认使用 pgsty/silo 镜像,私有镜像仓库环境需按上文覆盖 minio.image 与 minio.mcImage;
  • 写入 401/403 错误:Mimir 是多租户系统,推送与查询请求需要携带 X-Scope-OrgID 头。网关 nginx 会在该头缺失时自动填充默认 tenant(见 values.yaml 的 map 配置);
  • 查询返回数据为空:等待 Alloy 抓取一两个周期(scrape_interval 为 15s)后再查询;同时确认 Grafana 数据源 URL 使用了 http://mimir-gateway.mimir-test.svc:80/prometheus 且网络可达;
  • 查看完整可配置参数:执行 helm show values grafana/mimir-distributed 可查看全部 values 及其注释说明,也可以直接阅读仓库中的 values.yaml(约 4000 行,含每个组件的 replica、资源、持久化、autoscaling 等完整配置)。

小结

通过本文你已完成了从零到一的完整闭环:创建 namespace → 添加 Helm 仓库 → 安装 mimir-distributed → 确认微服务、MinIO、Kafka、网关全部就绪 → 用 Grafana Alloy 采集并远程写入 Mimir → 用 Grafana 配置 Prometheus 数据源查询验证。过程中也理解了默认部署架构中 ingest storage(Kafka 写入)、zone-aware replication、nginx 网关与内置对象存储各自的角色。该流程适合本地开发与功能验证;生产环境的高可用、外部对象存储、多 zone、自动扩缩容等主题,请继续阅读 Run Grafana Mimir in production using the Helm chart 系列文档。

登录后查看全文
mimir