Grafana Mimir 快速上手指南:使用 Helm Chart 在 Kubernetes 上部署
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 环境且未配置安全策略,可以安全跳过本节。但要注意以下两个关键限制:
- 如果启用了 PodSecurityPolicy 准入控制器(admission controller),本安装将无法成功。原因是 Chart 内置了来自 minio/minio chart 的对象存储部署,该子 Chart 不兼容 Restricted 策略,也不兼容 mimir-distributed Chart 自带的 PodSecurityPolicy。
- 如果强制使用 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
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 系列文档。