K8s Alloy 采集 Pod 控制台日志

1. 目标架构

::: warning Readme

Loki 的集群在k8s集群外部,不在k8s 内部,关于 Loki 的部署可参考:https://opforge.srebro.cn/project/log/loki/01.html

:::

K8s 集群内部署 Alloy DaemonSet,每个节点一个 Alloy Pod。Alloy 通过 Kubernetes API 采集本节点 Pod 的 stdout/stderr 控制台日志,然后推送到集群外现有 Loki Gateway。

整体架构图

2. 部署前确认

确认 K8s 节点或 Pod 网络能访问你的 Loki Gateway:

bash 复制代码
kubectl run curl-test -n default --rm -it --image=curlimages/curl -- \
  curl -v http://192.168.1.100:3100/ready

如果 Loki Gateway 有防火墙或安全组,需要放通 K8s Pod 网段或 Node 网段到 3100 端口。

3. 当前 YAML 里的关键配置

alloy-k8s-loki-logs.yaml文件在,https://cnb.cool/sre-demo/k8s-demo/-/blob/main/yaml/v1.32/loki/alloy-k8s-loki-logs.yaml

当前 alloy-k8s-loki-logs.yaml 已经按本环境配置好:

text 复制代码
Loki Gateway: 192.168.1.100:3100
Loki push URL: http://192.168.1.100:3100/loki/api/v1/push
Tenant: tenant1
Cluster label: xxx-k8s

对应 Alloy 配置:

alloy 复制代码
loki.write "default" {
  endpoint {
    url       = "http://192.168.1.100:3100/loki/api/v1/push"
    tenant_id = "tenant1"
  }
}

集群标签配置:

alloy 复制代码
stage.static_labels {
  values = {
    cluster  = "xxx-k8s",
    platform = "kubernetes",
    agent    = "alloy",
  }
}

说明:

  • cluster="xxx-k8s" 用来区分这批日志来自当前 K8s 集群。
  • tenant_id="tenant1" 需要和 Grafana Loki 数据源里的 X-Scope-OrgID 保持一致。
  • 如果未来接入多个 K8s 集群,可以给不同集群设置不同 cluster 标签,例如 prod-k8stest-k8s

4. 部署 Alloy

执行:

bash 复制代码
kubectl apply -f alloy-k8s-loki-logs.yaml

查看 DaemonSet:

bash 复制代码
kubectl -n monitoring get ds alloy
kubectl -n monitoring get pod -l app.kubernetes.io/name=alloy -o wide

每个 K8s 节点应该有一个 Alloy Pod。

5. 查看 Alloy 运行日志

bash 复制代码
kubectl -n monitoring logs -l app.kubernetes.io/name=alloy --tail=100 -f

如果配置正确,通常能看到 discovery、tail pod logs、push Loki 的相关日志。

6. 验证 Loki 是否收到日志

在 Grafana Explore 里选择 Loki 数据源,查询:

logql 复制代码
{cluster="xxx-k8s", platform="kubernetes"}

按命名空间查询:

logql 复制代码
{cluster="xxx-k8s", namespace="default"}

按 Java 微服务查询:

logql 复制代码
{cluster="xxx-k8s", app="your-java-service"}

按日志级别查询:

logql 复制代码
{cluster="xxx-k8s", level="ERROR"}

按命名空间、服务和日志级别组合查询:

logql 复制代码
{cluster="xxx-k8s", namespace="xxx", app="srebro-uc", level="INFO"}

如果你的 Pod 没有 appapp.kubernetes.io/name 标签,可以先用:

logql 复制代码
{cluster="xxx-k8s"} |~ "关键字"

8. level 标签说明

K8s 采集的是 Pod 控制台输出,没有这种文件目录结构,所以 level 需要从日志正文里解析。当前 YAML 在 loki.process "pod_logs" 里配置了:

alloy 复制代码
stage.regex {
  expression         = "(?i)\\b(?P<level>TRACE|DEBUG|INFO|WARN|WARNING|ERROR|FATAL)\\b"
  labels_from_groups = true
}

只要 Java 控制台日志里出现以下关键字,就会生成对应的 Loki 标签:

text 复制代码
TRACE
DEBUG
INFO
WARN
WARNING
ERROR
FATAL

例如日志正文:

text 复制代码
2026-06-11 16:30:00.123 INFO  [srebro-uc] user login success
2026-06-11 16:31:00.456 ERROR [srebro-uc] call remote service failed

会被打上:

text 复制代码
level="INFO"
level="ERROR"

注意:level 标签只会对修改 Alloy 配置后新采集的日志生效,历史日志不会自动补标签。

9. app 标签说明

传统部署里,app 是从日志文件路径第一级目录提取的:

alloy 复制代码
rule {
  source_labels = ["__path__"]
  regex         = "/home/application/logs/([^/]+)/[^/]+/.*\\.log"
  target_label  = "app"
  replacement   = "$1"
}

K8s 采集 Pod 控制台日志时没有这种日志目录结构,所以当前配置改为从 Deployment 名称提取 app 标签。

Deployment 创建 Pod 的链路通常是:

text 复制代码
Deployment: srebro-uc
  -> ReplicaSet: srebro-uc-6dccfd4db
  -> Pod: srebro-uc-6dccfd4db-l2zsv

当前 Alloy 配置使用 Pod 的 controller 元数据,把 ReplicaSet 名里的最后一段 hash 去掉:

alloy 复制代码
rule {
  source_labels = ["__meta_kubernetes_pod_controller_kind", "__meta_kubernetes_pod_controller_name"]
  regex         = "ReplicaSet;(.+)-[a-f0-9]{8,10}"
  action        = "replace"
  target_label  = "app"
  separator     = ";"
  replacement   = "$1"
}

这样最终会得到:

text 复制代码
app="srebro-uc"

同时保留了 workload 标签,用于查看原始 controller 名称:

text 复制代码
workload="srebro-uc-6dccfd4db"

如果未来有非 Deployment 类型的工作负载,例如 StatefulSet 或 Job,可以按同样思路增加对应规则。

可选:仍然建议给 Java 微服务 Deployment 增加标准标签,方便 K8s 资源管理和其他监控系统识别:

yaml 复制代码
metadata:
  labels:
    app.kubernetes.io/name: order-service
    app.kubernetes.io/part-of: business-platform
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/name: order-service
        app.kubernetes.io/part-of: business-platform

这样 Grafana 查询会更稳定:

logql 复制代码
{cluster="xxx-k8s", namespace="prod", app="order-service"}

10. 排除不想采集的 Pod

当前 YAML 支持通过注解排除采集。给 Pod template 加:

yaml 复制代码
metadata:
  annotations:
    loki.grafana.com/scrape: "false"

例如某个 Deployment:

yaml 复制代码
spec:
  template:
    metadata:
      annotations:
        loki.grafana.com/scrape: "false"
相关推荐
写代码的强哥13 小时前
云原生数据库与传统数据库相比“新”在哪里
数据库·云原生·架构
还有你Y14 小时前
读懂微服务
微服务·云原生·架构
沉迷学习 日益消瘦14 小时前
04-配置与扩缩
kubernetes
糟糕喔16 小时前
k8s-云原生cicd
云原生·容器·kubernetes
阿里云云原生16 小时前
亚太唯一!阿里云跻身 Gartner 可观测魔力象限“挑战者”象限
云原生
小二·16 小时前
云原生2026:Kubernetes + Wasm + Serverless 深度实战
云原生·kubernetes·wasm
啊啊啊迈 旋棍16 小时前
终端后端【重要,操作实用】
云原生·eureka
ruofu3317 小时前
下载nvidia_*_cu13的指令(更新:利用torch 版本拉取相关依赖)
docker·容器
独孤--蝴蝶17 小时前
Docker容器进阶(一)
运维·docker·容器
海兰17 小时前
基于 ES|QL 的 Kubernetes 监控工具箱:使用 ES|QL 进行 Kubernetes 监控,从内存压力到错误日志
大数据·elasticsearch·kubernetes