• elk 日志收集 filebeat 集群搭建 php业务服务日志 nginx日志 json 7.12版本 ELK 解决方案


    难的不是技术,难的是业务。熟悉业务流程才是最难的。

    其实搜索进来的每一个人的需求不一样,希望你能从我的这篇文章里面收获到。

    建议还是看官方文档,更全面一些。

    一、背景

    1,收集nginx  access  error日志,nginx日志最开始是main日志,后来被我改成了json日志方便收集

    2,收集php info  error日志,php日志就是标准的

    3,每一个php服务都是docker容器启动

    4,每一个php容器服务里面都有一个nginx服务

    5,需要收集日志的php服务大概30个

    6,k8s集群三台节点

    7,需要收集qa,dev环境日志,qa,dev其实就是k8s集群里面的两个namespaces

    8,需要提取特定的字段

    1.1 日志目录

    每一个php容器服务都是这个日志结构

    /var/log/nginx/access.log
    /var/log/nginx/error.log
    /var/www/html/storage/logs/lumen.log
    /var/www/html/storage/autoLogs/sysError/lumen.log

    1.2 思考点&解决方案

    1,采集的Beat用哪个

            filebeat:轻量级,cpu 内存小,咱们的需求只是单纯的采集数据。进程稳定。

    2,Beat的部署方式

            filebeat部署在k8s 节点宿主机,二进制部署

    3,日志的采集方式

            Php容器日志目录挂载到宿主机

    4,qa,dev环境怎么区分

            kibana区分用index

            容器日志目录挂载到宿主机。

            $env=qa,dev

            $appname=php所有的服务名称

            /data/service-logs/${env}/${appname}/{nginx,storage/{logs,autoLogs/sysError/}}

                    例如:wxx 服务的dev环境宿主机目录结构

                    /data/service-logs/dev/wxx/nginx/      这个下面有access  error日志

                    /data/service-logs/dev/wxx/storage/logs/      php info日志

                    /data/service-logs/dev/wxx/storage/autoLogs/sysError/        php  error日志

    5,怎么区分php服务

            kibana:添加字段app_name

    6,日志类型怎么区分

            kibana:添加字段log_topics

    二、集群服务器配置

    我这里采用的是3节点,其实主要就是es集群。

    这样的配置足够我这的需求了,你可以按照需求调整。

    我这里大概每小时收集5万条数据。每天数据量大概是2G。

    ip cpu mem 软件
    192.168.31.61 4 8G es,kibana,cerebro
    192.168.31.62 4 8G  
    192.168.31.63 4 8G  

     

    三、部署服务

    3.1 部署es

    3.1.1 下载

    cd /opt/

    wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.12.1-linux-x86_64.tar.gz

    3.1.2 配置

    tar xf elasticsearch-7.12.1-linux-x86_64.tar.gz
    cd /opt/elasticsearch-7.12.1/config
     
    node1
    vim elasticsearch.yml
    cluster.name: dev-qa-es                          # 集群的名称
    node.name: 192.168.31.61                         # node1节点的名称
    path.data: /data/elasticsearch/data              # 数据目录
    path.logs: /data/elasticsearch/log               # 日志目录
    network.host: 192.168.31.61                      # 节点的ip 就是监听的地址
    http.port: 9200                                  # es端口
    discovery.seed_hosts: ["192.168.31.62", "192.168.31.63"]        # 除自己之外的两个节点
    cluster.initial_master_nodes: ["192.168.31.61", "192.168.31.62", "192.168.31.63"]        # 所有的master
     
    node2
    cluster.name: dev-qa-es
    node.name: 192.168.31.62
    path.data: /data/elasticsearch/data
    path.logs: /data/elasticsearch/log
    network.host: 192.168.31.62
    http.port: 9200
    discovery.seed_hosts: ["192.168.31.61", "192.168.31.63"]
    cluster.initial_master_nodes: ["192.168.31.61", "192.168.31.62", "192.168.31.63"]
     
    node3
    cluster.name: dev-qa-es
    node.name: 192.168.31.63
    path.data: /data/elasticsearch/data
    path.logs: /data/elasticsearch/log
    network.host: 192.168.31.63
    http.port: 9200
    discovery.seed_hosts: ["192.168.31.61", "192.168.31.62"]
    cluster.initial_master_nodes: ["192.168.31.61", "192.168.31.62", "192.168.31.63"]

    3.1.3 配置jdk

    1,因为elasticsearch是java写的,所以需要java环境。

    2,可以自己手动在机器上面安装java。但是会造成这台机器上面的java环境固定。或者会对以前的java版本产生改变。

    3,所以elasticsearch 7以上版本会自带jdk,所以我们只需要告诉elasticsearch使用自带的jdk即可。

    其实主要控制es用不用自带java的 变量就俩 ES_JAVA_HOME   JAVA_HOME

    cd /opt/elasticsearch-7.12.1/bin
     
    vim elasticsearch-env
    ...
    ES_HOME=`dirname "$SCRIPT"`
    # now make ES_HOME absolute
    ES_HOME=`cd "$ES_HOME"; pwd`
    while [ "`basename "$ES_HOME"`" != "bin" ]; do
      ES_HOME=`dirname "$ES_HOME"`
    done
    ES_HOME=`dirname "$ES_HOME"`
    ES_JAVA_HOME=/opt/elasticsearch-7.12.1/jdk   # 我只是添加了一个ES_JAVA_HOME变量,下面的if判断会判断这个变量。
    # now set the classpath
    ES_CLASSPATH="$ES_HOME/lib/*"
    # now set the path to java
    if [ ! -z "$ES_JAVA_HOME" ]; then        # 会判断这个变量是否为空 !不为空 走下面的代码
      JAVA="$ES_JAVA_HOME/bin/java"          # 这样java环境就有了
      JAVA_TYPE="ES_JAVA_HOME"
    elif [ ! -z "$JAVA_HOME" ]; then
      # fallback to JAVA_HOME
      echo "warning: usage of JAVA_HOME is deprecated, use ES_JAVA_HOME" >&2
      JAVA="$JAVA_HOME/bin/java"
      JAVA_TYPE="JAVA_HOME"
    else
      # use the bundled JDK (default)
      if [ "$(uname -s)" = "Darwin" ]; then
        # macOS has a different structure
        JAVA="$ES_HOME/jdk.app/Contents/Home/bin/java"
      else
        JAVA="$ES_HOME/jdk/bin/java"
      fi
      JAVA_TYPE="bundled JDK"
    fi
    ...

    3.1.4 启动es

    elasticsearch 7以后的版本都自带启动脚本,只需要执行一下就行

    3.1.5 检查es集群

    访问三个节点的其中一个的 9200端口 :http://192.168.31.61:9200/

    查看一些接口:http://192.168.31.61:9200/_cat

    查看index:http://192.168.31.61:9200/_cat/indices

    3.2 部署cerebro

    cerebro是一个es的监控工具,类似于es的插件一样。可以同时监控多个集群。

    cd /opt/
    wget https://github.com/lmenezes/cerebro/releases/download/v0.9.4/cerebro-0.9.4.zip
    unzip cerebro-0.9.4.zip
    cd cerebro-0.9.4
     
    配置
    vim conf/application.conf
     
    加入以下配置
    hosts = [
      {
        host = "http://192.168.31.61:9200"    # es地址
        name = "dev-qa-es"                    # 集群名称
        headers-whitelist = [ "x-proxy-user", "x-proxy-roles", "X-Forwarded-For" ]
      }
    ]
    启动
    cd bin
    nohup ./cerebro 2>&1 &

    3.2.1 访问

    可以看到es集群的一些常用的信息

    http://192.168.31.61:9000

    3.3 Kibana

     

    3.3.1 下载

    cd /opt/
    wget https://artifacts.elastic.co/downloads/kibana/kibana-7.12.1-linux-x86_64.tar.gz

    3.3.2 配置

    cd /opt/
    tar xf kibana-7.12.1-linux-x86_64.tar.gz 
     
    配置
    cd /opt/kibana-7.12.1
    vim config/kibana.yml
    server.port: 5601                # 监听端口
    server.host: "192.168.31.61"     # 监听地址
    elasticsearch.hosts: ["http://192.168.31.61:9200", "http://192.168.31.62:9200", "http://192.168.31.63:9200"]    # es hosts
    i18n.locale: "zh-CN"

    3.3.3 启动&访问

    cd /opt/kibana-7.12.1-linux-x86_64/bin
     
    nohup su - kibana -c "/opt/kibana-7.12.1-linux-x86_64/bin/kibana" &    # 前提是需要新建好kibana用户

    访问:http://192.168.31.61:5601

    3.4 部署filebeat

    3.4.1 下载

    cd /opt/
    wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.12.1-linux-x86_64.tar.gz
    tar xf filebeat-7.12.1-linux-x86_64.tar.gz

    3.4.2 目录规划

    /data/service-logs/{dev,qa}/$appname/{nginx,storage/{logs,autoLogs/sysError}}

            $env=qa,dev

            $appname=php所有的服务名称

            /data/service-logs/${env}/${appname}/{nginx,storage/{logs,autoLogs/sysError/}}

                    例如:wxx 服务的dev环境宿主机目录结构

                    /data/service-logs/dev/wxx/nginx/      这个下面有access  error日志

                    /data/service-logs/dev/wxx/storage/logs/      php info日志

                    /data/service-logs/dev/wxx/storage/autoLogs/sysError/        php  error日志

    3.4.3 服务日志挂载到宿主机

    1,更改php服务容器的yaml文件的volumeMounts
    比如这个dev环境的wxx服务
    
    volumeMounts:
      - mountPath: /var/log/nginx
        name: pod-nginx-log
      - mountPath: /var/www/html/storage/logs
        name: pod-storage-logs
      - mountPath: /var/www/html/storage/autoLogs/sysError
        name: pod-storage-autologs
    volumes:
    - hostPath:
        path: /data/service-logs/dev/wxx/nginx
        type: ""
      name: pod-nginx-log
    - hostPath:
        path: /data/service-logs/dev/wxx/storage/logs
        type: ""
      name: pod-storage-logs
    - hostPath:
        path: /data/service-logs/dev/wxx/storage/autoLogs/sysError
        type: ""
      name: pod-storage-autologs

    3.4.4 nginx json格式输出

    更改nginx.conf
    加入json格式定义
     
    log_format access_json_log  escape=json '{"@timestamp":"$time_iso8601",'
                                      '"remote_addr":"$remote_addr",'
                                      '"remote_user":"$remote_user",'
                                      '"body_bytes_sent":"$body_bytes_sent",'
                                      '"request_time":"$request_time",'
                                      '"http_host":"$http_host",'
                                      '"request_length":"$request_length",'
                                      '"upstream_response_length":"$upstream_response_length",'
                                      '"upstream_response_time":"$upstream_response_time",'
                                      '"request_body":"$request_body",'
                                      '"upstream_status":"$upstream_status",'
                                      '"status":"$status",'
                                      '"request":"$request",'
                                      '"request_method":"$request_method",'
                                      '"http_referrer":"$http_referrer",'
                                      '"http_x_forwarded_for":"$http_x_forwarded_for",'
                                      '"http_user_agent":"$http_user_agent"}';
     
    access_log  /var/log/nginx/access.log  access_json_log;

    3.4.5 php info日志提取匹配

    原始日志:其实就是filebeat支持正则表达式,只要你能匹配出你想要的日志内容就行

    我们提取[2021-07-05 13:00:00] 到下一个[2021-07-05 13:01:00] 中间的内容

    所以匹配就可以写成,

    multiline.pattern: '^['    # 其实就是以[开头的行
    multiline.negate: true
    multiline.match: after
    multiline.negate: true
    multiline.match: after

    这俩就是控制满足匹配之前的还是之后的,官方文档:https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html

    3.4.5 php error日志提取匹配

     原始日志: 

    我们提取2021-07-05 15:00:00 到下一个 2021-07-05 15:01:00

    multiline.pattern: '^[0-9]{4}-[0-9]{2}-'    # 以日期开头
    multiline.negate: true
    multiline.match: after

    总结:各种不同的日志 可以用不同的正则表达式去匹配出来。

    3.4.6 我的filebeat配置

    cd /opt/k8s/efk/filebeat-7.12.1-linux-x86_64/
     
    服务太多我只展示了一个服务的配置。其他的都是一样的
    vim filebeat.yml
    filebeat.inputs:
    #########################################################################
    #### 日志收集 ####
    # 一个项目为一个#组,一个组里有4个收集规则
    # collectLogStart
    ############################## operation-api ##############################
    - type: log
      enabled: true                  # 启用输入
      encoding: utf-8                # 字符编码
      paths:
        - /data/service-logs/dev/operation-api/nginx/access.log     # 日志路径
      tail_files: true                # true 从文件的末尾读取,false 从开头读取文件
      json.keys_under_root: true      # json解码
      json.overwrite_keys: true       # json解码
      fields:                         # 额外增加字段
        app_env: "dev"
        app_name: "operation-api"
        log_topics: "nginx-access"
      fields_under_root: true         # 增加的字段是否为顶级key
    - type: log
      enabled: true
      encoding: utf-8
      paths:
        - /data/service-logs/dev/operation-api/nginx/error.log
      tail_files: true
      fields:
        app_env: "dev"
        app_name: "operation-api"
        log_topics: "nginx-error"
      fields_under_root: true
    - type: log
      enabled: true
      encoding: utf-8
      paths:
        - /data/service-logs/dev/operation-api/storage/logs/lumen*.log
      multiline.pattern: '^['
      multiline.negate: true
      multiline.match: after
      tail_files: true
      fields:
        app_env: "dev"
        app_name: "operation-api"
        log_topics: "php-logs"
      fields_under_root: true
    - type: log
      enabled: true
      encoding: utf-8
      paths:
        - /data/service-logs/dev/operation-api/storage/autoLogs/sysError/lumen*.log
      multiline.pattern: '^[0-9]{4}-[0-9]{2}-'
      multiline.negate: true
      multiline.match: after
      tail_files: true
      fields:
        app_env: "dev"
        app_name: "operation-api"
        log_topics: "php-errlogs"
      fields_under_root: true
    ############################## operation-api ##############################
     
    # collectLogEnd
    ################################### 日志收集配置 ########################
    filebeat.config.modules:
      path: ${path.config}/modules.d/*.yml
      reload.enabled: false
    
    
    # 自定义index
    setup.template.name: "zm-log"
    setup.template.pattern: "zm-log-*"
    setup.template.overwrite: true
    setup.template.enabled: true
    setup.ilm.enabled: false    # 这个配置至关重要,是关于ilm生命周期。可以查看官方文档。这个是关闭自带的,然后使用自定义的。
     
    output.elasticsearch:
      hosts: ["192.168.31.61:9200","192.168.31.62:9200","192.168.31.63:9200"]
      loadbalance: true       # 开启负载
      pipelines:              # 有关filebeat使用pipeline 我后期单独写一篇文章:https://www.cnblogs.com/fanfanfanlichun/p/14977166.html
        - pipeline: "extract-traceid-pipeline"
          when.contains:
            log_topics: "php-errlogs"
     
      indices:                # index的配置,这个配置就是说当app_env=qa的时候用index: "zm-log-qa-%{+yyyy.MM.dd-000001}"
        - index: "zm-log-qa-%{+yyyy.MM.dd-000001}"
          when.contains:
            app_env: "qa"
     
        - index: "zm-log-dev-%{+yyyy.MM.dd}-000001"
          when.contains:
            app_env: "dev"
     
    processors:
      - add_host_metadata:
          when.not.contains.tags: forwarded
      - add_cloud_metadata: ~
      - add_docker_metadata: ~
      - add_kubernetes_metadata: ~
     
      - drop_fields:         # 这个是丢弃哪些key
          fields: ["host.mac","host.ip","host.os.name"]

    3.4.7 启动

    nohup /opt/k8s/efk/filebeat-7.12.1-linux-x86_64/filebeat -e -c /opt/k8s/efk/filebeat-7.12.1-linux-x86_64/filebeat.yml >/dev/null 2>&1 &

    3.5 访问kibana

    http://192.168.31.61:5601

    3.5.1 字段解释

    app_name:服务名称

    log_topics:nginx-access    nginx-error    php-info   php-error

    四、总结

    1,其实我这个是按照我这边的业务场景配置的,希望对你有益。

    2,官方文档才是最好的。

    3,有问题留言,我会及时回复。

    共同成长。共同进步。

  • 相关阅读:
    rabbitMQ和对应的erlang版本匹配
    Jfinal文件上传基础路径问题,windows下会以项目根路径为基础路径
    Linux常用命令-vim
    nginx配置https
    mysql创建表时,设置timestamp DEFAULT NULL报错1067
    Linux命令yum和rpm
    git reset命令使用
    jfinal定时任务插件jfinal-quartz
    quartz配置参数org.quartz.jobStore.misfireThreshold含义解释
    多层级树形结构数据库存储方式
  • 原文地址:https://www.cnblogs.com/fanfanfanlichun/p/14917736.html
Copyright © 2020-2023  润新知