跳至主要內容

ELK

HeChuangJun约 1606 字大约 5 分钟

日志服务

日志服务功能

  • 1、收集 :能够采集多个来源的日志数据。
  • 2、传输 :能够稳定的把日志数据传输到日志服务。
  • 3、存储 :能够存储海量的日志数据。
  • 4、查询 :能够灵活且高效的查询日志数据,并提供一定的分析能力。
  • 5、告警 :能够提供提供告警功能,通知开发和运维等等。

解决方案

  • 开源解决方案
    • ELK
    • Apache Chukwa
    • Apache Kafka
    • Cloudera Fluentd
    • Syslog、Rsyslog、Syslog-ng
    • Facebook Scribe
  • 商业解决方案
    • 阿里云 SLS、腾讯云 CLS、华为云 LTS
    • Splunk
  • 目前线上采用阿里云 SLS 日志服务,主要考虑使用方便,成本合算。
  • 目前采用最多的日志服务的解决方案,是 ELK 搭建的日志服务。

ELK定义

官方 Elastic NV 定义 "ELK” 是三个开源项目的首字母缩写,分别是:Elasticsearch、Logstash 和 Kibana。

  • Elasticsearch 是一个搜索和分析引擎。
  • Logstash 是服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到诸如 Elasticsearch 等“存储库”中。
  • Kibana 则可以让用户在 Elasticsearch 中使用图形和图表对数据进行可视化。
    elk1.png

由于 Logstash 是基于 JVM 的重量级的采集器,对系统的 CPU、内存、IO 等等资源占用非常高,这样可能影响服务器上的其它服务的运行。所以,Elastic NV 推出 Beats ,基于 Go 的轻量级采集器,对系统的 CPU、内存、IO 等等资源的占用基本可以忽略不计。负责采集数据,并通过网路传输给 Logstash。
elk2.png

ELK+FileBeat8.14.1部署

  1. vim /etc/sysctl.conf添加下面的配置
vm.max_map_count=655360
  1. 创建.env文件
# Project namespace (defaults to the current folder name if not set)
#COMPOSE_PROJECT_NAME=myproject

# Password for the 'elastic' user (at least 6 characters)
ELASTIC_PASSWORD=abcdef

# Password for the 'kibana_system' user (at least 6 characters)
KIBANA_PASSWORD=abcdef

# Version of Elastic products
STACK_VERSION=8.14.1

# Set the cluster name
CLUSTER_NAME=docker-cluster

# Set to 'basic' or 'trial' to automatically start the 30-day trial
LICENSE=basic
#LICENSE=trial

# Port to expose Elasticsearch HTTP API to the host
ES_PORT=9200

# Port to expose Kibana to the host
KIBANA_PORT=5601

# Increase or decrease based on the available host memory (in bytes)
ES_MEM_LIMIT=2147483648
KB_MEM_LIMIT=2147483648
LS_MEM_LIMIT=2147483648

# SAMPLE Predefined Key only to be used in POC environments
ENCRYPTION_KEY=c34d38b3a14956121ff2170e5030b471551370178f43e5626eec58b04a30fae2

ELASTIC_PASSWORD和KIBANA_PASSWORD不要全数字,ES_MEM_LIMIT、KB_MEM_LIMIT、LS_MEM_LIMIT在8.14版本至少2g
Native controller process has stopped - no new native processes can be started报错是内存不够
docker-compose.yml

  1. 创建 ELK 堆栈的 docker-compose.yml 文件
version: "3.8"


volumes:
 certs:
   driver: local
 esdata01:
   driver: local
 kibanadata:
   driver: local
 metricbeatdata01:
   driver: local
 filebeatdata01:
   driver: local
 logstashdata01:
   driver: local


networks:
 default:
   name: elastic
   external: false


services:
 setup:
   image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
   volumes:
     - certs:/usr/share/elasticsearch/config/certs
   user: "0"
   command: >
     bash -c '
       if [ x${ELASTIC_PASSWORD} == x ]; then
         echo "Set the ELASTIC_PASSWORD environment variable in the .env file";
         exit 1;
       elif [ x${KIBANA_PASSWORD} == x ]; then
         echo "Set the KIBANA_PASSWORD environment variable in the .env file";
         exit 1;
       fi;
       if [ ! -f config/certs/ca.zip ]; then
         echo "Creating CA";
         bin/elasticsearch-certutil ca --silent --pem -out config/certs/ca.zip;
         unzip config/certs/ca.zip -d config/certs;
       fi;
       if [ ! -f config/certs/certs.zip ]; then
         echo "Creating certs";
         echo -ne \
         "instances:\n"\
         "  - name: es01\n"\
         "    dns:\n"\
         "      - es01\n"\
         "      - localhost\n"\
         "    ip:\n"\
         "      - 127.0.0.1\n"\
         "  - name: kibana\n"\
         "    dns:\n"\
         "      - kibana\n"\
         "      - localhost\n"\
         "    ip:\n"\
         "      - 127.0.0.1\n"\
         > config/certs/instances.yml;
         bin/elasticsearch-certutil cert --silent --pem -out config/certs/certs.zip --in config/certs/instances.yml --ca-cert config/certs/ca/ca.crt --ca-key config/certs/ca/ca.key;
         unzip config/certs/certs.zip -d config/certs;
       fi;
       echo "Setting file permissions"
       chown -R root:root config/certs;
       find . -type d -exec chmod 750 \{\} \;;
       find . -type f -exec chmod 640 \{\} \;;
       echo "Waiting for Elasticsearch availability";
       until curl -s --cacert config/certs/ca/ca.crt https://es01:9200 | grep -q "missing authentication credentials"; do sleep 30; done;
       echo "Setting kibana_system password";
       until curl -s -X POST --cacert config/certs/ca/ca.crt -u "elastic:${ELASTIC_PASSWORD}" -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;
       echo "All done!";
     '
   healthcheck:
     test: ["CMD-SHELL", "[ -f config/certs/es01/es01.crt ]"]
     interval: 1s
     timeout: 5s
     retries: 120
 es01:
   depends_on:
     setup:
       condition: service_healthy
   image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
   labels:
     co.elastic.logs/module: elasticsearch
   volumes:
     - certs:/usr/share/elasticsearch/config/certs
     - esdata01:/usr/share/elasticsearch/data
   ports:
     - ${ES_PORT}:9200
   environment:
     - node.name=es01
     - cluster.name=${CLUSTER_NAME}
     - discovery.type=single-node
     - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
     - bootstrap.memory_lock=true
     - xpack.security.enabled=true
     - xpack.security.http.ssl.enabled=true
     - xpack.security.http.ssl.key=certs/es01/es01.key
     - xpack.security.http.ssl.certificate=certs/es01/es01.crt
     - xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
     - xpack.security.transport.ssl.enabled=true
     - xpack.security.transport.ssl.key=certs/es01/es01.key
     - xpack.security.transport.ssl.certificate=certs/es01/es01.crt
     - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
     - xpack.security.transport.ssl.verification_mode=certificate
     - xpack.license.self_generated.type=${LICENSE}
   mem_limit: ${ES_MEM_LIMIT}
   ulimits:
     memlock:
       soft: -1
       hard: -1
   healthcheck:
     test:
       [
         "CMD-SHELL",
         "curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
       ]
     interval: 10s
     timeout: 10s
     retries: 120
 kibana:
   depends_on:
     es01:
       condition: service_healthy
   image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
   labels:
     co.elastic.logs/module: kibana
   volumes:
     - certs:/usr/share/kibana/config/certs
     - kibanadata:/usr/share/kibana/data
   ports:
     - ${KIBANA_PORT}:5601
   environment:
     - SERVERNAME=kibana
     - ELASTICSEARCH_HOSTS=https://es01:9200
     - ELASTICSEARCH_USERNAME=kibana_system
     - ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
     - ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=config/certs/ca/ca.crt
     - XPACK_SECURITY_ENCRYPTIONKEY=${ENCRYPTION_KEY}
     - XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY=${ENCRYPTION_KEY}
     - XPACK_REPORTING_ENCRYPTIONKEY=${ENCRYPTION_KEY}
   mem_limit: ${KB_MEM_LIMIT}
   healthcheck:
     test:
       [
         "CMD-SHELL",
         "curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",
       ]
     interval: 10s
     timeout: 10s
     retries: 120
 logstash01:
   depends_on:
     es01:
       condition: service_healthy
     kibana:
       condition: service_healthy
   image: docker.elastic.co/logstash/logstash:${STACK_VERSION}
   labels:
     co.elastic.logs/module: logstash
   user: root
   ports:
     - "5044:5044"
     - "9600:9600"
   volumes:
     - certs:/usr/share/logstash/certs
     - logstashdata01:/usr/share/logstash/data
     - "./logstash_ingest_data/:/usr/share/logstash/ingest_data/"
     - "./logstash.conf:/usr/share/logstash/pipeline/logstash.conf:ro"
   environment:
     - xpack.monitoring.enabled=false
     - ELASTIC_USER=elastic
     - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
     - ELASTIC_HOSTS=https://es01:9200
 filebeat01:
   depends_on:
     es01:
       condition: service_healthy
   image: docker.elastic.co/beats/filebeat:${STACK_VERSION}
   user: root
   volumes:
     - certs:/usr/share/filebeat/certs
     - filebeatdata01:/usr/share/filebeat/data
     - "./filebeat_ingest_data/:/usr/share/filebeat/ingest_data/"
     - "./filebeat.yml:/usr/share/filebeat/filebeat.yml:ro"
     - "/var/lib/docker/containers:/var/lib/docker/containers:ro"
     - "/var/run/docker.sock:/var/run/docker.sock:ro"
     - "/var/log:/var/log/test:ro"
   environment:
     - ELASTIC_USER=elastic
     - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
     - ELASTIC_HOSTS=https://es01:9200
     - KIBANA_HOSTS=http://kibana:5601
     - LOGSTASH_HOSTS=http://logstash01:9600
 metricbeat01:
   depends_on:
     es01:
       condition: service_healthy
     kibana:
       condition: service_healthy
   image: docker.elastic.co/beats/metricbeat:${STACK_VERSION}
   user: root
   volumes:
     - certs:/usr/share/metricbeat/certs
     - metricbeatdata01:/usr/share/metricbeat/data
     - "./metricbeat.yml:/usr/share/metricbeat/metricbeat.yml:ro"
     - "/var/run/docker.sock:/var/run/docker.sock:ro"
     - "/sys/fs/cgroup:/hostfs/sys/fs/cgroup:ro"
     - "/proc:/hostfs/proc:ro"
     - "/:/hostfs:ro"
   environment:
     - ELASTIC_USER=elastic
     - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
     - ELASTIC_HOSTS=https://es01:9200
     - KIBANA_HOSTS=http://kibana:5601
     - LOGSTASH_HOSTS=http://logstash01:9600

setup服务用于监听es和kibana正常启动
metricbeat用于查看宿主机cpu等情况,在kibana界面上Stack Monitoring可以看到
filebeat01中"/var/log:/var/log/test:ro"表示将系统日志以只读方式同步到容器中,这样可以监控宿主机的系统日志,同理监控宿主机容器日志达到监控java日志目的

clusteroverview.png
clusteroverview.png
  1. 创建logstash.conf文件
input {
  beats {
    port => 5044
  }
}
filter {
}
output {
 elasticsearch {
   index => "logstash-%{+YYYY.MM.dd}"
   hosts=> "${ELASTIC_HOSTS}"
   user=> "${ELASTIC_USER}"
   password=> "${ELASTIC_PASSWORD}"
   cacert=> "certs/ca/ca.crt"
 }
}
  1. 创建metricbeat.yml文件
metricbeat.config.modules:
 path: ${path.config}/modules.d/*.yml
 reload.enabled: false
metricbeat.modules:
- module: elasticsearch
  hosts: ${ELASTIC_HOSTS}
  username: ${ELASTIC_USER}
  password: ${ELASTIC_PASSWORD}
  xpack:
    enabled: true
  period: 10s
  ssl:
      enabled: true
      certificate_authorities: "certs/ca/ca.crt"
      certificate: "certs/es01/es01.crt"
      key: "certs/es01/es01.key"
- module: logstash
  xpack:
    enabled: true
  period: 10s
  hosts: ${LOGSTASH_HOSTS}
- module: kibana
  metricsets:
   - stats
  period: 10s
  hosts: ${KIBANA_HOSTS}
  username: ${ELASTIC_USER}
  password: ${ELASTIC_PASSWORD}
  xpack.enabled: true
- module: docker
  metricsets:
   - "container"
   - "cpu"
   - "diskio"
   - "healthcheck"
   - "info"
   #- "image"
   - "memory"
   - "network"
  hosts: ["unix:///var/run/docker.sock"]
  period: 10s
  enabled: true
processors:
 - add_host_metadata: ~
 - add_docker_metadata: ~
output.elasticsearch:
 hosts: ${ELASTIC_HOSTS}
 username: ${ELASTIC_USER}
 password: ${ELASTIC_PASSWORD}
 ssl:
   certificate: "certs/es01/es01.crt"
   certificate_authorities: "certs/ca/ca.crt"
   key: "certs/es01/es01.key"
  1. 创建filebeat.yml
filebeat.inputs:
- type: filestream
  id: default-filestream
  paths:
   - ingest_data/*.log
   - /var/log/test/*.log
- type: container
  id: java
  paths:
   - /var/lib/docker/containers/*/*.log
filebeat.autodiscover:
 providers:
   - type: docker
     hints.enabled: true


processors:
- add_docker_metadata: ~


setup.kibana:
 host: ${KIBANA_HOSTS}
 username: ${ELASTIC_USER}
 password: ${ELASTIC_PASSWORD}


# output.elasticsearch:
#  hosts: ${ELASTIC_HOSTS}
#  username: ${ELASTIC_USER}
#  password: ${ELASTIC_PASSWORD}
#  ssl.enabled: true
#  ssl.certificate_authorities: "certs/ca/ca.crt"

output.logstash:
  hosts: "logstash01"

  1. 将上面文件全部放入同一个目录并运行以下命令启动 ELK 堆栈:
docker-compose up -d
  1. 验证
    验证 Elasticsearch:打开浏览器并访问 https://localhost:9200open in new window。选择继续登陆输入账号密码,你应该会看到类似以下内容的 JSON 响应:
    esok.png

验证 Kibana:
打开浏览器并访问 http://localhost:5601open in new window。你应该会看到 Kibana 的欢迎页面。

kibanaok.png
kibanaok.png

kibana左侧中提供了一个DevTools界面:可以编写DSL来操作elasticsearch。并且对DSL语句有自动补全功能。
devtools.png
devtools2.png

POST /_analyze
{
  "analyzer": "ik_max_word",
  "text": "java学习java太棒了"
}

导航到 "Discover" 页面,查看日志数据是否成功索引到 Elasticsearch。