本文介绍如何通过控制台创建Logtail采集配置,并以DaemonSet采集方式采集容器标准输出。

前提条件

  • 已安装Logtail组件。具体操作,请参见安装Logtail组件
  • 在您安装Logtail组件时所使用的Project中已创建Logstore。具体操作,请参见创建Logstore

功能特点

Logtail支持采集容器内产生的标准输出,并附加容器的相关元数据信息一起上传到日志服务。Logtail具备以下功能特点。

  • 支持采集标准输出信息(stdout)和标准出错信息(stderr)。
  • 支持通过容器Label白名单指定待采集的容器。
  • 支持通过容器Label黑名单排除不要采集的容器。
  • 支持通过环境变量白名单指定待采集的容器。
  • 支持通过环境变量黑名单排除不要采集的容器。
  • 支持采集多行日志(例如Java Stack日志)。
  • 支持上报容器日志时自动关联Meta信息(例如容器名、镜像、Pod、Namespace、环境变量等)。
  • 当容器运行于Kubernetes时,Logtail还具有以下功能。
    • 支持通过Kubernetes Namespace名称、Pod名称、容器名称指定待采集的容器。
    • 支持通过Kubernetes Label白名单指定待采集的容器。
    • 支持通过Kubernetes Label黑名单排除不要采集的容器。
    • 支持上报容器日志时自动关联Kubernetes Label信息。

实现原理

Logtail与Docker的Domain Socket进行通信,查询该Docker上运行的所有容器,并根据容器中的Label和环境变量定位需要被采集的容器。Logtail通过docker logs命令获取指定容器日志。

Logtail在采集容器的标准输出时,会定期将采集的点位信息保存到checkpoint文件中。如果Logtail停止后再次启动,会从上一次保存的点位开始采集。实现原理

使用限制

  • 此功能目前仅支持Linux操作系统,依赖Logtail 0.16.0及以上版本。版本查看与升级,请参见安装Logtail(Linux系统)
  • Logtail支持Docker和Containerd两种容器引擎的数据采集,访问路径说明如下:
    • Docker:Logtail通过/run/docker.sock访问Docker,请确保该路径存在且具备访问权限。
    • Containerd:Logtail通过/run/containerd/containerd.sock访问Containerd,请确保该路径存在且具备访问权限。
  • 多行日志限制:为保证多行组成的一条日志不因为输出延迟而被分割成多条,多行日志情况下,采集的最后一条日志默认都会缓存一段时间。默认缓存时间为3秒,可通过BeginLineTimeoutMs参数修改,但此值不能低于1000(毫秒),否则容易出现误判。
  • 采集停止策略:当容器被停止后,Logtail监听到容器die的事件后会停止采集该容器的标准输出。如果此时采集出现延迟,则可能丢失停止前的部分输出。
  • Docker容器引擎限制:目前标准输出采集仅支持JSON类型的日志驱动。
  • 上下文限制:默认一个Logtail采集配置在同一上下文中。如果需要每个容器的日志在不同上下文中,请单独为每个容器创建Logtail采集配置。
  • 数据处理:采集到的数据默认保存在content字段中。Logtail对于采集到的容器标准输出,支持数据处理。更多信息,请参见使用Logtail插件处理数据

操作视频

本视频介绍通过日志服务Logtail采集容器标准输出的操作步骤。

创建采集配置

  1. 登录日志服务控制台
  2. 接入数据区域,单击Kubernetes-标准输出
  3. 选择目标Project和Logstore,单击下一步
    选择您在安装Logtail组件时所使用的Project。Logstore为您自定义创建的Logstore。
  4. 单击使用现有机器组
    安装Logtail组件后,日志服务自动创建名为k8s-group-${your_k8s_cluster_id}的机器组,您可以直接使用该机器组。
  5. 选中目标机器组(k8s-group-${your_k8s_cluster_id}),将该机器组从源机器组移动到应用机器组,单击下一步
    注意 如果机器组心跳为FAIL,您可单击自动重试。如果还未解决,请参见Logtail机器组无心跳进行排查。
  6. 设置数据源,单击下一步

    插件配置中填写您的采集配置信息,示例如下所示。

    {
        "inputs":[
            {
                "type":"service_docker_stdout",
                "detail":{
                    "Stdout":true,
                    "Stderr":true,
                    "IncludeContainerLabel":{
                        "LabelKey":"LabelValue"
                    },
                    "ExcludeContainerLabel":{
                        "LabelKey":"LabelValue"
                    },
                    "IncludeK8sLabel":{
                        "LabelKey":"LabelValue"
                    },
                    "ExcludeK8sLabel":{
                        "LabelKey":"LabelValue"
                    },
                    "IncludeEnv":{
                        "EnvKey":"EnvValue"
                    },
                    "ExcludeEnv":{
                        "EnvKey":"EnvValue"
                    },
                    "ExternalK8sLabelTag":{
                        "EnvKey":"EnvValue"
                    },
                    "ExternalEnvTag":{
                        "EnvKey":"EnvValue"
                    },
                    "K8sNamespaceRegex":"^(default|kube-system)$",
                    "K8sPodRegex":"^(deploy.*)$",
                    "K8sContainerRegex":"^(container1|container2)$"
                }
            }
        ]
    }

    重要参数说明如下:

    • 数据源类型

      固定为service_docker_stdout。

    • 容器过滤相关参数
      • Logtail 1.0.34以下版本,只支持通过环境变量、容器Label进行容器过滤。详细说明如下:

        Kubernetes中的命名空间名和容器名会映射到容器Label中,分别为io.kubernetes.pod.namespaceio.kubernetes.container.name。推荐使用这两个容器Label进行容器过滤。如果这两个容器Label未满足需求,请使用环境变量的黑白名单进行容器过滤。例如某Pod所属的命名空间为backend-prod,容器名为worker-server,如果您要采集包含该容器的日志,可以设置容器Label白名单为io.kubernetes.pod.namespace : backend-prodio.kubernetes.container.name : worker-server

        注意
        • 容器Label为Docker inspect中的Label,不是Kubernetes中的Label。如何获取,请参见获取容器Label
        • 环境变量为容器启动中配置的环境变量信息。如何获取,请参见获取容器环境变量
        • 请勿设置相同的LabelKey,如果重名只生效一个。
        参数 数据类型 是否必填 说明
        IncludeLabel map类型,其中LabelKey和LabelValue为string类型。 可选 容器Label白名单,用于指定待采集的容器。默认为空,表示采集所有容器的标准输出。如果您要设置容器Label白名单,那么LabelKey必填,LabelValue可选填。
        • 如果LabelValue为空,则容器Label中包含LabelKey的容器都匹配。
        • 如果LabelValue不为空,则容器Label中包含LabelKey=LabelValue的容器才匹配。

          LabelValue默认为字符串匹配,即只有LabelValue和容器Label的值完全相同才会匹配。如果该值以^开头并且以$结尾,则为正则匹配。例如:配置LabelKeyio.kubernetes.container.name,配置LabelValue^(nginx|cube)$,表示可匹配名为nginx、cube的容器。

        多个白名单之间为或关系,即只要容器Label满足任一白名单即可被匹配。

        ExcludeLabel map类型,其中LabelKey和LabelValue为string类型。 可选 容器Label黑名单,用于排除不采集的容器。默认为空,表示不排除任何容器。如果您要设置容器Label黑名单,那么LabelKey必填,LabelValue可选填。
        • 如果LabelValue为空,则容器Label中包含LabelKey的容器都将被排除。
        • 如果LabelValue不为空,则容器Label中包含LabelKey=LabelValue的容器才会被排除。

          LabelValue默认为字符串匹配,即只有LabelValue和容器Label的值完全相同才会匹配。如果该值以^开头并且以$结尾,则为正则匹配。例如:设置LabelKeyio.kubernetes.container.name,设置LabelValue^(nginx|cube)$,表示可匹配名为nginx、cube的容器。

        多个黑名单之间为或关系,即只要容器Label满足任一黑名单对即可被排除。

        IncludeEnv map类型,其中EnvKey和EnvValue为string类型。 可选 环境变量白名单,用于指定待采集的容器。默认为空,表示采集所有容器的标准输出。如果您要设置环境变量白名单,那么EnvKey必填,EnvValue可选填。
        • 如果EnvValue为空,则容器环境变量中包含EnvKey的容器都匹配。
        • 如果EnvValue不为空,则容器环境变量中包含EnvKey=EnvValue的容器才匹配。

          EnvValue默认为字符串匹配,即只有EnvValue和环境变量的值完全相同才会匹配。如果该值以^开头并且以$结尾,则为正则匹配,例如:设置EnvKeyNGINX_SERVICE_PORT,设置EnvValue^(80|6379)$,表示可匹配服务端口为80、6379的容器。

        多个白名单之间为或关系,即只要容器的环境变量满足任一键值对即可被匹配。

        ExcludeEnv map类型,其中EnvKey和EnvValue为string类型。 可选 环境变量黑名单,用于排除不采集的容器。默认为空,表示不排除任何容器。如果您要设置环境变量黑名单,那么EnvKey必填,EnvValue可选填。
        • 如果EnvValue为空,则容器环境变量中包含EnvKey的容器的日志都将被排除。
        • 如果EnvValue不为空,则容器环境变量中包含EnvKey=EnvValue的容器才会被排除。

          EnvValue默认为字符串匹配,即只有EnvValue和环境变量的值完全相同才会匹配。如果该值以^开头并且以$结尾,则为正则匹配,例如:设置EnvKeyNGINX_SERVICE_PORT,设置EnvValue^(80|6379)$,表示可匹配服务端口为80、6379的容器。

        多个黑名单之间为或关系,即只要容器的环境变量满足任一键值对即可被排除。

      • Logtail 1.0.34及以上版本,推荐使用Kubernetes层级的信息(Pod名称、Namespace名称、容器名称、Label)进行容器过滤。
        说明 由于在Kubernetes管控类资源(例如Deployment )运行时更改Label,不会重启具体的工作资源Pod,因此Pod无法感知此变更,可能导致匹配规则失效。设置K8s Label黑白名单时,请以Pod中的Kubernetes Label为准。关于Kubernetes Label的更多信息,请参见Labels and Selectors
        参数 数据类型 是否必填 说明
        IncludeK8sLabel map类型,其中LabelKey和LabelValue为string类型。 可选 通过Kubernetes Label白名单指定待采集的容器。如果您要设置Kubernetes Label白名单,那么LabelKey必填,LabelValue可选填。
        • 如果LabelValue为空,则Kubernetes Label中包含LabelKey的容器都匹配。
        • 如果LabelValue不为空,则Kubernetes Label中包含LabelKey=LabelValue的容器才匹配。

          LabelValue默认为字符串匹配,即只有LabelValue和Kubernetes Label的值完全相同才会匹配。如果该值以^开头并且以$结尾,则为正则匹配。例如设置LabelKeyapp,设置LabelValue^(test1|test2)$,表示匹配Kubernetes Label中包含app:test1、app:test2的容器。

        多个白名单之间为或关系,即只要Kubernetes Label满足任一白名单即可被匹配。

        ExcludeK8sLabel map类型,其中LabelKey和LabelValue为string类型。 可选 通过Kubernetes Label黑名单排除不采集的容器。如果您要设置Kubernetes Label黑名单,那么LabelKey必填,LabelValue可选填。
        • 如果LabelValue为空,则Kubernetes Label中包含LabelKey的容器都被排除。
        • 如果LabelValue不为空,则Kubernetes Label中包含LabelKey=LabelValue的容器才会被排除。

          LabelValue默认为字符串匹配,即只有LabelValue和Kubernetes Label的值完全相同才会匹配。如果该值以^开头并且以$结尾,则为正则匹配。例如设置LabelKeyapp,设置LabelValue^(test1|test2)$,表示匹配Kubernetes Label中包含app:test1、app:test2的容器。

        多个黑名单之间为或关系,即只要Kubernetes Label满足任一黑名单对即可被排除。

        K8sNamespaceRegex string 可选 通过Namespace名称指定采集的容器,支持正则匹配。例如设置为"K8sNamespaceRegex":"^(default|nginx)$",表示匹配nginx命名空间、default命名空间下的所有容器。
        K8sPodRegex string 可选 通过Pod名称指定待采集的容器,支持正则匹配。例如设置为"K8sPodRegex":"^(nginx-log-demo.*)$",,表示匹配以nginx-log-demo开头的Pod下的所有容器。
        K8sContainerRegex string 可选 通过容器名称指定待采集的容器(Kubernetes容器名称是定义在spec.containers中),支持正则匹配。例如设置为"K8scontainerRegex":"^(container-test)$",表示匹配所有名为container-test的容器。
    • 日志标签相关参数

      如果您使用的是Logtail 1.0.34及以上版本,您可以将环境变量和Kubernetes Label添加到日志,作为日志标签。

      参数 数据类型 是否必填 说明
      ExternalEnvTag map类型,其中EnvKey和EnvValue为string类型。 可选 设置环境变量日志标签后,日志服务将在日志中新增环境变量相关字段。例如设置EnvKeyVERSION,设置EnvValueenv_version,当容器中包含环境变量VERSION=v1.0.0时,会将该信息添加到日志中,即添加字段__tag__:__env_version__: v1.0.0
      ExternalK8sLabelTag map类型,其中LabelKey和LabelValue为string类型。 可选 设置Kubernetes Label日志标签后,日志服务将在日志中新增Kubernetes Label相关字段。例如设置LabelKeyapp,设置LabelValuek8s_label_app,当Kubernetes中包含Label app=serviceA时,会将该信息添加到日志中,即添加字段__tag__:__k8s_label_app__: serviceA
    • 其他参数
      参数 数据类型 是否必填 说明
      Stdout boolean 可选 是否采集标准输出stdout。

      该配置项为空,表示true,即默认采集标准输出stdout。

      Stderr boolean 可选 是否采集标准出错信息stderr。

      该配置项为空,表示true,即默认采集标准出错信息stderr。

      BeginLineRegex string 可选 行首匹配的正则表达式。

      该配置项为空,表示单行模式。

      如果该表达式匹配某行的开头,则将该行作为一条新的日志,否则将此行拼接到上一条日志。

      BeginLineTimeoutMs int 可选 行首匹配的超时时间。

      该配置项为空,表示使用默认的超时时间,即3000毫秒。

      如果3000毫秒内没有出现新日志,则结束匹配,将最后一条日志上传到日志服务。

      BeginLineCheckLength int 可选 行首匹配的长度。

      该配置项为空,表示使用默认的行首匹配的长度,即10×1024字节。

      如果行首匹配的正则表达式在前N个字节即可体现,推荐设置此参数,提升行首匹配效率。

      MaxLogSize int 可选 日志最大长度。

      该配置项为空,表示使用默认的最大长度,即512×1024字节。

      如果日志长度超过该值,则不再继续查找行首,直接上传。

      StartLogMaxOffset int 可选 首次采集时回溯历史数据长度。建议取值在[131072,1048576]之间,单位:字节。

      该配置项为空,表示使用默认的回溯历史数据长度,即131072字节(128 KB)。

  7. 预览数据及设置索引,单击下一步
    日志服务默认开启全文索引。您也可以根据采集到的日志,手动或者自动设置字段索引。更多信息,请参见配置索引

普通日志的Logtail采集配置示例

示例1:通过环境变量黑白名单过滤容器

采集环境变量为NGINX_SERVICE_PORT=80且不为POD_NAMESPACE=kube-system的容器的标准输出。

  1. 获取环境变量。

    您可以登录容器所在的宿主机查看容器的环境变量。具体操作,请参见获取容器环境变量

    环境变量配置方式
  2. 创建Logtail采集配置。

    Logtail采集配置示例如下所示。

    {
        "inputs": [
            {
                "type": "service_docker_stdout",
                "detail": {
                    "Stdout": true,
                    "Stderr": true,
                    "IncludeEnv": {
                        "NGINX_SERVICE_PORT": "80"
                    },
                    "ExcludeEnv": {
                        "POD_NAMESPACE": "kube-system"
                    }
                }
            }
        ]
    }

示例2:通过容器Label黑白名单过滤容器

采集容器Label为io.kubernetes.container.name=nginx的容器的标准输出。

  1. 获取容器Label。

    您可以登录容器所在的宿主机查看容器的Label。具体操作,请参见获取容器Label

    Label配置方式
  2. 创建Logtail采集配置。

    Logtail采集配置示例如下所示。

    {
        "inputs": [
            {
                "type": "service_docker_stdout",
                "detail": {
                    "Stdout": true,
                    "Stderr": true,
                    "IncludeLabel": {
                        "io.kubernetes.container.name": "nginx"
                    }
                }
            }
        ]
    }

示例3:通过Kubernetes Namespace名称、Pod名称和容器名称过滤容器

采集default命名空间下以nginx-log-demo开头的Pod中的nginx-log-demo-0容器的标准输出。

  1. 获取Kubernetes层级的信息。
    1. 获取Pod信息。k8s资源
    2. 获取Namespace等信息。K8s资源
  2. 创建Logtail采集配置。
    Logtail采集配置示例如下所示。
    {
        "inputs": [
            {
                "type": "service_docker_stdout",
                "detail": {
                    "Stdout": true,
                    "Stderr": true,
                    "K8sNamespaceRegex":"^(default)$",
                    "K8sPodRegex":"^(nginx-log-demo.*)$",
                    "K8sContainerRegex":"^(nginx-log-demo-0)$"
                }
            }
        ]
    }

示例4:通过Kubernetes Label过滤容器

采集Kubernetes Label中Key为job-name,Value以nginx-log-demo开头的所有容器的标准输出。

  1. 获取Kubernetes Label。K8s资源
  2. 创建Logtail采集配置。
    Logtail采集配置示例如下所示。
    {
        "inputs": [
            {
                "type": "service_docker_stdout",
                "detail": {
                    "Stdout": true,
                    "Stderr": true,
                    "IncludeK8sLabel":{
                        "job-name":"^(nginx-log-demo.*)$"
                    }
                }
            }
        ]
    }

多行日志的Logtail采集配置示例

对于Java异常堆栈输出(多行日志),您可以参见如下配置。
  • 日志示例
    2021-02-03 14:18:41.968  INFO [spring-cloud-monitor] [nio-8080-exec-4] c.g.s.web.controller.DemoController : service start
    2021-02-03 14:18:41.969 ERROR [spring-cloud-monitor] [nio-8080-exec-4] c.g.s.web.controller.DemoController : java.lang.NullPointerException
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    ...
    2021-02-03 14:18:41.968  INFO [spring-cloud-monitor] [nio-8080-exec-4] c.g.s.web.controller.DemoController : service start done
  • Logtail采集配置

    采集容器Label为app=monitor的容器的Java异常堆栈输出,该输出内容以固定格式的日期开头。为提高匹配效率,此处只判断行首的10个字节。采集到日志服务后,日志服务使用正则表达将其解析成timelevelmodulethreadmessage等字段。

    • inputs为Logtail采集配置,必选项,请根据您的数据源配置。
      说明 一个inputs中只允许配置一个类型的数据源。
    • processors为Logtail处理配置,可选项。您可以配置一种或多种处理方式。具体操作,请参见使用Logtail插件处理数据
    {
    "inputs": [
      {
        "detail": {
          "BeginLineCheckLength": 10,
          "BeginLineRegex": "\\d+-\\d+-\\d+.*",
          "IncludeLabel": {
            "app": "monitor"
          }
        },
        "type": "service_docker_stdout"
      }
    ],
    "processors": [
        {
            "type": "processor_regex",
            "detail": {
                "SourceKey": "content",
                "Regex": "(\\d+-\\d+-\\d+ \\d+:\\d+:\\d+\\.\\d+)\\s+(\\w+)\\s+\\[([^]]+)]\\s+\\[([^]]+)]\\s+([\\s\\S]*)",
                "Keys": [
                    "time",
                    "level",
                    "module",
                    "thread",
                    "message"
                ],
                "NoKeyError": true,
                "NoMatchError": true,
                "KeepSource": false
            }
        }
    ]
    }
  • 解析后的日志
    例如2018-02-03 14:18:41.968 INFO [spring-cloud-monitor] [nio-8080-exec-4] c.g.s.web.controller.DemoController : service start done日志,经过解析后的日志内容如下所示。其中:
    • _time_为日志采集时间。您可以通过Logtail采集配置中的时区属性参数设置_time_的时区。
    • time为日志中存在的时间内容,是从日志中提取得到的。
    __tag__:__hostname__:logtail-dfgef
    _container_name_:monitor
    _image_name_:example.com-hangzhou.aliyuncs.xxxxxxxxxxxxxxx
    _namespace_:default
    _pod_name_:monitor-6f54bd5d74-rtzc7
    _pod_uid_:7f012b72-04c7-11e8-84aa-00163f00c369
    _source_:stdout
    _time_:2018-02-02T14:18:41.979147844Z
    time:2018-02-02 02:18:41.968
    level:INFO
    module:spring-cloud-monitor
    thread:nio-8080-exec-4
    class:c.g.s.web.controller.DemoController
    message:service start done

日志字段

Kubernetes集群的每条日志默认上传的字段如下所示。
字段名称 说明
_time_ 日志采集时间,例如2021-02-02T02:18:41.979147844Z
_source_ 日志源类型,stdout或stderr。
_image_name_ 镜像名
_container_name_ 容器名
_pod_name_ Pod名
_namespace_ Pod所在的命名空间
_pod_uid_ Pod的唯一标识