上一篇 分享链接 返回 返回顶部

多台服务器日志集中检索前,Promtail权限、网络与Loki标签如何确认?

发布人:Minchunlin 发布时间:2026-10-03 11:21 阅读量:2

我们先把现场还原成一条完整链路:每台业务服务器上的 Promtail 读取本机日志,通过网络把日志推送到 Loki,Grafana 再从 Loki 查询和展示。实施前真正需要确认的,不是三个组件能否分别启动,而是 Promtail 运行账户能否遍历并读取目标文件、源服务器能否访问 Loki 的正确 HTTP 地址,以及写入 Loki 的标签是否稳定、唯一且便于检索。

只要这三项通过,集中检索平台通常就具备了可验收的基础条件。反过来,如果文件权限、网络状态或标签设计没有先确认,后续看到“没有日志”“查询不到主机”或“Loki 负载异常”时,很难判断问题究竟出在采集端、传输链路还是查询条件。

先确定这次检查要验证什么

以一组应用日志为例,我们希望在多台服务器上统一采集:

  • /var/log/myapp/app.log
  • /var/log/myapp/error.log

并在 Grafana 中使用类似下面的查询:

{job="app-file", env="prod", service="order-api", host="node-a"}

这条查询能够返回日志,需要同时满足以下条件:

检查项必须确认的内容不满足时的表现
日志文件路径存在,文件会持续写入,轮转后新文件仍符合采集规则Promtail 正常运行但没有新日志
运行权限Promtail 账户可以进入父目录、读取文件,并写入 positions 文件日志中出现 permission denied
网络访问源服务器可以解析 Loki 地址并访问正确端口、路径和认证入口连接超时、拒绝连接、401 或 403
标签设计host、job、service 等标签值稳定且可区分查询范围过大、主机无法区分或标签数量快速增长
时间信息源服务器时间基本一致,日志时间格式和时区明确日志出现在错误时间范围,甚至看起来像“丢失”

这里的检查应先在一台服务器上完成,再复制到其他节点。不要一开始就在所有主机上同时修改配置,否则一个错误的标签或路径可能迅速产生大量无效数据。

第一步:确认 Promtail 实际使用的账户和路径

查看服务账户,不要凭经验判断。 Promtail 可能由 systemd、容器或其他进程管理器启动。以 systemd 为例,先查看服务定义:

systemctl cat promtail
systemctl show promtail -p User -p Group -p ExecStart

如果服务名不是 promtail,先用下面的命令查找实际服务名:

systemctl list-unit-files | grep -i promtail

重点看三项:

  1. User 和 Group 指向哪个账户;
  2. ExecStart 使用的是哪份配置文件;
  3. positions 文件和日志路径是否与当前主机实际目录一致。

有些环境没有显式设置 User,这时不能直接假设 Promtail 一定以 root 运行,应继续查看进程身份:

ps -eo user,group,pid,cmd | grep '[p]romtail'

如果使用容器运行,还要在容器内确认身份和挂载路径。宿主机存在 /var/log/myapp/app.log,并不代表容器内也能看到同一路径。

用目标账户测试目录遍历和文件读取。 Linux 文件读取不只是看文件本身的 r 权限。Promtail 还需要对路径上的每一级目录拥有执行权限,也就是能够“进入”这些目录。我们可以直接以服务账户测试:

以 Promtail 账户验证日志访问权限

namei -l /var/log/myapp/app.log
sudo -u promtail -- test -r /var/log/myapp/app.log && echo "file-readable"
sudo -u promtail -- test -x /var/log && echo "log-dir-traversable"
sudo -u promtail -- find /var/log/myapp -maxdepth 1 -type f -name '*.log' -print

如果服务账户不是 promtail,将命令中的账户替换为前面查到的实际账户。判断时,test -r 失败表示文件本身不可读,或上级目录无法遍历;test -x 失败表示目录权限不足,即使文件显示为可读也无法访问;find 找不到文件,可能是目录权限、文件名匹配规则或路径配置错误。若 namei -l 显示某一级目录没有执行权限,应只调整对应目录的访问策略,不要直接对整个 /var/log 递归放开权限。

如果系统启用了访问控制列表,还要补充查看 ACL:

getfacl /var/log/myapp/app.log
getfacl /var/log/myapp

对于启用 SELinux 的系统,可以确认当前状态和近期拒绝记录:

getenforce
ls -Zd /var/log/myapp /var/log/myapp/app.log
sudo ausearch -m AVC -ts recent | tail -n 20

遇到 SELinux 拒绝时,应按照现有安全策略为目录和服务配置正确的访问上下文,不要为了验证方便直接关闭 SELinux。临时关闭安全控制可能掩盖真正的权限问题,也会扩大影响范围。

检查 positions 文件的写权限。 Promtail 需要记录已经读取到的位置,否则进程重启或主机恢复后,可能出现重复采集或采集位置异常。配置中常见的路径如下:

positions:
  filename: /var/lib/promtail/positions.yaml

检查目录和文件权限:

sudo -u promtail -- test -w /var/lib/promtail && echo "positions-dir-writable"
sudo -u promtail -- test -w /var/lib/promtail/positions.yaml && echo "positions-file-writable"

如果目录不存在,创建目录前应先确认服务账户、所属组和现有目录状态。下面的操作只针对新的 positions 目录,不会修改日志目录,也不会修改日志文件:

sudo install -d -o promtail -g promtail -m 0750 /var/lib/promtail

执行前应确认:

  • promtail 是实际运行账户;
  • 该路径没有保存其他程序的重要文件;
  • 变更范围仅为 /var/lib/promtail;
  • 已记录原有目录的所有者和权限,必要时可恢复;
  • 不使用 chmod -R 777 或对整个日志目录递归改权。

如果配置错误需要回滚,应先停止或重启对应节点上的 Promtail,恢复备份配置,再检查目录权限。不要删除现有 positions 文件来“解决重复日志”,因为这会改变采集起点,影响范围可能覆盖整个日志目录。

第二步:验证轮转、软链接和时间条件

检查 glob 是否覆盖真实文件。 配置中常见写法如下:

__path__: /var/log/myapp/*.log

这只匹配当前目录下符合条件的文件,不一定覆盖子目录、软链接或特殊命名的轮转文件。可以在目标账户下检查:

sudo -u promtail -- find /var/log/myapp -maxdepth 1 -type f -name '*.log' -printf '%f %s bytes\n'

如果业务日志实际写入的是 /data/myapp/logs/,而配置仍指向 /var/log/myapp/,Promtail 不会因为服务正常就自动发现新路径。

检查轮转后的权限和所有者。 日志轮转常见的风险是:当前文件可读,但轮转后由 logrotate 创建的新文件权限不同。可以先进行无修改的配置检查:

sudo logrotate -d /etc/logrotate.conf

重点观察轮转配置中的新文件创建模式、所属用户和用户组、是否使用压缩、是否通过软链接指向实际日志,以及应用是继续写入原文件还是重新打开新文件。

不要直接用强制轮转命令验证生产日志。更稳妥的方式是先在测试目录验证,或安排低风险时间窗口进行一次受控轮转。验收时应至少覆盖“当前文件持续写入”和“轮转后新文件继续采集”两个状态。

如果日志被写入 journald,而不是普通文件,就不能仅靠 static_configs 和 path 读取。此时需要采用对应的 journal 采集配置,并确认服务账户对 journal 数据的读取权限。文件采集和 journal 采集是两条不同路径,不应混用检查结论。

确认时间和时区。 在每台源服务器上查看时间同步状态:

timedatectl status
date '+%F %T %z'

我们不必要求所有服务器显示完全相同的秒数,但至少应明确时区,并保证系统时间处于可接受范围。若 Promtail 解析应用日志中的时间字段,日志格式、时区和时间戳精度也要一致;否则日志可能已经写入 Loki,却落在 Grafana 当前查询时间范围之外。

第三步:从源服务器验证到 Loki 的网络链路

网络检查应从低风险的 DNS 和 HTTP 访问开始,不要一上来修改防火墙规则。

确认域名、端口和入口路径。 假设 Loki 地址是 loki.internal.example,监听端口为 3100,先检查解析:

getent ahosts loki.internal.example

然后从每台部署 Promtail 的服务器访问 Loki 的就绪接口:

curl -sS -D- \
  --connect-timeout 5 \
  --max-time 10 \
  http://loki.internal.example:3100/ready

通常可以这样判断:

  • 返回 HTTP 200,并出现 ready:Loki 当前能够接受就绪检查;
  • Connection refused:目标地址可达,但端口没有服务监听,或监听地址不对;
  • Connection timed out:路由、防火墙、安全组或中间网络策略需要检查;
  • 401 或 403:网络已到达认证入口,但需要补充认证信息;
  • 404:访问路径、端口或前置入口可能不是 Loki 的实际 API;
  • 5xx:入口可达,但 Loki 或其后端状态异常。

/ready 是健康检查接口,不要用对 /loki/api/v1/push 发 GET 请求的结果判断推送是否正常。推送接口主要接受 POST,请求方法不正确时返回 405 并不代表网络故障。

用实际配置中的 URL 做一次检查。 Promtail 的客户端配置至少要明确完整 URL:

clients:
  - url: http://loki.internal.example:3100/loki/api/v1/push

如果环境使用 HTTPS 或认证,还要确认协议、证书信任、认证头和租户信息与 Loki 端设置一致。不要只测试 http://loki.internal.example:3100,然后在配置中填写另一条路径或另一个域名。

源服务器到 Loki 通常只需要允许出站访问,Loki 不需要主动连接回每台源服务器。Grafana 到 Loki 则是另一条查询链路。这样可以分别定位问题:

第三步:从源服务器验证到 Loki 的网络链路配图

  • Promtail 能访问 Loki,但 Grafana 查不到:优先看标签、租户和 Grafana 数据源;
  • Grafana 能访问 Loki,但 Promtail 访问失败:优先看源服务器到 Loki 的网络;
  • 两边都无法访问:先检查 Loki 监听状态和入口配置。

如果需要调整防火墙或安全组,应先备份现有规则,且只放行源服务器网段到 Loki 实际端口。变更前记录原规则,变更后用 curl /ready 和实际采集验证;回滚时恢复原规则,不要用“允许全部来源”的临时规则代替排查。

估算日志流量,避免把网络问题误判成采集问题。 以 20 台服务器、每台平均产生 2 MB/分钟的原始日志为例:

  • 汇总速率:20 × 2 MB/分钟 = 40 MB/分钟;
  • 换算为比特:40 × 8 = 320 Mb/分钟;
  • 换算为秒:320 ÷ 60 ≈ 5.33 Mbps。

这是压缩、协议开销和突发流量之前的原始估算,不是链路实测值。实际验收还应观察业务高峰期的瞬时增长,并确认 Loki 侧的写入限制、认证入口和存储配置不会因为突发流量返回 429 或 5xx。

第四步:设计并验证 Loki 标签

标签应该表达稳定的检索维度。 Loki 标签会参与日志流的组织和索引。一个标签组合的值越多,产生的日志流越多,查询和写入压力也可能随之上升。因此,标签应优先选择数量有限、含义稳定的字段。

标签推荐含义适用条件
host采集节点的稳定名称每台服务器必须唯一,不能所有节点都写成同一个值
envprod、test 等环境环境数量有限,命名统一
service应用或服务名称同一服务在多台主机上保持一致
job一类采集任务例如 app-file、nginx-access
level日志级别只有 info、warn、error 等有限值时适合

不建议把请求 ID、Trace ID、用户 ID、订单号、完整 URL 或带参数的 URL、原始错误信息、精确时间戳,以及每次发布都变化的临时实例标识直接做成标签。这些字段更适合作为日志正文或结构化字段,在查询时使用行过滤或解析条件。比如先用稳定标签缩小范围,再过滤正文:

{job="app-file", env="prod", service="order-api"} |= "timeout"

每台服务器的 host 标签必须不同。 下面是一份适合单台主机的基础配置。部署到其他节点时,至少要修改 host,并确认 path 和 positions 路径真实存在:

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /var/lib/promtail/positions.yaml

clients:
  - url: http://loki.internal.example:3100/loki/api/v1/push

scrape_configs:
  - job_name: app-file
    static_configs:
      - targets:
          - localhost
        labels:
          job: app-file
          env: prod
          service: order-api
          host: node-a
          __path__: /var/log/myapp/*.log

这里的 path 是采集匹配规则,不应被当成普通业务标签使用。host: node-a 只是示例值;在第二台服务器上应改成实际且唯一的主机标识,例如 node-b。

如果日志是 JSON,可以只把有限集合的字段提升为标签,例如日志级别。请求 ID、用户 ID 等高变化字段仍保留在正文中,不要为了方便检索而全部标签化。

先验证配置,再启动服务。 修改配置前先保留副本,并确认只影响当前节点:

sudo cp -a /etc/promtail/config.yml /etc/promtail/config.yml.bak

部分 Promtail 版本支持配置语法检查:

promtail -config.file=/etc/promtail/config.yml -check-syntax

如果当前版本不支持该参数,应先查看帮助信息:

promtail -help | grep -E 'check|config'

语法检查通过后,再重启当前节点上的 Promtail:

sudo systemctl restart promtail
sudo systemctl status promtail --no-pager

回滚时恢复备份文件并再次重启:

sudo cp -a /etc/promtail/config.yml.bak /etc/promtail/config.yml
sudo systemctl restart promtail

这个回滚只针对 Promtail 配置,不会删除 Loki 中已经写入的日志,也不会自动恢复错误标签产生的历史数据。

第五步:做一次端到端验收

配置和网络都通过后,我们按照“源文件—Promtail—Loki—Grafana”的顺序验收,不要只看服务状态为 active。

先看 Promtail 是否真正读取到了文件。

journalctl -u promtail --since "10 minutes ago" --no-pager

重点搜索以下线索:permission denied 时回到目录、文件和 SELinux 权限检查;connection refused、timeout 时回到 DNS、端口和网络策略;出现 401、403 时检查认证和租户信息;没有报错但没有日志时,检查 glob、positions、文件是否持续写入和时间范围。

“Promtail 没有报错”只能说明进程可能正常,并不能证明日志已经到达 Loki。

在 Loki API 中按标签查询。 可以从一台能够访问 Loki 的服务器执行查询。下面的查询会返回最近匹配到的日志流:

LOKI_URL='http://loki.internal.example:3100'

curl -G -sS "${LOKI_URL}/loki/api/v1/query_range" \
  --data-urlencode 'query={job="app-file",env="prod",service="order-api",host="node-a"}' \
  --data-urlencode 'limit=20'

如果返回数据,说明至少完成了从标签写入到查询的闭环。如果返回空结果,按以下顺序检查:

  1. 查询的 host 是否与配置中的值完全一致;
  2. Grafana 或 API 查询的时间范围是否覆盖日志写入时间;
  3. 是否连接到了正确的 Loki 租户;
  4. /loki/api/v1/labels 是否能看到预期标签;
  5. Promtail 是否实际读取了目标文件。

也可以先查看标签名:

curl -sS "${LOKI_URL}/loki/api/v1/labels"

标签名存在但查询不到数据,通常是标签值、时间范围或租户不一致;标签名本身也不存在,则优先检查 Promtail 是否成功推送。

在 Grafana 中验证可用查询。 Grafana Explore 中先使用稳定标签查询:

{job="app-file", env="prod", service="order-api", host="node-a"}

确认结果后,再增加正文过滤:

{job="app-file", env="prod", service="order-api"} |= "error"

最后用另一台服务器执行同样的查询,只改变 host 值。如果 node-a 能查到、node-b 查不到,应比较两台主机的运行账户、日志路径、网络地址和 Promtail 配置,而不是立即修改 Loki 查询语句。

常见失败现象与处理方向

现象优先判断处理方向
服务 active,但没有任何日志文件路径或 glob 不匹配以 Promtail 账户执行 find 和 test -r
报目录权限错误缺少父目录执行权限用 namei -l 逐级检查,不要递归放开权限
能访问 /ready,但推送返回 401/403认证或租户不匹配核对客户端 URL、认证头和租户设置
连接超时网络策略或路由问题从源服务器测试解析、端口和 HTTP 入口
标签 API 没有预期标签没有成功写入或查错租户查看 Promtail 日志和 Loki 接收端日志
日志写入了但 Grafana 查不到标签选择器或时间范围错误先用 /labels 和宽时间范围确认
轮转后日志消失新文件权限或路径不匹配检查轮转创建规则和 path
同一条日志重复出现多个采集器或 positions 异常确认同一文件只有一个采集任务负责

回到这次验收,哪些条件可以作为上线门槛

我们可以把上线前的判断收敛成四个问题:

  1. Promtail 运行账户能否读取每一个目标文件,并能写入 positions 文件?
  2. 源服务器能否访问 Loki 的准确 URL,认证和租户是否与服务端一致?
  3. 每台主机的 host 是否唯一,job、service、env 是否保持统一?
  4. 经过轮转、重启和 Grafana 查询后,日志仍能按主机和服务稳定检索?

四项都通过,再批量部署到其他服务器,问题范围会明显收窄。需要特别注意的是,集中采集只能处理 Promtail 实际能够读取到的日志;历史文件是否补采、压缩轮转文件是否纳入范围、journal 日志是否单独配置,都必须在本次验收中明确。标签也不应随着临时排障不断增加,而应保留少量稳定维度,把高变化信息放在日志正文中。这样搭建出的 Promtail、Loki、Grafana 平台,才更适合长期进行跨服务器集中检索。

目录结构
全文