配置变更的蝴蝶效应
记得去年一个周五的下午,我们对一台核心服务器的SSH配置进行了"简单优化":将MaxSessions从默认的10调整为5,目的是"增强安全性"。结果周一早上,自动化部署系统全面瘫痪。经过两个小时的排查,才发现是CI/CD工具依赖的SSH连接池因为会话数限制而耗尽。
教训:
- 任何配置变更,无论多么微小,都要考虑依赖该服务的所有客户端
- 修改前使用
sshd -T验证运行配置,避免配置文件中的注释干扰判断 - 通过
lsof -i :22查看SSH连接详情,评估实际并发需求
磁盘空间的隐形杀手
一次生产环境告警显示/var分区使用率超过90%。常规排查发现是日志文件堆积,但清理后空间释放不明显。深入调查才揪出元凶:
# 发现大量被删除但未释放的文件
lsof +L1 | grep deleted
# 找出占用inode最多的目录
find /var -type d -exec sh -c 'echo "$(ls -a "$1" | wc -l) $1"' _ {} \; | sort -n
原来是一个Java应用使用Files.createTempFile创建临时文件,但进程异常退出导致文件句柄未释放。这些"幽灵文件"虽然已被删除,但仍占用磁盘空间。
防护措施:
- 定期监控inode使用率:
df -i - 为关键分区设置保留空间:
tune2fs -m 1 /dev/sda1 - 使用logrotate时注意
delaycompress选项的副作用
系统时间的微妙陷阱
某次数据库主从同步突然中断,排查许久才发现是两台服务器的时间偏差超过了2秒。NTP服务看似正常运行,但仔细检查发现:
# 检查时间同步状态
chronyc sources -v
# 查看时钟漂移
chronyc tracking
# 手动立即同步
chronyc makestep
问题根源是虚拟机的时钟源配置不当。在VMware环境中,需要确保使用精确的时钟源:
<!-- VMware VMX配置片段 -->
<clock offset="utc">
<timer name="hpet" present="yes"/>
<timer name="hypervclock" present="yes"/>
</clock>
内存管理的认知误区
新手运维常被free -m的输出误导,看到"used"接近100%就紧张。实际上Linux的内存管理策略很积极:
# 更准确的内存视图
cat /proc/meminfo
# 关注关键指标
MemFree: 真实的空闲内存
MemAvailable: 实际可用内存(包括可回收的cache)
# 检查大页内存配置
grep Huge /proc/meminfo
曾经有个案例:Oracle数据库因为透明大页(Transparent HugePages)导致性能抖动。解决方案:
# 禁用透明大页
echo never > /sys/kernel/mm/transparent_hugepage/enabled
服务依赖的隐藏链条
一次计划内的网络设备维护,意外导致整个监控系统失效。原因是:
- 监控系统依赖Redis缓存
- Redis配置了绑定IP为内部网络地址
- 网络设备维护触发了IP地址变更
- Redis无法绑定到新的IP地址
依赖管理清单:
- 维护所有服务的依赖关系图
- 区分硬依赖和软依赖
- 关键服务要有降级方案
- 定期进行"断网测试"模拟依赖失效
内核参数的长期影响
某高负载Web服务器运行数月后出现连接数限制。排查发现:
# 检查当前连接数
ss -s
# 查看内核参数
sysctl net.netfilter.nf_conntrack_max
# 监控连接跟踪表
cat /proc/sys/net/netfilter/nf_conntrack_count
连接跟踪表被填满是因为默认值太小,且未设置合适的超时时间。解决方案:
# /etc/sysctl.d/99-conntrack.conf
net.netfilter.nf_conntrack_max = 655360
net.netfilter.nf_conntrack_tcp_timeout_established = 1200
经验总结
服务器运维就像在雷区行走,最大的危险往往来自那些"看起来没问题"的改动。每次变更前,我都会问自己三个问题:
- 这个改动会影响哪些我没想到的地方?
- 如何快速验证改动效果并回滚?
- 监控系统能否及时捕获异常?
保持谨慎,但不畏手畏脚;相信经验,但不盲目自信——这大概是运维工程师最难得的状态。
暂无评论