_prometheus默认本地存储的保留期通常只有15天,超过这个时间的数据会被自动清理。对于故障复盘、容量规划和长期趋势分析来说,十五天远远不够。Grafana Mimir正是为解决这个问题而生,它可以将Prometheus采集的时序数据持续写入对象存储,保存数年都不成问题,同时保持较高的查询性能。不过Mimir本身是一个分布式系统,组件较多,直接对外暴露并不安全也不方便,这时候Nginx就派上用场了:作为统一的反向代理入口,它承担TLS卸载、负载均衡、限流和路由分发等职责,让整套架构更加清晰健壮。

为什么长期存储首选Mimir
在Mimir出现之前,社区里比较常见的长期存储方案是Thanos和VictoriaMetrics。Thanos通过Sidecar方式把Prometheus的数据块上传到对象存储,架构相对松散,查询大规模数据时依赖Store Gateway组件,跨集群查询延迟较高。VictoriaMetrics是单二进制设计,部署简单,但在超大规模集群下的水平扩展能力不如专门为多租户设计的Mimir。
Mimir最初由Grafana团队基于Cortex二次开发而来,做了大量性能优化,比如引入了列式存储的查询引擎和流式拆分机制,官方的基准测试显示它在相同硬件下能比Cortex快数倍。更关键的一点是,Mimir原生支持对象存储(S3、GCS、Azure Blob、MinIO等),存储成本只相当于本地SSD的零头。对于保留期在一年以上的场景,对象存储加Mimir的组合几乎是目前最经济的选择。
Mimir的写入路径遵循Prometheus的远程写入协议:Prometheus通过remote_write把指标推送到Mimir的Distributor,数据经Ingestor落地到对象存储;查询路径则由Query Frontend接收请求,做查询拆分和缓存后分发给Querier执行。理解这条链路,是后面配置Nginx的基础。
Nginx与Mimir的集成配置
Mimir是多租户架构,租户通过HTTP头X-Scope-OrgID区分。Prometheus的远程写入、Grafana的查询以及管理接口都走同一个端口,如果直接把Mimir暴露出去,既无法区分内外部流量,也没有任何TLS保护。用Nginx做前置代理是业界通行的做法。
首先给出一个典型的Nginx配置,包含远程写入入口和查询入口的分流,并开启了长连接支持,这一点对远程写入的吞吐影响很大:
upstream mimir_distributors {
least_conn;
server 10.0.1.11:8080 max_fails=3 fail_timeout=30s;
server 10.0.1.12:8080 max_fails=3 fail_timeout=30s;
keepalive 64;
}
upstream mimir_query_frontend {
least_conn;
server 10.0.1.21:8080 max_fails=3 fail_timeout=30s;
server 10.0.1.22:8080 max_fails=3 fail_timeout=30s;
keepalive 32;
}
# 远程写入入口,仅允许内网网段访问
server {
listen 8080;
location /api/v1/push {
proxy_pass http://mimir_distributors;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Scope-OrgID tenant-main;
proxy_request_buffering off; # 大块写入体直接流式转发
client_max_body_size 512m; # 远程写入的批次可能很大
proxy_read_timeout 300s;
}
}
# 查询入口,走HTTPS并做限流
server {
listen 443 ssl;
server_name mimir.example.ipipp.com;
ssl_certificate /etc/nginx/ssl/mimir.crt;
ssl_certificate_key /etc/nginx/ssl/mimir.key;
location / {
limit_req zone=query_limit burst=50 nodelay;
proxy_pass http://mimir_query_frontend;
proxy_set_header X-Scope-OrgID tenant-main;
proxy_set_header Host $host;
}
}这份配置里有几个细节值得展开。第一,upstream里的keepalive配合proxy_http_version 1.1和清空Connection头,可以让Nginx与后端维持连接池,避免每次写入都重建TCP连接,远程写入的QPS越高收益越明显。第二,proxy_request_buffering off让Nginx不再把请求体完整缓存到本地磁盘,而是边收边转,对压缩后的快照数据尤其重要。第三,租户头在Nginx层统一注入,意味着外部调用方无需感知多租户细节,也避免了租户ID被随意伪造,安全上更可控。
限流配置需要在http块中预先声明,例如:
limit_req_zone $binary_remote_addr zone=query_limit:10m rate=100r/s;
对于查询入口来说,限流几乎是必需的。Mimir的查询前端虽然有并发控制和队列拆分,但一个不怀好意的大范围查询仍然可能拖垮整个查询组件,在Nginx层先挡一道是廉价而有效的保险。
对象存储对接与保留策略
Mimir的数据最终都落在对象存储上,生产环境推荐使用S3或者自建的MinIO。配置写在Mimir的启动参数或配置文件里:
blocks_storage:
backend: s3
bucket_store:
sync_dir: /data/tsdb-sync
s3:
endpoint: minio.internal:9000
access_key_id: YOUR_AK
secret_access_key: YOUR_SK
insecure: false
bucket_name: mimir-blocks
compactor:
data_dir: /data/compactor
retention: 730dretention即保留期,直接决定你能回溯多久的数据。设置成730d表示保留两年,这个时间长度下对象存储的费用依旧可控。需要注意的是,保留期的变更由Compactor在压实数据块时生效,修改后不会立即删除旧数据,要有心理预期。
自建MinIO时,务必开启纠删码模式而非单机模式,并保证Mimir的每个组件都能稳定访问MinIO的endpoint。Nginx同样可以放在MinIO前面做内部入口收敛,但Mimir与对象存储之间走大流量传输,通常建议保持同机房直连,中间不加代理层,减少不必要的性能损耗。
高可用部署与常见踩坑
Mimir官方推荐用mimirtool以monolithic模式加-target=read,write参数拆分读写两组进程部署。小规模场景可以两台机器各跑一个读写实例,Nginx轮询转发即可获得基本的高可用;规模上来之后,再逐步拆出独立的Query Frontend、Store Gateway和Ruler组件。
Prometheus端的远程写入建议这样配置,配合max_shards控制并发:
remote_write:
- url: http://nginx.internal:8080/api/v1/push
queue_config:
max_shards: 30
max_samples_per_send: 2000
batch_send_deadline: 5s
send_exemplars: false实际落地时有几个坑需要提醒。一是查询特别久远的数据时,首查会很慢,因为Store Gateway要从对象存储拉取索引,建议适当调大bucket_store.sync_interval并开启查询结果缓存。二是Grafana数据源里填写Nginx的查询入口地址时,认证方式选择Forward OAuth Identity或者直接在Nginx层注入租户头,否则会收到租户缺失的错误。三是观察到一个经典问题:远程写入突然报429,这通常是Ingestor达到限流阈值,先检查租户级别的写入速率限制,必要时在Mimir配置里调大对应参数,而不是盲目加Nginx的worker数量。
最后,监控这套系统本身也很重要。Mimir自身暴露了完整的指标,建议把它的/metrics同样接入Prometheus,重点盯写入失败率、查询P99延迟和Compactor积压情况,配合Grafana官方提供的Mimir仪表盘,基本可以做到问题早发现早处理。整体而言,Nginx加Mimir的组合部署不复杂,成本可控,是当下搭建监控指标长期存储的稳妥选择。