Kubernetes Loki 日志收集系统部署文档 (读写分离模式 + Ceph S3 + Nginx 日志分离)

Kubernetes Loki 日志收集系统部署文档 (读写分离模式 + Ceph S3 + Nginx 日志分离)

本文档将指导你在自建的 Kubernetes 集群中,针对每天 TB 级别的海量日志场景,使用 Helm 部署 Loki 的读写分离模式(Simple Scalable)和 Promtail 日志收集系统。

其核心特点为:

  1. 高吞吐与高可用:采用读写分离架构(Write/Read/Backend),可水平扩展,轻松应对每天 1TB 以上的日志写入和并行查询。
  2. 对象存储:完全依赖 Ceph 提供的 S3 对象存储(RGW)来存储索引和日志块,摆脱本地磁盘容量和并发写入的限制。
  3. 日志分离 :文档支持通过多租户隔离 (Tenant)分类标签 (Label) 两种方式,将 Nginx 日志与其他业务日志进行物理流隔离或逻辑分类,便于独立查询和告警。

1. 环境准备与 Ceph S3 (RGW) 配置

Loki 的读写分离模式强依赖对象存储。既然你已经部署了 Rook-Ceph,我们需要使用 Ceph 的 RADOS Gateway (RGW) 来提供 S3 服务,并为 Loki 创建专属的 Bucket 和账号。

1.1 确认并获取 Ceph S3 Endpoint

如果你的 Rook-Ceph 已经部署了对象存储(CephObjectStore),可以通过以下命令查看内部访问地址:

bash 复制代码
# 获取 Rook-Ceph 命名空间下的 svc 列表
kubectl get svc -n rook-ceph | grep rgw

根据你的环境输出,Endpoint 为:

http://rook-ceph-rgw-my-store.rook-ceph.svc.cluster.local:8080

(注:如果尚未部署 CephObjectStore,你需要先应用包含 CephObjectStore 的 YAML 文件来启动 RGW 服务。)

1.2 创建安全保留策略的 StorageClass (Retain)

为了防止未来误删 Loki 的 ObjectBucketClaim (OBC) 导致 Ceph 底层的日志数据被一并销毁,我们强烈建议创建一个 reclaimPolicy: Retain(保留策略)的 StorageClass。

首先,确认你的 CephObjectStore 的名称:

bash 复制代码
kubectl get CephObjectStore -n rook-ceph

(假设输出的 NAME 为 my-store)

创建 sc-retain-bucket.yaml 文件:

yaml 复制代码
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: rook-ceph-retain-bucket
provisioner: rook-ceph.ceph.rook.io/bucket # 必须匹配 Rook-Ceph 的 provisioner
reclaimPolicy: Retain # 关键配置:删除 OBC 时保留底层 Bucket 和数据
parameters:
  objectStoreName: my-store # 替换为你的 CephObjectStore 名称
  objectStoreNamespace: rook-ceph

应用该配置:

bash 复制代码
kubectl apply -f sc-retain-bucket.yaml

1.3 创建 Loki 专属 Bucket 与凭证 (使用 OBC)

现在,我们可以使用刚刚创建的安全 StorageClass 来为 Loki 自动配置专属的 Bucket 和独立的 AK/SK 凭证。

创建一个专门的 namespace,并提交 OBC 请求 loki-obc.yaml

yaml 复制代码
apiVersion: v1
kind: Namespace
metadata:
  name: loki-stack
---
apiVersion: objectbucket.io/v1alpha1
kind: ObjectBucketClaim
metadata:
  name: loki-data-claim
  namespace: loki-stack
spec:
  bucketName: loki-data # 明确指定具体的 Bucket 名称,不使用随机后缀
  storageClassName: rook-ceph-retain-bucket # 使用我们刚创建的安全 SC

应用该配置:

bash 复制代码
kubectl apply -f loki-obc.yaml

获取自动生成的专属配置:

Rook-Ceph 会在 loki-stack 命名空间下自动创建一个 ConfigMap(包含 Bucket 名称和 Endpoint)和一个 Secret(包含专属的 AK/SK)。

bash 复制代码
# 1. 获取专属 Access Key (AK)
kubectl get secret loki-data-claim -n loki-stack -o jsonpath='{.data.AWS_ACCESS_KEY_ID}' | base64 --decode && echo

# 2. 获取专属 Secret Key (SK)
kubectl get secret loki-data-claim -n loki-stack -o jsonpath='{.data.AWS_SECRET_ACCESS_KEY}' | base64 --decode && echo

至此,你已经获得了 Loki 所需的 Endpoint、专属 AK 以及专属 SK。Bucket 名称为你指定的 loki-data。请妥善保存这些值,稍后将它们填入 Loki 的配置中。

1.4 安装基础工具

  1. 安装 Helm:确保集群管理节点已安装 Helm v3。

  2. 添加 Grafana Helm 仓库

    bash 复制代码
    helm repo add grafana https://grafana.github.io/helm-charts
    helm repo update

2. 部署 Loki (Simple Scalable 读写分离模式)

对于 TB 级日志,我们必须使用读写分离架构。这会将 Loki 拆分为三种角色的 Pod:

  • Write: 负责接收日志并写入 S3(可横向扩容应对写入高峰)。
  • Read: 负责从 S3 读取数据响应查询请求(支持分布式拆分查询)。
  • Backend: 负责后台任务(如压缩、过期数据清理等)。

2.1 创建 Loki 配置文件

创建 values-loki-scalable.yaml 文件,请务必将 S3 的连接信息替换为你实际的 Ceph RGW 配置

yaml 复制代码
deploymentMode: SimpleScalable

loki:
  # 是否开启多租户 (开启后需配置 X-Scope-OrgID Header,关闭则混租)
  auth_enabled: true
  
  commonConfig:
    replication_factor: 1 # 因为我们将 write/read 副本数降为了 1,这里必须同步设置为 1,否则会导致 500 报错
  
  # 配置统一的对象存储 (指向 Ceph S3)
  storage:
    bucketNames:
      chunks: loki-data  # 替换为你的 Bucket 名称
      ruler: loki-data
      admin: loki-data
    type: s3
    s3:
      endpoint: http://rook-ceph-rgw-my-store.rook-ceph.svc.cluster.local:8080 # 替换为实际的 Ceph RGW 地址 (注意必须保留 http:// 前缀)
      region: default # Ceph 默认通常是 default 或者 us-east-1
      accessKeyId: HR4UJM3NUCIBL7V1S4PZ       # 替换为你的 AK
      secretAccessKey: VBAOrEod0oIooXaGyDAlgvE5wYWELd0duWguaK2A   # 替换为你的 SK
      s3ForcePathStyle: true                     # Ceph S3 必须开启路径模式
      insecure: true                             # 如果没有配置 https 则设为 true

  # 存储 Schema 配置 (使用 TSDB 引擎)
  schemaConfig:
    configs:
      - from: "2024-01-01" # 表示这个存储格式规则从这个日期开始生效。可以填一个早于当前的任意日期。
        store: tsdb
        object_store: s3
        schema: v13
        index:
          prefix: index_
          period: 24h

  # 日志保留策略 (Retention) - 例如保留 30 天
  compactor:
    working_directory: /var/loki/compactor
    retention_enabled: true
    retention_delete_delay: 2h
    retention_delete_worker_count: 150
    delete_request_store: s3 # 开启保留策略后必须配置此项,指定用于存放"删除请求记录"的后端存储
  limits_config:
    retention_period: 30d                     # 全局日志保留时间,超过该时间的日志将被 Compactor 自动清理
    ingestion_rate_mb: 1024                   # 全局每秒允许写入的日志量 (MB/s),调大至 1GB/s 避免初始化时大量历史日志导致 429 报错
    ingestion_burst_size_mb: 1024             # 允许的全局瞬间突发写入量 (MB),应对突发的高并发日志
    per_stream_rate_limit: 1024MB             # 单个日志流 (相同的 Label 组合) 每秒允许的写入量
    per_stream_rate_limit_burst: 1024MB       # 单个日志流允许的瞬间突发写入量

# 禁用单体模式
singleBinary:
  replicas: 0

# --- 读写分离组件扩容配置 ---

# 资源消耗优化 (关闭不必要的附加组件)
# 如果集群内存/CPU 资源紧张,强烈建议将以下组件关闭。
chunksCache:
  enabled: false # 关闭用于缓存日志块(Chunks)的 Memcached 集群,节约大量内存
resultsCache:
  enabled: false # 关闭用于缓存查询结果的 Memcached 集群,节约大量内存
test:
  enabled: true # 开启 Helm test 框架,允许使用 helm test 命令来验证 Loki 集群是否正常工作
lokiCanary:
  enabled: true # 开启 Canary 守护进程,它会持续向 Loki 写入和查询模拟日志,用于自我监控和告警

# 写入节点配置 (根据日志量调整副本数,可按需扩容)
write:
  replicas: 1
  persistence:
    # 写入节点需要少量本地存储用于 WAL (预写日志),避免宕机丢失缓存的日志
    size: 10Gi
    storageClass: "rook-ceph-block"

# 读取节点配置 (根据查询并发量调整,支持横向扩容)
read:
  replicas: 1

# 后端节点配置 (处理定时任务,通常 1 个或 2 个即可)
backend:
  replicas: 1
  persistence:
    # Backend 需要本地存储用于 Compactor 的临时工作空间
    size: 10Gi
    storageClass: "rook-ceph-block"

2.2 执行 Loki 部署

创建一个独立的 namespace 并部署:

bash 复制代码
helm upgrade --install loki grafana/loki \
  --namespace loki-stack --create-namespace \
  -f values-loki-scalable.yaml

验证 Loki Pod 和 Ceph PVC 状态:

bash 复制代码
kubectl get pods -n loki-stack -l app.kubernetes.io/name=loki
kubectl get pvc -n loki-stack
# 确保 PVC 状态为 Bound,说明 Ceph 已成功分配存储卷

3. 部署 Promtail 并实现 Nginx 日志分离

Promtail 以 DaemonSet 的方式运行在每个节点上。为了将 Nginx 日志与其他业务日志分离,我们将使用 Promtail 的 pipeline_stagesmatch 机制。

分离逻辑

  • 识别标签中包含 nginx 的 Pod(例如 Nginx Ingress 或你部署的 Nginx 业务)。
  • 给 Nginx 日志打上 log_category: nginx 标签,并提取出 Nginx 专有的字段(如状态码、请求路径)。
  • 给非 Nginx 的日志打上 log_category: app 标签。

3.1 创建 Promtail 配置文件

创建 values-promtail.yaml 文件:

yaml 复制代码
config:
  clients:
    # 指向上面部署的 Loki 统一网关服务
    # 读写分离模式下,所有请求都必须打给 loki-gateway
    - url: http://loki-gateway.loki-stack.svc.cluster.local:80/loki/api/v1/push
  
  snippets:
    pipelineStages:
      # 1. 容器运行时日志基础解析 (docker/cri)
      - cri: {}
      
      # 2. 匹配 Nginx 相关的日志
      # 匹配 Ingress Nginx Controller
      - match:
          selector: '{app="ingress-nginx"}'
          stages:
            # 方案 A: 设置多租户 (与 loki.auth_enabled: true 配合使用,默认推荐)
            - tenant:
                value: "tenant-nginx"
            # 方案 B: 添加分类标签 (若 loki.auth_enabled 为 false,则取消下方注释,查询时用 {log_category="nginx"})
            # - static_labels:
            #     log_category: "nginx"

      # 3. 匹配非 Nginx 的其他所有业务日志
      # 排除 Ingress Nginx Controller
      - match:
          selector: '{app!="ingress-nginx"}'
          stages:
            # 方案 A: 设置多租户
            - tenant:
                value: "tenant-app"
            # 方案 B: 添加分类标签
            # - static_labels:
            #     log_category: "application"

# 容忍所有的污点,确保 Promtail 能在所有节点(包括 Master 节点)上收集日志
tolerations:
  - operator: Exists

3.2 执行 Promtail 部署

bash 复制代码
helm upgrade --install promtail grafana/promtail \
  --namespace loki-stack --create-namespace \
  -f values-promtail.yaml

检查 Promtail 运行状态:

bash 复制代码
kubectl get pods -n loki-stack -l app.kubernetes.io/name=promtail
# 应该在集群的每个节点上都有一个处于 Running 状态的 Pod

4. 验证与 Grafana 集成

4.1 在 Grafana 中添加数据源

根据你在第 3 节中选择的方案,配置数据源的方法有所不同:

方案 A: 多租户隔离 (auth_enabled: true)

  1. 登录到你的 Grafana 面板。
  2. 进入 Connections -> Data Sources -> Add new data source ,选择 Loki
  3. 在 HTTP URL 中填写 Loki Gateway 的内部服务地址:
    http://loki-gateway.loki-stack.svc.cluster.local:80
  4. HTTP headers 部分,点击 Add header ,填写:
    • Header : X-Scope-OrgID
    • Value : tenant-nginx
  5. 将这个数据源命名为 Loki-Nginx
  6. 点击 Save & test,如果提示成功则说明连接正常。
  7. 重复以上步骤 ,再添加一个名为 Loki-App 的数据源,并将 X-Scope-OrgID 的值设置为 tenant-app

方案 B: 标签分类 (auth_enabled: false)

  1. 登录到你的 Grafana 面板。
  2. 进入 Connections -> Data Sources -> Add new data source ,选择 Loki
  3. 在 HTTP URL 中填写:http://loki-gateway.loki-stack.svc.cluster.local:80
  4. 不需要配置任何 Header,直接将数据源命名为 Loki
  5. 点击 Save & test 测试连接即可。

💡 获取 Loki 地址方法 :你可以通过执行 kubectl get svc -n loki-stack | grep gateway 确认服务名称和端口。Kubernetes 集群内部服务地址的标准格式为 http://<服务名>.<命名空间>.svc.cluster.local:<端口>

4.2 查询与验证日志分离

进入 Grafana 的 Explore 页面。

如果你使用的是多租户方案 (auth_enabled: true)

  1. 在顶部的数据源下拉菜单中,选择 Loki-Nginx
  2. 输入查询 {app="ingress-nginx"} 即可查询 Nginx 租户下的日志。
  3. 切换为 Loki-App 数据源,由于查询需要至少包含一个明确的正向匹配标签,所以不能只输入 {app!="ingress-nginx"}。你可以输入 {namespace=~".+"}{job=~".+"} 即可查询其他所有业务容器日志。

如果你使用的是分类标签方案 (auth_enabled: false)

  1. 只需要一个配置了 Loki 内部地址的普通数据源即可(无需 Header)。

  2. 在 Log browser 中输入以下 LogQL 查询 Nginx 日志:

    logql 复制代码
    {log_category="nginx"}
  3. 查询其他业务日志:

    logql 复制代码
    {log_category="application"}

💡 排查查询不到 Nginx 日志的问题

如果查不到数据,通常是因为你的 Nginx Pod 的标签与 Promtail 配置中的选择器不匹配。

  1. 文档中 Promtail 的 match 规则是 selector: '{app="ingress-nginx"}'。但请注意,在 Promtail 的管道处理 (pipeline_stages) 中,match 选择器使用的是经过 Promtail relabel 处理后最终保留的标签 。(查看最终标签的方法 :执行 kubectl port-forward -n loki-stack daemonset/promtail --address 0.0.0.0 3101:3101,然后在浏览器访问 http://<节点IP>:3101/targets,在页面中即可看到各 Pod 目标被 Promtail 最终保留的实际标签)。
  2. 如果你在 Promtail 的 target 页面发现最终生成的标签不匹配,你需要将 match 规则修改为匹配现有的标签。
  3. 修改 values-promtail.yaml 中的 selector 并重新执行 helm upgrade
  4. 触发日志产生 :如果没有日志产生,查询结果也会为空。你可以通过访问你的 Ingress 域名或直接请求 Nginx 服务来产生访问日志,例如:curl -I http://<你的Ingress节点IP或域名>(可通过 curl -I http://<你的Ingress域名> | grep ingress-nginx 搜索确认请求是否成功到达 Ingress Nginx),然后再去 Grafana 重新查询。
  5. 确认 Nginx 自身是否打印了日志 :你可以直接通过 kubectl 查看 Ingress Nginx 的原生日志,确认它是否记录了刚才的请求:kubectl logs -n <你的nginx命名空间> -l app.kubernetes.io/name=ingress-nginx --tail=10。如果这里也没有日志,说明是 Nginx 配置本身没有开启访问日志输出。
  6. 排查 Promtail 采集问题 :如果 Nginx 本身有日志,但在 Grafana 中查不到,说明 Promtail 没有成功采集或发送。请执行 kubectl logs -n loki-stack -l app.kubernetes.io/name=promtail --tail=50 查看 Promtail 的运行日志,检查是否有连接 Loki Gateway 失败的报错(如 401 认证失败、DNS 解析失败等)或是读取节点容器日志目录权限不足的问题。
  7. 处理 Loki 写入限流 (429 错误) :如果在 Promtail 日志中发现 server returned HTTP status 429 Too Many Requests (429): ingestion rate limit exceeded,说明你的日志产生量超过了 Loki 默认的写入限制(默认通常是 4MB/s)。你需要修改 values-loki-scalable.yaml,在 loki.limits_config 下增加或调大 ingestion_rate_mbingestion_burst_size_mb (例如设置为 1024 即 1GB/s),然后执行 helm upgrade 应用新配置。
  8. 查看 Promtail 采集目标状态 :如果以上都没问题,可以通过端口转发访问 Promtail 的内置 Web 页面,查看它到底抓取了哪些目标以及打上了什么标签:kubectl port-forward -n loki-stack daemonset/promtail --address 0.0.0.0 3101:3101,然后在浏览器访问 http://<任意节点IP>:3101/targets 确认 Nginx 的 Pod 是否在列,以及它的标签是什么。

5. 维护与建议 (进阶)

  1. Write/Read 节点本地盘扩容 :如果日后发现 Write 节点的 WAL (预写日志) 空间不足(如 10Gi 不够),由于它们挂载的是 Rook-Ceph 的块存储,可以直接编辑对应的 PVC (kubectl edit pvc ...) 修改大小实现在线扩容。
  2. 多租户隔离 :我们已经通过 Promtail 的 tenant 机制和 Loki 的 auth_enabled: true 实现了多租户分离(已在本次部署中完成)。如果未来有新的业务线接入,只需在 Promtail 配置中增加相应的 match 规则,并为其分配新的 tenant_id,然后在 Grafana 中添加对应的带 X-Scope-OrgID Header 的数据源即可实现硬隔离。
  3. 数据清理监控:文档中我们已经配置了 Compactor(保留 30 天日志),请确保 Backend 节点正常运行,否则过期数据将不会被清理,会导致 S3 存储容量持续增长。

6. 进阶场景:使用 Sidecar 模式收集容器内文件日志 (支持 Java 多行异常)

文档前述部署的 DaemonSet 模式 Promtail 默认只收集容器的标准输出 (stdout/stderr)。如果业务应用将日志写到了容器内部的文件中(例如 /app/logs/app.log),我们需要使用 Sidecar(边车)模式 进行收集。

为了避免为每个业务硬编码标签,以下方案结合了 Kubernetes Downward API 自动注入 Pod 标签,并配置了 multiline 阶段来完美合并 Java 的多行异常堆栈。

6.1 创建通用的 Promtail ConfigMap

该 ConfigMap 可以被集群中所有需要 Sidecar 的业务复用。它通过读取环境变量动态生成日志标签。

步骤 1:创建配置文件 promtail-sidecar-config.yaml

将以下内容保存为 promtail-sidecar-config.yaml 文件:

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: promtail-sidecar-config-universal
  namespace: default
data:
  promtail.yaml: |
    server:
      http_listen_port: 9080
      grpc_listen_port: 0
    
    clients:
      # 指向 Loki Gateway 地址。
      # 注意:如果 Loki 开启了多租户 (auth_enabled: true),这里必须配置 tenant_id。
      # 建议为 Sidecar 收集的日志配置独立的 tenant_id,以便与 DaemonSet 收集的容器标准输出隔离。
      - url: http://loki-gateway.loki-stack.svc.cluster.local:80/loki/api/v1/push
        tenant_id: "tenant-sidecar-app" 
    
    positions:
      filename: /tmp/positions.yaml
      
    scrape_configs:
      - job_name: sidecar-local-logs
        static_configs:
          - targets:
              - localhost
            labels:
              log_source: file
              # 指定共享目录下的日志文件路径
              __path__: /shared-logs/*.log
              
        pipeline_stages:
          # --- Java 多行异常合并 ---
          - multiline:
              # 匹配新日志的开头(例如以 2023-10-01 或 2023/10/01 开头)
              firstline: '^\d{4}[-/]\d{2}[-/]\d{2}'
              max_wait_time: 3s
              max_lines: 500
              
          # --- 通过环境变量展开写入静态标签 ---
          - static_labels:
              # 启动时自动将 ${XXX} 替换为真实的 Pod 环境变量值
              pod: "${POD_NAME}"
              namespace: "${POD_NAMESPACE}"
              app: "${APP_LABEL}"

步骤 2:应用 ConfigMap 到集群

执行以下命令,将配置部署到 Kubernetes 中:

bash 复制代码
kubectl apply -f promtail-sidecar-config.yaml

6.2 业务 Deployment 注入 Sidecar 示例

业务方只需在原有的 Deployment 中加入一个共享的 emptyDir 卷,并增加 promtail-sidecar 容器即可。

步骤 1:创建部署文件 java-multiline-demo.yaml

将以下内容保存为 java-multiline-demo.yaml 文件:

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-multiline-demo
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: java-demo-app
  template:
    metadata:
      labels:
        app: java-demo-app 
    spec:
      volumes:
        - name: shared-logs
          emptyDir: {}
        - name: promtail-config
          configMap:
            name: promtail-sidecar-config-universal
            
      containers:
        # 1. 主业务容器
        - name: main-app
          image: busybox:latest
          command: ["/bin/sh", "-c"]
          args:
            - |
              mkdir -p /app/logs
              while true; do 
                echo "$(date +'%Y-%m-%d %H:%M:%S') INFO  com.example.MyApp - Starting application..." >> /app/logs/app.log
                sleep 2
                echo "$(date +'%Y-%m-%d %H:%M:%S') ERROR com.example.MyApp - An unexpected error occurred:" >> /app/logs/app.log
                echo "java.lang.NullPointerException" >> /app/logs/app.log
                echo "        at com.example.MyApp.process(MyApp.java:42)" >> /app/logs/app.log
                sleep 5
              done
          volumeMounts:
            # 将共享卷挂载到业务代码写日志的目录
            - name: shared-logs
              mountPath: /app/logs 
              
        # 2. Promtail Sidecar 容器
        - name: promtail-sidecar
          image: grafana/promtail:2.9.2
          args:
            - -config.file=/etc/promtail/promtail.yaml
            # 核心参数:允许解析配置文件中的 ${ENV_VAR}
            - -config.expand-env=true 
          env:
            # 通过 Downward API 自动注入元数据
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: APP_LABEL
              valueFrom:
                fieldRef:
                  fieldPath: metadata.labels['app']
          volumeMounts:
            # 必须和 ConfigMap 里的 __path__ 匹配
            - name: shared-logs
              mountPath: /shared-logs
            - name: promtail-config
              mountPath: /etc/promtail

步骤 2:执行部署并验证

执行以下命令,启动带有 Sidecar 的业务 Pod:

bash 复制代码
kubectl apply -f java-multiline-demo.yaml

6.3 在 Grafana 中配置 Sidecar 专用数据源

由于我们在 ConfigMap 中为 Sidecar 指定了独立的租户 (tenant-sidecar-app),我们需要在 Grafana 中创建一个专门的数据源来查询这些容器内文件日志,以便与直接从容器终端获取的日志进行隔离。

配置步骤:

  1. 登录 Grafana 面板,进入 Connections -> Data Sources -> Add new data source ,选择 Loki
  2. 在 HTTP URL 中填写 Loki Gateway 地址:http://loki-gateway.loki-stack.svc.cluster.local:80
  3. HTTP headers 部分,点击 Add header ,填写:
    • Header : X-Scope-OrgID
    • Value : tenant-sidecar-app (必须与 Promtail ConfigMap 中的 tenant_id 保持一致)
  4. 将该数据源命名为 Loki-Sidecar-File
  5. 点击 Save & test 测试连接。

查询验证:

在 Grafana 的 Explore 页面中选择 Loki-Sidecar-File 数据源。由于我们注入了动态标签并合并了 Java 多行异常,你可以使用以下查询语句精准定位:

  • 查询特定应用的日志:{app="java-demo-app", log_source="file"}
  • 验证 Java 异常是否被正确合并:你会看到完整的包含多行 at com.example... 的堆栈信息作为一条完整的日志条目展示,而不再是支离破碎的单行。
相关推荐
潮起鲸落入海3 小时前
ceph分布式存储认证和授权,块存储管理
分布式·ceph
齐齐大魔王3 小时前
OpenSSL 原理
运维·网络·nginx·ssh·ssl
蜀道山老天师4 小时前
Docker 部署 Nginx Proxy Manager:可视化反向代理 + SSL 证书一键配置
nginx·docker·ssl
宇明一不急5 小时前
K8S-中nodePort、port、targetPort和containerPort
云原生·容器·kubernetes
TheSumSt5 小时前
日常教程丨远程串流打游戏方法介绍(Parsec/Tailscale+Headscale+DERP+Sunshine&Moonlight)
linux·网络·经验分享·nginx·开源·玩游戏
像我这样帅的人丶你还5 小时前
🚀🚀🚀2026年还不会Nginx?
前端·nginx
小二·6 小时前
Nginx 高级配置实战:负载均衡/SSL/缓存优化
nginx·负载均衡·ssl
做个文艺程序员7 小时前
第03篇:K8s 网络深度解析:Ingress、Service Mesh 与 CoreDNS——Java 微服务通信全链路剖析(生产级实战)
网络·kubernetes·service_mesh
成为你的宁宁7 小时前
【Kubernetes监控实战:NFS持久化存储 + Prometheus Operator + etcd监控】
kubernetes·prometheus·etcd