日志服务

更新时间: 2023-04-12 10:16:18

ADP底座对于客户的业务日志提供了日志采集、字段提取、监控分析、告警通知等能力。

功能概述

ADP底座的日志采集器有以下功能:

  • 根据日志路径配置日志采集任务,定期汇集日志到Loki存储中,便于后续做日志查询和分析。

  • 根据分隔符、json、表达式对日志文件进行字段提取,可以对提取的字段打标添加索引,客户可以根据打标的字段进行查询和聚合分析。

接入流程

ADP-Local提供的日志采集器需要先配置日志采集策略,然后加载线上日志,配置字段提取方式,并生成字段列,可以对字段列进行打标并生成Prometheus Metrics。接下来我们可以根据提取的字段进行查询和日志监控。

image

默认采集配置

ADP底座使用promtail作为日志采集工具,把日志采集上报至loki,由于日志的过滤查询、指标定义都依赖标签(label),在ADP的场景中会添加以下采集配置,在这个基础上,用户可以通过"component"标签对组件日志进行查询,若需要对promtail配置进行手动编辑,请不要删除这些配置项

scrape_configs:
  - job_name: kubernetes-pods
    relabel_configs:
      - source_labels:
          [
            __meta_kubernetes_pod_label_app_kubernetes_io_component,
            __meta_kubernetes_pod_label_component,
            __meta_kubernetes_pod_label_adp_aliyuncs_com_component_name,
          ]
        regex: ^;*([^;]+)(;.*)?$
        target_label: component
        action: replace
  - job_name: kubernetes-pods-logdir-csi
    relabel_configs:
      - source_labels:
          [
            __meta_kubernetes_pod_label_app_kubernetes_io_component,
            __meta_kubernetes_pod_label_component,
            __meta_kubernetes_pod_label_adp_aliyuncs_com_component_name,
          ]
        regex: ^;*([^;]+)(;.*)?$
        target_label: component
        action: replace
  - job_name: kubernetes-pods-logdir
    relabel_configs:
      - source_labels:
          [
            __meta_kubernetes_pod_label_app_kubernetes_io_component,
            __meta_kubernetes_pod_label_component,
            __meta_kubernetes_pod_label_adp_aliyuncs_com_component_name,
          ]
        regex: ^;*([^;]+)(;.*)?$
        target_label: component
        action: replace

在logQL中使用component标签进行日志查询

# 查询组件为mysql-mysql 且日志级别为error的日志
{component="mysql-mysql"} |="error"

默认采集说明

默认会对所有Pod的Stdout进行日志采集,存储至Loki,可通过ADP-Local或Grafana可视化查询,也可以通过调用loki API查询

日志采集器

由于对promtail的采集配置进行修改需要掌握一定量的背景知识,ADP提供了名为'LogCollector'的CR,帮助用户低成本地对日志采集进行配置

有日志采集需求的组件可提前配置好,放在组件helm chart内文件采集器示例及说明正则表达式编写

stdout日志采集器示例及说明

kind: LogCollector
apiVersion: logging.adp.aliyuncs.com/v1alpha1
metadata:
  name: adp-local-stdout
  namespace: acs-system
spec:
  # 描述采集的内容
  description: for analyse stdout log
  # 采集哪个workload的日志,需要与采集位于同一namespace
  workloadName: StatefulSet/adp-local
  # 采集Pod Stdout 日志
  logType: Stdout
  # 若只对部分container进行分析采集,配置container属性
  container:
    - console
    - system
  # 当前支持Regexp、JSON两种提取模式
  extractMode: Regexp
  # 提取表达式(正则),JSON类型则不需要
  extractExpression: ^time=(?P<time>.+) level=(?P<level>.+) msg="(?P<msg>.+)"
  logColumns:
    # name与正则匹配到的name一致或使用JSON的key
    - name: level
      description: 日志等级
      # isLabel 为 true 时,作为label,可在logQL中的labelQuery被使用
      isLabel: true
    - name: msg
      description: 描述信息
      isLabel: false

文件采集器示例及说明

kind: LogCollector
apiVersion: logging.adp.aliyuncs.com/v1alpha1
metadata:
  name: adp-local-access
  namespace: acs-system
spec:
  # 描述采集的内容
  description: local-access-log
  # 采集哪个workload的日志,需要与采集位于同一namespace
  workloadName: StatefulSet/adp-local
  # 采集Pod 内的文件日志
  logType: File
  # {volumeName}为卷名称,使用emptyDir的名称或CSI挂载卷的名称
  paths:
    - {volumeName}/*.access.log
  # Regexp、JSON,不同提取方式需要配合不同的表达式
  extractMode: Regexp
  extractExpression: ^time=(?P<time>.+) level=(?P<level>.+) msg="(?P<msg>.+)"
  # 日志切割,label做重复的校验提示
  logColumns:
    # name与正则匹配到的name一致或使用JSON的key
    - name: level
      description: 日志等级
      # isLabel 为 true 时,作为label,可在logQL中的labelQuery被使用
      isLabel: true
    - name: msg
      description: 描述信息
      isLabel: false

正则表达式编写

日志样例

level=info ts=2022-05-10T08:16:57.403Z caller=custom_mysql_user_connections.go:82 scraper=custom.info_schema.processlist msg="custom user connections collect end."

对应的样例正则表达式

level=(?P<level>.+) ts=(?P<ts>.+) caller=(?P<caller>.+) scraper=(?P<scraper>.+) msg=(?P<msg>.+)

这里的正则表达式需要使用"(?'name'ABC) (?P<name>ABC) (?<name>ABC)"的格式标记"named capturing group"

正则表达式可以在站点https://regexr.com/进行调试,注意右上角Regex Engine选择'PCRE'

image

若调试成功,在Tools预览界面可以看到日志被分隔为多个键值对,键可作为logColumns中的name

JSON日志提取说明

extractMode为JSON时,可提取JSON格式日志

此时extractExpression留空,因为解析JSON格式不需要表达式

把JSON结构首层的key填入logColumns即可对特定key的打标

什么字段适合打标

仅建议把可枚举字段进行打标,如logLevel这样一般只有几种可枚举情况的

类似message、浮点数据这样每次内容都不一样的,不建议进行打标操作

由于Loki会将有同样标签的日志作为一个stream,使用不可枚举的标签会导致stream激增,达到上限(默认5000个stream),然后有新label的stream就无法写入了

Loki + Minio配置实践

说明:

  • 此配置下loki可配置多副本,chunks数据写至minio

  • loki仍需配置数据盘,用于存放

    • ingester-WAL

    • rule-WAL

    • boltdb-shipper-cache

    • compactor working directory

  • 性能瓶颈参数主要会受制于配置 server.grpc_server_max_recv_msg_size,默认 4194304bytes/sec(4MB/s),切换至minio后可提升数倍,具体视minio写入能力;

loki:
 # 副本数在对接时minio后可配置为多个,提升采集性能
 replicas: 3
  # 依旧依赖PV存储,写入WAL、cache等数据,但容量要求不高,1Gi即可
  persistence:
    enabled: true
    size: 1Gi
 # 配置minio为s3存储,config下的其他配置如limits_config、ruler等维持原状
  config:
   server:
     # 若速度受限可增大此参数配置
     grpc_server_max_recv_msg_size: 4194304
    common:
      storage:
        s3:
         # minio服务地址
          endpoint: http://minio-minio-svc.default:9000
         # 存放日志的bucket
          bucketnames: logs
         # minio的AK/SK
          access_key_id: foo
          secret_access_key: bar
          s3forcepathstyle: true
          insecure: true
     # 日志副本数
      replication_factor: 3
    compactor:
      shared_store: s3
    storage_config:
      boltdb_shipper:
        shared_store: s3
    schema_config:
      configs:
      - from: 2020-10-24
        store: boltdb-shipper
        object_store: s3
        schema: v11
        index:
          prefix: index_
          period: 24h
阿里云首页 云原生应用交付平台 相关技术圈