zoukankan      html  css  js  c++  java
  • k8s 应用日志收集

    • [ ] 在进行日志收集的过程中,我们首先想到的是使用Logstash,因为它是ELK stack中的重要成员,但是在测试过程中发现,Logstash是基于JDK的,在没有产生日志的情况单纯启动Logstash就大概要消耗500M内存,在每个Pod中都启动一个日志收集组件的情况下,使用logstash有点浪费系统资源,经人推荐我们选择使用Filebeat替代,经测试单独启动Filebeat容器大约会消耗12M内存,比起logstash相当轻量级。

    方案选择
    Kubernetes官方提供了EFK的日志收集解决方案,但是这种方案并不适合所有的业务场景,它本身就有一些局限性,例如:

    所有日志都必须是out前台输出,真实业务场景中无法保证所有日志都在前台输出
    只能有一个日志输出文件,而真实业务场景中往往有多个日志输出文件
    Fluentd并不是常用的日志收集工具,我们更习惯用logstash,现使用filebeat替代
    我们已经有自己的ELK集群且有专人维护,没有必要再在kubernetes上做一个日志收集服务
    基于以上几个原因,我们决定使用自己的ELK集群。

    Kubernetes集群中的日志收集解决方案

    编号 方案 优点 缺点
    1 每个app的镜像中都集成日志收集组件 部署方便,kubernetes的yaml文件无须特别配置,可以为每个app自定义日志收集配置 强耦合,不方便应用和日志收集组件升级和维护且会导致镜像过大
    2 单独创建一个日志收集组件跟app的容器一起运行在同一个pod中 低耦合,扩展性强,方便维护和升级 需要对kubernetes的yaml文件进行单独配置,略显繁琐
    3 将所有的Pod的日志都挂载到宿主机上,每台主机上单独起一个日志收集Pod 完全解耦,性能最高,管理起来最方便 需要统一日志收集规则,目录和输出方式

    综合以上优缺点,我们选择使用方案二。

    该方案在扩展性、个性化、部署和后期维护方面都能做到均衡,因此选择该方案。

    filebeat日志收集架构图
    图片 - filebeat日志收集架构图
    image

    镜像地址:https://github.com/flyhxg/docker-test/tree/master/filebeat-5.4.0

    测试
    我们部署一个应用filebeat来收集日志的功能测试。

    创建应用yaml文件filebeat-test.yaml。

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: filebeat-test
      namespace: default
    spec:
      replicas: 3
      template:
        metadata:
          labels:
            k8s-app: filebeat-test
        spec:
          containers:
          - image: 192.168.20.210:5000/filebeat:5.4.0
            name: filebeat
            volumeMounts:
            - name: app-logs
              mountPath: /log
            - name: filebeat-config
              mountPath: /etc/filebeat/
          - image: harbor-001.jimmysong.io/library/analytics-docker-test:Build_8
            name : app
            ports:
            - containerPort: 80
            volumeMounts:
            - name: app-logs
              mountPath: /usr/local/TalkingData/logs
          volumes:
          - name: app-logs
            emptyDir: {}
          - name: filebeat-config
            configMap:
              name: filebeat-config
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: filebeat-test
      labels:
        app: filebeat-test
    spec:
      ports:
      - port: 80
        protocol: TCP
        name: http
      selector:
        run: filebeat-test
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: filebeat-config
    data:
      filebeat.yml: |
        filebeat.prospectors:
        - input_type: log
          paths:
            - "/log/*"
            - "/log/usermange/common/*"
        output.elasticsearch:
          hosts: ["172.23.5.255:9200"]
          username: "elastic"
          password: "changeme"
          index: "filebeat-docker-test"
    

    说明

    该文件中包含了配置文件filebeat的配置文件的ConfigMap,因此不需要再定义环境变量。

    当然你也可以不同ConfigMap,通过传统的传递环境变量的方式来配置filebeat。

    例如对filebeat的容器进行如下配置:

      containers:
      - image: 192.168.20.210:5000/filebeat:5.4.0
        name: filebeat
        volumeMounts:
        - name: app-logs
          mountPath: /log
        env: 
        - name: PATHS
          value: "/log/*"
        - name: ES_SERVER
          value: 172.23.5.255:9200
        - name: INDEX
          value: logstash-docker
        - name: INPUT_TYPE
          value: log
    

    这里如果有想不通路径下的日志区分,可以加上document_type

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: filebeat-config
    data:
      filebeat.yml: |
        filebeat.prospectors:
        - input_type: log
          paths:
            - "/log/*.log"
          document_type: app-logs
          multiline.pattern: '^[[:space:]]+|^Caused by:|^#{3}|^;|^org|^com'
          multiline.negate: false
          multiline.match: after
        - input_type: log
          paths:
            - "/logs/*.log"
          document_type: access-logs
          multiline.pattern: '^[[:space:]]+|^Caused by:|^#{3}|^;|^org|^com'
          multiline.negate: false
          multiline.match: after
        output.elasticsearch:
          hosts: ["192.168.30.21:9200"]
          index: "filebeat-test-%{+yyyy.MM.dd}"
    

    目前使用这种方式会有个问题,及时PATHS只能传递单个目录,如果想传递多个目录需要修改filebeat镜像的docker-entrypoint.sh脚本,对该环境变量进行解析增加filebeat.yml文件中的PATHS列表。

    推荐使用ConfigMap,这样filebeat的配置就能够更灵活。

    注意事项

    将app的/usr/local/TalkingData/logs目录挂载到filebeat的/log目录下。
    该文件可以在manifests/test/filebeat-test.yaml找到。
    我使用了自己的私有镜像仓库,测试时请换成自己的应用镜像。
    Filebeat的环境变量的值配置请参考https://github.com/rootsongjc/docker-images
    创建应用

    部署Deployment

    kubectl create -f filebeat-test.yaml
    

    查看http://172.23.5.255:9200/_cat/indices将可以看到列表有这样的indices:

    green open filebeat-docker-test            7xPEwEbUQRirk8oDX36gAA 5 1   2151     0   1.6mb 841.8kb
    

    访问Kibana的web页面,查看filebeat-2017.05.17的索引,可以看到filebeat收集到了app日志。

    点开每个日志条目,可以看到以下详细字段:

    filebeat收集的日志详细信息
    图片 - filebeat收集的日志详细信息
    _index值即我们在YAML文件的configMap中配置的index值
    beat.hostname和beat.name即pod的名称
    source表示filebeat容器中的日志目录
    我们可以通过人为得使index = service name,这样就可以方便的收集和查看每个service的日志。

    在使用了6.2.4版本的ELK以后,使用如上配置,if [type]匹配不到在filebeat里面使用document_type定义的字符串。在多次调试和询问后,发现在6.0版本以上已经取消了document_type的定义。如果要实现以上的配置只能使用如下配置
    三、解决方案
    ?解决方案为在filebeat里面新增一个fields字段,service : GameStatis都是自己定义的,定义完成后使用Logstash的if 判断,条件为if [fields][service] == "GameStatis".就可以了。
    ?filebeat配置:

      filebeat.yml: |
        filebeat.prospectors:
        - input_type: log
          paths:
            - "/log/*.log"
          fields:
            service: app_logs
    
  • 相关阅读:
    SQL之mysql常用操作语句(入门级)
    总结了一些指针易出错的常见问题(七)
    C++之类和对象课后习题1
    SQL之50个常用的SQL语句
    SQL之经典SQL语句大全
    C语言之计算字符串最后一个单词的长度,单词以空格隔开
    spring之HttpInvoker
    Java之解压流(ZipInputStream)
    jetty之嵌入式开发
    java之压缩流(ZipOutputStream)
  • 原文地址:https://www.cnblogs.com/flyhgx/p/9055774.html
Copyright © 2011-2022 走看看