1.3 机器准备:CVM 规格与服务拓扑
拓扑定不下来,后面所有章节都没有落脚点。这一篇把 17 个服务怎么摆到几台机器上、每台什么规格、网络怎么分、etcd 和 Redis 放哪里,一次性定死。定机器之前我们先踩了个坑:第一版拓扑是按服务数堆的,17 个服务 17 台机器,账单出来比预算高 40%,第二版按负载合并后降到 11 台。
拓扑文档的写法也定死:每个服务一张「实例卡」,写清服务名、规格、可用区、端口、归属组、依赖的上游下游。11 台共 23 张卡,机器故障时直接拿卡对账,不再凭记忆。卡的格式在 5.2 的容灾演练里会变成切换清单,一台卡对应一次演练。
场景:从 17 台缩到 11 台
第一版拓扑的问题是每个服务一台机,但 17 个服务里有 9 个是低频的内部服务,白天 CPU 占用不到 3%。按 5.1 篇的压测结论(单机 4C8G 能扛 3000 QPS 的订单主链路)反推,低频服务完全可以合并部署,合并部署的实例选择与成本对比我们在 k8s-pipeline-guide 里也有一套对照。最终拓扑是 11 台 CVM,分四个角色。
| 角色 | 数量 | 规格 | 跑什么 |
|---|---|---|---|
| 网关与边缘 | 2 | 4C8G | gateway、灰度控制器 |
| 核心服务 | 4 | 4C8G | 订单、用户、支付、库存 |
| 低频服务 | 3 | 2C4G | 6 个内部服务两两合并 |
| 基础设施 | 2 | 4C16G | etcd 集群 2 节点加云数据库 Redis |
etcd 按 3 节点标准部署,第 3 节点与一台核心服务共机(资源隔离用 cgroup),这是预算与可用区跨度的折中。
缩容不是单纯省钱,更是把故障域画清楚:17 台时一台故障无感,11 台时每台的权重变了,所以每台的监控必须到位。我们给每台 CVM 配了 CLS 的日志 agent,指标进 4.3 篇的告警看板,拓扑变了但观测口径不变。
成本口径统一按月度全量计:11 台加网络与存储,月账单较 17 台版本降 38%,但单台故障的影响面上去了 1.5 倍。用故障域换来的省钱必须能被 5.2 的容灾设计接住,否则这笔账是负的。两条一起验收才敢关账。
方案:拓扑三条硬规则
机子摆之前先立规则,规则比机型重要,否则下次扩容一定乱。
| 规则 | 内容 | 原因 |
|---|---|---|
| 同服务跨可用区 | 每个核心服务至少 2 个可用区有实例 | 单可用区故障不致命,5.2 会演练 |
| 基础设施不混布 | etcd、Redis 不与高频服务共机 | 磁盘 IO 与内存抖动会误下线服务 |
| 每机 ≤ 8 个进程 | 低频合并上限 8 | 内存超卖有界,dump 互不影响 |
实例数估算方法是压测天花板反推:订单服务单机 3000 QPS、P99 40ms,线上峰值 4500 QPS,留 50% 余量需 4 台?算下来 2 台就够(4500/3000=1.5,余量后 2),但考虑跨可用区两两部署取 4。库存服务峰值 800 QPS、单机 1500,2 台。这套数字全部来自 5.1 的压测表,不拍脑袋。
网络侧的摆法同样写进规则:VPC 内网段按角色分段,网关 10.0.1.0/24、核心服务 10.0.2.0/24、基础设施 10.0.3.0/24。分段的好处是安全组可以按角色一刀切,后来审计发现网关段对 2379 的开放规则是历史遗留,按分段清理只动了 3 条规则。跨段流量走内网不产生费用,但带宽上限要算:核心服务 4 台互调峰值约 40MB/s,千兆内网够用两倍以上。
可用区分布上,网关 2 台分两个可用区,核心服务 4 台两个可用区各 2 台,低频 3 台分布到 3 个可用区各 1 台——低频服务单点可接受,因为它白天几乎无流量,故障时人工重启来得及。基础设施 2 台固定两个可用区,第 3 个 etcd 节点挂在核心服务可用区 A 上,构成 2 加 1 的表决结构:任一可用区全灭,剩余两节点仍能多数派选主。
配置:CVM 上的落地细节
【腾讯云】云服务器 CVM,新用户限时特惠中 是我们买机器的入口,开机器时的三个实测要点:
其一,带宽买按量付费而非固定 100Mbps。订单链路单机峰值带宽 6MB/s,固定带宽 90% 时间在付闲置钱,按量后月账单降 1/3。其二,系统盘 SSD 最低 50GB,但 CLS 日志代理与制品缓存会吃 8GB,我们统一开 60GB。其三,核心服务开「安全组默认拒绝加白名单」,gRPC 的 9001 端口只放行内网 VPC 段,etcd 的 2379 只开给服务网段,2380 只开给 etcd 三个节点。
带宽选型还可以参考 tencent-cloud-practice 里的按量与固定带宽对照案例。
# 服务容器启动前的资源隔离(每进程一组 cgroup 限额)
echo 4096 > /sys/fs/cgroup/memory/gov/orders/memory.limit_in_bytes
# 4C8G 机器上给订单进程限 4C,防止合并机被挤占
部署统一用 COS 存制品:构建产物传 gov-artifacts/{svc}/{version}/,CVM 上脚本拉包再起进程。COS 选它的理由是快照回滚直接切 version 即可,5.2 的故障切换会用到。制品命名带构建号加 commit 短 hash,拉包脚本按 version 精确匹配,不允许 latest 这种模糊引用——回滚时差一个 hash 就会拉错版本,这条纪律在 5.2 演练里救过一次。
机器初始化脚本固定五步:装内核参数(somaxconn 1024、tcp_tw_reuse 开)、时区对齐、起 CLS agent、拉 COS 制品、注册 etcd 租约。顺序不能换:先注册后起服务会拿到租约但没流量承接,先起服务后注册则注册前 3 秒的流量全 502。脚本幂等可重跑,新机器与故障恢复共用同一份,恢复流程不用临时写脚本。
踩坑:两个拓扑事故
第一个事故:第一版把网关和订单共机,大促时网关转发层占满带宽,订单服务 P99 从 40ms 涨到 210ms,还查不出共机原因。拆机后恢复。教训进规则一。
第二个事故:etcd 3 节点里 2 个在同可用区,那个可用区一次网络抖动导致多数派失联 40s,期间 5 个服务的实例租约没续上被 watch 摘掉,调用方全切到剩余节点,流量瞬间打满。40s 后恢复。这个事故直接把我们顶到跨可用区改造加 5.2 篇的演练清单。
还有一个小坑:合并部署的低频服务里有一个内存泄漏,2C4G 机器 3 天后 OOM,重启后全机其他 7 个进程跟着挂。之后所有合并机都配了单进程内存上限与 OOM 自动重启,泄漏服务单独移到 2C4G 专机。
开机器时还有两个容易忘的:CVM 的时区要与构建环境一致,否则日志时间戳和 CLS 检索窗口对不上,排障时差 8 小时;另一台机器内核参数 somaxconn 默认 128,订单服务高并发下 listen 队列溢出表现为间歇性 connection refused,统一改到 1024 后才消失。这两条写进了机器初始化脚本,之后不再复发。
还有一个采购细节:CVM 的计费模式按服务分级,网关与核心服务按月计费(负载稳定、长期在线),低频服务按年付更划算,etcd 三台按月。混合计费后同规格账单比全月付低 12%。机型代际也要注意:同代 4C8G 与上一代 4C8G 单价接近但 CPU 主频差 20%,压测时按新一代规格算的天花板,换回老一代会直接打八折,扩容公式要乘 0.8 补偿。
采购流程本身也立了一条纪律:开机器走发布单,单子里写清服务名、规格、可用区、归属组、到期提醒,CVM 控制台批量开完后自动回填内网 IP 到 CMDB。11 台里 9 台是这个流程开的,剩下 2 台是 etcd 事故后补的跨区节点,因为走得急没进 CMDB,后来一次网络巡检对着 CMDB 查防火墙时把 etcd 的 2379 规则漏了,排查半天才发现是台账不一致。机器账和代码账要同步更新,否则拓扑就变成两张图。
小结
机器准备的核心是三条硬规则加一条纪律:实例数永远从压测天花板反推,不抄别人不猜。11 台 CVM 的账单与预算持平,同服务跨可用区、基础设施不混布这两条写进了团队规范,后续扩容照此执行。机器的钱花在刀刃上依赖观测闭环,所以这一篇同时把 CLS agent、安全组分段与混合计费口径钉死。扩容量产的公式也留给 5.2:新实例跨可用区、先注册后接流、旧实例先摘流后下线。下一篇 1.4 把 Go 库与云产品一一对齐,定下每个组件用哪个版本。
延伸阅读
- CVM 规格选择与成本控制的更多场景,见 tencent-cloud-practice。
- 单机部署到多机拓扑的演进路径,见 k8s-pipeline-guide。
- 制品管理与 COS 配合的做法,见 go-micro-cps-guide。
