Loki单点故障时,Promtail与Grafana日志平台如何切换并恢复数据?
某台 Loki 主机失联后,Grafana 可能报查询错误,也可能仍能打开但看不到最新日志;Promtail 则可能持续采集、暂存,或因发送失败而重试。处置时先确认故障发生在采集端、写入端还是查询端,再决定切换入口、恢复副本或补采日志。单纯把 Grafana 的数据源改到另一台 Loki,并不能让尚未复制的日志自动出现。
现场排查建议按这个顺序推进:先检查 Grafana 到 Loki 的访问,再检查 Loki 的就绪状态和副本,随后确认 Promtail 是否还在采集与发送,最后核对故障期间的日志缺口和恢复后的重复情况。若当前只有一台 Loki,首要目标是尽快恢复服务;要降低下一次故障的影响,则需要把 Loki 写入和存储设计成高可用,并为日志源保留可重放的文件。
先判断故障影响在哪一段
日志链路可以拆成三段:服务器上的 Promtail 读取文件并发送日志;Loki 接收、复制和存储日志;Grafana 通过 Loki 数据源查询。不同位置故障,表象相似,处置方法却不同。

| 观察结果 | 优先怀疑 | 下一步检查 |
|---|---|---|
| Grafana 页面无法打开或数据源测试失败 | Grafana、数据源地址、网络连通性 | 检查 Grafana 服务和到 Loki 地址的连接 |
| Grafana 可打开,但查询报错或超时 | Loki 不就绪、查询组件异常、存储不可用 | 查看 Loki 就绪接口、服务日志和组件指标 |
| 旧日志可查,新日志不再出现 | Promtail 发送失败,或 Loki 写入链路异常 | 检查 Promtail 日志、Loki 接收端错误和最近时间范围的查询 |
| Loki 与 Grafana 正常,只有部分主机缺日志 | 对应主机的 Promtail、日志路径或文件轮转 | 检查采集配置、文件权限、positions 文件和日志文件是否仍存在 |
| 故障后出现重复日志或时间段空洞 | 重放位置不一致、日志源已轮转删除,或复制未完成 | 对比故障时间、各副本状态和源文件保留范围 |
排查开始前记录故障时间、受影响的主机、Grafana 数据源地址,以及最后一条可查日志的时间。若条件允许,先保存 Loki、Promtail 和 Grafana 的相关日志及监控数据;不要一开始就删除 Loki 数据目录、positions 文件或对象存储中的块。这些操作可能扩大数据缺口,也会让后续难以判断日志究竟是未采集、未写入还是暂时不可查询。
按优先级检查:由入口到日志源
以下命令适用于常见 Linux systemd 环境。服务名和配置路径可能因安装方式而异,先用 systemctl list-units 或部署清单确认实际名称;涉及重启前,应确认配置已备份并了解它影响的实例。
1. 检查 Grafana 到 Loki 的入口
在 Grafana 页面检查 Loki 数据源的地址与连接测试结果。若数据源配置指向负载均衡地址或 DNS 名称,先从 Grafana 所在主机测试连通性:
curl -fsS --max-time 5 http://loki.example.internal:3100/ready
/ready 返回成功,通常表示该 Loki 实例已达到可接收请求的状态;连接超时、拒绝连接或解析失败,则分别指向网络路径、服务监听或名称解析问题。此检查只说明该地址当前可访问,不代表日志副本完整,也不代表查询覆盖了故障期间的数据。
如果 Grafana 连接的是单台 Loki 主机,且该主机已故障,可将数据源切换到已验证可用的备用入口。但备用入口必须连接到包含目标日志的同一套 Loki 集群或共享存储;若只是另一台独立 Loki,它只能查询自己接收过的日志。修改数据源前记录原地址和认证配置,切换后执行数据源测试并查询一条已知日志;验证失败时恢复原配置,避免把入口变更误当成数据恢复。
2. 检查 Loki 是否就绪、是否仍有写入能力
在 Loki 主机上检查服务状态和最近日志:
sudo systemctl status loki --no-pager
sudo journalctl -u loki --since "30 minutes ago" --no-pager
如果使用容器或编排部署,应查看对应实例的状态和日志,不要直接照搬 systemd 命令。重点留意存储访问错误、磁盘空间不足、组件无法加入 ring、写入拒绝、查询超时等信息。
可进一步查询实例指标:
curl -fsS http://127.0.0.1:3100/metrics \
| grep -E 'loki_.*(ingester|request|discard|error|flush)'
指标名称会随 Loki 版本和部署模式变化,匹配不到某个指标不应直接判断服务正常或异常;先查看该版本实际暴露的指标。若实例未就绪,先修复导致未就绪的原因,例如存储不可达或 ring 状态异常,再考虑切换流量。盲目重启可能短暂恢复接口,却不能补回尚未落盘或未复制的数据。
在分布式部署中,还要检查写入请求是否仍能到达足够数量的 ingester,以及成员状态是否稳定。启用副本不等于所有时刻都能容忍任意数量的实例故障:可写能力取决于副本数、写入仲裁和当时健康的成员。具体阈值应以正在使用的 Loki 版本及配置为准,不要在未核对配置时假设“有三副本就一定能写”。
3. 检查 Promtail 是否采集并发送
在受影响的日志服务器上查看 Promtail 状态与日志:
sudo systemctl status promtail --no-pager
sudo journalctl -u promtail --since "30 minutes ago" --no-pager
若 Promtail 暴露了本地 HTTP 端口,可按实际配置检查就绪状态和指标:
curl -fsS --max-time 5 http://127.0.0.1:9080/ready
curl -fsS http://127.0.0.1:9080/metrics \
| grep -E 'promtail_.*(read|sent|entry|error|retry)'
检查日志中是否有目标地址连接失败、超时、拒绝写入或配置加载错误;再确认采集路径存在、服务账号可读、日志文件仍在增长。Promtail 显示运行中只代表进程存活,不代表日志已成功送达 Loki。
Promtail 的 positions 文件记录采集进度,不是日志内容的备份。应确认它位于持久化磁盘、可被当前服务账号读写,并且每台采集主机使用独立文件。多个 Promtail 实例共用同一个 positions 文件,可能造成进度相互覆盖。也不要为了“重新采集”而直接清空该文件:从旧位置重读会带来重复日志;从文件末尾开始则可能跳过尚未送达的内容。
4. 查明是“没采集”还是“暂时查不到”
在 Grafana 中先把时间范围扩大到故障前后,并按主机标签查询。例如:
{host="app-01"}
如果常用标签名不是 host,应替换为实际标签。查询结果没有新日志时,再检查对应 Promtail 的发送错误和 Loki 写入端日志。若 Promtail 已经成功发送、Loki 也返回接收成功,但查询仍不可见,继续检查 Loki 的查询路径、时间范围、标签是否变化,以及数据块是否仍在刷新或读取。
需要区分三种情况:日志仍留在源文件中但未送达,可以在修复后补采;日志已被 Loki 接收但查询组件或存储暂时不可用,恢复服务后可能重新可查;日志文件已轮转删除且未送达,同时 Loki 也没有副本,则通常无法从这条链路恢复。Promtail 的进度文件不能替代源日志备份。
单点切换和高可用设计的边界
单实例 Loki 的切换方式通常是恢复原实例,或把 Grafana 指向已准备好的备用实例。若备用实例没有接收相同日志,也没有访问同一份有效数据,它只是“能打开的空平台”,不能承担数据恢复。切换前应确认备用端的数据范围、标签和数据源地址,并保留原实例以便恢复或取证。
要让故障切换不仅恢复查询入口,也尽量保住日志,应同时考虑写入复制、日志存储和采集端缓冲:

- Loki 写入层:分布式部署中配置多个 ingester,并按版本要求配置副本数和 ring。常见设计会将副本数设为 3,但这是配置示例,不是对任意故障都可写的保证。需要结合写入仲裁、节点数量和故障域核对容错能力。
- 日志存储:采用 Loki 支持的对象存储等共享持久化后端,并做好后端自身的冗余与备份。多个 Loki 实例共用对象存储,有助于避免数据只落在单台主机,但不能替代 ingester 复制、元数据可用性设计或存储侧保护。
- 查询与写入入口:Grafana 和 Promtail 分别连接稳定的服务地址,例如经过健康检查的内部负载均衡地址。健康检查应以实例就绪为依据,而不只是 TCP 端口开放。切换时确保新入口指向同一集群,避免把日志写入两个彼此隔离的数据集。
- 采集端保留:源日志文件应至少保留覆盖预期故障恢复时间的窗口。Promtail 发送失败时会重试,但不能把它当作长期消息队列;重试期间日志文件若被轮转并删除,尚未送达的内容就可能丢失。
高可用与数据一致性之间需要明确取舍。复制可降低单个 ingester 故障造成的数据缺口,但故障时能否继续写入取决于可用副本和仲裁条件;对象存储中已有的数据通常也不能证明故障瞬间的所有新日志都已持久化。若要求明确的恢复点目标(RPO),应通过故障演练测量“最多丢失多长时间的日志”;若要求恢复时间目标(RTO),则测量从告警到 Grafana 能重新查询的耗时。目标应基于业务需要设定,而不是仅凭副本数推断。
恢复步骤:先止损,再补齐和验证
1. 固定故障现场并确认影响范围
记录故障开始和结束时间、异常实例、Promtail 发送错误、Loki 写入状态,以及对象存储或本地磁盘是否可用。确认哪些主机仍保留故障时间段的原始日志。若 Loki 数据目录或对象存储出现异常,先按部署的备份和恢复流程保护现有数据;不要把一份不完整的数据目录直接覆盖到正在运行的实例上。
2. 恢复或切换 Loki 服务
若只是单实例故障,优先恢复原实例并确认 /ready 成功,再恢复 Grafana 查询。若切换到备用入口,先验证它连接的是目标集群且能够查到故障前的已知日志;确认后再调整 Grafana 数据源和 Promtail 目标。入口变更应保留原配置,切换失败时可回滚至原地址或原服务。
分布式集群中,先让成员和存储状态稳定,再逐步恢复写入流量。不要同时重启所有 Loki 实例,也不要在尚未确认数据目录用途时清理 WAL、索引或块文件。此类操作可能影响尚未完成刷写的数据,回滚应依赖事先保留的配置和符合该版本要求的备份,而不是临时复制其他节点的数据目录。
3. 检查 Promtail 重试和源文件保留
Loki 恢复后观察 Promtail 是否停止报错、发送指标是否回升,并检查源日志文件是否覆盖故障时间段。若 Promtail 自动从原进度继续发送,先让队列和重试逐步消化,避免同时手动重放大量文件造成 Loki 写入突增。
只有确认源文件还在、当前采集位置和目标 Loki 都正确,才考虑手动补采。补采前备份 Promtail 配置和 positions 文件,并记录原始位置;应先在一台主机、小时间段验证结果,再扩大范围。重置进度可能生成重复日志,也可能因文件轮转、压缩或时间戳解析变化而漏采。回滚时恢复备份的配置和位置文件,并重新启动对应 Promtail;不要在多台机器上共用一份位置文件。
4. 用已知日志验证恢复效果
选择一个故障前、故障期间和恢复后的时间点,分别在 Grafana 查询对应主机与业务标签。验证至少覆盖以下内容:
- Grafana 数据源测试成功,Loki 查询能返回故障前已知日志。
- Promtail 不再持续报发送失败,受影响主机的最新日志时间逐步追上当前时间。
- 故障期间的日志要么能从源文件补采,要么已确认其在 Loki 中可查;不能只凭服务恢复就认定数据完整。
- 检查重复日志、时间戳顺序和标签变化。重放可能产生重复,标签配置变化则可能让日志落入不同的查询结果。
- 检查 Loki 的磁盘或对象存储、ingester 和查询组件状态,确认恢复后没有持续增长的错误或积压。
可用简单查询观察某主机最近日志是否更新:
{host="app-01"} |= "ERROR"
若查询为空,不一定表示日志丢失:也可能是该时间段没有匹配内容、标签名称不一致,或日志级别文本不同。应先用更宽的标签选择器核对,再逐步添加过滤条件。
复盘时容易漏掉的几项
首先核对日志轮转策略。若保留时间短于 Loki 故障恢复时间,Promtail 即使之后恢复也没有完整源文件可补。其次检查 Promtail 的 positions 文件是否持久化、是否被清理任务误删,以及不同主机是否错误共用位置文件。再次确认 Grafana 和 Promtail 的备用入口确实指向同一套 Loki 数据,而非一台没有历史数据的独立实例。
最后,应定期做受控的故障演练:分别验证单个 Loki 实例不可用时的查询与写入表现、Promtail 暂时无法连接时源文件能保留多久、恢复后日志能否追上,以及切换入口后是否仍能查到故障前的数据。只有把这些结果与设定的 RPO、RTO 对照,才能判断当前方案是在“服务能切换”,还是同时具备可验证的数据恢复能力。