Docker搭建ELK收集所有容器日志
ELK 是 ElasticSearch、Logstash、Kibana 的简称,一般用于日志系统,从日志收集,日志转储,日志展示等入手,用以提供简洁高效的日志处理机制。这篇文章记录一下我用 Docker 搭建 ELK,并且结合 logspout 实现自动化地把所有 Docker 容器的日志数据传输给 ELK 的过程。
# ELK 介绍
ELK 是一套开源实时日志分析系统,由 ElasticSearch、Logstash 和 Kiabana 三个开源工具组成。
官方网站:https://www.elastic.co/products
Elasticsearch:开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful 风格接口,多数据源,自动搜索负载等。
Logstash:一个完全开源的工具,他可以对你的日志进行收集、过滤,并将其存储供以后使用(如,搜索)。
Kibana:一个开源和免费的工具,它可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助您汇总、分析和搜索重要数据日志。
# 基础镜像
在构建自己的镜像之前,先把官方的基础镜像拉下来,我这里使用的是 6.2.4 版本。
$ docker pull docker.elastic.co/elasticsearch/elasticsearch-oss:6.2.4
$ docker pull docker.elastic.co/logstash/logstash-oss:6.2.4
$ docker pull docker.elastic.co/kibana/kibana-oss:6.2.4
2
3
为避免版本混乱,从 5.0 开始,Elastic 公司将各组件的版本号进行统一。
使用时,各组件版本号应一致。(版本号形式:x.y.z
, z
可以不同)
如果想基于其它版本,可以到 https://www.docker.elastic.co/ 查看各版本对应的镜像的 tag。
# 构建镜像
# ElasticSearch
# elasticsearch.yml
先创建一个配置文件 elasticsearch.yml
,添加以下内容:
---
network.host: 0.0.0.0
# minimum_master_nodes need to be explicitly set when bound on a public IP
# set to 1 to allow single node clusters
# Details: https://github.com/elastic/elasticsearch/pull/17288
discovery.zen.minimum_master_nodes: 1
## Use single node discovery in order to disable production mode and avoid bootstrap checks
## see https://www.elastic.co/guide/en/elasticsearch/reference/current/bootstrap-checks.html
#
discovery.type: single-node
# add elasticsearch-head cors support.
http.cors.enabled: true
http.cors.allow-origin: "*"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Dockerfile
在 elasticsearch.yml
同个文件夹目录下,创建一个 Dockerfile
文件,添加以下内容:
FROM docker.elastic.co/elasticsearch/elasticsearch-oss:6.2.4
COPY elasticsearch.yml /usr/share/elasticsearch/config/elasticsearch.yml
2
# 构建
$ docker build -t elasticSearch .
# Logstash
# logstash.yml
创建一个配置文件 logstash.yml
,添加以下内容
http.host: "0.0.0.0"
path.config: /usr/share/logstash/pipeline
2
# logstash.conf
再创建一个配置文件 logstash.conf
,添加以下内容
input {
tcp {
port => 5000
codec => json
}
udp {
port => 5000
codec => json
}
}
output {
elasticsearch {
hosts => "elasticsearch:9200"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Dockerfile
FROM docker.elastic.co/logstash/logstash-oss:6.2.4
COPY logstash.yml /usr/share/logstash/config/logstash.yml
COPY logstash.conf /usr/share/logstash/pipeline/logstash.conf
EXPOSE 5000
2
3
4
# 构建
$ docker build -t logstash .
# Kibana
# kibana.yml
server.name: kibana
server.host: "0"
elasticsearch.url: http://elasticsearch:9200
2
3
# Dockerfile
FROM docker.elastic.co/kibana/kibana-oss:6.2.4
COPY kibana.yml /usr/share/kibana/config/kibana.yml
2
# 构建
$ docker build -t kibana .
至此,ELK 三个镜像我们都已经构建好了。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
elasticsearch latest be6f4f0f0b5c 48 minutes ago 424MB
logstash latest 8708312ccbfc 50 minutes ago 657MB
kibana latest b08d2aa33797 About an hour ago 527MB
...
2
3
4
5
6
# Docker compose 运行 ELK 容器
创建一个 docker-compose.yml
文件,添加以下内容:
version: "2"
services:
elasticsearch:
restart: always
image: elasticsearch
container_name: elasticsearch
volumes:
- ./data/elasticsearch:/usr/share/elasticsearch/data
ports:
- "9200:9200"
logstash:
restart: always
image: logstash
container_name: logstash
ports:
- "5000:5000"
depends_on:
- elasticsearch
links:
- elasticsearch:elasticsearch
kibana:
restart: always
image: kibana
container_name: kibana
ports:
- "5601:5601"
depends_on:
- elasticsearch
links:
- elasticsearch:elasticsearch
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
然后使用 docker-compose up
命令,即可启动容器服务:
$ docker-compose up -d
启动完成,查看运行的容器:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b4a9825a061 kibana "/bin/bash /usr/loca…" About an hour ago Up About an hour 0.0.0.0:5601->5601/tcp kibana
82e6de4822d4 logstash "/usr/local/bin/dock…" About an hour ago Up About an hour 5044/tcp, 0.0.0.0:5000->5000/tcp, 9600/tcp logstash
0aba77e5d6f5 elasticsearch "/usr/local/bin/dock…" About an hour ago Up About an hour 0.0.0.0:9200->9200/tcp, 9300/tcp elasticsearch
2
3
4
5
# Logspout
到目前为止,ELK 已经搭建完毕,但还没有数据。
想要让某一台服务器上所有的 Docker 容器,都自动将日志输出到 ELK(准确地说是输出到 logstash),还需要一个另外的容器,也就是 Logspout。
具体实现可以看:
- bingozb/docker-logspout:https://github.com/bingozb/docker-logspout
- looplab/logspout-logstash:https://github.com/looplab/logspout-logstash
这里我们直接用起来,使用 bingozb/docker-logspout
镜像。
在某一台服务器(跟部署了ELK的服务器可以不是同一台)上的 docker-compose.yml
中,添加 logspout
服务:
logspout:
restart: always
image: bingozb/logspout
container_name: logspout
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
ROUTE_URIS: logstash://localhost:5000
LOGSTASH_TAGS: docker-elk
2
3
4
5
6
7
8
9
如果是外网部署,ROUTE_URIS
中的 localhost
需替换为部署了 ELK 的服务器的 IP。
这样,这台服务器上所有的容器的日志就都会输出到 Logstash,收集后通过 pipeline 存储到 es 中,就可以在 kibana 上看日志了。
# 测试
这里我添加一个简单的前后端分离的应用,进行测试。
javaee-zfbh5:
restart: always
image: bingozb/javaee-zfbh5
container_name: javaee-zfbh5
ports:
- "8088:8080"
web-zfbh5:
restart: always
image: bingozb/web-zfbh5
container_name: web-zfbh5
ports:
- "8090:80"
2
3
4
5
6
7
8
9
10
11
12
13
启动后,就可以在 kibana 上看到日志了。
$ docker-compose up -d
elasticsearch is up-to-date
kibana is up-to-date
logstash is up-to-date
logspout is up-to-date
Creating javaee-zfbh5 ... done
Creating web-zfbh5 ... done
2
3
4
5
6
7
访问 http://localhost:5601,查看页面数据。
可以做一个简单的筛选,比如只看 message
字段,然后搜索 INFO
:
# 后话
至此,我们通过 ElasticSearch、Logstash、Kibana、Logspout 四个容器,搭建了一套基于 Docker 环境下,自动化地对所有容器的日志进行收集、存储、以及提供前端页面可便捷检索日志的系统。
有了这么一套系统,开发人员再也不需要在每个项目代码中把 log 输出到文件,然后每次查日志的时候连上服务器去翻阅对应的日志文件,现在只需要打开 kibana 即可直接检索。