容器引擎Docker和容器编排kubernetes`如何优雅的收集容器日志

Log-Pilot 介绍

log-Pilot 是一个阿里开源的智能容器日志采集工具,它不仅能够高效便捷地将容器日志采集输出到多种存储日志后端,同时还能够动态地发现和采集容器内部的日志文件。

针对前面提出的日志采集难题,Log-Pilot 通过声明式配置实现强大的容器事件管理,可同时获取容器标准输出和内部文件日志,解决了动态伸缩问题,此外,Log-Pilot 具有自动发现机制,CheckPoint 及句柄保持的机制,自动日志数据打标,有效应对动态配置、日志重复和丢失以及日志源标记等问题。

log-pilot开源地址: https://github.com/AliyunContainerService/log-pilot

log-pilot官方帮助文档: https://help.aliyun.com/document_detail/50441.html

使用Log-Pilot进行Docker日志收集

部署Log-PilotDocker

执行docker命令启动 log-pilot

docker run --rm -it \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /:/host \
    --privileged  \
    registry.cn-hangzhou.aliyuncs.com/acs-sample/log-pilot:0.9.5-filebeat

至此你会看到Log-Pilot的启动日志

怎么精确搜索容器日志 容器日志采集_怎么精确搜索容器日志

不要关闭终端。新开一个终端启动 tomcat。tomcat 镜像属于少数同时使用了 stdout 和文件日志的 Docker 镜像,非常适合这里的演示。

docker run -it --rm -p 10880:8080 -v /usr/local/tomcat/logs --label aliyun.logs.catalina=stdout hub.c.163.com/library/tomcat:latest

启动 tomcat 之后,您会发现 log-pilot 的终端立即输出了一大堆的内容,其中包含 tomcat 启动时输出的 stdout 日志,也包括 log-pilot 自己输出的一些调试信息。

怎么精确搜索容器日志 容器日志采集_怎么精确搜索容器日志_02

说明:

  • aliyun.logs.catalina=stdout 告诉 log-pilot 这个容器要收集 stdout 日志。
  • aliyun.logs.access=/usr/local/tomcat/logs/localhost_access_log.*.txt 则表示要收集容器内 /usr/local/tomcat/logs/ 目录下所有名字匹配 localhost_access_log.*.txt 的文件日志。后面会详细介绍 label 的用法。

使用 ElasticSearch + kibana + Log-Pilot

说明 执行之前,先把 ELASTICSEARCH_HOSTELASTICSEARCH_PORT 两个变量替换成您实际使用的值。 ELASTICSEARCH_PORT 一般为 9200。

docker run --rm -it \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /:/host \
    --privileged \
    -e FLUENTD_OUTPUT=elasticsearch \
    -e ELASTICSEARCH_HOST=${ELASTICSEARCH_HOST} \
    -e ELASTICSEARCH_PORT=${ELASTICSEARCH_PORT} \
    registry.cn-hangzhou.aliyuncs.com/acs-sample/log-pilot:0.9.5-filebeat

相比前面启动 log-pilot 的方式,这里增加了三个环境变量:

  • FLUENTD_OUTPUT=elasticsearch:把日志发送到 ElasticSearch。
  • ELASTICSEARCH_HOST=${ELASTICSEARCH_HOST}:ElasticSearch 的域名。
  • ELASTICSEARCH_PORT=${ELASTICSEARCH_PORT}:ElasticSearch 的端口号。

继续运行前面的 tomcat,再次访问,让 tomcat 产生一些日志,所有这些新产生的日志都将发送到 ElasticSearch 里。

打开 kibana,此时您还看不到新日志,需要先创建 index。log-pilot 会把日志写到 ElasticSearch 特定的 index下,规则如下:

如果应用上使用了标签 aliyun.logs.tags,并且 tags 里包含 target,使用 target 作为 ElasticSearch 里的 index。否则,使用标签 aliyun.logs.XXX 里的 XXX 作为 index。

怎么精确搜索容器日志 容器日志采集_怎么精确搜索容器日志_03

最终会在 ElasticSearch中看到日志信息

label 说明

启动 tomcat 时,声明了下面两个 label 来告诉 log-pilot 这个容器的日志位置。

--label aliyun.logs.catalina=stdout 
--label aliyun.logs.access=/usr/local/tomcat/logs/localhost_access_log.*.txt

您还可以在应用容器上添加更多的标签。

aliyun.logs.$name = $path
  • 变量 name 是日志名称,只能包含 09、az、A~Z 和连字符(-)。
  • 变量 path 是要收集的日志路径,必须具体到文件,不能只写目录。文件名部分可以使用通配符,例如,/var/log/he.log/var/log/*.log 都是正确的值,但 /var/log 不行,不能只写到目录。stdout 是一个特殊值,表示标准输出。
aliyun.logs.$name.format

:日志格式,目前支持以下格式。

  • none:无格式纯文本。
  • json:json 格式,每行一个完整的 json 字符串。
  • csv:csv 格式。
aliyun.logs.$name.tags

:上报日志时,额外增加的字段,格式为k1=v1,k2=v2,每个 key-value 之间使用逗号分隔,例如

aliyun.logs.access.tags="name=hello,stage=test"

上报到存储的日志里就会出现name 字段和stage字段。

如果使用 ElasticSearch 作为日志存储,target 这个 tag 具有特殊含义,表示 ElasticSearch 里对应的 index。

使用Log-Pilotkubernetes进行日志收集

部署Log-pilotk8s集群中

这里Log-Pilot整合了ElasticSearch作为日志存储

执行该yaml文件部署log-pliot, 执行完成后会看到每个node节点中都有一个log-pilot的守护pod

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: log-pilot
  labels:
    app: log-pilot
  # 设置期望部署的namespace
  namespace: logging
spec:
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: log-pilot
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
    spec:
      # 是否允许部署到Master节点上
      # tolerations:
      # - key: node-role.kubernetes.io/master
      #   effect: NoSchedule
      containers:
      - name: log-pilot
        # 版本请参考https://github.com/AliyunContainerService/log-pilot/releases
        image: registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.7-fluentd
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            memory: 500Mi
          requests:
            cpu: 200m
            memory: 200Mi
        env:
          - name: "NODE_NAME"
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: "LOGGING_OUTPUT"
            value: "elasticsearch"
          # 请确保集群到ES网络可达
          - name: "ELASTICSEARCH_HOSTS"
            value: "k8s-es-service:9200"
          # 配置ES访问权限
          #- name: "ELASTICSEARCH_USER"
          #  value: "{es_username}"
          #- name: "ELASTICSEARCH_PASSWORD"
          #  value: "{es_password}"
        volumeMounts:
        - name: sock
          mountPath: /var/run/docker.sock
        - name: root
          mountPath: /host
          readOnly: true
        - name: varlib
          mountPath: /var/lib/filebeat
        - name: varlog
          mountPath: /var/log/filebeat
        - name: localtime
          mountPath: /etc/localtime
          readOnly: true
        livenessProbe:
          failureThreshold: 3
          exec:
            command:
            - /pilot/healthz
          initialDelaySeconds: 10
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 2
        securityContext:
          capabilities:
            add:
            - SYS_ADMIN
      terminationGracePeriodSeconds: 30
      volumes:
      - name: sock
        hostPath:
          path: /var/run/docker.sock
      - name: root
        hostPath:
          path: /
      - name: varlib
        hostPath:
          path: /var/lib/filebeat
          type: DirectoryOrCreate
      - name: varlog
        hostPath:
          path: /var/log/filebeat
          type: DirectoryOrCreate
      - name: localtime
        hostPath:
          path: /etc/localtime

执行个demo测试log-pilot是否正常

apiVersion: v1
kind: Pod
metadata:
  name: tomcat
spec:
  containers:
  - name: tomcat
    image: hub.c.163.com/library/tomcat:7-jre8-alpine
    env:
    - name: aliyun_logs_catalina
      value: "stdout"
    - name: aliyun_logs_access
      value: "/usr/local/tomcat/logs/catalina.*.log"
    - name: aliyun_logs_access_tags
      value: "aa=bb,cc=dd"
    - name: aliyun_logs_catalina_tags
      value: "aa=bb,cc=ddaaa"
    volumeMounts:
      - name: tomcat-log
        mountPath: /usr/local/tomcat/logs
  volumes:
    - name: tomcat-log
      emptyDir: {}

最终日志会在es中出现,至此日志配置完成