集中管理日志

集中管理日志

为什么需要集中日志管理

在容器化环境中,日志的特点是:容器短暂、分布分散、数据量大。手动 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])

最佳实践

  1. 应用输出结构化日志:JSON 格式,统一字段
  2. 配置日志轮转:防止日志撑爆磁盘
  3. 使用集中日志系统:避免 ssh 到每台机器看日志
  4. 设置合理保留期:热数据 7 天,冷数据 30 天
  5. 异常日志告警:ERROR 级别集中通知
  6. 日志脱敏:避免敏感信息进入日志平台
  7. 日志采样:高流量系统采样而非全量收集

集中日志管理是容器化运维的基石,选择合适的方案可以极大提升问题排查效率。

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容