Docker日志处理—ELK
高效的监控和日志管理对保持生产系统持续稳定地运行以及排查问题至关重要。
在微服务架构中,由于容器的数量众多以及快速变化的特性使得记录日志和监控变得越来越重要。考虑到容器短暂和不固定的生命周期,当我们需要 debug(调试) 问题时有些容器可能已经不存在了。因此,一套集中式的日志管理系统是生产环境中不可或缺的组成部分。
监控容器的各种可用技术和方案,首先先看一下 Docker 自带的 logs 子命令,然后讨论 Docker 的 logging driver,接着就尝试去部署ELK进行日志的收集和管理
Docker logs
默认配置下 Docker 的日志功能。
对于一个运行的容器,Docker 会将日志发送到 容器的 标准输出设备(STDOUT)和标准错误设备(STDERR),STDOUT 和 STDERR 实际上就是容器的控制台终端。也就是发送到了物理机,后面会说到是通过什么机制去发送到物理机的什么位置。
例如:运行一个容器
如果不使用-d
选项,将会直接把日志信息输出到屏幕上
[root@localhost ~]# docker run -p 80:80 --name test httpd
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
[Wed Apr 08 09:50:24.016624 2020] [mpm_event:notice] [pid 1:tid 139784209921152] AH00489: Apache/2.4.41 (Unix) configured -- resuming normal operations
[Wed Apr 08 09:50:24.016822 2020] [core:notice] [pid 1:tid 139784209921152] AH00094: Command line: 'httpd -D FOREGROUND'
删除容器
[root@localhost ~]# docker rm -f test
test
如果使用了-d
选项,又怎么去查看日志
[root@localhost ~]# docker run -p 80:80 -d --name test1 httpd
575cec7f272ae2453c594f1d4f0c6c072240ff43e72a6e73e3e8e891317e1a00
- 使用
docker attch
进入容器阻塞去查看日志
[root@localhost ~]# docker attach test1
# 运行之后会阻塞,没有任何输出信息,这时使用另一个终端或者主机去访问这个端口
# curl 192.168.1.11
# 会输出以下信息,也就是test1容器的日志
192.168.1.11 - - [08/Apr/2020:09:56:18 +0000] "GET / HTTP/1.1" 200 45
attach 的方法在实际使用中不太方便,因为:
只能看到 attach 之后的日志,以前的日志不可见。
退出 attach 状态比较麻烦(Ctrl+p 然后 Ctrl+q 组合键),一不小心很容器将容器杀掉(比如按下 Ctrl+C)。
使用各种方法退出之后,发现该容器确实也被停止了,这时就可以去使用docker logs
来查看日志比较方便
2.使用docker logs
查看容器日志
这个方法可以看到容器内的所有日志信息
# 重新运行刚才停止的容器
[root@localhost ~]# docker start test1
test1
[root@localhost ~]# docker logs test1
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
[Wed Apr 08 09:51:46.095262 2020] [mpm_event:notice] [pid 1:tid 140106547037312] AH00489: Apache/2.4.41 (Unix) configured -- resuming normal operations
[Wed Apr 08 09:51:46.095674 2020] [core:notice] [pid 1:tid 140106547037312] AH00094: Command line: 'httpd -D FOREGROUND'
192.168.1.12 - - [08/Apr/2020:09:53:10 +0000] "GET / HTTP/1.1" 200 45
...
logging driver
将容器日志发送到 STDOUT 和 STDERR 是 Docker 的默认日志行为。实际上,Docker 提供了多种日志机制帮助用户从运行的容器中提取日志信息。这些机制被称作 logging driver。
json-file
json-file这种格式的文件是一种交互式的文件,可以很方便的发送到其他主机,读取解析也很方便。
Docker 的默认 logging driver 是 json-file
。可以通过查看docker info
看到docker默认的logging driver
[root@localhost ~]# docker info | grep "Logging Driver"
Logging Driver: json-file
如果容器在启动时没有特别指明,就会使用这个默认的 logging driver。
json-file
会将容器的日志保存在 json 文件中,Docker 负责格式化其内容并输出到 STDOUT 和 STDERR。
可以在 Host 的容器目录中找到这个文件
查找该文件,以刚才运行的test1容器为例
[root@localhost ~]# docker inspect test1 | grep LogPath
"LogPath": "/var/lib/docker/containers/575cec7f272ae2453c594f1d4f0c6c072240f
f43e72a6e73e3e8e891317e1a00/575cec7f272ae2453c594f1d4f0c6c072240ff43e72a6e73
e3e8e891317e1a00-json.log"
json-file文件的路径就是/var/lib/docker/containers/容器id/容器id-json.log
也可以通过cat去查看该文件中的内容,就是容器中的日志信息
docker支持的logging driver
除了 json-file
,Docker 还支持多种 logging driver。如下图所示,是官网中的内容,已使用谷歌翻译
以下简单说明一个logging driver
none
:用于关闭容器日志功能
json-file
:docker默认使用的,就是将日志存放到物理机的一个json文件中
syslog
/journald
:Linux上的两种日志管理服务
awslogs/splunk/gcplogs
:第三方日志托管服务
gelf/fluentd
:开源日志管理方案
后面会有几种驱动器的使用
修改默认的logging driver
修改logging driver
有两种方法
1、修改文件
针对所有启动的容器
[root@localhost ~]# vim /usr/lib/systemd/system/docker.service
# 找到14行或者以ExecStart开头的一行
# 在这行末尾添加--log-driver=
# 引号内可以写以上在官网中查到的类型,如:
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --log-driver=none
2、运行容器时添加
指定单独容器使用的logging driver
[root@localhost ~]# docker run -itd --name test --rm --log-driver none httpd
9543f7aa5d02e8c5844016037dfddc7bcd7b866fe8f1962bd6517408a1ef6f82
查看是否有日志路径生成
[root@localhost ~]# docker inspect test | grep LogPath
"LogPath": "",
ELK
在开源的日志管理方案中,最出名的莫过于 ELK 了,ELK 是三个软件的合称:Elasticsearch、Logstash、Kibana
上述内容中说到,json文件可以方便的进行交互数据,使用ELK方案,json格式的日志文件就会传递给ELK。
Elasticsearch
一个近乎实时查询的全文搜索引擎。Elasticsearch 的设计目标就是要能够处理和搜索巨量的日志数据。Logstash
读取原始日志,并对其进行分析和过滤,然后将其转发给其他组件(比如 Elasticsearch)进行索引或存储。Logstash 支持丰富的 Input 和 Output 类型,能够处理各种应用的日志。Kibana
一个基于 JavaScript 的 Web 图形界面程序,专门用于可视化 Elasticsearch 的数据。Kibana 能够查询 Elasticsearch 并通过丰富的图表展示结果。用户可以创建 Dashboard 来监控系统的日志。
日志处理流程
Logstash 负责从各个 Docker 容器中提取日志,Logstash将日志转发到 Elasticsearch 进行索引和保存,Kibana 分析和可视化数据。
部署ELK
ELK 的部署方案可以非常灵活,在规模较大的生产系统中,ELK 有自己的集群,实现了高可用和负载均衡。我们的目标是在最短的时间内学习并实践 ELK,因此将采用最小部署方案:在容器中搭建 ELK。
由于之前的测试中,启动了两个test容器,这里先将他们删除
[root@localhost ~]# docker rm -f test test1
ELK环境
ip | 服务 | 备注 |
---|---|---|
192.168.1.11 | Docker | 内存8G |
部署ELK容器的环境中,对物理机的内存有明确要求,Elasticsearch需要至少使用2G内存,Docker需要使用4G,为了保证运行正常,这里将虚拟机关机,调整内存为8G,推荐cpu内核为2,官方说明在此
实验目的
使用ELK监控容器日志,在web页面中可以查看到
实验步骤
下载ELK镜像
下载ELK镜像,这个镜像需要下载很时间,大小2个G
[root@elk ~]# docker pull sebp/elk
查看镜像
[root@elk ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
sebp/elk latest c21727ae794b 2 weeks ago 2.07GB
busybox latest 83aa35aa1c79 4 weeks ago 1.22MB
httpd latest c5a012f9cf45 6 weeks ago 165MB
centos latest 5e35e350aded 4 months ago 2
限制进程使用VMA
Elasticsearch默认使用目录来存储其索引。默认的操作系统对mmap计数的限制可能太低,这可能会导致内存不足异常。以致于Elasticsearch无法启动
[root@elk ~]# vim /etc/sysctl.conf
# 添加
vm.max_map_count = 262144
[root@elk ~]# sysctl -p
max_map_count\文件包含限制一个进程可以拥有的VMA(虚拟内存区域)的数量。虚拟内存区域是一个连续的虚拟地址空间区域。在进程的生命周期中,每当程序尝试在内存中映射文件,链接到共享内存段,或者分配堆空间的时候,这些区域将被创建。调优这个值将限制进程可拥有VMA的数量。限制一个进程拥有VMA的总数可能导致应用程序出错,因为当进程达到了VMA上线但又只能释放少量的内存给其他的内核进程使用时,操作系统会抛出内存不足的错误。如果你的操作系统在NORMAL区域仅占用少量的内存,那么调低这个值可以帮助释放内存给内核用
启动ELK
[root@elk ~]# systemctl start docker
[root@elk ~]# docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -itd \
-e ES_HEAP_SIZE="2g" -e LS_HEAP_SIZE="2g" --name elk sebp/elk
2620103dda58f8183f5f977e896c82d2dc9a07d7dccab9af8ce039c06e766c0c
建议检测这几个端口是否启动,netstat -anput | grep 5044
、netstat -anput | grep 5061
、netstat -anput | grep 9200
5601 - Kibana web 接口
9200 - Elasticsearch JSON 接口
5044 - Logstash 日志接收接口
防火墙放行端口
[root@elk ~]# firewall-cmd --add-port=5601/tcp
success
[root@elk ~]# firewall-cmd --add-port=5044/tcp
success
[root@elk ~]# firewall-cmd --add-port=9200/tcp
success
添加日志数据
使用浏览器访问http://192.168.1.11:5601
运行之后多等一会,这是cpu会疯转,会在网络上下载一些东西
进入之后的界面,选择Explore on my own
,自己创建数据
添加日志数据
日志数据为使用elasticsearch存储的日志
根据页面提示下载安装filebeat,Linux系统选择RPM
安装filebeat
复制第一步中的第一条命令进行下载filebeat
[root@elk ~]# curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.6.1-x86_64.rpm
安装filebeat
[root@elk ~]# sudo rpm -vi filebeat-7.6.1-x86_64.rpm
修改filebeat配置文件
根据网页的提示修改两处的URL之外,还要将filebeat.inputs
的功能开启
[root@elk ~]# vim /etc/filebeat/filebeat.yml
# 24行修改为
enabled: true
# 28行添加一行,指定收集本机日志的路径,这个路径就是所有容器json-file存放的位置
- /var/lib/docker/containers/*/*.log
# 125行,kibana的配置下,修改或者添加以下,ip为本机ip
host: "192.168.1.11:5601"
# 152行,Elasticsearch output的配置下
hosts: ["192.168.1.11:9200"]
启动filebeat
# 启动并配置elasticsearch
[root@elk ~]# sudo filebeat modules enable elasticsearch
Enabled elasticsearch
# 加载kibana仪表盘
[root@elk ~]# sudo filebeat setup
# 启动filebeat
[root@elk ~]# sudo service filebeat start
Starting filebeat (via systemctl): [ OK ]
发现日志数据
回到刚才的页面中,完成所有步骤可以,检测数据,由于没有数据也是检测不到的,可以点击**Discover
**,进行发现数据
模拟容器生成日志
[root@elk ~]# docker run busybox sh -c \
'while true; do echo "This is a log message from container FeiYi"; sleep 10; done;'
等待数据几条信息后,去刷新页面,我这里好像因为虚拟机的时间与宿主机不同步的原因,我需要将时间选择为检测本周内的日志,搜索日志中的关键字**FeiYi
**,如图所示