第09章 运维监控与故障排除

第09章 运维监控与故障排除

9.1 系统监控

有效的监控是保障系统稳定运行的关键。本节将介绍如何全面监控 BillionMail 系统。

9.1.1 监控指标

系统资源指标

CPU 使用率

  • 总体 CPU 使用率
  • 各进程 CPU 使用率
  • CPU 负载(load average)

监控命令:

# 查看 CPU 使用率
top

# 查看特定进程
ps aux | grep postfix

# 查看负载
uptime

内存使用

  • 总内存和可用内存
  • Swap 使用情况
  • 各进程内存占用

监控命令:

# 内存使用情况
free -h

# 详细内存信息
cat /proc/meminfo

# 进程内存排序
ps aux --sort=-%mem | head

磁盘使用

  • 磁盘空间使用率
  • I/O 性能
  • inode 使用率

监控命令:

# 磁盘空间
df -h

# 磁盘 I/O
iostat -x 1

# inode 使用
df -i

网络流量

  • 带宽使用
  • 连接数
  • 丢包率

监控命令:

# 网络流量
iftop

# 连接统计
ss -s

# 网络接口统计
netstat -i

应用指标

邮件队列

# Postfix 队列大小
postqueue -p | tail -1

# 各队列详情
qshape active
qshape deferred

发送统计

  • 每小时发送量
  • 每天发送量
  • 送达率
  • 退信率

数据库性能

-- PostgreSQL 连接数
SELECT count(*) FROM pg_stat_activity;

-- 慢查询
SELECT query, calls, total_time, mean_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;

-- 数据库大小
SELECT pg_size_pretty(pg_database_size('billionmail'));

-- 表大小
SELECT 
    schemaname,
    tablename,
    pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
LIMIT 10;

Redis 性能

# Redis 信息
redis-cli INFO

# 内存使用
redis-cli INFO memory

# 慢查询日志
redis-cli SLOWLOG GET 10

9.1.2 日志管理

日志文件位置

系统日志

  • /var/log/syslog/var/log/messages

Postfix 日志

  • /var/log/mail.log
  • /var/log/mail.err

Dovecot 日志

  • /var/log/dovecot.log
  • /var/log/dovecot-info.log

应用日志

  • /var/log/billionmail/api.log
  • /var/log/billionmail/error.log

Nginx 日志

  • /var/log/nginx/access.log
  • /var/log/nginx/error.log

日志查看命令

实时查看

# 实时跟踪日志
tail -f /var/log/mail.log

# 多个日志文件
tail -f /var/log/mail.log /var/log/dovecot.log

搜索和过滤

# 搜索特定关键词
grep "error" /var/log/mail.log

# 统计错误数量
grep -c "error" /var/log/mail.log

# 显示上下文
grep -C 5 "error" /var/log/mail.log

# 搜索多个文件
grep "error" /var/log/*.log

# 正则表达式搜索
grep -E "error|warning" /var/log/mail.log

日志分析

# 统计最常见的错误
awk '/error/ {print}' /var/log/mail.log | sort | uniq -c | sort -rn | head -10

# 统计每小时的邮件数量
awk '/postfix.*sent/ {print substr($0,1,13)}' /var/log/mail.log | uniq -c

# 查找特定收件人的日志
grep "recipient@example.com" /var/log/mail.log

日志轮转配置

/etc/logrotate.d/billionmail

/var/log/billionmail/*.log {
    daily
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        systemctl reload billionmail
    endscript
}

/var/log/mail.log {
    daily
    rotate 30
    compress
    delaycompress
    notifempty
    create 0640 syslog adm
    postrotate
        invoke-rc.d postfix reload > /dev/null
    endscript
}

9.1.3 监控工具

Prometheus + Grafana

安装 Prometheus

# 下载 Prometheus
wget https://github.com/prometheus/prometheus/releases/download/v2.40.0/prometheus-2.40.0.linux-amd64.tar.gz
tar xvfz prometheus-2.40.0.linux-amd64.tar.gz
cd prometheus-2.40.0.linux-amd64

# 配置 prometheus.yml
cat > prometheus.yml <<EOF
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'billionmail'
    static_configs:
      - targets: ['localhost:9090']
      
  - job_name: 'node_exporter'
    static_configs:
      - targets: ['localhost:9100']
      
  - job_name: 'postgres'
    static_configs:
      - targets: ['localhost:9187']
EOF

# 启动 Prometheus
./prometheus --config.file=prometheus.yml

安装 Node Exporter(系统指标):

wget https://github.com/prometheus/node_exporter/releases/download/v1.5.0/node_exporter-1.5.0.linux-amd64.tar.gz
tar xvfz node_exporter-1.5.0.linux-amd64.tar.gz
cd node_exporter-1.5.0.linux-amd64
./node_exporter

安装 Grafana

# Ubuntu/Debian
sudo apt-get install -y software-properties-common
sudo add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install grafana

# 启动 Grafana
sudo systemctl start grafana-server
sudo systemctl enable grafana-server

访问 Grafana:http://your-server:3000(默认用户名密码:admin/admin)

配置 Grafana

  1. 添加 Prometheus 数据源
  2. 导入预设的仪表板或创建自定义仪表板
  3. 设置告警规则

常用的 Grafana 面板

  • 系统资源(CPU、内存、磁盘、网络)
  • 邮件发送量趋势
  • 邮件队列大小
  • 数据库性能
  • Redis 性能
  • 应用响应时间
  • 错误率

9.1.4 告警配置

邮件告警

配置 Prometheus Alertmanager:

alertmanager.yml

global:
  smtp_smarthost: 'localhost:587'
  smtp_from: 'alerts@example.com'
  smtp_auth_username: 'alerts@example.com'
  smtp_auth_password: 'password'

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1h
  receiver: 'email'

receivers:
  - name: 'email'
    email_configs:
      - to: 'admin@example.com'

告警规则

alert_rules.yml

groups:
  - name: billionmail_alerts
    rules:
      # 高 CPU 使用率
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[2m])) * 100) > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU 使用率过高"
          description: "{{ $labels.instance }} CPU 使用率 {{ $value }}%"
      
      # 高内存使用
      - alert: HighMemoryUsage
        expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 90
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "内存使用率过高"
          description: "{{ $labels.instance }} 内存使用率 {{ $value }}%"
      
      # 磁盘空间不足
      - alert: LowDiskSpace
        expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 10
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "磁盘空间不足"
          description: "{{ $labels.instance }} 根分区剩余空间 {{ $value }}%"
      
      # 邮件队列过大
      - alert: LargeMailQueue
        expr: postfix_queue_size > 10000
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "邮件队列过大"
          description: "Postfix 队列中有 {{ $value }} 封邮件等待发送"
      
      # 数据库连接数过多
      - alert: HighDatabaseConnections
        expr: pg_stat_activity_count > 100
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "数据库连接数过多"
          description: "当前有 {{ $value }} 个活动连接"

Webhook 告警

发送告警到 Slack、钉钉等:

receivers:
  - name: 'slack'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
        channel: '#alerts'
        title: '{{ .GroupLabels.alertname }}'
        text: '{{ range .Alerts }}{{ .Annotations.description }}{{ end }}'

9.2 备份和恢复

9.2.1 数据库备份

PostgreSQL 备份

完整备份

# 备份单个数据库
pg_dump -U billionmail -h localhost billionmail > backup_$(date +%Y%m%d).sql

# 备份所有数据库
pg_dumpall -U postgres > backup_all_$(date +%Y%m%d).sql

# 压缩备份
pg_dump -U billionmail -h localhost billionmail | gzip > backup_$(date +%Y%m%d).sql.gz

自动化备份脚本

/usr/local/bin/backup_database.sh

#!/bin/bash

# 配置
BACKUP_DIR="/var/backups/postgresql"
DB_NAME="billionmail"
DB_USER="billionmail"
RETENTION_DAYS=30

# 创建备份目录
mkdir -p $BACKUP_DIR

# 备份文件名
BACKUP_FILE="$BACKUP_DIR/${DB_NAME}_$(date +%Y%m%d_%H%M%S).sql.gz"

# 执行备份
pg_dump -U $DB_USER -h localhost $DB_NAME | gzip > $BACKUP_FILE

# 检查备份是否成功
if [ $? -eq 0 ]; then
    echo "数据库备份成功: $BACKUP_FILE"
    
    # 删除旧备份
    find $BACKUP_DIR -name "${DB_NAME}_*.sql.gz" -mtime +$RETENTION_DAYS -delete
    
    # 上传到远程存储(可选)
    # aws s3 cp $BACKUP_FILE s3://your-bucket/backups/
else
    echo "数据库备份失败"
    exit 1
fi

设置定时任务

# 编辑 crontab
crontab -e

# 每天凌晨 2 点执行备份
0 2 * * * /usr/local/bin/backup_database.sh

增量备份(WAL 归档):

配置 PostgreSQL:

# postgresql.conf
wal_level = replica
archive_mode = on
archive_command = 'test ! -f /var/lib/postgresql/wal_archive/%f && cp %p /var/lib/postgresql/wal_archive/%f'

9.2.2 邮件数据备份

Maildir 备份

# 备份邮件目录
tar -czf maildir_backup_$(date +%Y%m%d).tar.gz /var/mail/vhosts/

# 使用 rsync 增量备份
rsync -avz --delete /var/mail/vhosts/ /backup/mail/

配置文件备份

#!/bin/bash

# 备份目录
BACKUP_DIR="/var/backups/config"
mkdir -p $BACKUP_DIR

# 备份配置文件
tar -czf $BACKUP_DIR/config_$(date +%Y%m%d).tar.gz \
    /etc/postfix/ \
    /etc/dovecot/ \
    /etc/nginx/ \
    /opt/BillionMail/.env

9.2.3 数据恢复

PostgreSQL 恢复

从 SQL 备份恢复

# 解压备份
gunzip backup_20240115.sql.gz

# 恢复数据库
psql -U billionmail -h localhost -d billionmail < backup_20240115.sql

# 或创建新数据库并恢复
createdb -U postgres billionmail_restored
psql -U billionmail -h localhost -d billionmail_restored < backup_20240115.sql

时间点恢复(PITR)

# 1. 停止 PostgreSQL
sudo systemctl stop postgresql

# 2. 恢复基础备份
rm -rf /var/lib/postgresql/14/main
tar -xzf base_backup.tar.gz -C /var/lib/postgresql/14/

# 3. 创建 recovery.conf
cat > /var/lib/postgresql/14/main/recovery.conf <<EOF
restore_command = 'cp /var/lib/postgresql/wal_archive/%f %p'
recovery_target_time = '2024-01-15 12:00:00'
EOF

# 4. 启动 PostgreSQL
sudo systemctl start postgresql

邮件数据恢复

# 从 tar 归档恢复
tar -xzf maildir_backup_20240115.tar.gz -C /

# 从 rsync 备份恢复
rsync -avz /backup/mail/ /var/mail/vhosts/

# 修复权限
chown -R vmail:vmail /var/mail/vhosts/
chmod -R 700 /var/mail/vhosts/

9.2.4 灾难恢复计划

制定 DR 计划

  1. 识别关键数据

    • 数据库
    • 邮件内容
    • 配置文件
    • DKIM 密钥
  2. 备份策略

    • 每日完整备份
    • 每小时增量备份
    • 实时复制到异地
  3. 恢复时间目标(RTO)

    • 关键服务:< 1 小时
    • 非关键服务:< 4 小时
  4. 恢复点目标(RPO)

    • 数据库:< 15 分钟
    • 邮件内容:< 1 小时
  5. 测试

    • 每季度进行恢复演练
    • 验证备份完整性

异地备份

使用 AWS S3、阿里云 OSS 等云存储:

# AWS S3
aws s3 sync /var/backups/ s3://your-bucket/billionmail-backups/

# 阿里云 OSS
ossutil cp -r /var/backups/ oss://your-bucket/billionmail-backups/

9.3 常见问题排查

9.3.1 邮件无法发送

症状:邮件停留在队列中,无法发送

排查步骤

  1. 检查队列
postqueue -p
  1. 查看日志
tail -f /var/log/mail.log
  1. 常见原因和解决方法

DNS 问题

# 测试 DNS 解析
dig recipient-domain.com MX

# 测试 25 端口连接
telnet mail.recipient-domain.com 25

网络问题

# 测试网络连通性
ping recipient-domain.com

# 检查防火墙
sudo iptables -L -n
sudo ufw status

认证问题
检查 Postfix 配置:

postconf | grep sasl

速率限制

# 检查是否被限制
grep "too many" /var/log/mail.log

# 调整速率限制
postconf -e "smtp_destination_rate_delay = 2s"
postfix reload

9.3.2 邮件被标记为垃圾邮件

排查 DNS 配置

# 检查 SPF
dig yourdomain.com TXT | grep spf

# 检查 DKIM
dig default._domainkey.yourdomain.com TXT

# 检查 DMARC
dig _dmarc.yourdomain.com TXT

# 检查反向 DNS
dig -x YOUR_SERVER_IP

测试邮件质量

  1. 发送邮件到 check-auth@verifier.port25.com

  2. 查看返回的认证报告

  3. 使用 Mail Tester:

    • 发送邮件到 Mail Tester 提供的地址
    • 查看得分和建议

常见问题

  • SPF 记录不正确或缺失
  • DKIM 签名失败
  • 反向 DNS 不匹配
  • IP 在黑名单中
  • 内容触发垃圾邮件过滤器

9.3.3 性能问题

数据库慢查询

-- 查找慢查询
SELECT query, calls, total_time, mean_time, max_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 20;

-- 分析查询计划
EXPLAIN ANALYZE
SELECT * FROM messages WHERE campaign_id = '123';

解决方法

  • 添加索引
  • 优化查询
  • 增加缓存

邮件队列积压

# 查看队列大小
postqueue -p | tail -1

# 查看队列分布
qshape

解决方法

  • 增加并发连接数
  • 调整速率限制
  • 检查目标服务器是否响应慢
  • 考虑增加服务器资源

内存不足

# 检查内存使用
free -h

# 查看内存占用最多的进程
ps aux --sort=-%mem | head -10

# 检查 swap 使用
vmstat 1

解决方法

  • 增加物理内存
  • 优化应用内存使用
  • 调整数据库缓存设置
  • 清理不必要的进程

9.3.4 认证问题

IMAP/POP3 登录失败

# 查看 Dovecot 日志
tail -f /var/log/dovecot.log

# 测试认证
doveadm auth test user@example.com password

# 检查用户是否存在
doveadm user user@example.com

常见原因

  • 密码错误
  • 用户不存在
  • 数据库连接问题
  • 权限问题

SMTP 认证失败

# 查看 Postfix 日志
grep "authentication failed" /var/log/mail.log

# 测试 SMTP 认证
swaks --auth --server localhost --port 587 \
      --auth-user user@example.com --auth-password password

9.4 安全事件响应

9.4.1 检测安全事件

监控异常活动

  • 异常高的发送量
  • 来自不常见位置的登录
  • 多次失败的登录尝试
  • 异常的 API 调用

日志分析

# 查找失败的登录尝试
grep "authentication failed" /var/log/mail.log | wc -l

# 查找可疑的 IP
awk '/authentication failed/ {print $NF}' /var/log/mail.log | sort | uniq -c | sort -rn

# 查找异常高的发送量
awk '/postfix.*sent/ {print $1" "$2" "$3}' /var/log/mail.log | uniq -c

9.4.2 响应步骤

账户被盗用

  1. 立即禁用账户
# 通过 API 或管理界面禁用账户
  1. 重置密码
# 为用户生成新密码
  1. 撤销 API 密钥
# 撤销所有与该账户相关的 API 密钥
  1. 审计活动
# 查看该账户的所有活动日志
  1. 通知用户
    发送邮件通知用户账户异常

垃圾邮件滥用

  1. 停止发送
# 暂停所有活动
postsuper -d ALL
  1. 识别滥用源
# 查找异常邮件
grep "from=<suspicious@domain.com>" /var/log/mail.log
  1. 清理队列
# 删除队列中的垃圾邮件
postqueue -p | grep "suspicious@domain.com" | awk '{print $1}' | postsuper -d -
  1. 加强安全
  • 启用更严格的认证
  • 实施速率限制
  • 审查账户权限

IP 被列入黑名单

  1. 识别黑名单
# 使用 MXToolbox 等工具检查
  1. 清理系统
  • 确保没有垃圾邮件发送
  • 修复安全问题
  1. 申请移除
  • 向各黑名单提供商申请移除
  • 提供已采取的纠正措施
  1. 预防未来问题
  • 实施更严格的发送策略
  • 监控发送质量

9.4.3 安全加固

定期安全审计

  • 每月审查用户账户和权限
  • 每季度审查系统配置
  • 每年进行渗透测试

更新和补丁

# Ubuntu/Debian 更新
sudo apt update
sudo apt upgrade

# 查看可用更新
apt list --upgradable

# 自动安全更新
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

入侵检测

安装 Fail2ban:

sudo apt install fail2ban

# 配置 /etc/fail2ban/jail.local
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600

[postfix]
enabled = true
port = smtp,ssmtp
filter = postfix
logpath = /var/log/mail.log
maxretry = 5

9.5 小结

在本章中,我们学习了 BillionMail 的运维监控和故障排除,包括:

  1. 系统监控:监控指标、日志管理、监控工具、告警配置
  2. 备份和恢复:数据库备份、邮件数据备份、恢复流程、灾难恢复计划
  3. 常见问题排查:邮件发送问题、垃圾邮件问题、性能问题、认证问题
  4. 安全事件响应:检测安全事件、响应步骤、安全加固

通过实施全面的监控和及时的故障排除,可以确保 BillionMail 系统的稳定运行和数据安全。在最后一章中,我们将通过实战案例来综合应用所学知识。

posted @ 2025-12-17 07:35  我才是银古  阅读(1)  评论(0)    收藏  举报