集中管理日志
为什么需要集中日志管理
在容器化环境中,日志的特点是:容器短暂、分布分散、数据量大。手动 docker logs 在单机小规模场景可行,但生产环境需要集中日志管理。
核心需求:
– 统一收集:所有容器日志自动采集
– 集中存储:日志存储在统一的平台
– 快速检索:支持全文搜索和过滤
– 可视化:通过 Dashboard 分析数据
– 告警:异常日志触发告警
ELK/EFK 栈
最流行的容器日志方案是 ELK(Elasticsearch + Logstash + Kibana)或 EFK(Elasticsearch + Fluentd + Kibana)。
EFK 架构
容器 → Fluentd → Elasticsearch → Kibana
↑ ↑ ↑ ↑
收集 传输 存储 可视化
Docker Compose 部署 EFK
version: "3.8"
services:
# 应用服务
app:
image: myapp
logging:
driver: "fluentd"
options:
fluentd-address: "localhost:24224"
tag: "app.{{.Name}}"
# 日志收集
fluentd:
image: fluent/fluentd:v1.16
ports:
- "24224:24224"
- "24224:24224/udp"
volumes:
- ./fluentd.conf:/fluentd/etc/fluent.conf:ro
- fluentd-buffer:/fluentd/log
# 日志存储
elasticsearch:
image: elasticsearch:7.17
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- es-data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
# 可视化
kibana:
image: kibana:7.17
ports:
- "5601:5601"
environment:
ELASTICSEARCH_HOSTS: http://elasticsearch:9200
volumes:
es-data:
fluentd-buffer:
Fluentd 配置
# fluentd.conf
@type forward
port 24224
bind 0.0.0.0
docker.**>
@type parser
key_name log
@type json
app.**>
@type elasticsearch
host elasticsearch
port 9200
logstash_format true
logstash_prefix docker-logs
flush_interval 5s
Loki + Promtail + Grafana
Grafana Loki 是轻量级的日志系统,比 ELK 资源消耗更少:
services:
# 应用服务
app:
image: myapp
logging:
driver: "json-file"
options:
max-size: "10m"
# 日志采集
promtail:
image: grafana/promtail:2.9
volumes:
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- ./promtail.yml:/etc/promtail/config.yml:ro
# 日志存储
loki:
image: grafana/loki:2.9
ports:
- "3100:3100"
volumes:
- ./loki-config.yml:/etc/loki/local-config.yaml
- loki-data:/loki
# 可视化
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_AUTH_ANONYMOUS_ENABLED=true
Docker Syslog 方案
Syslog 发送到远程服务器
# 容器配置
docker run \
--log-driver=syslog \
--log-opt syslog-address=tcp://syslog.example.com:514 \
--log-opt syslog-facility=daemon \
--log-opt tag="{{.Name}}" \
nginx
Compose 配置
services:
web:
image: nginx
logging:
driver: syslog
options:
syslog-address: "tcp://syslog.example.com:514"
tag: "web.{{.Name}}"
syslog-facility: "local0"
云平台日志方案
AWS CloudWatch
{
"log-driver": "awslogs",
"log-opts": {
"awslogs-region": "us-east-1",
"awslogs-group": "myapp-prod",
"awslogs-create-group": "true"
}
}
Google Cloud Logging
{
"log-driver": "gcplogs",
"log-opts": {
"gcp-log-name": "myapp",
"gcp-labels": "environment=prod"
}
}
日志格式标准化
JSON 格式日志
// 应用输出 JSON 格式日志
{"timestamp": "2023-01-01T00:00:00Z", "level": "info", "message": "Server started", "service": "api"}
{"timestamp": "2023-01-01T00:00:01Z", "level": "error", "message": "DB connection failed", "error": "connection refused"}
结构化日志
// Node.js
const logger = require('pino')()
logger.info({ user: 'admin', action: 'login' }, 'User logged in')
// Python
import structlog
logger = structlog.get_logger()
logger.info("user.login", user="admin")
// Java (Logback)
// {"timestamp": "%d", "level": "%p", "logger": "%c", "message": "%m"}%n
日志查询技巧
Kibana
# 搜索语法
docker-logs-*
level:error
message:"connection refused"
container_name:web AND level:error
Grafana Loki
# LogQL 语法
{container_name="web"} |= "error"
{container_name=~"web|api"} |~ "timeout|refused"
rate({job="docker"} |= "error" [5m])
最佳实践
- 应用输出结构化日志:JSON 格式,统一字段
- 配置日志轮转:防止日志撑爆磁盘
- 使用集中日志系统:避免 ssh 到每台机器看日志
- 设置合理保留期:热数据 7 天,冷数据 30 天
- 异常日志告警:ERROR 级别集中通知
- 日志脱敏:避免敏感信息进入日志平台
- 日志采样:高流量系统采样而非全量收集
集中日志管理是容器化运维的基石,选择合适的方案可以极大提升问题排查效率。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容