管理和调试错误
“Loki: 网关错误。502”
当 Grafana Loki 作为数据源添加到 Grafana 中时,可能会出现此错误,表明 Grafana 无法连接到 Loki。可能的原因有很多:
- 如果 Loki 是使用 Docker 部署的,并且 Grafana 和 Loki 未运行在同一节点上,请检查您的防火墙以确保节点可以连接。
- 如果 Loki 是使用 Kubernetes 部署的
- 如果 Grafana 和 Loki 位于同一命名空间中,请将 Loki URL 设置为
http://$LOKI_SERVICE_NAME:$LOKI_PORT
- 否则,请将 Loki URL 设置为
http://$LOKI_SERVICE_NAME.$LOKI_NAMESPACE:$LOKI_PORT
- 如果 Grafana 和 Loki 位于同一命名空间中,请将 Loki URL 设置为
“数据源已连接,但未接收到任何标签。请验证 Loki 和 Promtail 配置是否正确。”
当 Loki 作为数据源添加到 Grafana 中时,可能会出现此错误,表明 Grafana 已连接到 Loki,但 Loki 尚未从 Promtail 收到任何日志。可能的原因有很多:
- Promtail 正在运行并收集日志,但无法连接到 Loki 发送日志。检查 Promtail 的输出。
- Promtail 在 Loki 准备就绪之前就开始向 Loki 发送日志。这可能发生在测试环境中,Promtail 已经读取并发送了所有日志。您可以这样做:
- 在 Loki 之后启动 Promtail,例如 60 秒后。
- 要强制 Promtail 重新发送日志消息,请删除 positions 文件(默认位置
/tmp/positions.yaml
)。
- 由于配置问题,Promtail 正在忽略目标,并且没有读取任何日志。
- 可以通过在 Promtail 中开启调试日志,查找
dropping target, no labels
或ignoring target
消息来检测此问题。
- 可以通过在 Promtail 中开启调试日志,查找
- Promtail 找不到您的日志文件位置。检查
scrape_configs
是否包含用于在您的工作节点上查找日志的有效路径设置。 - 您的 pod 运行时的标签与 Promtail 配置读取的标签不同。检查
scrape_configs
进行验证。
Loki 超时错误
Loki 504 错误、上下文取消和处理请求错误可能有许多可能的原因。
检查 Loki 配置
- Loki 配置
limits_config.query_timeout
server.http_server_read_timeout
server.http_server_write_timeout
server.http_server_idle_timeout
- Loki 配置
检查您的 Loki 部署。如果您在 Loki 前面(即 Loki 和 Grafana 之间)有一个反向代理,请检查任何配置的超时设置,例如 NGINX 代理读取超时。
其他原因。要确定问题是与 Loki 本身还是与 Grafana 或客户端错误等其他系统有关,请尝试尽可能直接地运行 LogCLI 查询。例如,如果在虚拟机上运行,请在本地机器上运行查询。如果在 Kubernetes 集群中运行,则端口转发 Loki HTTP 端口,然后尝试在那里运行查询。如果您没有遇到超时,则考虑以下原因:
- 调整 Grafana dataproxy 超时。为 Grafana 配置足够大的 dataproxy 超时。
- 检查客户端与 Grafana 之间的反向代理或负载均衡器的超时设置。对 Grafana 的查询是从您的本地浏览器发起的,Grafana 充当代理(dataproxy)。因此,必须配置从您的客户端到 Grafana 的连接超时。
缓存生成错误
Loki 缓存生成编号错误 (Loki >= 2.6)
加载缓存生成编号错误
症状
- Loki 在日志中暴露出错误,消息为
msg="error loading cache generation numbers" err="unexpected status code: 403"
或msg="error getting cache gen numbers from the store"
- Loki 在日志中暴露出错误,消息为
调查
检查
/metrics
上的指标loki_delete_cache_gen_load_failures_total
,这是问题发生的指示器。如果该值大于 1,则表示该组件存在问题。尝试对路由发送 Http GET 请求:/loki/api/v1/cache/generation_numbers
- 如果响应为
"deletion is not available for this tenant"
,则表示该租户未启用删除 API。要启用此 API,请通过配置设置将该租户的allow_deletes
设置为true
。查看更多 删除文档
- 如果响应为
目标故障排除
Promtail 提供了两个可用于了解其服务发现工作原理的网页。
服务发现页面 (/service-discovery
) 显示所有已发现的目标及其重新打标签前后的标签,以及目标被丢弃的原因。
目标页面 (/targets
) 仅显示正在活跃抓取的目标及其相应的标签、文件和位置。
在 Kubernetes 上,您可以通过本地端口转发 Promtail 端口(使用 Helm 时为 9080
或 3101
)访问这两个页面
$ kubectl port-forward loki-promtail-jrfg7 9080
然后,在 Web 浏览器中访问 https://:9080/service-discovery
调试输出
Loki 和 Promtail 都支持通过添加命令行选项来设置日志级别标志
loki -log.level=debug
promtail -log.level=debug
创建目标失败,ioutil.ReadDir: readdirent: not a directory
Promtail 配置中包含一个 __path__
条目指向一个 Promtail 找不到的目录。
连接到 Promtail Pod 进行故障排除
首先检查上面的目标故障排除部分。如果仍无法解答您的问题,您可以连接到 Promtail Pod 进行进一步调查。
如果您的集群中以 DaemonSet 方式运行 Promtail,则每个节点上都会有一个 Promtail Pod,因此请先确定您需要调试哪个 Promtail。
$ kubectl get pods --all-namespaces -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
...
nginx-7b6fb56fb8-cw2cm 1/1 Running 0 41d 10.56.4.12 node-ckgc <none>
...
promtail-bth9q 1/1 Running 0 3h 10.56.4.217 node-ckgc <none>
该输出已截断,仅突出显示我们关心的两个 pod,您可以使用 -o wide
标志查看它们正在运行的 NODE。
您需要将您关注的 Pod(在此示例中为 NGINX)的节点与在同一节点上运行的 Promtail 相匹配。
要进行调试,您可以连接到 Promtail Pod
kubectl exec -it promtail-bth9q -- /bin/sh
连接后,验证 /etc/promtail/promtail.yml
中的配置是否包含您期望的内容。
还要检查 /var/log/positions.yaml
(通过 Helm 部署时为 /run/promtail/positions.yaml
或为 positions.file
指定的任何值),并确保 Promtail 正在跟踪您期望的日志。
您可以通过查看 /var/log/containers
中的 Promtail 容器日志来检查 Promtail 日志。
为 Loki 启用跟踪
通过将环境变量 JAEGER_AGENT_HOST
设置为 Jaeger 运行的主机名和端口,可以使用 Jaeger 对 Loki 进行跟踪。
如果您使用 Helm 部署,请使用以下命令
$ helm upgrade --install loki loki/loki --set "loki.tracing.enabled=true"
--set "read.extraEnv[0].name=JAEGER_AGENT_HOST" --set "read.extraEnv[0].value=<JAEGER_AGENT_HOST>"
--set "write.extraEnv[0].name=JAEGER_AGENT_HOST" --set "write.extraEnv[0].value=<JAEGER_AGENT_HOST>"
--set "backend.extraEnv[0].name=JAEGER_AGENT_HOST" --set "backend.extraEnv[0].value=<JAEGER_AGENT_HOST>"
--set "gateway.extraEnv[0].name=JAEGER_AGENT_HOST" --set "gateway.extraEnv[0].value=<JAEGER_AGENT_HOST>"
在 Istio Sidecar 中运行 Loki
Istio sidecar 与 Pod 一起运行。它拦截进出 Pod 的所有流量。当 Pod 尝试使用给定协议与另一个 Pod 通信时,Istio 使用 协议选择 来检查目标服务。此机制使用端口名称约定(例如,http-my-port
或 grpc-my-port
)来确定如何处理此出站流量。然后,Istio 可以执行授权和智能路由等操作。
当一个 Pod 使用主机名与另一个 Pod 通信时,这工作正常。但是,Istio 不允许 Pod 使用 IP 地址与另一个 Pod 通信,除非流量类型是 tcp
。
Loki 内部使用 DNS 解析不同组件的 IP 地址。Loki 尝试向这些 Pod 的 IP 地址发送请求。Loki 服务定义了 grpc
(:9095/:9096) 端口,因此 Istio 会认为这是 grpc
流量。它将不允许 Loki 组件使用 IP 地址相互访问。因此,流量将失败,并且环将保持不健康状态。
此问题的解决方案是向 Loki 组件的所有 grpc
(:9095) 和 grpclb
(:9096) 服务端口添加 appProtocol: tcp
。这会覆盖 Istio 的协议选择,并强制 Istio 将此流量视为原始 tcp
,从而允许 Pod 使用原始 IP 地址进行通信。
这会禁用 Istio 流量拦截机制的一部分,但仍然启用 mTLS。这允许 Pod 通过 grpc 使用 IP 地址相互通信。