赞
踩
(Elasticsearch+Fluentd+Kibana)EFK
部署手册最近需要用到容器日志收集,目前比较流行的应该是EL(Logstash)K
,EF(Fluentd)K
,相比之下Fluentd
要比Logstash
轻量级,所以决定采用Fluentd
。因此产生了此文档.
本文主要是通过docker-compose部署Elasticsearch + Fluentd + Kibana
部署相关服务,并支持在多个docker-compose中收集不同容器产生的日志.
docker pull kibana:7.6.0
docker pull elasticsearch:7.6.0
docker pull fluent/fluentd:v1.3.2
准备fluentd
配置文件和制作镜像的Dockerfile
文件,fluent.conf
这个是fluentd
启动的配置文件.目录结构如下:
efk
|fluentd
| conf
|---fluent.conf
|Dockerfile
其中 efk,fluentd,conf是文件夹, fluent.conf和Dockerfile是文件.
这个是fluent.conf里面的具体内容
<source>
@type forward
port 24224
bind 0.0.0.0
</source>
<match **>
@type copy
<store>
@type elasticsearch
host elasticsearch
port 9200
logstash_format true
logstash_prefix fluentd
logstash_dateformat %Y%m%d
include_tag_key true
type_name access_log
tag_key @log_name
flush_interval 1s
</store>
<store>
@type stdout
</store>
</match>
Dockerfile
文件FROM fluent/fluentd:v1.3.2
USER root
RUN echo "source 'https://mirrors.tuna.tsinghua.edu.cn/rubygems/'" > Gemfile && gem install bundler
RUN gem install fluent-plugin-elasticsearch -v 4.0.3 --no-document
CMD ["fluentd"]
yml
文件version: '2'
services:
web:
image: httpd
ports:
- "1080:80"
links:
- fluentd
logging:
driver: "fluentd"
options:
fluentd-address: localhost:24224
tag: httpd.access
container_name: web
app_v1:
image: app:v1
ports:
- "9090:9090"
links:
- fluentd
logging:
driver: "fluentd"
options:
fluentd-address: localhost:24224
tag: app.h1
container_name: app_v1
fluentd:
build: ./fluentd
volumes:
- ./fluentd/conf/:/etc/fluent/
links:
- "elasticsearch"
ports:
- "24224:24224"
- "24224:24224/udp"
container_name: fluentd
elasticsearch:
image: elasticsearch:7.6.0
environment:
- discovery.type=single-node
expose:
- 9200
ports:
- "9200:9200"
container_name: elasticsearch
kibana:
image: kibana:7.6.0
environment:
I18N_LOCALE: "zh-CN"
links:
- "elasticsearch"
ports:
- "5601:5601"
container_name: kibana
镜像一
docker pull httpd:latest
镜像二
是自己制作的python镜像,需要依赖镜像python3.7.9
.首先得拉取下面的镜像
docker pull python:3.7.9
镜像拉取完成后准备好一个简单的flask
项目文件项目的目录结构如下,test
和app
是目录,app.py
和Dockerfile
是文件.
test
|app
|---app.py
|Dockerfile
app.py
的文件内容如下:
#!/usr/bin/python
# -*- coding: UTF-8 -*
"""
@file_name: app.py
@author:lzl
@create date: 2021/3/30 0004 13:12
@description:
@update date:
@file url:
@git path:
"""
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/')
def hello_world():
a = {
'code': 200,
'msg': 'OK',
'data': [1, 3, 4, 5]
}
return jsonify(a)
if __name__ == "__main__":
app.run(host='0.0.0.0',port=9090)
这样在准备制作镜像二的Dockerfile文件,内容如下
FROM python:3.7.9
USER root
RUN pip install flask
COPY app /var/app
WORKDIR /var/app
EXPOSE 9090
CMD python app.py
为了测试我弄得比较简单.进入xxx/test/
目录 Dockerfile
目录执行
docker build -t app:v1 .
完成app:v1镜像的构建.
version: '2'
services:
app_v2:
image: app:v1
ports:
- "9091:9090"
external_links:
- fluentd
logging:
driver: "fluentd"
options:
fluentd-address: 192.169.0.141:24224
tag: app.h2
container_name: app_v2
external_links : 用于链接到外部容器。所有容器需要在同一个网络中
配置文件路径/usr/share/kibana/kibana.yml
#
# ** THIS IS AN AUTO-GENERATED FILE **
#
# Default Kibana configuration for docker target
server.name: kibana
server.host: "0"
elasticsearch.hosts: [ "http://elasticsearch:9200" ]
xpack.monitoring.ui.container.elasticsearch.enabled: true
i18n.locale: zh-CN
配置文件路径/usr/share/elasticsearch/elasticsearch.yml
cluster.name: "docker-cluster"
network.host: 0.0.0.0
单docker-compose
文件的容器日志收集,首先启动同一个docker-compose
文件里面的服务进行收集.启动命令,在有文件docker-compose.yml
文件的目录执行如下命令
docker-compose up -d
查看服务运行状态
这样界面通过访问 192.169.0.141:5601
打开kibana UI
界面
点击试用我的样例数据,进入
添加索引如图
点击创建索引模式
选择索引时间筛选字段名称,我这里选择的是@timestamp
点击创建索引模式
然后在点击Discover
这样就能看见相关的日志了.这样只要安装的服务在控制台有产生日志输出就能看见日志了
上图标红的就是我们启动的容器的服务名称.我们就完成了容器为web和app_v1两个容器的日志收集.
场景一只解决了在同一个docker-compose
中容器日志的收集.然而实际工作中会存在启动多个docker-compose
文件的容器日志收集,我们只需要配置为两个docker-compose能够通信,这样先启动场景一的docker-compose,然后在启动ext.yml里面配置的另外一个服务.具体启动命令如下:
docker-compose up -d
docker-compose -f ext.yml up -d
重新刷新kibana就能看见另外一个docker-compose部署的服务日志也被有效的收集起来了.
在windows系统中安装日志收集器,并完成日志收集.这是自己模拟的一个定时日志数据源.
# !/usr/bin/python
# -*- coding: utf-8 -*-
"""
@file_name : test_log.py
@author : lzl
@create date: 2021/4/1 0001 10:40
@description:
@update date:
@file url :
@git path :
"""
import time
import logging
import os
import random
# 1.创建1个logger:
from logging import handlers
mylog = logging.getLogger("Error")
def init_log():
log_path = os.getcwd() + "/log"
try:
if not os.path.exists(log_path):
os.makedirs(log_path)
except:
print("创建日志目录失败")
exit(1)
if len(mylog.handlers) == 0: # 避免重复
# 2.创建handler(负责输出,输出到屏幕streamhandler,输出到文件filehandler)
filename = os.path.join(log_path, 'cscips.log')
# fh = logging.FileHandler(filename,mode="a",encoding="utf-8")#默认mode 为a模式,默认编码方式为utf-8
sh = logging.StreamHandler()
fh = handlers.TimedRotatingFileHandler(filename=filename, when="D", interval=2, backupCount=3,
encoding="utf-8") #
fh.suffix = "%Y-%m-%d.log"
# 3.创建formatter:
formatter = logging.Formatter(
fmt='%(asctime)s - %(levelname)s - Model:%(filename)s - Fun:%(funcName)s - Message:%(message)s - Line:%(lineno)d')
# 4.绑定关系:①logger绑定handler
mylog.addHandler(fh)
mylog.addHandler(sh)
# # ②为handler绑定formatter
fh.setFormatter(formatter)
sh.setFormatter(formatter)
# # 5.设置日志级别(日志级别两层关卡必须都通过,日志才能正常记录)
# mylog.setLevel(40)
# fh.setLevel(40)
# sh.setLevel(40)
mylog.setLevel('INFO')
fh.setLevel('INFO')
sh.setLevel('INFO')
def log_record(level):
if level == 'INFO':
msg = '处理请求或者状态变化等日常事务'
mylog.info(f'{msg} - {time.time()}')
time.sleep(15)
elif level == 'ERROR':
msg = '发生错误时,如IO操作失败或者连接问题'
mylog.error(f'{msg} - {time.time()}')
time.sleep(30)
elif level == 'WARNING':
msg = '发生很重要的事件,但是并不是错误时,如用户登录密码错误'
mylog.warning(f'{msg} - {time.time()}')
time.sleep(20)
elif level == 'CRITICAL':
msg = '特别糟糕的事情,如内存耗尽、磁盘空间为空,一般很少使用'
mylog.critical(f'{msg} - {time.time()}')
time.sleep(60)
elif level == 'DEBUG':
msg = '调试过程中使用DEBUG等级,如算法中每个循环的中间状态'
mylog.debug(f'{msg} - {time.time()}')
time.sleep(5)
else:
msg = '致命错误'
mylog.debug(f'{msg} - {time.time()}')
time.sleep(120)
while True:
init_log()
"""
日志等级:使用范围
FATAL:致命错误
CRITICAL:特别糟糕的事情,如内存耗尽、磁盘空间为空,一般很少使用
ERROR:发生错误时,如IO操作失败或者连接问题
WARNING:发生很重要的事件,但是并不是错误时,如用户登录密码错误
INFO:处理请求或者状态变化等日常事务
DEBUG:调试过程中使用DEBUG等级,如算法中每个循环的中间状态
"""
l = ['INFO', 'ERROR', 'WARNING', 'DEBUG', 'FATAL', 'CRITICAL']
s = random.choice(l)
log_record(s)
windows
中使用filebeat
可以完成日志的采集,首先得下载好windows
版本的filebeta
.我这里下载的zip包,直接解压就能够使用.
filebeat-7.12.0-windows-x86_64.zip
解压后的目录结构为
有了这个文件我们需要修改filebeat.yml中的配置项为
filebeat.inputs:
# Each - is an input. Most options can be set at the input level, so
# you can use different inputs for various configurations.
# Below are the input specific configurations.
- type: log
# Change to true to enable this input configuration.
enabled: true
# Paths that should be crawled and fetched. Glob based paths.
paths:
# 配置日志文件的路径
- E:\TestDemo\loging\log\*.log
setup.kibana:
host: "192.169.0.234:5601"
output.elasticsearch:
# Array of hosts to connect to.
hosts: ["192.169.0.234:9200"]
然后使用 cmd进入解压好的filebeat目录,执行启动命令
filebeat.exe -e -c filebeat.yml
这样filebeat windows版本的日志收集器就安装成功了 我们就可以进入kibana中配置好相应的索引,然后就可以通过Discover
选择创建好的索引就能看见收集到的日志了.
kibana
设置默认语言为中文,配置文件/usr/share/kibana/config/kibana.yml
中添加
i18n.locale: "zh-CN"
redis
日志标准输出,在配置文件中注释 logfile
配置
logfile
nginx
日志文件标准输出配置
error_log /dev/stdout warn;
access_log /dev/stdout main;
gunicorn日志标准输出配置
accesslog='-'
uwsgi 日志标准输出配置
log-master=true
elasticsearch
配置和数据文件
/usr/share/elasticsearch/config/elasticsearch.yml
/usr/share/elasticsearch/data
kibana
配置和数据文件
/usr/share/kibana/config/kibana.yml
/usr/share/kibana/data
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。