• ELK:收集k8s容器日志最佳实践


    简介


    • 关于日志收集这个主题,这已经是第三篇了,为什么一再研究这个课题,因为这个课题实在太重要,而当今优秀的开源解决方案还不是很明朗;

    • 就docker微服务化而言,研发有需求标准输出,也有需求文件输出,每次登录到服务器上去查看日志又多有不妥;现有的解决方案ELK,每次收集新应用日志都要更改配置文件重新适配日志路径足以让我们崩溃;

    • 对于k8s,没有日志系统推行工作就无法进行,总不能让开发小伙伴登录到k8s上去找日志吧,鬼知道在哪个pod里;当然,k8s官方提供了解决方案efk,efk最大的问题就是无法对日志有效分组,所有日志都在一个索引里,影响查询速度不说,对于研发小伙伴查找属于自己应用的日志也很困难,不得不说,这个解决方案很鸡肋;

    • 综上三条,能够统筹普通应用、docker微服务、k8s的日志收集方案迫在眉睫,今天就将能解决这些问题的日志收集方案的最佳实践分享给大家;

    • 该实践采用的是阿里云的开源工具 log-pilot 采集日志,采集的过程中就将各种日志打标分类,类似最近比较火的垃圾分类,逻辑结构图如下:
      img-w500

    • 三种节点类型:

      • k8s使用daemonset类型的副本集,使每个节点运行一个 log-pilot 来收集日志,该日志会含有 k8s_container_name、k8s_pod、k8s_node_name、 k8s_pod_namespace 等打标数据,输出到相应的 logstash 来做索引
      • 运行docker微服务的主机上运行一个 log-pilot 来收集日志,该日志会含有 docker_container、topic、index 等打标数据,输出到相应的 logstash 来做索引
      • 普通非容器程序的日志可以采用 filebeat 收集,日志中可以自定义标签和字段,输出到对应的 logstash 来做索引

    log-pilot 说明和配置


    • 容器日志采集模式现在流行的方式有 SideCar模式和 Node模式,SideCar模式会占用大量资源,而Node模式需要智能的 logging agent 配合,而 log-pilot 就是那个智能的agent
    • log-pilot 可同时支持stdout和容器内文件日志采集,支持声明式日志配置,同时拥有自动感知(发现)机制、自动checkpoint及具柄保持机制和自动日志数据打标
    • log-pilot 除拥有上述功能,还支持多插件多后端,低消耗,高性能,具体情况请看 K8S 日志实践

    log-pilot 插件支持

    img-w500

    log-pilot 工作模式

    img-w500

    log-pilot 配置方法

    • Kubernetes 下,Log-Pilot 可以依据环境变量 aliyun_logs_$name = $path 动态地生成日志采集配置文件,其中包含两个变量:
      • $name 是我们自定义的一个字符串,它在不同的场景下指代不同的含义,在本场景中,将日志采集到 ElasticSearch 的时候,这个 $name 表示的是 Index
      • 另一个是 $path,支持两种输入形式,stdout 和容器内部日志文件的路径,对应日志标准输出和容器内的日志文件。
      • 第一种约定关键字 stdout 表示的是采集容器的标准输出日志,如本例中我们要采集 tomcat 容器日志,那么我们通过配置标签 aliyun.logs.catalina=stdout 来采集 tomcat 标准输出日志。
      • 第二种是容器内部日志文件的路径,也支持通配符的方式,通过配置环境变量 aliyun_logs_access=/usr/local/tomcat/logs/*.log 来采集 tomcat 容器内部的日志。当然如果你不想使用 aliyun 这个关键字,Log-Pilot 也提供了环境变量 PILOT_LOG_PREFIX 可以指定自己的声明式日志配置前缀,比如 PILOT_LOG_PREFIX: "aliyun,custom"
    • 此外,Log-Pilot 还支持多种日志解析格式,通过 aliyun_logs_$name_format=<format> 标签就可以告诉 Log-Pilot 在采集日志的时候,同时以什么样的格式来解析日志记录,支持的格式包括:none、json、csv、nginx、apache2regxp
    • Log-Pilot 同时支持自定义 tag,我们可以在环境变量里配置 aliyun_logs_$name_tags="K1=V1,K2=V2",那么在采集日志的时候也会将 K1=V1K2=V2 采集到容器的日志输出中。自定义 tag 可帮助您给日志产生的环境打上 tag,方便进行日志统计、日志路由和日志过滤。

    log-pilot 在k8s上的配置

    cat > ops-log-pilot-filebeat-ds.yaml << EOF
    apiVersion: extensions/v1beta1
    kind: DaemonSet
    metadata:
      name: ops-log-pilot-filebeat-ds
      namespace: ops
    spec:
      selector:
        matchLabels:
          app: log-pilot-filebeat
          release: stable
      template:
        metadata:
          labels:
            app: log-pilot-filebeat
            release: stable
        spec:
          containers:
          - name: log-pilot-filebeat
            image: registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.6-filebeat
            env:
            - name: "NODE_NAME"
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: "PILOT_LOG_PREFIX"
              value: "glinux"
            - name: "LOGGING_OUTPUT"
              value: "logstash"
            # 请确保集群到ES网络可达
            - name: "LOGSTASH_HOST"
              value: "logstash.glinux.top"
            - name: "LOGSTASH_PORT"
              value: "5053"
            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
          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
    EOF
    # 调用方法
    kubectl apply -f ops-log-pilot-filebeat-ds.yaml
    

    log-pilot 在docker主机上配置

    docker run -d 
       --name log-pilot-filebeat 
       -v /var/run/docker.sock:/var/run/docker.sock 
       -v /etc/localtime:/etc/localtime 
       -v /:/host:ro 
       --cap-add SYS_ADMIN 
       -e PILOT_LOG_PREFIX=glinux 
       -e LOGGING_OUTPUT=logstash 
       -e LOGSTASH_HOST=logstash..glinux.top 
       -e LOGSTASH_PORT=5063 
       --restart=always 
       registry.cn-hangzhou.aliyuncs.com/acs/log-pilot:0.9.5-filebeat
    

    logstash 配置方法


    • logstash的三个实例,我是运行在同一台机器上,同时kibana也是运行在这台机器上
    • 当然也可以通过一个logstash实例,配置中采用判断条件建立不同索引,但会影响性能,所以这里我起了三个实例
    • logstash的主要功能是将收集到的日志进行拆分,采用某些字段建成索引,传递给 elasticsearch 集群
    • 这里强烈建议使用阿里云的 elasticsearch 集群,可以先使用免费版 1核2G内存20G SSD 三组,原因是阿里云和elastic有合作,es有授权,很多功能可以使用,比如用户管理,监控等,后面会说到

    logstash 处理k8s日志

    • logstash 监控配置文件,监控信息会体现在kibana中
    cat > /data/logslogstash.yml << EOF
    xpack.monitoring.elasticsearch.url: http://xxxxxxxxxxxxxxxx.es.aliyuncs.com:9200
    xpack.monitoring.elasticsearch.username: "user"
    xpack.monitoring.elasticsearch.password: "pass"
    EOF
    

    配置文件

    cat > /data/conf/logstash-k8s.conf << EOF
    input {
      beats {
        host => "0.0.0.0"
        port => "5043"
      }
    }
    filter {
      grok {
        match => { "message" => "%{TIMESTAMP_ISO8601:log-timestamp} %{LOGLEVEL:log-level} %{JAVALOGMESSAGE:log-msg}" }
      }
      mutate {
    #    remove_field => ["message"]
        remove_field => ["beat"]
       }
    }
    output {
      stdout { codec => rubydebug }
      elasticsearch {
            hosts => ["http://xxxxxxxxxxxxxxxx.es.aliyuncs.com:9200"]
            user => ["user"]
            password => ["pass"]
            index => "%{k8s_container_name}-%{+YYYY.MM.dd}"
      }
    }
    EOF
    

    启动命令

    docker run -p 5053:5043 -d 
        --user root 
        --log-driver json-file 
        --log-opt max-size=10m 
        --log-opt max-file=3 
        --name logstash-k8s 
        --restart=always 
        -v /data/conf/logstash-k8s.conf:/usr/share/logstash/pipeline/logstash.conf 
        -v /data/conf/logstash.yml:/usr/share/logstash/config/logstash.yml 
        logstash:6.6.2
    

    logstash 处理docker日志

    配置文件

    cat > /data/conf/logstash-docker.conf << EOF
    input {
      beats {
        host => "0.0.0.0"
        port => "5043"
      }
    }
    filter {
      grok {
        match => { "message" => "%{TIMESTAMP_ISO8601:log-timestamp} %{LOGLEVEL:log-level} %{JAVALOGMESSAGE:log-msg}" }
      }
      mutate {
    #    remove_field => ["message"]
        remove_field => ["beat"]
       }
    }
    output {
      stdout { codec => rubydebug }
      elasticsearch {
            hosts => ["xxxxxxxxxxxxxxxx.es.aliyuncs.com:9200"]
            user => ["uesr"]
            password => ["pass"]
            index => "%{docker_container}-%{+YYYY.MM.dd}"
      }
    }
    EOF
    

    启动命令

    docker run -p 5063:5043 -d 
        --user root 
        --log-driver json-file 
        --log-opt max-size=10m 
        --log-opt max-file=3 
        --name logstash-docker 
        --restart=always 
        -v /data/conf/logstash-docker.conf:/usr/share/logstash/pipeline/logstash.conf 
        -v /data/conf/logstash.yml:/usr/share/logstash/config/logstash.yml 
        logstash:6.6.2
    

    elasticsearch 说明


    • 如上所述,elasticsearch 使用阿里云的产品 阿里云 · Elasticsearch
    • 可以先使用免费版 1核2G内存20G SSD 三组
    • 开通后会有 地址、用户名、密码等信息,这些是要填写在logstash的输出配置文件中
    • 阿里云和elastic有合作,es有授权,用户管理、用户登录、索引监控、节点监控、logstash监控等功能均可正常使用
    • 除以上外,定期清理es的索引也很有必要,可以参考我之前的博客 ELK:收集Docker容器日志 中 定时删除过期日志索引文件 章节
    • 使用阿里云的es后,kibana上会有授权体现,这里贴两张图展示一下功能

    kibana 的监控

    img-w500

    kibana 的管理

    img-w500

    kibana 说明和配置


    • 下面步骤操作完毕启动后,此处访问 http://IP:5603,用户名和密码同 elasticserach 的,输入即可登录kibana,如此建立索引,就可以正常的玩耍了

    kibana 配置文件

    • 如下的配置文件会屏蔽掉许多没用的插件功能模块,如上图显示的清爽界面
    cat > /data/conf/kibana-es-aliyun.yml << EOF
    # Default Kibana configuration from kibana-docker.
    server.name: kibana
    server.host: "0"
    elasticsearch.hosts: http://xxxxxx.es.aliyuncs.com:9200
    elasticsearch.username: user
    elasticsearch.password: pass
    xpack.monitoring.ui.container.elasticsearch.enabled: true
    timelion.enabled: false
    console.enabled: false
    xpack.grokdebugger.enabled: false
    xpack.searchprofiler.enabled: false
    xpack.canvas.enabled: false
    xpack.ml.enabled: false
    xpack.infra.enabled: false
    xpack.apm.enabled: false
    xpack.graph.enabled: false
    EOF
    

    kibana 启动命令

    docker run -p 5603:5601 -d 
        --user root 
        --log-driver json-file 
        --log-opt max-size=10m 
        --log-opt max-file=3 
        --name kibana-es-aliyun 
        --restart=always 
        -e ELASTICSEARCH_URL=http://xxxxxx.es.aliyuncs.com:9200 
        kibana:6.6.2
    
    • 下面来看下优秀的登录界面
      img-w500

    日志收集效果验证


    docker日志收集案例 tomcat

    • 注意 label 的配置
       docker run -it -d --name tomcat -p 10080:8080 
        -v /var/logs/:/usr/local/tomcat/logs 
        --label glinux.logs.catalina=stdout 
        --label glinux.logs.access=/usr/local/tomcat/logs/localhost_access_log.*.txt 
        tomcat
    
    • 日志收集效果如下图:
      img-w500

    k8s日志收集案例 tomcat

    • 注意env的配置
    cat > tomcat-pod.yaml << EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: tomcat
    spec:
      containers:
      - name: tomcat
        image: "tomcat:7.0"
        env:
    # 1、stdout为约定关键字,表示采集标准输出日志
    # 2、配置标准输出日志采集到ES的catalina索引下
        - name: glinux_logs_catalina
          value: "stdout"
    # 1、配置采集容器内文件日志,支持通配符
    # 2、配置该日志采集到ES的access索引下
        - name: glinux_logs_access
          value: "/usr/local/tomcat/logs/catalina.*.log"
    # 容器内文件日志路径需要配置emptyDir
        volumeMounts:
        - name: tomcat-log
          mountPath: /usr/local/tomcat/logs
      volumes:
      - name: tomcat-log
        emptyDir: {}
    EOF
    # 调用
    kubectl apply -f tomcat-pod.yaml -n ops
    
    • 日志收集效果如下图:
      img-w500

    参考文档


  • 相关阅读:
    jdk1.8StreamApi
    Python 【类的创建和类的实例化】
    Python【网络编程】
    Python 【图片转字符画】
    echarts 【图表的基本使用】
    Java 【Math】
    Java 【循环语句】
    Java 【instanceof使用】
    java【第三课 条件语句】
    Java【第二课 扫描仪 & 布尔数据类型】
  • 原文地址:https://www.cnblogs.com/William-Guozi/p/elk-k8s.html
Copyright © 2020-2023  润新知