Ubuntu服务器高可用运维的核心不是装几个工具,而是先厘清业务对“不可用”的真实容忍度。很多团队一上来就堆DRBD、Corosync、Keepalived,结果故障转移链路比单机故障还难排查。高可用首先要回答三个问题:哪些服务必须常驻、允许丢失多少秒数据、故障切换后是否需要人工介入。以典型的Web+数据库架构为例,Nginx或Apache的无状态特性适合用多节点负载均衡解决,而PostgreSQL或MySQL这类有状态服务必须优先处理数据一致性,否则切过去也是一份坏数据。

双机热备与脑裂防护的落地细节

在Ubuntu 22.04/24.04 LTS环境里,Keepalived+HAProxy仍然是四层与七层高可用的基础组合。但直接使用默认配置很容易出现VIP漂移后ARP缓存不更新的问题,导致部分客户端仍连到旧节点。建议在keepalived.conf中明确声明vrrp_script检查项,并且检查脚本不要只探测本机进程,要实际请求一次后端健康接口。比如:

vrrp_script chk_haproxy {
    script "/usr/bin/killall -0 haproxy"
    interval 2
    weight -20
}
vrrp_instance VI_1 {
    state BACKUP
    interface ens18
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass your-secret
    }
    virtual_ipaddress {
        192.168.10.100/24 dev ens18
    }
    track_script {
        chk_haproxy
    }
}

这里把两个节点都设为BACKUP并依赖优先级竞选,比一个MASTER一个BACKUP更不容易在启动阶段发生抢占。更重要的是,如果业务网段和存储网段没有隔离,VRRP组播包可能被交换机策略丢弃,此时需要改成单播模式,在配置中显式加入对端IP。脑裂的根因往往是心跳链路与业务链路共用一张网卡,网络抖动导致双方都认为对方挂了。生产环境至少要有两条独立心跳路径,一条走直连网线,一条走管理交换机,Keepalived的advert_int不建议小于1秒,否则瞬时拥塞就会触发误切换。

数据层高可用:别让主从复制成为新的单点

Ubuntu上部署MySQL或PostgreSQL主从复制时,最常见的误区是只配置了异步复制就认为高可用完成。异步复制在主机宕机时可能丢失已经提交的事务,对订单、支付类业务不可接受。PostgreSQL 12以上版本推荐使用基于流复制的同步提交模式,配合repmgr或Patroni实现自动故障转移。Patroni在Ubuntu上可以直接通过apt安装,但更建议用pip安装到虚拟环境,避免系统Python升级破坏依赖。关键配置项synchronous_mode要设置为on,并且synchronous_commit至少为remote_apply,确保备机真正应用了WAL才返回客户端成功。

MySQL方向,Group Replication是比传统主从更可靠的选择,但要求所有节点网络延迟极低,跨机房部署时性能会急剧下降。如果只有两个节点,不要强行上Group Replication,因为多数派机制在两节点场景下任何一个节点故障都会导致集群不可写。此时更务实的做法是主从+半同步复制,配合Orchestrator做拓扑发现和自动切换。Ubuntu的AppArmor默认策略可能限制MySQL访问非标准目录,切换脚本放在自定义路径时务必更新/etc/apparmor.d/usr.sbin.mysqld并重新加载。

存储与文件系统:共享存储不是银弹

很多人认为高可用必须上共享存储,但共享存储本身就是一个新的单点。如果使用NFS,NFS服务器挂了所有节点都无法写入;如果使用SAN,光纤交换机或控制器故障同样致命。对于中小规模业务,Ubuntu自带的DRBD 9配合LVM是成本较低的块设备同步方案。DRBD的协议C保证数据同时写入两端磁盘才返回成功,但会显著增加写延迟,适合对写入性能要求不极端的场景。配置DRBD时resource中的disk参数要指定底层设备,不要直接使用整个磁盘,应划分LVM卷,方便后续扩容。同步速率rate参数需要根据实际网卡带宽调整,默认值往往过慢,导致初始化同步需要数天。

更现代的方案是采用分布式存储,例如Ceph。Ubuntu对Ceph的支持非常成熟,三节点起配。Ceph的副本池默认三副本,任何一块盘或一个节点故障都不影响读写。但Ceph的运维复杂度远高于DRBD,需要单独规划OSD日志盘、监控MON节点、处理PG状态异常。如果团队没有专职存储运维,不要轻易把核心数据库放在Ceph RBD上,数据库的随机写放大效应会让Ceph集群的写放大问题更加严重。数据库用本地NVMe盘+流复制,静态文件和对象存储用Ceph或MinIO,这样分层更合理。

故障转移的自动化与人为介入边界

自动化切换最大的风险是“误切换”。一个真实案例:某公司数据库主库因大查询导致CPU 100%,监控脚本连续三次探测超时,触发自动切换到备库,但备库同样在重放积压的WAL,切换后依然不可用,反而丢失了主库正在执行的事务。因此,切换脚本必须区分“进程不存在”和“进程存在但响应慢”。对于响应慢的情况,应该告警而非切换。在Ubuntu上可以用systemd的Restart=on-failure配合RestartSec限制自动重启次数,避免服务反复拉起掩盖真实故障。

另一个容易被忽略的环节是切换后的回切。很多团队只测试从主到备的切换,从不测试从备切回主。结果真正发生故障后,主库恢复上线,但数据已经落后于备库,直接回切导致数据错乱。正确的做法是:主库恢复后先作为备库加入集群,追平数据后再通过计划性切换恢复原角色。这个流程必须写成运维手册,并且每季度演练一次。演练时使用Ubuntu的LXD容器模拟多节点环境,成本极低,但能暴露大量配置问题。

监控与告警:高可用的最后一道防线

没有监控的高可用是盲目的。Ubuntu服务器上建议部署Prometheus+Alertmanager+Grafana组合,node_exporter负责主机指标,postgres_exporter或mysqld_exporter负责数据库指标。监控项不能只关注CPU、内存、磁盘,还要关注复制延迟、连接数饱和度、慢查询数量、文件句柄使用率。特别是复制延迟,对于半同步或同步复制,延迟超过阈值意味着备机已经无法及时确认事务,继续写入会阻塞所有客户端。

告警规则要避免“告警疲劳”。如果每天收到上百条CPU超过80%的告警,运维人员会逐渐麻木,真正严重的磁盘故障告警可能被忽略。建议对告警分级:P1级立即电话通知,例如服务宕机、复制中断、磁盘只读;P2级发即时消息,例如CPU持续高负载、连接数接近上限;P3级仅记录到看板,例如磁盘容量预计7天后耗尽。在Ubuntu上配置Alertmanager的route规则时,用group_by按服务分组,避免同一故障触发几十条重复通知。

安全加固与高可用的关系

安全漏洞导致的服务中断往往比硬件故障更常见。Ubuntu的unattended-upgrades可以自动安装安全更新,但直接开启自动重启可能在高可用切换期间引发二次故障。建议将安全更新分为两类:内核更新需要重启,安排在业务低峰期手动执行,并先切换流量再逐台重启;用户态软件更新可以自动安装,但配置为不自动重启服务,由运维确认后统一重启。另外,Ubuntu的ufw防火墙默认规则要显式放行高可用组件端口,例如Keepalived的VRRP协议是IP协议号112,不是TCP或UDP端口,很多人只放行了22和80端口,结果VRRP报文被丢弃导致脑裂。

SSH访问控制也是高可用的一部分。如果所有节点使用同一个密码,一旦泄露攻击者可以同时控制主备节点,高可用形同虚设。建议使用SSH密钥认证,并且每个运维人员使用独立密钥,配合Ubuntu的auditd审计登录行为。对于数据库节点,只允许从跳板机登录,禁止直接暴露在公网。这些措施看似与高可用无关,但在真实攻击事件中,安全失守造成的停机时间远超硬件故障。

容量规划与扩展性预留

高可用架构必须考虑未来半年到一年的容量增长。很多系统初期运行稳定,但业务量上来后,主从复制的单线程回放成为瓶颈,备库永远追不上主库。PostgreSQL 10以上支持并行回放,但需要设置max_parallel_workers相关参数;MySQL 8.0的MTS回放也需要合理设置slave_parallel_workers。在Ubuntu上调整这些参数后,要监控回放线程是否真正并行工作,而不是只看参数已生效。

负载均衡层同样存在扩展问题。HAProxy单节点吞吐量有限,当并发连接数超过十万级别,单台HAProxy会成为瓶颈。此时应该考虑使用LVS或直接上云负载均衡器。如果必须自建,可以在Keepalived之上再叠加一层ECMP,用多个VIP分散流量。但这些复杂度只有在确实遇到性能瓶颈时才引入,过早优化只会增加运维负担。

最终,Ubuntu服务器高可用不是一个可以一次性交付的项目,而是一个持续迭代的过程。每一次故障复盘都要更新架构图和运维手册,每一次切换演练都要记录耗时和异常。只有把高可用当作日常运维的一部分,而不是某个季度的专项任务,才能真正保障业务安全稳定。