1. 背景
以下来自
日志主要包括系统日志、应用程序日志和安全日志。系统运维和开发人员可以通过日志了解服务器软硬件信息、检查配置过程中的错误及错误发生的原因。经常分析日志可以了解服务器的负荷,性能安全性,从而及时采取措施纠正错误。(3种日志作用)
通常,日志被分散的储存不同的设备上。如果你管理数十上百台服务器,你还在使用依次登录每台机器的传统方法查阅日志。这样是不是感觉很繁琐和效率低下。当务之急我们使用集中化的日志管理,例如:开源的 syslog ,将所有服务器上的日志收集汇总。
集中化管理日志后,日志的统计和检索又成为一件比较麻烦的事情,一般我们使用 grep 、 awk 和 wc 等 Linux命令能实现检索和统计,但是对于要求更高的查询、排序和统计等要求和庞大的机器数量依然使用这样的方法难免有点力不从心。
开源实时日志分析 ELK 平台能够完美的解决我们上述的问题, ELK 由 ElasticSearch 、 Logstash 和 Kiabana 三个开源工具组成。
官方网站:
另一篇入门:组件说明
日志收集(Beats, Logstash),日志存储搜索(Elasticsearch),展示查询(Kibana),更多见官网简介
组件组合&扩展
- ELK: Logstash -> Elasticsearch -> Kibana
- EFK: Fluentd -> Elasticsearch -> Kibana
- ELKStack: Filebeat -> Logstash -> Elasticsearch -> Kibana
- 扩展: Logstash -> 队列(redis, kafaka) -> Logstash -> Elasticsearch -> Kibana
组件简介
-
Elasticsearch:开源基于JSON分布式搜索引擎,它的特点有:分布式,实时,基于Lucence全文搜索,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等;
-
kibana: 开源和免费的工具, Kibana 可以为 Logstash 和 ElasticSearch 提供日志分析友好的 Web 界面,可以帮助您汇总、分析和搜索重要数据日志;
-
Logstash:完全开源的工具,他可以对你的日志进行收集、分析,并将其存储供以后使用。可以定制多种输入、输出及转换规则(过滤,分析,格式化)。Logstash 是动态数据收集管道,拥有可扩展的插件生态系统,能够与 Elasticsearch 产生强大的协同作用;
-
Beats:轻量型采集器的平台,从边缘机器向 Logstash 和 Elasticsearch 发送数据;
工作流程
在需要收集日志的所有服务上部署 logstash ,作为 logstash agent(logstash shipper)用于监控并过滤收集日志,将过滤后的内容发送到 logstash indexer , logstash indexer 将日志收集在一起交给全文搜索服务 ElasticSearch ,可以用 ElasticSearch 进行自定义搜索通过 Kibana 来结合自定义搜索进行页面展示。
目录 Directory Layout
4个组件的目录基本统一:
类型 | 描述 | 配置项 | ElasticSearch | Kibana | Logstash | Filebeat |
---|---|---|---|---|---|---|
home | home目录 | $ES_HOME | $KIBANA_HOME | {extract.path} | path.home | |
bin | 二进制文件 | $ES_HOME/bin<br>elasticsearch<br>elasticsearch-plugin | $KIBANA_HOME\bin<br>kibana<br>kibana-plugin | {extract.path}/bin<br>logstash<br>logstash-plugin | {path.home}<br>filebeat | |
conf | 配置文件 | $ES_HOME/conf<br>elasticsearch.yml<br>jvm.options<br>log4j2.properties | $KIBANA_HOME/config<br>kibana.yml | {path.home}<br>filebeat.yml | ||
settings | 配置文件 | path.settings | {extract.path}/config<br>logstash.yml<br>jvm.options<br>log4j2.properties<br>startup.options | |||
data | 数据文件 | path.data | $ES_HOME/data<br>可配置多个 | $KIBANA_HOME/data | {extract.path}/data | {path.home}/data |
logs | 日志文件 | path.logs | $ES_HOME/logs | {extract.path}/logs | {path.home}/logs | |
plugins | 插件目录 | $ES_HOME/plugins | $KIBANA_HOME/plugins | {extract.path}/plugins | ||
script | 脚本目录 | path.scripts | $ES_HOME/scripts | |||
repo | path.repo | |||||
optimize | $KIBANA_HOME/optimize |
- 公用的或不经常变化的命令写在前面,可以镜像间层可以复用,制作镜像时也可以复用不用重新构建
- 使用add或copy,再tar会导致文件会有2倍的大小,即使镜像压缩后可以变小,但是公用层不能复用
- 使用curl不使用wget,curl支持管道操作,管道后接tar命令,构建出来的镜像不会出现2倍体积
- 如果需要另外的用户启动服务,可以再Dockerfile先用root用户,再最后的启动脚本中使用gosu切换用户启动应用,并再此之前更改文件的所有者
- 可以在启动脚本中设置环境变量的默认值,在配置文件中使用环境变量注入配置。软件的根目录使用环境变量替代,还有设置PATH
- -x84_64.tar.gz后缀的包貌似不兼容alpine系统,需要FROM其他小的系统如ubuntu-slim
ES
1.镜像制作
目录
ES├──Dockerfile-es├──config/| ├── elasticsearch.yml //ES配置文件| ├── jvm.options //ES jvm 调优配置,使用官方默认配置| └── log4j2.properties //ES 日志配置文件,使用官方默认配置└──shell ├── env-es //公共的环境变量配置属性键值对 ├── env-es-master //master节点的环境变量配置属性键值对 ├── env-es-slave //slave节点的环境变量配置属性键值对 ├── run.sh //启动脚本 └── sysConfig.sh //es宿主机优化脚本
Dockerfile-es
FROM java:openjdk-8-jre-alpineENV LANG='zh_CN.UTF-8'RUN apk update \ && apk --no-cache add \ --repository https://dl-3.alpinelinux.org/alpine/edge/main \ --repository https://dl-3.alpinelinux.org/alpine/edge/testing \ --repository https://dl-3.alpinelinux.org/alpine/edge/community \ shadow curl tar gosuENV ELASTICSEARCH_VERSION=5.6.4 \ ES_HOME=/ES \ PATH=${ES_HOME}/bin:$PATHWORKDIR ${ES_HOME}RUN curl -fL https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-$ELASTICSEARCH_VERSION.tar.gz \ | tar --strip-components=1 -zxRUN mkdir data logs \ && useradd --no-create-home --user-group elasticsearch \ && apk del curl tarCOPY config configCOPY shell/run.sh /RUN chmod 775 /run.shCMD ["/run.sh"]
run.sh
#!/bin/shexport NODE_NAME=${NODE_NAME:-${HOSTNAME}}export NODE_DATA=${NODE_DATA:-true}export NODE_PORT_HTTP=${NODE_PORT_HTTP:-9200}export NODE_PORT_TCP=${NODE_PORT_TCP:-9300}chown -R elasticsearch:elasticsearch ${ES_HOME}exec gosu elasticsearch sh ${ES_HOME}/bin/elasticsearch
elasticsearch.yml
#节点&集群#集群名称,节点通过集群名称加入集群cluster.name: es-logging#节点名称node.name: ${NODE_NAME}#是否为master节点,默认为truenode.master: ${NODE_MASTER}#是否为数据节点,默认为truenode.data: truediscovery.zen.minimum_master_nodes: 1discovery.zen.ping.unicast.hosts: - ${DISC_NODE_1} - ${DISC_NODE_2}#网络transport.tcp.port: ${NODE_PORT_TCP}http.port: ${NODE_PORT_HTTP}#节点绑定的IP地址network.host: 0.0.0.0network.publish_host: ${NODE_IP}#路径配置:数据和日志路径path.data: ${ES_HOME}/datapath.logs: ${ES_HOME}/logs#验证关闭系统swapping#bootstrap.memory_lock: true
sysConfig.sh
#设置MMapsysctl -w vm.max_map_count=262144#打开文件的最大数目ulimit -n 65536#shell所能建立的最大文件ulimit -f unlimited#最大内存大小ulimit -m unlimited# 虚拟内存ulimit -v unlimited#最大进程ulimit -u 2048#要使 limits.conf 文件配置生效,必须要确保 pam_limits.so 文件被加入到启动文件中。#查看 /etc/pam.d/login 文件中有: session required /lib/security/pam_limits.soecho "session required /lib/security/pam_limits.so" >> /etc/pam.d/login# vi /etc/security/limits.conf#打开文件的最大数目echo "root - nofile 65536" >> /etc/security/limits.confecho "elasticsearch - nofile 65536" >> /etc/security/limits.conf#最大锁定内存地址空间echo "root - memlock unlimited" >> /etc/security/limits.confecho "elasticsearch - memlock unlimited" >> /etc/security/limits.conf#地址空间限制echo "root - as unlimited" >> /etc/security/limits.confecho "elasticsearch - as unlimited" >> /etc/security/limits.conf#最大文件大小echo "root - fsize unlimited" >> /etc/security/limits.confecho "elasticsearch - fsize unlimited" >> /etc/security/limits.conf#最大进程echo "root - noproc 2048" >> /etc/security/limits.confecho "elasticsearch - noproc 2048" >> /etc/security/limits.conf# vi /etc/security/limits.d/20-nproc.conf #打开进程数echo "root - nproc 65536 ">> /etc/security/limits.d/20-nproc.confecho "elasticsearch - nproc 65536">> /etc/security/limits.d/20-nproc.conf
2.启动示例
docker build -t es:5.6.4 -f Dockerfile-es .mkdir -p /data/ELK/ES/master/datamkdir -p /data/ELK/ES/master/logsmkdir -p /data/ELK/ES/slave1/datamkdir -p /data/ELK/ES/slave1/logs### master docker run -d -p 9200:9200 -p 9300:9300 \ --env-file /data/ELK/ES/shell/env-es-master \ --env-file /data/ELK/ES/shell/env-es \ -v /data/ELK/ES/master/data:/ES/data \ -v /data/ELK/ES/master/logs:/ES/logs \ --name es-master \ es:5.6.4### slave1docker run -d -p 9201:9201 -p 9301:9301 \ --env-file /data/ELK/ES/shell/env-es-slave \ --env-file /data/ELK/ES/shell/env-es \ -v /data/ELK/ES/slave1/data:/ES/data \ -v /data/ELK/ES/slave1/logs:/ES/logs \ --name es-slave1 \ es:5.6.4
Kibana
1.镜像制作
目录
Kibana├──Dockerfile-kibana└──shell └── run.sh //启动脚本
Dockerfile-kibana
FROM docker.io/zshiki/ubuntu-slimENV LANG='zh_CN.UTF-8'RUN apt-get update \ && apt-get install -y curl \ && apt-get cleanENV KIBANA_VERSION=5.6.4 \ KIBANA_HOME=/kibana \ PATH=${KIBANA_HOME}/bin:$PATHWORKDIR ${KIBANA_HOME}RUN curl -fL https://artifacts.elastic.co/downloads/kibana/kibana-$KIBANA_VERSION-linux-x86_64.tar.gz \ | tar --strip-components=1 -zxCOPY shell/run.sh /RUN chmod 775 /run.shCMD ["/run.sh"]
run.sh
#!/bin/shexport PORT=${PORT:-5601}export ES_URL=${ES_URL:-"http://localhost:9200"}echo "server.host: \"0\""echo "server.host: \"0\"" >> ${KIBANA_HOME}/config/kibana.ymlecho "server.name: kibana-logging"echo "server.name: kibana-logging" >> ${KIBANA_HOME}/config/kibana.ymlecho "server.port: ${PORT}"echo "server.port: ${PORT}" >> ${KIBANA_HOME}/config/kibana.ymlecho "elasticsearch.url: ${ES_URL}"echo "elasticsearch.url: ${ES_URL}" >> ${KIBANA_HOME}/config/kibana.ymlsh ${KIBANA_HOME}/bin/kibana
2.启动示例
docker build -t kibana:5.6.4 -f Dockerfile-kibana .docker run -d -p 5601:5601 \ -e ES_URL=http://192.168.52.7:9200 \ --name kibana-logging \ kibana:5.6.4
Logstash
1.镜像制作
目录
Logstash├──Dockerfile-logstash├──config/| ├── logstash.yml //logstash配置文件| ├── jvm.options //logstash jvm 调优配置,使用官方默认配置| └── log4j2.properties //logstash 日志配置文件,使用官方默认配置└──shell └── run.sh //启动脚本
Dockerfile-logstash
FROM java:openjdk-8-jre-alpineENV LANG='zh_CN.UTF-8'RUN apk update \ && apk --no-cache add \ --repository https://dl-3.alpinelinux.org/alpine/edge/main \ --repository https://dl-3.alpinelinux.org/alpine/edge/testing \ --repository https://dl-3.alpinelinux.org/alpine/edge/community \ shadow curl tar fontconfig freetype gosu bashENV LOGSTASH_VERSION=5.6.4 \ LOGSTASH_HOME=/logstash \ PATH=${LOGSTASH_HOME}/bin:$PATHWORKDIR ${LOGSTASH_HOME}RUN curl -Lf https://artifacts.elastic.co/downloads/logstash/logstash-$LOGSTASH_VERSION.tar.gz \ | tar --strip-components=1 -xzRUN mkdir pipeline logs \ && useradd --no-create-home --user-group logstash \ && apk del curl tarCOPY config configCOPY shell/run.sh /RUN chmod 775 /run.shCMD ["/run.sh"]
run.sh
#!/bin/shexport LOG_LEVEL=${LOG_LEVEL:-info}export PIPELINE_WORKERS=${PIPELINE_WORKERS:-2}chown -R logstash:logstash ${LOGSTASH_HOME}exec gosu logstash sh ${LOGSTASH_HOME}/bin/logstash
logstash.yml
pipeline.workers: ${PIPELINE_WORKERS}log.level: ${LOG_LEVEL}http.host: "0.0.0.0"path.config: ${LOGSTASH_HOME}/pipelineconfig.reload.automatic: true
2.启动示例
pipeline/logstash.conf
input { beats { port => 5044 }}filter { if [fields][app_id] == "portal" { grok { match => { "message" => "%{HOUR:hour}:%{MINUTE:minute}:%{SECOND:second} \[%{DATA:thread}\] %{LOGLEVEL:log_level} %{DATA}" } } } if [fields][source_type] == "docker_log" { mutate { rename => { "log" => "message" } } grok { match => { "message" => "\[%{DATA}%{HOUR:hour}:%{MINUTE:minute}:%{SECOND:second}\] %{DATA:thread} %{LOGLEVEL:log_level} %{DATA}" } } }}output { elasticsearch { hosts => [ "192.168.0.7:9200" ] }}
启动示例
docker build -t logstash:5.6.4 -f Dockerfile-logstash .docker run -d -p 5044:5044 \ -v /data/ELK/Logstash/pipeline:/logstash/pipeline \ --name logstash \ logstash:5.6.4
Filebeat
1.镜像制作
目录
Filebeat└──Dockerfile-filebeat
Dockerfile-filebeat
FROM docker.io/zshiki/ubuntu-slimENV LANG='zh_CN.UTF-8'RUN apt-get update \ && apt-get install -y curl \ && apt-get cleanENV BEAT_VERSION=5.6.4 \ FILEBEAT_HOME=/filebeat \ PATH=${FILEBEAT_HOME}:$PATHWORKDIR ${FILEBEAT_HOME}RUN curl -Lf https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-${BEAT_VERSION}-linux-x86_64.tar.gz \ | tar --strip-components=1 -xzRUN mkdir data logs \ && apt-get purge -y curlRUN ls -l ${FILEBEAT_HOME}CMD ["filebeat, "-e"]
2.启动示例
config/filebeat.yml
filebeat.prospectors:- type: log scan_frequency: 10s json.keys_under_root: true json.add_error_key: true json.message_key: log multiline.pattern: '^\[' multiline.negate: true multiline.match: after fields: source_type: docker_log paths: - /data/docker/containers/*/*-json.logoutput.logstash: hosts: ["192.168.0.7:5044"] worker: 2 loadbalance: true index: filebeat
启动示例
docker build -t filebeat:5.6.4 -f Dockerfile-filebeat .docker run -d \ -v /opt/filebeat/config/filebeat.yml:/filebeat/filebeat.yml \ -v /data/docker/containers:/data/docker/containers \ --name filebeat-docker \ filebeat:5.6.4