穷鬼架构师自白:单机转集群,别被K8s拖死

我曾以为架构师的价值在于由于使用了多么牛逼的CNCF全家桶,直到2018年那个黑色的周五。

那时我负责一个日活刚过万的电商SaaS,为了追求所谓的"大厂标准",我强行上了一套自建Kubernetes集群。结果在一次大促前夕,Etcd节点因为磁盘IO抖动导致集群脑裂,整个系统瘫痪了4个小时。老板站在我身后,看着满屏红色的Pod重启日志,只问了一句:“我们真的需要这么复杂的东西吗?”

那次事故后,我甚至形成了PTSD:每到周五下午,我都会下意识地去检查监控面板,生怕那个昂贵的"高大上"架构再次崩塌。

痛定思痛,我开始给架构做减法。对于99%的中小团队来说,“高可用"不等于"微服务+K8s”,而是"低成本+消除单点+快速恢复"。

如果你正处于单机扛不住、集群玩不转的尴尬阶段,下面这三个"穷鬼"过渡方案,或许能救你一命。

接入层:别迷信硬负载,Keepalived+Nginx才是平民神器

很多兄弟从单机扩展到双机时,第一反应是去买云厂商的SLB(负载均衡)。SLB确实好用,但如果你是私有化部署,或者预算极其有限(比如每年IT预算卡得死死的),硬件F5买不起,云SLB又是一笔持续的月租费。

其实,两台2核4G的虚拟机,就能搞定千万级流量的入口高可用。

配图

2020年,我接手一个制造业的MES系统改造。现场只有两台破旧的物理服务器,却要求"只要电不断,服务就不能断"。

配图

我们没用任何收费组件,直接采用了 VIP(虚拟IP)漂移方案

操作逻辑很简单:

  1. 两台服务器都装上Nginx和Keepalived。
  2. 对外只暴露一个VIP(比如 192.168.1.100)。
  3. 平时VIP绑定在主节点(Master)上,流量全走它。
  4. 一旦主节点Nginx进程挂了,Keepalived在3秒内感知,立马把VIP"抢"到备节点(Backup)上。

真实代码片段(keepalived.conf):

vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh" # 检测Nginx存活的脚本
    interval 2
    weight -20
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.100 # 对外暴露的VIP
    }
    track_script {
        chk_nginx
    }
}

结果复盘: 上线三年,主服务器电源坏过一次,网卡松过一次。系统自动切换,工厂流水线甚至没感觉到卡顿。 核心教训: 在流量没撑爆网卡前,不要引入复杂的四层/七层负载均衡设备,简单的VIP漂移是最极致的低成本高可用。

应用层:文件存储的"幽灵404",别急着上Ceph

单机转集群,最大的坑往往不在代码,而在状态(State)

最典型的场景:用户A在服务器1上传了头像,下次请求被分发到了服务器2,结果图片裂了(404)。新手通常会想:“我要搞个Ceph分布式存储!”

千万别!

如果你团队里没有一个能手搓Crush算法的运维,上Ceph就是找死。由于维护难度极大,一旦Ceph集群崩了,数据恢复的成本是灾难级的。

我曾经为了解决这个问题,在内网搭了一套GlusterFS。刚开始觉得很酷,双向同步。结果随着小文件数量达到百万级,同步延迟越来越高,导致用户刚上传完,刷新页面还是旧图。

针对中小项目,我有两个"土办法":

  1. 极简版(适合内网/低并发):NFS挂载 找一台磁盘大的机器做NFS Server,所有应用服务器把/data/uploads目录挂载到这台NFS上。

    • 优点:代码一行不用改,就像操作本地文件一样。
    • 缺点:NFS Server是单点(虽然可以用DRBD做高可用,但复杂了)。
  2. 进阶版(推荐):MinIO 这是我目前最推崇的方案。MinIO兼容S3协议,部署极快(一个Docker命令搞定)。

真实案例: 某医疗SaaS项目,由于要做私有化交付,客户不提供云OSS。我们直接在两台应用服务器上各起一个MinIO容器,组建了一个最简单的分布式集群。

  • 代码改动:把文件写入逻辑封装一个Interface,本地开发用Local实现,生产环境注入S3实现。
  • 收益:数据自带冗余,任意坏一块盘数据不丢,且不用维护复杂的分布式文件系统元数据。

避坑指南: 除非你的数据量达到PB级,否则不要碰Hadoop/HDFS或Ceph。MinIO或者直接买云厂商的OSS(如果有外网),是性价比最高的选择。

数据层:数据库的高可用,“半同步"是底线

应用挂了可以重启,数据库挂了(或者数据丢了),你就得跑路了。

很多资深开发在做架构设计时,喜欢搞"双主(Master-Master)“架构,觉得这样写谁都行。 这绝对是中小团队最大的谎言。 如果没有强大的冲突解决机制,双主复制导致的数据不一致(Duplicate Key Error)会让你在半夜哭出声。

我亲测最稳妥的低成本过渡方案是:MySQL主从(Master-Slave) + 半同步复制(Semi-Sync)。

为什么强调半同步? 默认的异步复制,主库挂掉的那一瞬间,可能还有几条数据没传给从库。这时候如果强行把从库提升为主库,数据就丢了。涉及金钱交易的系统,这是死罪。

2021年的一次实战: 我们为一家物流公司做核心业务系统。为了省钱,没买云RDS高可用版(太贵)。 我们配置了MySQL 5.7的半同步复制:

事务提交时,主库必须收到至少一个从库的"ACK"确认,才算成功。

这确实会损失一点点写性能(大约10%-20%),但换来了**RPO=0(数据零丢失)**的安全感。

配合 orchestrator 或者简单的 MHA 工具,我们可以做到:

  1. 主库宕机。
  2. 检测脚本确认无法连接。
  3. 自动把拥有最新数据的从库提升为主库。
  4. 修改应用层的数据库连接配置(或VIP指向新主库)。

硬核建议: 如果你连配置MHA都觉得费劲,我有一个更"土"但有效的建议:写一个自动备份脚本,每小时做一次binlog备份推送到异地。 高可用是这一秒的事,但数据备份是保命的事。在资源极其匮乏时,优先保数据,而不是保服务时长。


结尾:架构是长出来的,不是画出来的

回顾这几年的架构演进,我发现一个规律:好的架构都是被业务倒逼出来的,而不是架构师在白板上画出来的。

当你从单机走向集群时,不要一上来就追求Google级别的基础设施。

  1. Keepalived搞定入口高可用;
  2. MinIO或者NFS搞定文件共享;
  3. MySQL半同步搞定数据安全。

这三板斧,足够支撑你的业务从0做到10万日活。至于K8s、ServiceMesh、Serverless?等你的业务赚到了足够的钱,雇得起专门的SRE团队时,再考虑也不迟。

最后,做个小调查: 在你们目前的团队中,如果你要引入一个新中间件,阻力最大的是什么? A. 没人会维护,出了事抓瞎 B. 服务器资源不够,老板不批预算 C. 现有代码改造成本太高

欢迎在评论区告诉我你的痛点。

【落地行动卡】 如果你想这周就开始改进,建议做这3件事:

  1. 大扫除:梳理现有的单机系统,找出所有的本地状态(Session、本地文件、本地缓存)。
  2. 实弹演习:找个夜深人静的时候,拔掉备用数据库的网线,看你的主从同步报错是否及时触发报警。
  3. 极简容灾:给你的Nginx配置一个特定的Error Page,当后端全挂时,至少给用户展示一个友好的"系统维护中"页面,而不是冷冰冰的502。