🐧 第07课:日志管理

📚 核心概念

🎯 日志:系统的黑匣子

日志是故障排查的黄金线索。一个成熟的日志体系能够让你在几分钟内定位问题,而不是花几小时翻找文件。从本地日志到集中式日志平台,这是DevOps的必经之路。

📋 日志管理演进

Level 0: 直接看文件     → tail -f /var/log/app.log
Level 1: 日志轮转       → logrotate 自动切割压缩
Level 2: 集中收集       → Filebeat/Fluentd → Elasticsearch
Level 3: 结构化日志     → JSON格式 + 链路ID
Level 4: 可观测性平台   → 指标+日志+链路三位一体

📝 结构化日志标准

传统文本日志难以搜索和分析,结构化日志(JSON格式)是现代应用的标准:

结构化日志示例
{
  "timestamp": "2026-05-19T10:30:00.123Z",
  "level": "ERROR",
  "service": "order-service",
  "trace_id": "abc123def456",
  "span_id": "span789",
  "user_id": "U10086",
  "method": "POST",
  "path": "/api/orders",
  "status": 500,
  "duration_ms": 2345,
  "error": "database connection timeout",
  "stack_trace": "at OrderService.create() ..."
}

⌨️ 命令实操

⌨️ 实操命令

1. 日志查看与搜索 ✅

日志查看
# systemd日志
journalctl -u nginx -f              # 实时跟踪nginx日志
journalctl -u nginx --since today   # 今天的日志
journalctl -u nginx -n 100          # 最近100行
journalctl -p err                   # 只看error级别
journalctl --since "2026-05-19 10:00" --until "2026-05-19 11:00"

# 传统日志
tail -f /var/log/nginx/access.log   # 实时跟踪
less +F /var/log/syslog             # less的follow模式
head -100 /var/log/auth.log         # 查看开头

# 搜索与过滤
grep -E "ERROR|FATAL" /var/log/app.log
grep "10.0.1.100" /var/log/nginx/access.log
awk '$9 >= 500' access.log           # HTTP 5xx错误
journalctl -u docker --grep "OOM"   # 搜索关键词

2. logrotate配置 ✅

日志轮转
# 应用日志轮转配置
cat > /etc/logrotate.d/myapp << 'EOF'
/var/log/myapp/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 0644 appuser appgroup
    sharedscripts
    postrotate
        systemctl reload myapp >/dev/null 2>&1 || true
    endscript
}
EOF

# 手动测试轮转
logrotate -d /etc/logrotate.d/myapp    # 调试模式
logrotate -f /etc/logrotate.d/myapp    # 强制执行

# Nginx日志轮转
cat /etc/logrotate.d/nginx
# /var/log/nginx/*.log {
#     daily
#     rotate 14
#     compress
#     create 0640 www-data adm
#     postrotate
#         [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
#     endscript
# }

3. 集中式日志:Fluentd ✅

Fluentd
# 安装Fluentd(td-agent)
curl -L https://toolbelt.treasuredata.com/sh/install-ubuntu-jammy-td-agent4.sh | sh

# 配置Fluentd
cat > /etc/td-agent/td-agent.conf << 'EOF'

  @type tail
  path /var/log/nginx/access.log
  pos_file /var/log/td-agent/nginx-access.pos
  tag nginx.access
  
    @type nginx
  



  @type tail
  path /var/log/app/*.log
  pos_file /var/log/td-agent/app.pos
  tag app.log
  
    @type json
  



  @type elasticsearch
  host elasticsearch.internal
  port 9200
  logstash_format true
  logstash_prefix fluentd
  
    @type file
    path /var/log/td-agent/buffer
    flush_interval 10s
  

EOF

sudo systemctl restart td-agent

📐 架构图

📐 架构图:ELK日志平台

  数据源                 采集层              存储层          展示层
  ┌──────┐           ┌─────────┐        ┌─────────┐    ┌─────────┐
  │ Nginx│──文件────▶│         │        │         │    │         │
  └──────┘           │ Fluentd │──bulk──▶│ Elastic │───▶│ Kibana  │
  ┌──────┐           │ /File   │   ▶    │ search  │    │ Dashboard│
  │ App  │──stdout──▶│ beat    │        │ Engine  │    └─────────┘
  └──────┘           │         │        │         │
  ┌──────┐           │ 解析    │        │ 索引    │    ┌─────────┐
  │MySQL │──慢查询──▶│ 过滤    │        │ 生命周期│    │ Alert   │
  └──────┘           │ 标签    │        │ 管理    │───▶│ →钉钉   │
  ┌──────┐           └─────────┘        └─────────┘    └─────────┘
  │Syslog│──rsyslog──▶
  └──────┘

🔧 故障排查

🔧 故障排查

❌ 问题1:日志文件过大导致磁盘满

# 紧急处理:清空日志但不删除文件
> /var/log/nginx/access.log   # 保留文件,清空内容
# 或 truncate
truncate -s 0 /var/log/app.log

# 根本解决:配置logrotate
# 参见上方logrotate配置

# 检查日志增长速度
lsof | grep deleted | sort -k7 -rn | head
# 找到被删但未释放的大日志文件

📋 日志分级标准

级别含义生产环境示例
TRACE最详细的调试信息❌ 关闭函数入参出参
DEBUG调试信息❌ 关闭(排查时临时开启)SQL查询、缓存命中
INFO关键业务事件✅ 开启请求开始/结束、订单创建
WARN潜在问题✅ 开启重试、降级、接近阈值
ERROR错误但系统可继续✅ 开启+告警异常捕获、外部调用失败
FATAL致命错误,系统停止✅ 开启+紧急告警数据库连接耗尽、OOM

🔗 分布式链路追踪

微服务架构下,一个请求可能经过多个服务。链路追踪通过trace_id串联所有日志,让你能追踪完整的请求路径:

链路追踪
# 请求流程:Gateway → User Service → Order Service → Payment
trace_id: abc-123-def

[Gateway]       INFO  trace=abc-123  "GET /api/orders" started
[User Service]  INFO  trace=abc-123  span=get-user  "Fetching user U10086"
[Order Service] INFO  trace=abc-123  span=create-order  "Creating order"
[Payment]       ERROR trace=abc-123  span=charge  "Payment gateway timeout"
[Gateway]       WARN  trace=abc-123  "GET /api/orders" completed with 202

# 通过trace_id一键搜索所有相关日志!

4. Elasticsearch + Kibana部署 ✅

ELK Stack
# Docker Compose部署ELK
cat > /opt/elk/docker-compose.yml << 'EOF'
version: "3.8"
services:
  elasticsearch:
    image: elasticsearch:8.12.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms1g -Xmx1g"
    volumes:
      - es_data:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"

  kibana:
    image: kibana:8.12.0
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch

volumes:
  es_data:
EOF

docker compose up -d

5. 日志分析实战 ✅

Log Analysis
# Nginx日志实时分析
# Top 10 访问IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

# 统计HTTP状态码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 用jq分析JSON日志
cat app.log | jq 'select(.level=="ERROR") | {timestamp, service, error}' 
cat app.log | jq -s 'group_by(.service) | map({service: .[0].service, count: length}) | sort_by(-.count)'

❌ 问题2:Elasticsearch集群状态Red

# 查看集群健康状态
curl -s localhost:9200/_cluster/health?pretty

# 查看未分配分片
curl -s localhost:9200/_cat/shards?v | grep UNASSIGNED

# 常见原因与解决:
# 1. 磁盘满 → 清理或增加磁盘
# 2. 节点数不够 → 增加节点  
# 3. 分片数超限 → 调整cluster.max_shards_per_node

🏆 成就解锁:日志大师!

掌握日志轮转、结构化日志、ELK/EFK日志平台——日志是故障排查的黄金线索。