对于不少刚接触容器化部署的朋友来说docker 日志,Docker跑起来容易,但日志管理往往让人头疼。我这些年帮团队处理过无数次线上故障,有一条经验越来越深:日志是容器世界的眼睛,看不清楚,排查问题就像摸黑走路。Docker的日志机制其实并不复杂,但需要理解它的设计逻辑,才能用好它。

容器日志到底存在哪里

很多人第一次查Docker日志时,会纳闷日志文件究竟藏在哪。Docker默认使用json-file驱动,日志以JSON格式保存在宿主机的/var/lib/docker/containers/<容器ID>/目录下,文件名通常是<容器ID>-json.log。这些文件会一直增长,如果不加干预,几个月下来能吃掉几十GB磁盘空间。

我曾经接手过一个项目,生产环境一台服务器上跑了二十几个容器,半年没清理过日志。某天凌晨磁盘报警,一看根目录剩余空间不到1GB,排查下来全是容器日志撑爆的。当时紧急写了个定时清理脚本,才勉强救回来。后来我养成了习惯,每次部署新容器,第一件事就是确认日志有没有做轮转配置。

日志羽绒服属于什么档次_docker 日志_日志型劳力士多少钱

Docker本身提供了docker logs命令,可以实时查看标准输出和标准错误流。这条命令背后读取的就是json.log文件。但需要注意,这个命令只能查看挂载到容器标准输出的日志,如果你在容器内部写文件日志,docker logs是看不到的。很多团队踩过这个坑,以为日志丢了,实际是方法没找对。

如何限制日志文件大小和数量

限制日志文件大小,最直接的方法是在启动容器时指定--log-opt参数。两个最关键的参数是max-sizemax-file,前者控制单个日志文件最大容量,后者控制保留的日志文件数量。比如--log-opt max-size=10m --log-opt max-file=3,表示每个日志文件最多10MB,保留最近3个文件,超出部分自动删除。

如果容器已经运行着,或者想全局统一配置,可以修改Docker daemon的配置文件/etc/docker/daemon.json。在这个文件里加上日志相关的配置项,重启Docker服务后,新启动的容器都会继承这些设置。我一般在daemon.json里写这样一段:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

这样做的好处是一劳永逸,团队里任何人启动容器都不用再手动加参数。但要注意,修改daemon.json后一定要systemctl restart docker,而且这个配置只对新容器生效,已有的旧容器不会自动应用新规则。

日志驱动选哪个更合适

Docker支持多种日志驱动,除了默认的json-file,还有syslog、journald、fluentd、awslogs、gelf等。选哪个要看你的运维体系。如果是单机测试或小规模部署,json-file完全够用。如果公司有统一的日志收集平台,比如ELK或者Splunk,通常会选fluentd或者gelf驱动,让日志直接流到中央日志服务器。

我遇到过一些团队,日志收集链路搭得非常复杂。容器日志先写到文件linux系统iso下载,再用Filebeat采集,最后送到Elasticsearch。这个方案虽然也能用,但中间多了一层文件IO,效率不高。更好的做法是直接用Docker的fluentd驱动,日志直接从容器标准输出流到fluentd agent,再转发到后端存储。少了一次磁盘写入,性能明显提升。

不过选驱动时要考虑一个细节:不同驱动对日志字段的解析方式不同。比如json-file驱动会把每条日志按JSON格式存储,而syslog驱动会按系统日志格式处理。如果需要保留容器名称、镜像版本等元信息,fluentd和gelf这类支持结构化日志的驱动会更友好。

集中式日志收集怎么搭

当容器数量超过十来个,靠一台台机器手动查日志就不现实了。这时候需要搭建集中式日志系统。最常见的组合是ELK(Elasticsearch、Logstash、Kibana)或EFK(用Fluentd替代Logstash)。我比较推荐EFKdocker 日志,因为Fluentd和Docker的集成度更高,性能也比Logstash好一些。

日志羽绒服属于什么档次_docker 日志_日志型劳力士多少钱

具体做法很简单:在每个Docker宿主机上部署一个Fluentd容器,挂载宿主机的docker.sock,让它能监听Docker的事件和日志流。Fluentd会实时收集所有容器的标准输出日志kali linux,打上宿主机IP、容器名、时间戳等标签,然后批量发送到Elasticsearch集群。Kibana负责展示和搜索。

刚开始搭的时候容易忽略一个点:日志的时间戳。Docker日志默认使用容器的本地时间,如果容器和宿主机的时区不一致,收集到的日志时间就会乱。我踩过这个坑,排查问题时发现日志时间对不上,折腾了半天才发现是时区问题。解决方法是启动容器时挂载宿主机的/etc/localtime,或者在日志收集端统一转换时区。

日志丢失了怎么排查

有时候docker logs看不到任何输出,但容器明明在正常运行。这种情况多半是因为应用没有把日志写入标准输出,而是写到了容器内的文件里。很多Java应用默认把日志写到/var/log/app.log,而不是标准输出。Docker只能捕获标准输出和标准错误流,文件日志它是看不到的。

解决方法有两种。一种是在启动容器时做软链接,把应用日志文件软链接到/dev/stdout上。另一种是修改应用配置,让日志直接输出到标准输出。我倾向于后者,因为更干净,也符合12-Factor App的理念。如果改应用配置比较麻烦,软链接也是个办法。

还有一种情况是日志驱动配置错误。比如你明明配了fluentd驱动,但日志收不到,可能是fluentd的服务地址或者端口写错了。这时候先切回json-file驱动,确认容器本身能正常产生日志,再排查外部日志收集链路的问题。

Docker日志管理不是一朝一夕能搞定的,需要在实践中不断调整。每次线上故障都是一次学习机会,把日志机制摸透了,运维起来会轻松很多。

Tagged:
Author

这篇优质的内容由TA贡献而来

刘遄

《Linux就该这么学》书籍作者,RHCA认证架构师,教育学(计算机专业硕士)。

发表回复