第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:
- 添加 Prometheus 数据源
- 导入预设的仪表板或创建自定义仪表板
- 设置告警规则
常用的 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 计划
-
识别关键数据:
- 数据库
- 邮件内容
- 配置文件
- DKIM 密钥
-
备份策略:
- 每日完整备份
- 每小时增量备份
- 实时复制到异地
-
恢复时间目标(RTO):
- 关键服务:< 1 小时
- 非关键服务:< 4 小时
-
恢复点目标(RPO):
- 数据库:< 15 分钟
- 邮件内容:< 1 小时
-
测试:
- 每季度进行恢复演练
- 验证备份完整性
异地备份
使用 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 邮件无法发送
症状:邮件停留在队列中,无法发送
排查步骤:
- 检查队列:
postqueue -p
- 查看日志:
tail -f /var/log/mail.log
- 常见原因和解决方法:
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
测试邮件质量:
-
发送邮件到 check-auth@verifier.port25.com
-
查看返回的认证报告
-
使用 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 响应步骤
账户被盗用:
- 立即禁用账户:
# 通过 API 或管理界面禁用账户
- 重置密码:
# 为用户生成新密码
- 撤销 API 密钥:
# 撤销所有与该账户相关的 API 密钥
- 审计活动:
# 查看该账户的所有活动日志
- 通知用户:
发送邮件通知用户账户异常
垃圾邮件滥用:
- 停止发送:
# 暂停所有活动
postsuper -d ALL
- 识别滥用源:
# 查找异常邮件
grep "from=<suspicious@domain.com>" /var/log/mail.log
- 清理队列:
# 删除队列中的垃圾邮件
postqueue -p | grep "suspicious@domain.com" | awk '{print $1}' | postsuper -d -
- 加强安全:
- 启用更严格的认证
- 实施速率限制
- 审查账户权限
IP 被列入黑名单:
- 识别黑名单:
# 使用 MXToolbox 等工具检查
- 清理系统:
- 确保没有垃圾邮件发送
- 修复安全问题
- 申请移除:
- 向各黑名单提供商申请移除
- 提供已采取的纠正措施
- 预防未来问题:
- 实施更严格的发送策略
- 监控发送质量
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 的运维监控和故障排除,包括:
- 系统监控:监控指标、日志管理、监控工具、告警配置
- 备份和恢复:数据库备份、邮件数据备份、恢复流程、灾难恢复计划
- 常见问题排查:邮件发送问题、垃圾邮件问题、性能问题、认证问题
- 安全事件响应:检测安全事件、响应步骤、安全加固
通过实施全面的监控和及时的故障排除,可以确保 BillionMail 系统的稳定运行和数据安全。在最后一章中,我们将通过实战案例来综合应用所学知识。

浙公网安备 33010602011771号