关于 mimir
mimir 是一份 Grafana Mimir 部署与运维指南,面向需要长期存储 Prometheus 和 OpenTelemetry 指标的团队。内容涵盖分布式组件、对象存储、多租户、查询和故障排查。
主要功能
- 01说明单体与微服务部署模式
- 02配置对象存储后端
- 03接收 Prometheus 与 OTLP 指标
- 04设置多租户及租户限制
- 05提供查询、告警与排障指引
适用场景
- 01部署用于长期指标存储的 Mimir
- 02配置租户隔离和每租户限制
- 03接入 OpenTelemetry 指标并查询
- 04排查存储、摄取或查询问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ julianobarbosa/ claude-code-skills --skill mimir安装后在 Claude Code 中输入/mimir确认已加载。
详细介绍
Grafana Mimir 技能
Grafana Mimir 综合指南——用于长期存储 Prometheus 指标的水平可扩展、高可用、多租户时序数据库。
什么是 Mimir?
Mimir 是一个面向 Prometheus 和 OpenTelemetry 指标的开源、水平可扩展、高可用、多租户长期存储解决方案,它:
- 突破 Prometheus 的限制——实现可扩展性和长期保留
- 默认支持多租户——通过
X-Scope-OrgID请求头内置租户隔离 - 将数据存储在对象存储中——支持 S3、GCS、Azure Blob Storage 或 Swift
- 100% 兼容 Prometheus——支持 PromQL 查询和远程写入协议
- 属于 LGTM+ 技术栈——统一的日志、Grafana、追踪和指标可观测性
架构概览
核心组件
| 组件 | 用途 |
|---|---|
| 分发器 | 验证请求,并通过哈希环将传入指标路由到摄取器 |
| 摄取器 | 在内存中存储时序数据,并将数据刷新到对象存储 |
| 查询器 | 从摄取器和存储网关执行 PromQL 查询 |
| 查询前端 | 缓存查询结果、优化并拆分查询 |
| 查询调度器 | 管理每个租户的查询队列,确保公平性 |
| 存储网关 | 提供对对象存储中历史指标块的访问 |
| 压缩器 | 整合并优化存储的指标数据块 |
| 规则评估器 | 评估记录规则和告警规则(可选) |
| Alertmanager | 处理告警路由和去重(可选) |
数据流
写入路径:
Prometheus/OTel → Distributor → Ingester → Object Storage
↓
Hash Ring
(routes by series)
读取路径:
Query → Query Frontend → Query Scheduler → Querier
↓
Ingesters (recent)
↓
Store-Gateway (historical)
部署模式
1. 单体模式(-target=all)
- 所有组件在同一个进程中运行
- 适用场景:开发、测试、小规模部署(约 1M 个序列)
- 通过部署多个实例可实现水平扩展
- 不建议用于大规模部署(所有组件会一起扩展)
2. 微服务模式(分布式)——推荐用于生产环境
# Using mimir-distributed Helm chart
distributor:
replicas: 3
ingester:
replicas: 3
zoneAwareReplication:
enabled: true
querier:
replicas: 3
queryFrontend:
replicas: 2
queryScheduler:
replicas: 2
storeGateway:
replicas: 3
compactor:
replicas: 1
Helm 部署
添加仓库
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
安装分布式 Mimir
helm install mimir grafana/mimir-distributed \
--namespace monitoring \
--values values.yaml
预构建的 Values 文件
| 文件 | 用途 |
|---|---|
values.yaml | 使用 MinIO 进行非生产环境测试 |
small.yaml | 约 100 万个序列(单副本,非高可用) |
large.yaml | 生产环境(约 1,000 万个序列) |
生产环境 Values 示例
# Deployment mode
mimir:
structuredConfig:
multitenancy_enabled: true
# Storage configuration
mimir:
structuredConfig:
common:
storage:
backend: azure # or s3, gcs
azure:
account_name: ${AZURE_STORAGE_ACCOUNT}
account_key: ${AZURE_STORAGE_KEY}
endpoint_suffix: blob.core.windows.net
blocks_storage:
azure:
container_name: mimir-blocks
alertmanager_storage:
azure:
container_name: mimir-alertmanager
ruler_storage:
azure:
container_name: mimir-ruler
# Distributor
distributor:
replicas: 3
resources:
requests:
cpu: 1
memory: 2Gi
limits:
memory: 4Gi
# Ingester
ingester:
replicas: 3
zoneAwareReplication:
enabled: true
persistentVolume:
enabled: true
size: 50Gi
resources:
requests:
cpu: 2
memory: 8Gi
limits:
memory: 16Gi
# Querier
querier:
replicas: 3
resources:
requests:
cpu: 1
memory: 2Gi
limits:
memory: 8Gi
# Query Frontend
query_frontend:
replicas: 2
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
memory: 2Gi
# Query Scheduler
query_scheduler:
replicas: 2
# Store Gateway
store_gateway:
replicas: 3
persistentVolume:
enabled: true
size: 20Gi
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
memory: 8Gi
# Compactor
compactor:
replicas: 1
persistentVolume:
enabled: true
size: 50Gi
resources:
requests:
cpu: 1
memory: 4Gi
limits:
memory: 8Gi
# Gateway for external access
gateway:
enabledNonEnterprise: true
replicas: 2
# Monitoring
metaMonitoring:
serviceMonitor:
enabled: true
存储配置
关键要求
- 必须手动创建存储桶——Mimir 不会创建存储桶
- 必须使用独立存储桶——blocks_storage、alertmanager_storage、ruler_storage 不能共用同一个存储桶和前缀
- Azure:必须禁用分层命名空间
Azure Blob Storage
mimir:
structuredConfig:
common:
storage:
backend: azure
azure:
account_name: <storage-account-name>
# Option 1: Account Key (via environment variable)
account_key: ${AZURE_STORAGE_KEY}
# Option 2: User-Assigned Managed Identity
# user_assigned_id: <identity-client-id>
endpoint_suffix: blob.core.windows.net
blocks_storage:
azure:
container_name: mimir-blocks
alertmanager_storage:
azure:
container_name: mimir-alertmanager
ruler_storage:
azure:
container_name: mimir-ruler
AWS S3
mimir:
structuredConfig:
common:
storage:
backend: s3
s3:
endpoint: s3.us-east-1.amazonaws.com
region: us-east-1
access_key_id: ${AWS_ACCESS_KEY_ID}
secret_access_key: ${AWS_SECRET_ACCESS_KEY}
blocks_storage:
s3:
bucket_name: mimir-blocks
alertmanager_storage:
s3:
bucket_name: mimir-alertmanager
ruler_storage:
s3:
bucket_name: mimir-ruler
Google Cloud Storage
mimir:
structuredConfig:
common:
storage:
backend: gcs
gcs:
service_account: ${GCS_SERVICE_ACCOUNT_JSON}
blocks_storage:
gcs:
bucket_name: mimir-blocks
alertmanager_storage:
gcs:
bucket_name: mimir-alertmanager
ruler_storage:
gcs:
bucket_name: mimir-ruler
限制配置
mimir:
structuredConfig:
limits:
# Ingestion limits
ingestion_rate: 25000 # Samples/sec per tenant
ingestion_burst_size: 50000 # Burst size
max_series_per_metric: 10000
max_series_per_user: 1000000
max_global_series_per_user: 1000000
max_label_names_per_series: 30
max_label_name_length: 1024
max_label_value_length: 2048
# Query limits
max_fetched_series_per_query: 100000
max_fetched_chunks_per_query: 2000000
max_query_lookback: 0 # No limit
max_query_parallelism: 32
# Retention
compactor_blocks_retention_period: 365d # 1 year
# Out-of-order samples
out_of_order_time_window: 5m
每租户覆盖项(运行时配置)
# runtime-config.yaml
overrides:
tenant1:
ingestion_rate: 50000
max_series_per_user: 2000000
compactor_blocks_retention_period: 730d # 2 years
tenant2:
ingestion_rate: 75000
max_global_series_per_user: 5000000
启用运行时配置:
mimir:
structuredConfig:
runtime_config:
file: /etc/mimir/runtime-config.yaml
period: 10s
高可用配置
Prometheus 去重的 HA 跟踪器
mimir:
structuredConfig:
distributor:
ha_tracker:
enable_ha_tracker: true
kvstore:
store: memberlist
cluster_label: cluster
replica_label: __replica__
memberlist:
join_members:
- mimir-gossip-ring.monitoring.svc.cluster.local:7946
Prometheus 配置:
global:
external_labels:
cluster: prom-team1
__replica__: replica1
remote_write:
- url: http://mimir-gateway:8080/api/v1/push
headers:
X-Scope-OrgID: my-tenant
感知可用区的复制
ingester:
zoneAwareReplication:
enabled: true
zones:
- name: zone-a
nodeSelector:
topology.kubernetes.io/zone: us-east-1a
- name: zone-b
nodeSelector:
topology.kubernetes.io/zone: us-east-1b
- name: zone-c
nodeSelector:
topology.kubernetes.io/zone: us-east-1c
store_gateway:
zoneAwareReplication:
enabled: true
Shuffle Sharding
将租户数据限制在一部分实例中,以实现故障隔离:
mimir:
structuredConfig:
limits:
# Write path
ingestion_tenant_shard_size: 3
# Read path
max_queriers_per_tenant: 5
store_gateway_tenant_shard_size: 3
OpenTelemetry 集成
OTLP 指标摄取
OpenTelemetry Collector 配置:
exporters:
otlphttp:
endpoint: http://mimir-gateway:8080/otlp
headers:
X-Scope-OrgID: "my-tenant"
service:
pipelines:
metrics:
receivers: [otlp]
exporters: [otlphttp]
指数直方图(实验性)
// Go SDK configuration
Aggregation: metric.AggregationBase2ExponentialHistogram{
MaxSize: 160, // Maximum buckets
MaxScale: 20, // Scale factor
}
主要优势:
- 明确的最小值/最大值(无需估算)
- 极端百分位数的准确性更高
- 原生保留 OTLP 格式
多租户
mimir:
structuredConfig:
multitenancy_enabled: true
no_auth_tenant: anonymous # Used when multitenancy disabled
使用租户请求头进行查询:
curl -H "X-Scope-OrgID: tenant-a" \
"http://mimir:8080/prometheus/api/v1/query?query=up"
租户 ID 限制:
- 最多 150 个字符
- 允许使用:字母数字字符、
!-_.*'() - 禁止使用:单独的
.或..、__mimir_cluster、斜杠
API 参考
摄取端点
# Prometheus remote write
POST /api/v1/push
# OTLP metrics
POST /otlp/v1/metrics
# InfluxDB line protocol
POST /api/v1/push/influx/write
查询端点
# Instant query
GET,POST /prometheus/api/v1/query?query=<promql>&time=<timestamp>
# Range query
GET,POST /prometheus/api/v1/query_range?query=<promql>&start=<start>&end=<end>&step=<step>
# Labels
GET,POST /prometheus/api/v1/labels
GET /prometheus/api/v1/label/{name}/values
# Series
GET,POST /prometheus/api/v1/series
# Exemplars
GET,POST /prometheus/api/v1/query_exemplars
# Cardinality
GET,POST /prometheus/api/v1/cardinality/label_names
GET,POST /prometheus/api/v1/cardinality/active_series
管理端点
# Flush ingester data
GET,POST /ingester/flush
# Prepare shutdown
GET,POST,DELETE /ingester/prepare-shutdown
# Ring status
GET /ingester/ring
GET /distributor/ring
GET /store-gateway/ring
GET /compactor/ring
# Tenant stats
GET /distributor/all_user_stats
GET /api/v1/user_stats
GET /api/v1/user_limits
健康状态与配置
GET /ready
GET /metrics
GET /config
GET /config?mode=diff
GET /runtime_config
Azure 身份配置
用户分配的托管标识
1. 创建标识:
az identity create \
--name mimir-identity \
--resource-group <rg>
IDENTITY_CLIENT_ID=$(az identity show --name mimir-identity --resource-group <rg> --query clientId -o tsv)
IDENTITY_PRINCIPAL_ID=$(az identity show --name mimir-identity --resource-group <rg> --query principalId -o tsv)
2. 分配给节点池:
az vmss identity assign \
--resource-group <aks-node-rg> \
--name <vmss-name> \
--identities /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/mimir-identity
3. 授予存储权限:
az role assignment create \
--role "Storage Blob Data Contributor" \
--assignee-object-id $IDENTITY_PRINCIPAL_ID \
--scope /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storage>
4. 配置 Mimir:
mimir:
structuredConfig:
common:
storage:
azure:
user_assigned_id: <IDENTITY_CLIENT_ID>
工作负载标识联合
1. 创建联合凭据:
az identity federated-credential create \
--name mimir-federated \
--identity-name mimir-identity \
--resource-group <rg> \
--issuer <aks-oidc-issuer-url> \
--subject system:serviceaccount:monitoring:mimir \
--audiences api://AzureADTokenExchange
2. 配置 Helm 值:
serviceAccount:
annotations:
azure.workload.identity/client-id: <IDENTITY_CLIENT_ID>
podLabels:
azure.workload.identity/use: "true"
故障排查
常见问题
1. 找不到容器(Azure)
# Create required containers
az storage container create --name mimir-blocks --account-name <storage>
az storage container create --name mimir-alertmanager --account-name <storage>
az storage container create --name mimir-ruler --account-name <storage>
2. 授权失败(Azure)
# Verify RBAC assignment
az role assignment list --scope /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storage>
# Assign if missing
az role assignment create \
--role "Storage Blob Data Contributor" \
--assignee-object-id <principal-id> \
--scope <storage-scope>
# Restart pod to refresh token
kubectl delete pod -n monitoring <ingester-pod>
3. Ingester 内存溢出
ingester:
resources:
limits:
memory: 16Gi # Increase memory
4. 查询超时
mimir:
structuredConfig:
querier:
timeout: 5m
max_concurrent: 20
5. 高基数
mimir:
structuredConfig:
limits:
max_series_per_user: 5000000
max_series_per_metric: 50000
诊断命令
# Check pod status
kubectl get pods -n monitoring -l app.kubernetes.io/name=mimir
# Check ingester logs
kubectl logs -n monitoring -l app.kubernetes.io/component=ingester --tail=100
# Check distributor logs
kubectl logs -n monitoring -l app.kubernetes.io/component=distributor --tail=100
# Verify readiness
kubectl exec -it <mimir-pod> -n monitoring -- wget -qO- http://localhost:8080/ready
# Check ring status
kubectl port-forward svc/mimir-distributor 8080:8080 -n monitoring
curl http://localhost:8080/distributor/ring
# Check configuration
kubectl exec -it <mimir-pod> -n monitoring -- cat /etc/mimir/mimir.yaml
# Validate configuration before deployment
mimir -modules -config.file <path-to-config-file>
需要监控的关键指标
# Ingestion rate per tenant
sum by (user) (rate(cortex_distributor_received_samples_total[5m]))
# Series count per tenant
sum by (user) (cortex_ingester_memory_series)
# Query latency
histogram_quantile(0.99, sum by (le) (rate(cortex_request_duration_seconds_bucket{route=~"/api/prom/api/v1/query.*"}[5m])))
# Compactor status
cortex_compactor_runs_completed_total
cortex_compactor_runs_failed_total
# Store-gateway block sync
cortex_bucket_store_blocks_loaded
断路器(Ingester)
mimir:
structuredConfig:
ingester:
push_circuit_breaker:
enabled: true
request_timeout: 2s
failure_threshold_percentage: 10
cooldown_period: 10s
read_circuit_breaker:
enabled: true
request_timeout: 30s
状态:
- 关闭 - 正常运行
- 打开 - 停止向故障实例转发请求
- 半开 - 冷却后发送数量有限的试探请求
外部资源
注意事项
- 通过 X-Scope-OrgID 实现多租户:缺少此标头时,数据会被静默写入租户 "fake" —— 这和 Loki 是同一个陷阱。
- 保留期按租户设置;全局保留期环境变量仅作回退值 —— 配置错误的租户会被静默覆盖。
- Ingester 复制因子 < 3 时,单次故障就会导致数据丢失 —— 某些 Helm Chart 的默认值为 1;不要直接部署。
- 查询前端缓存 TTL 变更会使所有缓存结果失效 —— 调高
query_range_results_cache_ttl不会延长现有条目的有效期。 - 多租户存储路径共用同一个 S3 存储桶前缀 —— 意外允许 tenant-1 读取 tenant-2 的路径属于配置错误,而 Chart 不会对此进行阻止。
distributor.ingestion-rate-limit-strategy: global需要正常工作的 memberlist —— 静默故障模式:各 Distributor 独立执行限流,互不协调,导致流量可达预期值的 10 倍。
评论
支持 Markdown