容器日志管理的核心挑战
Docker容器日志管理是SRE日常运维的高频痛点。容器生命周期短暂,日志随容器销毁而丢失;默认json-file日志驱动无滚动机制,磁盘占满导致节点不可用是常见故障。EFK(Elasticsearch + Fluentd/Filebeat + Kibana)体系是容器日志领域最成熟的解决方案,本文从部署到排错覆盖完整实操路径。
Docker日志驱动选型与配置
Docker支持多种日志驱动,生产环境推荐json-file(配合滚动限制)或fluentd(直发模式):
# /etc/docker/daemon.json - 全局日志配置
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "3"
}
}
# 单容器覆盖日志驱动
# docker run --log-driver=fluentd # --log-opt fluentd-address=localhost:24224 # --log-opt tag="app.{{.Name}}" # nginx:latest
max-size限制单文件最大50MB,max-file保留3个轮转文件。单容器日志上限150MB。未配置此参数时,json-file驱动会无限增长,曾导致多起磁盘100%占满事故。
Fluentd采集层部署与配置
Fluentd作为日志采集和路由层,负责从Docker容器收集日志并转发至Elasticsearch。使用fluent-plugin-docker_metadata_filter插件自动注入容器元数据:
# Fluentd配置文件 td-agent.conf
<source>
@type tail
path /var/lib/docker/containers/*/*-json.log
pos_file /var/log/fluentd/docker-containers.log.pos
tag docker.*
read_from_head false
<parse>
@type json
time_key time
time_format %Y-%m-%dT%H:%M:%S.%NZ
</parse>
</source>
<filter docker.**>
@type docker_metadata
@id container_metadata_filter
<inject>
hostname_key hostname
</inject>
</filter>
<match docker.**>
@type elasticsearch
host elasticsearch.logging.svc
port 9200
logstash_format true
logstash_prefix docker-logs
include_tag_key true
tag_key @log_name
flush_interval 5s
retry_max_interval 30s
retry_forever true
</match>
关键配置说明:@type tail以尾部读取模式跟踪日志文件,pos_file记录读取位置保证重启后不丢数据。Docker元数据过滤器注入容器名、镜像名、标签等信息,方便后续在Kibana中按服务筛选。
Elasticsearch索引生命周期管理
日志场景下Elasticsearch索引无限增长会耗尽存储。ILM(Index Lifecycle Management)自动执行索引滚动、缩减副本和删除策略:
# 创建ILM策略
PUT _ilm/policy/docker-logs-policy
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "50gb",
"max_age": "7d"
}
}
},
"warm": {
"min_age": "7d",
"actions": {
"shrink": { "number_of_shards": 1 },
"forcemerge": { "max_num_segments": 1 }
}
},
"delete": {
"min_age": "30d",
"actions": {
"delete": {}
}
}
}
}
}
# 关联到索引模板
PUT _template/docker-logs-template
{
"index_patterns": ["docker-logs-*"],
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"lifecycle.name": "docker-logs-policy",
"lifecycle.rollover_alias": "docker-logs"
}
}
Hot阶段:索引超过50GB或7天触发滚动,生成新索引。Warm阶段:7天后合并分片和段文件,降低存储开销。Delete阶段:30天后自动删除,释放磁盘空间。这套策略在日均10GB日志量下运行稳定,Elasticsearch存储维持在150GB左右。
Kibana可视化与告警看板
Kibana提供日志搜索和可视化能力。推荐创建以下看板:
# 常用Kibana查询DSL
# 按容器名过滤
{"query": {"match": {"docker.container_name": "api-gateway"}}}
# 错误日志统计(5分钟粒度)
{"aggs": {
"errors_over_time": {
"date_histogram": {"field": "@timestamp", "fixed_interval": "5m"},
"aggs": {"error_count": {
"filter": {"match": {"log": "ERROR"}}
}}
}
}}
# 慢请求日志(响应时间>2s)
{"query": {"range": {"response_time": {"gt": 2000}}}}
告警方面,Elasticsearch Watcher或开源替代方案(如ElastAlert)可基于日志模式触发告警。典型场景:5分钟内ERROR日志超过阈值、特定容器连续Crash、磁盘使用率超85%。
常见故障排查清单
EFK体系运维中的高频问题及解法:
1. Fluentd采集延迟
查看Fluentd缓冲区:curl http://localhost:24220/api/plugins.json,关注buffer_queue_length和buffer_total_bytes。队列积压时增大flush_interval的并发度或扩容Fluentd实例。
2. Elasticsearch写入拒绝
日志中出现429 Too Many Requests时,索引写入速度超过Elasticsearch处理能力。解决方案:增大refresh_interval(默认1s改为30s)、增加索引分片数、启用批量请求缓冲。
3. 磁盘水位线告警
Elasticsearch默认在磁盘使用率超过85%时停止分配分片,超过95%时设索引为只读。提前配置cluster.routing.allocation.disk.watermark阈值,并确保ILM删除策略正常运行。
# Elasticsearch磁盘水位线配置
cluster.routing.allocation.disk.threshold_enabled: true
cluster.routing.allocation.disk.watermark.low: 85%
cluster.routing.allocation.disk.watermark.high: 90%
cluster.routing.allocation.disk.watermark.flood_stage: 95%
EFK体系搭建完成后,核心运维动作是监控Fluentd缓冲区积压、Elasticsearch集群健康状态和磁盘水位线。建议将这三个指标接入Prometheus告警体系,确保日志管道持续可靠运行。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/docker-rong-qi-ri-zhi-cai-ji-yu-efk-ti-xi-da-jian-yun-wei/