Kubernetes日志采集——使用Fluent Bit采集和转发Kubernetes日志(三)

1、概览

本文主要讲解下如何编写Fluent Bit配置文件来采集和转发Kubernetes日志。如果对Kubernetes日志管理机制和Fluent Bit不熟悉,请先阅读《从 Docker 到 Kubernetes 日志管理机制详解》、《Kubernetes日志采集——Fluent Bit详细介绍(一)》、《Kubernetes日志采集——Fluent Bit插件详细配置(二)》这三篇博文。

2、Kubernetes 的日志种类

在 Kubernetes 中日志也主要有两大类:

  • Kuberntes 集群组件日志;
  • 应用 Pod 日志;

所以,使用Fluent Bit采集Kubernetes日志就是采集Kuberntes 集群组件日志和应用 Pod 日志。

2.1 Kuberntes 集群组件日志

Kuberntes 集群组件日志分为两类:

  • 运行在容器中的 Kubernetes scheduler 和 kube-proxy等。
  • 未运行在容器中的 kubelet 和容器 runtime,比如 Docker。

在使用 systemd 机制的服务器上,kubelet 和容器 runtime 写入日志到 journald(常用的centos7正是使用 systemd 机制)。如果没有 systemd,他们写入日志到 /var/log 目录的 .log 文件。

2.2 应用 Pod 日志

Kubernetes Pod 的日志管理是基于 Docker 引擎的,Kubernetes 并不管理日志的轮转策略,日志的存储都是基于 Docker 的日志管理策略。k8s 集群调度的基本单位就是 Pod,而 Pod 是一组容器,所以 k8s 日志管理基于 Docker 引擎这一说法也就不难理解了,最终日志还是要落到一个个容器上面。 

3、在Kubernetes集群部署Fluentbit

由于在Kubernetes部署Fluent-bit Daemonset比较简单,本文就不再介绍Fluent-bit Daemonset的安装过程。

下面粘贴一下Fluentbit Daemonset的配置文件,对于Fluentbit Daemonset的配置文件着重看下volumeMounts部分。

  • 把节点的/var/log/journal目录挂载到fluent-bit容器内,通过/var/log/journal目录即可采集Kuberntes 集群组件日志。
  • 把节点的/var/log目录和/data/docker-data/containers(docker数据盘路径)目录挂载到fluent-bit容器内,通过/var/log/containers/目录即可采集当前节点所有Pod下所有容器的所有日志文件(这里如果有疑问可以参见《从 Docker 到 Kubernetes 日志管理机制详解》)。
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app.kubernetes.io/name: fluent-bit
  name: fluent-bit
  namespace: logging-system
spec:
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/name: fluent-bit
  template:
    metadata:
      creationTimestamp: null
      labels:
        app.kubernetes.io/name: fluent-bit
      name: fluent-bit
      namespace: logging-system
    spec:
      containers:
      - env:
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: spec.nodeName
        image: fluent-bit:v1.8.3
        imagePullPolicy: IfNotPresent
        name: fluent-bit
        ports:
        - containerPort: 2020
          name: metrics
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /fluent-bit/config
          name: config
          readOnly: true
        - mountPath: /var/log/
          name: varlogs
          readOnly: true
        - mountPath: /var/log/journal
          name: systemd
          readOnly: true
        - mountPath: /fluent-bit/tail
          name: positions
        - mountPath: /data/docker-data/containers
          name: varlibcontainers0
          readOnly: true
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      serviceAccount: fluent-bit
      serviceAccountName: fluent-bit
      terminationGracePeriodSeconds: 30
      tolerations:
      - operator: Exists
      volumes:
      - name: config
        secret:
          defaultMode: 420
          secretName: fluent-bit-config
      - hostPath:
          path: /var/log
          type: ""
        name: varlogs
      - hostPath:
          path: /var/log/journal
          type: ""
        name: systemd
      - emptyDir: {}
        name: positions
      - hostPath:
          path: /data/docker-data/containers
          type: ""
        name: varlibcontainers0
  updateStrategy:
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
    type: RollingUpdate

注意:配置文件中的fluent-bit:v1.8.3镜像是基于官方镜像二次构建的,所以不要直接粘贴以上Fluentbit Daemonset的配置文件到其他k8s环境部署。另外,fluent-bit采集和转发的配置是通过密钥的形式挂载到fluent-bit容器内部,由于二次构建了镜像所以fluent-bit启动时能直接加载此密钥里面的配置文件。

4、通过编写Fluent Bit配置文件来采集和转发Kubernetes日志

此章节是本文的核心,通过配置Fluent Bit输入、解析、过滤、缓存和输出模块来采集和转发Kubernetes日志。

这里先整体粘贴下Fluent Bit输入、解析、过滤、缓存和输出模块的配置,下文会依次解释Input、Parser、Filter、Buffer、Routing 和 Output模块的配置。

[Service]
    Parsers_File    parsers.conf
[Input]
    Name    systemd
    Path    /var/log/journal
    DB    /fluent-bit/tail/docker.db
    DB.Sync    Normal
    Tag    service.docker
    Systemd_Filter    _SYSTEMD_UNIT=docker.service
[Input]
    Name    systemd
    Path    /var/log/journal
    DB    /fluent-bit/tail/kubelet.db
    DB.Sync    Normal
    Tag    service.kubelet
    Systemd_Filter    _SYSTEMD_UNIT=kubelet.service
[Input]
    Name    tail
    Path    /var/log/containers/*.log
    Exclude_Path    /var/log/containers/*_cloudbases-logging-system_events-exporter*.log,/var/log/containers/kube-auditing-webhook*_cloudbases-logging-system_kube-auditing-webhook*.log
    Refresh_Interval    10
    Skip_Long_Lines    true
    DB    /fluent-bit/tail/pos.db
    DB.Sync    Normal
    Mem_Buf_Limit    5MB
    Parser    docker
    Tag    kube.*
[Filter]
    Name    kubernetes
    Match    kube.*
    Kube_URL    https://kubernetes.default.svc:443
    Kube_CA_File    /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    Kube_Token_File    /var/run/secrets/kubernetes.io/serviceaccount/token
    Labels    false
    Annotations    false
[Filter]
    Name    nest
    Match    kube.*
    Operation    lift
    Nested_under    kubernetes
    Add_prefix    kubernetes_
[Filter]
    Name    modify
    Match    kube.*
    Remove    stream
    Remove    kubernetes_pod_id
    Remove    kubernetes_host
    Remove    kubernetes_container_hash
[Filter]
    Name    nest
    Match    kube.*
    Operation    nest
    Wildcard    kubernetes_*
    Nest_under    kubernetes
    Remove_prefix    kubernetes_
[Filter]
    Name    lua
    Match    service.*
    script    /fluent-bit/config/systemd.lua
    call    add_time
    time_as_table    true
[Output]
    Name    es
    Match_Regex    (?:kube|service)\.(.*)
    Host    elasticsearch-logging-data.logging-system.svc
    Port    9200
    Logstash_Format    true
    Logstash_Prefix    cb-logstash-log
    Time_Key    @timestamp
    Generate_ID    true

注意:docker容器日志默认都是以JSON 的格式写到文件中,每一条 json 日志中默认包含 logstreamtime 三个字段。

{
    "log":  ....,
    "stream": .....,
    "time": .......
} 

以下图这条容器日志为例,下面会详细说明此条日志在Fluent Bit不同模块的日志格式:

4.1 全局配置——SERVICE

[Service]
    Parsers_File    parsers.conf

这里Parsers_File引用了parsers.conf配置文件,在[Input]模块会使用parsers.conf文件中定义的[PARSER]将 Input 抽取的非结构化数据转化为标准的结构化数据,下面粘贴一下parsers.conf配置文件内容:

[PARSER]
    Name   apache
    Format regex
    Regex  ^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$
    Time_Key time
    Time_Format %d/%b/%Y:%H:%M:%S %z

[PARSER]
    Name   apache2
    Format regex
    Regex  ^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>.*)")?$
    Time_Key time
    Time_Format %d/%b/%Y:%H:%M:%S %z

[PARSER]
    Name   apache_error
    Format regex
    Regex  ^\[[^ ]* (?<time>[^\]]*)\] \[(?<level>[^\]]*)\](?: \[pid (?<pid>[^\]]*)\])?( \[client (?<client>[^\]]*)\])? (?<message>.*)$

[PARSER]
    Name   nginx
    Format regex
    Regex ^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")
    Time_Key time
    Time_Format %d/%b/%Y:%H:%M:%S %z

[PARSER]
    # https://rubular.com/r/IhIbCAIs7ImOkc
    Name        k8s-nginx-ingress
    Format      regex
    Regex       ^(?<host>[^ ]*) - (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*) "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" (?<request_length>[^ ]*) (?<request_time>[^ ]*) \[(?<proxy_upstream_name>[^ ]*)\] (\[(?<proxy_alternative_upstream_name>[^ ]*)\] )?(?<upstream_addr>[^ ]*) (?<upstream_response_length>[^ ]*) (?<upstream_response_time>[^ ]*) (?<upstream_status>[^ ]*) (?<reg_id>[^ ]*).*$
    Time_Key    time
    Time_Format %d/%b/%Y:%H:%M:%S %z

[PARSER]
    Name   json
    Format json
    Time_Key time
    Time_Format %d/%b/%Y:%H:%M:%S %z

[PARSER]
    Name         docker
    Format       json
    Time_Key     time
    Time_Format  %Y-%m-%dT%H:%M:%S.%L
    Time_Keep    On
    # --
    # Since Fluent Bit v1.2, if you are parsing Docker logs and using
    # the Kubernetes filter, it's not longer required to decode the
    # 'log' key.
    #
    # Command      |  Decoder | Field | Optional Action
    # =============|==================|=================
    #Decode_Field_As    json     log

[PARSER]
    Name        docker-daemon
    Format      regex
    Regex       time="(?<time>[^ ]*)" level=(?<level>[^ ]*) msg="(?<msg>[^ ].*)"
    Time_Key    time
    Time_Format %Y-%m-%dT%H:%M:%S.%L
    Time_Keep   On

[PARSER]
    Name        syslog-rfc5424
    Format      regex
    Regex       ^\<(?<pri>[0-9]{1,5})\>1 (?<time>[^ ]+) (?<host>[^ ]+) (?<ident>[^ ]+) (?<pid>[-0-9]+) (?<msgid>[^ ]+) (?<extradata>(\[(.*?)\]|-)) (?<message>.+)$
    Time_Key    time
    Time_Format %Y-%m-%dT%H:%M:%S.%L%z
    Time_Keep   On

[PARSER]
    Name        syslog-rfc3164-local
    Format      regex
    Regex       ^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$
    Time_Key    time
    Time_Format %b %d %H:%M:%S
    Time_Keep   On

[PARSER]
    Name        syslog-rfc3164
    Format      regex
    Regex       /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
    Time_Key    time
    Time_Format %b %d %H:%M:%S
    Time_Keep   On

[PARSER]
    Name    mongodb
    Format  regex
    Regex   ^(?<time>[^ ]*)\s+(?<severity>\w)\s+(?<component>[^ ]+)\s+\[(?<context>[^\]]+)]\s+(?<message>.*?) *(?<ms>(\d+))?(:?ms)?$
    Time_Format %Y-%m-%dT%H:%M:%S.%L
    Time_Keep   On
    Time_Key time

[PARSER]
    # https://rubular.com/r/3fVxCrE5iFiZim
    Name    envoy
    Format  regex
    Regex ^\[(?<start_time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)? (?<protocol>\S+)" (?<code>[^ ]*) (?<response_flags>[^ ]*) (?<bytes_received>[^ ]*) (?<bytes_sent>[^ ]*) (?<duration>[^ ]*) (?<x_envoy_upstream_service_time>[^ ]*) "(?<x_forwarded_for>[^ ]*)" "(?<user_agent>[^\"]*)" "(?<request_id>[^\"]*)" "(?<authority>[^ ]*)" "(?<upstream_host>[^ ]*)"  
    Time_Format %Y-%m-%dT%H:%M:%S.%L%z
    Time_Keep   On
    Time_Key start_time

[PARSER]
    # http://rubular.com/r/tjUt3Awgg4
    Name cri
    Format regex
    Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<message>.*)$
    Time_Key    time
    Time_Format %Y-%m-%dT%H:%M:%S.%L%z

[PARSER]
    Name    kube-custom
    Format  regex
    Regex   (?<tag>[^.]+)?\.?(?<pod_name>[a-z0-9](?:[-a-z0-9]*[a-z0-9])?(?:\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace_name>[^_]+)_(?<container_name>.+)-(?<docker_id>[a-z0-9]{64})\.log$

4.2 输入——Input(包含解析模块引用)

通过配置[Input]模块采集Kubernetes集群组件日志和应用容器日志。

[Input]
    Name    systemd     //使用systemd输入插件从systemd或journaled读取日志
    Path    /var/log/journal  //采集k8s未运行在容器中的集群组件日志: Docker
    DB    /fluent-bit/tail/docker.db
    DB.Sync    Normal
    Tag    service.docker	//定义Tag用于识别数据源
    Systemd_Filter    _SYSTEMD_UNIT=docker.service 	//采集当前节点docker服务日志(_SYSTEM_UNIT必须加下划线)  
[Input]
    Name    systemd
    Path    /var/log/journal  //采集k8s未运行在容器中的集群组件日志: Kubelet
    DB    /fluent-bit/tail/kubelet.db
    DB.Sync    Normal
    Tag    service.kubelet
    Systemd_Filter    _SYSTEMD_UNIT=kubelet.service  //采集当前节点kubelet服务日志  
[Input]
    Name    tail   //使用tail输入插件
    Path    /var/log/containers/*.log    //采集k8s应用Pod日志和运行在容器中的集群组件日志(Kubernetes scheduler 和 kube-proxy、etcd等)
    Exclude_Path    /var/log/containers/*_cloudbases-logging-system_events-exporter*.log,/var/log/containers/kube-auditing-webhook*_cloudbases-logging-system_kube-auditing-webhook*.log    //使用通配符排除日志文件采集
    Refresh_Interval    10    //刷新监视文件列表的时间间隔
    Skip_Long_Lines    true   //当受监视的文件由于行很长而达到缓冲区容量时,默认停止监视该文件
    DB    /fluent-bit/tail/pos.db
    DB.Sync    Normal
    Mem_Buf_Limit    5MB      //缓存使用的内存限制如果达到了极限,input就会暂停读取;当刷新数据到output后,它将恢复读取
    Parser    docker          //使用docker解析插件将Input抽取的非结构化容器日志转化为标准的结构化数据
    Tag    kube.*

应用容器日志通过配置[Input]模块中引用docker解析插件将Input抽取的非结构化容器日志转化为标准的结构化数据,此时容器的日志格式为:

docker解析插件内容如下:

[PARSER]
    Name         docker
    Format       json
    Time_Key     time
    Time_Format  %Y-%m-%dT%H:%M:%S.%L
    Time_Keep    On 

4.3 过滤——Filter

对Input模块采集的格式化数据进行过滤和修改。一个数据管道中可以包含多个 Filter,Filter 会顺序执行,其执行顺序与配置文件中的顺序一致。

4.3.1 使用kubernetes过滤器插件为应用容器日志和运行在容器中的k8s集群组件日志添加kubernetes元数据

[Filter]   
    Name    kubernetes
    Match    kube.*   //匹配输入模块中的Tag,即匹配上文中的使用tail插件的那个input模块
    Kube_URL    https://kubernetes.default.svc:443
    Kube_CA_File    /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    Kube_Token_File    /var/run/secrets/kubernetes.io/serviceaccount/token
    Labels    false   //不将标签添加到容器日志中
    Annotations    false    //不将注解添加到容器日志中

经过kubernetes过滤器插件后,此时容器的日志格式为:

4.3.2 使用nest过滤器插件对应用容器和运行在容器中的k8s集群组件的嵌套日志进行操作

[Filter]
    Name    nest
    Match    kube.*
    Operation    lift   //通过lift模式,从记录的将指定map中的key value都提取出来放到上一层
    Nested_under    kubernetes  //指定需要提取的map名
    Add_prefix    kubernetes_   //添加前缀

经过nest过滤器插件后,此时容器的日志格式为: 

4.3.3 通过modify调整应用容器和运行在容器中的k8s集群组件日志字段

[Filter]
    Name    modify
    Match    kube.*
    Remove    stream  //移除stream字段
    Remove    kubernetes_pod_id  //移除kubernetes_pod_id字段
    Remove    kubernetes_host	 //移除kubernetes_host字段
    Remove    kubernetes_container_hash	  //移除kubernetes_container_hash字段
经过modify过滤器插件后,此时容器的日志格式为:
 

4.3.4 使用nest过滤器插件对应用容器和运行在容器中的k8s集群组件的嵌套日志进行操作

[Filter]
    Name    nest
    Match    kube.* 
    Operation    nest  //通过nest模式,从记录中指定一组key value合并,并放到一个map里
    Wildcard    kubernetes_*  //选择日志记录中以kubernetes_为前缀的key,将这些key value放到一个map里
    Nest_under    kubernetes  //存放key value的map名
    Remove_prefix    kubernetes_ //移除这些key的前缀

经过nest过滤器插件后,此时容器的日志格式为: 

经过以上4个过滤器插件后,将应用容器日志和运行在容器中的k8s集群组件日志过滤和修改成了想要的格式,当以上配置不满足公司业务需求时,对应调整过滤器模块配置即可。

4.3.5 通过lua过滤器插件处理kubernetes非容器化集群组件(Docker、Kubelet)日志

需要注意的是经过systemd输入插件采集的日志直接是格式化的,并不需要解析。

示例日志如下:

service.kubelet: [1657004329.109221000, {"PRIORITY"=>"6", "_UID"=>"0", "_GID"=>"0", "_CAP_EFFECTIVE"=>"1fffffffff", "_SYSTEMD_SLICE"=>"system.slice", "_BOOT_ID"=>"f1b154f127cf479f9c150f84038fd70b", "_MACHINE_ID"=>"d96b070ae8844338a3170e4ee73453f8", "_HOSTNAME"=>"node1", "_TRANSPORT"=>"stdout", "_STREAM_ID"=>"f984c86546344c88811be43d44b93394", "SYSLOG_FACILITY"=>"3", "SYSLOG_IDENTIFIER"=>"kubelet", "_PID"=>"79465", "_COMM"=>"kubelet", "_EXE"=>"/usr/local/bin/kubelet", "_CMDLINE"=>"/usr/local/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --cgroup-driver=cgroupfs --network-plugin=cni --pod-infra-container-image=harbor.openserver.cn:443/big_data-cloudbases/pause:3.4.1 --node-ip=10.20.30.31 --hostname-override=node1", "_SYSTEMD_CGROUP"=>"/system.slice/kubelet.service", "_SYSTEMD_UNIT"=>"kubelet.service", "MESSAGE"=>"E0705 14:58:49.108605   79465 cadvisor_stats_provider.go:151] "Unable to fetch pod etc hosts stats" err="failed to get stats failed command 'du' ($ nice -n 19 du -x -s -B 1) on path /var/lib/kubelet/pods/57d16b3d-23f5-4a40-87a6-9e547793a519/etc-hosts with error exit status 1" pod="ingress-nginx/ingress-nginx-admission-create-2q7xc""}]

接着看下kubernetes非容器化集群组件的过滤器配置:

[Filter]
    Name    lua
    Match    service.*
    script    /fluent-bit/config/systemd.lua  //脚本文件
    call    add_time  //调用脚本add_time方法
    time_as_table    true

其中script脚本内容如下,逻辑为:新生成个空的日志记录,然后将采集到的systemd服务日志记录的指定字段放到新的日志记录中,然后返回新组装的日志记录,将新组装的日志记录输出到指定目的地。这样就可以将采集到的systemd服务日志过滤和修改成我们想要的日志内容。

function add_time(tag, timestamp, record) //record是获取的日志记录
     new_record = {} //初始化一个空的日志记录
	  
     //时间格式化
     timeStr = os.date("!*t", timestamp["sec"])
     t = string.format("%4d-%02d-%02dT%02d:%02d:%02d.%sZ",
     timeStr["year"], timeStr["month"], timeStr["day"],
     timeStr["hour"], timeStr["min"], timeStr["sec"],
     timestamp["nsec"])
	 
     //初始化空的kubernetes map 并新增数据
     kubernetes = {}
     kubernetes["pod_name"] = record["_HOSTNAME"]
     kubernetes["container_name"] = record["SYSLOG_IDENTIFIER"]
     kubernetes["namespace_name"] = "kube-system"
	
     //把新增的数据都放到空的map中
     new_record["time"] = t
     new_record["log"] = record["MESSAGE"]
     new_record["kubernetes"] = kubernetes
 
     return 1, timestamp, new_record

4.4 输出——Output

将数据发送到不同的目的地。

[Output]
    Name    es  //输出插件使用es
    Match_Regex    (?:kube|service)\.(.*)   //在输出模块配置中指定 Match 规则,Match输入模块中的Tag,这样通过标签和匹配规则就能将数据路由到一个或多个目的地
    Host    elasticsearch-logging-data.logging-system.svc  //es地址
    Port    9200  //es端口
    Logstash_Format    true  
    Logstash_Prefix    cb-logstash-log 
    Time_Key    @timestamp
    Generate_ID    true

5、总结

 Fluent Bit采集Kubernetes日志就是采集Kuberntes 集群组件日志和应用 Pod 日志,其中Kuberneters集群组件日志又分为:

  • 运行在容器中的 Kubernetes scheduler 和 kube-proxy等。
  • 未运行在容器中的 kubelet 和容器 runtime,比如 Docker。

通过分析Kubernetes日志种类就能明确出日志采集点,对于容器日志采集/var/log/containers/路径即可,对于非容器服务根据服务名通过systemd插件采集即可,至此就可以将Kubernetes日志采集到。接下来再通过编写Fluent Bit输入、解析、过滤、缓存和输出模块的配置就可以将Kubernetes日志转换成我们想要的格式,并将日志输出到指定目的地。

posted @ 2022-07-08 16:42  人艰不拆_zmc  阅读(4907)  评论(4编辑  收藏  举报