从 Docker Machine 退役说起:GitLab CI Runner 弹性架构与缓存治理的 7 个生产决策

概述 凌晨 1 点,你收到告警:GitLab CI 流水线队列堆积了 47 个 pending job。开发群炸了——“代码推了 40 分钟还没跑起来"“是不是 Runner 挂了"“赶紧加机器啊”。你登录控制台一看,3 个 Runner 全部满载,每个并发 10 个 job,30 个 slot 全占满了。加机器?Docker Machine 执行器拉起新 EC2 要 3 分钟,等机器 Ready 又要 2 分钟。5 分钟过去了,队列又涨了 20 个。 这不是假设。2025 年我在某出行项目做 CI/CD 平台重构时,就遇到过这个场景。当时的 Runner 架构是经典的 Docker Machine + AWS EC2 自动伸缩,高峰期排队 30-40 分钟是常态。后来我们迁移到 Kubernetes Executor + HPA 弹性伸缩,排队时间降到 30 秒以内。这中间踩了不少坑,也做了不少架构决策。 本文不讲 .gitlab-ci.yml 基础语法(那些 CSDN 上够多了),只聊 7 个真正影响生产效率的工程决策:执行器选型、资源规划、弹性伸缩、缓存设计、流水线编排、节点隔离、监控告警。每个决策都附实测数据和踩坑细节。 如果你在评估 CI/CD 平台选型,可以参考我之前的文章 相关文章:别让 Jenkins 决定你的发布节奏:用 Go 自研 DAG 调度引擎的架构决策与踩坑实录,里面对比了 Jenkins、GitLab CI 和自研调度引擎的差异。...

August 13, 2026 · 9 分钟 · 1910 字 · 徐保金

别把容灾做成备份:跨机房 RPO<5min、RTO<30min 的架构决策与踩坑实录

概述 凌晨 2 点 17 分,手机弹出告警:核心机房 A 区网络设备故障,数据库主从同步中断。值班 SRE 切到灾备机房 B 区,发现应用连上新主库后,部分订单数据查不到——异步复制窗口期丢了 47 秒数据。业务恢复用了 38 分钟,超出 RTO 目标 8 分钟。 这是一次真实的容灾切换事故。事后复盘发现,系统设计了容灾架构,配置了数据同步,也写了切换脚本,但真正切换时还是出了问题。问题不在于"有没有灾备",而在于容灾架构的每个环节是否真正经得起生产级考验。 本文拆解跨机房容灾的核心架构决策,覆盖同城双活、异地灾备、两地三中心三种模式的选型权衡,同步复制的性能代价与脑裂防护,异步复制的窗口期补偿机制,以及故障切换从决策到执行的完整流程。每个环节都附有真实踩坑记录和性能数据。 在我经手过的跨机房容灾方案中,最终达成 RPO<5min、RTO<30min 的指标。这个数字看起来不算极致,但它是成本、稳定性和业务需求三方博弈后的工程最优解——不是理论上的 RPO=0,而是生产环境能跑通、能验证、能回滚的方案。 RPO 和 RTO 的工程真相 不是技术指标,是业务指标 RPO(Recovery Point Objective)和 RTO(Recovery Time Objective)这两个词被技术圈用烂了,但很多人理解反了——它们首先是业务指标,然后才是技术指标。 RPO 回答的是"能容忍丢多少数据"。比如一个电商系统,订单数据的 RPO 必须是 0(不能丢订单),但用户行为日志的 RPO 可以是 1 小时(丢了不影响核心交易)。RTO 回答的是"能容忍停多久"——核心交易系统 RTO 要 <5 分钟,而报表系统的 RTO 可以是 4 小时。 关键认知:不要一刀切。 我见过太多团队把所有系统都按 RPO=0、RTO<1min 设计,结果容灾建设成本翻了好几倍,非核心系统根本不需要这么高的规格。 按业务重要性分级设计容灾目标: 级别 系统类型 RPO 目标 RTO 目标 同步方式 P0 核心交易、支付 0 <5min 同步复制 P1 用户中心、订单查询 <1min <15min 半同步复制 P2 内容管理、报表 <30min <2h 异步复制 P3 日志分析、离线计算 <1h <4h 定时备份 RPO=0 的代价不是线性的 很多人觉得"RPO 越小越好",但 RPO 从 1 分钟到 0 的成本跳跃是指数级的:...

August 11, 2026 · 9 分钟 · 1798 字 · 徐保金

托管集群不是甩手掌柜:从自建 K8s 迁移到 ACK 后的 5 个生产级踩坑

概述 “控制面全托管”——这句话让不少团队以为迁移到 ACK 托管集群后就能当甩手掌柜。实际上,托管只解决了 etcd、kube-apiserver、kube-controller-manager、kube-scheduler 这几个控制面组件的运维,数据面的问题一个不少。 我曾在一次 120+ 微服务的 K8s 迁移项目中,把自建集群切到 ACK 托管集群 Pro 版。迁移过程用了 3 个月,零故障切换——但切换之后的第一个月,凌晨告警没断过。不是 ACK 本身有问题,而是托管集群和自建集群在"看不见的地方"有很多行为差异,这些差异在自建集群时被你自己的运维习惯掩盖了,到托管集群上才暴露出来。 这篇文章把我踩过的 5 个最痛的坑整理出来,每个都附根因分析和修复方案。如果你正准备从自建 K8s 迁移到 ACK,或者刚迁移完正在经历告警风暴,这篇文章能帮你少走弯路。 先说结论:这 5 个坑不是 ACK 的 bug,而是从自建迁移到托管时的认知差。自建集群时你完全掌控每个组件,出了问题能从头排查;托管后控制面是个黑盒,你得换一套思路来运维。 踩坑一:网络插件选型——Flannel 还是 Terway,选错就是性能灾难 问题背景 迁移到 ACK 时第一个决策就是网络插件。ACK 支持两种:Flannel 和 Terway。这两个东西选错了,后面所有网络相关的性能问题都跟它有关。而且集群创建完成后不支持切换——选错了只能重建集群。 我在这个项目上选了 Flannel,原因很简单:自建集群用的也是 Flannel,迁移时 Pod 网段不用改,应用配置零调整。上线两周后,问题开始暴露。 先是某个微服务的 P99 延迟从自建集群的 170ms 飙升到 230ms。应用层没改过,代码没变,唯一变的是底层网络。然后是等保 2.0 审计,审计员要求 Pod 流量可审计,Flannel 的 Pod IP 在独立网段,VPC 流日志抓不到——直接开了一个中风险项。 根因分析 Flannel 在阿里云上基于 VPC 自定义路由实现跨节点 Pod 通信。简单说就是每个节点分一个 Pod CIDR 子网,Pod 的流量通过 VPC 路由表转发。这个方案能用,但有三个硬伤:...

August 8, 2026 · 10 分钟 · 2128 字 · 徐保金

审批 3 天还炸了:用错误预算门禁替代人工 CAB,变更类故障减少 60%

概述 凌晨 1 点 47 分,手机震了。告警群弹出 200 多条消息,订单成功率从 99.8% 掉到 92%。值班同学重启服务、回滚版本,折腾了 40 分钟才恢复。 第二天复盘,根因是下午发版时改了一行数据库连接池配置。这个变更走了完整的审批流程——开发提交、测试验证、主管签字、SRE 评审,审批花了 3 天。3 天审批,1 行配置,40 分钟故障。 这不是个案。Google SRE Book 里有个数据:大约 70% 的服务中断是由变更引起的。我在某电商平台做了 6 个月的统计,比例更夸张——82% 的 P1/P2 故障直接或间接跟变更有关。 问题出在哪?传统变更管理靠"人审",而人审解决不了三个矛盾: 审批者不一定懂代码:签字的人大多是管理者,看不懂配置变更的技术影响 审批再严也挡不住低级错误:3 天审批审查的是流程合规性,不是技术正确性 审批拖慢迭代速度:开发为了过审拆小包、绕流程,反而增加变更频次 Google 的解法很直接:把变更管理从"人审"变成"机器门禁",用错误预算做自动裁决,用渐进式发布做安全网。本文拆解我在某出行项目落地这套体系的完整过程——从审批流程改造到 Go 代码实现,包含真实踩坑和性能数据。 传统 CAB 模式的困境 CAB(Change Advisory Board,变更顾问委员会)是 ITIL 时代的标准做法。每次变更提交申请,CAB 成员(通常是运维主管、安全负责人、架构师)开会评审,投票决定是否放行。 听起来很合理,实际跑起来全是问题。 人工审批的三个死结 死结一:审批者看不懂变更内容 我见过一个 CAB,5 个审批人里 3 个是管理层。他们审查什么?表单填写是否完整、影响范围评估是否打钩、回滚方案是否写了。至于那行配置改了什么、对系统有什么实际影响——看不懂,也没法判断。 结果就是,审批变成了走过场。表单填得漂亮就过,填得丑就打回。技术风险?全靠开发自觉。 死结二:审批速度和变更质量无关 审批 3 天,不代表这 3 天里有人在做技术验证。实际情况是:变更提交后躺在 OA 系统里等 2 天,第 3 天 CAB 开会 10 分钟过一下就批了。3 天里有 2 天 22 小时是等待时间。...

August 6, 2026 · 8 分钟 · 1680 字 · 徐保金

别让 Jenkins 决定你的发布节奏:用 Go 自研 DAG 调度引擎的架构决策与踩坑实录

概述 凌晨两点,某出行平台的发布窗口刚打开,Jenkins Master 突然 CPU 100%,构建队列积压了 200 多个任务,整个发布流水线卡死。运维团队花了 40 分钟才定位到根因——一个老项目的 Git 仓库里塞了 15G 二进制文件,单次 clone 就要 20 分钟,把 Master 的线程池全部耗尽。 这不是个例。Jenkins 是个优秀的 CI 工具,但当你有 120+ 微服务、发布依赖关系错综复杂、需要精细化控制并发度和回滚顺序时,Jenkins 的 Stage 模型就开始捉襟见肘了。Stage 是线性的,parallel 虽然能并行但无法表达复杂的 DAG 依赖——“服务 A 和 B 可以并发部署,但 C 必须等 A 和 B 都完成后才能部署,D 只依赖 B”——这种关系用 Jenkinsfile 写出来就是一堆嵌套的 parallel 和 stage,维护噩梦。 我在为某新能源物流平台搭建运维平台时,用 Go 自研了一套 DAG 调度引擎,把 120+ 微服务的发布耗时从 1.5 小时压缩到 5 分钟。这篇文章不是教你重新造轮子(除非你的发布场景确实需要),而是把架构决策过程和踩过的坑完整记录下来,让你在选型时有参考、在实现时有避坑指南。 这篇文章适合谁:有 CI/CD 使用经验、正在考虑自研发布平台或对任务编排有深度定制需求的运维开发工程师。我会假设你已经熟悉 Jenkins/GitLab CI 的基本概念,直接上生产级架构设计。 为什么不用现成工具 先说结论:如果你的发布场景是"一个仓库一条流水线",用 Jenkins/GitLab CI/ArgoCD 完全够了,别自研。但如果你遇到以下场景,自研 DAG 引擎就值得考虑。...

August 4, 2026 · 12 分钟 · 2537 字 · 徐保金

IaC 不测试就上生产?Terraform 四层验证体系让凌晨告警少 80%

概述 去年接手一个项目,前同事写的 Terraform 代码跑得好好的,某个周一上午他改了一行 instance_type,terraform plan 显示正常,apply 也成功了。然后业务炸了。 原因不是代码写错,是那个 instance_type 对应的 AMI 在目标可用区不存在。plan 能过是因为它只检查"逻辑上通不通",不检查"云上到底有没有这个资源"。这种问题在静态检查阶段就能拦住,但那个团队的 IaC 流水线里只有 terraform fmt && terraform validate,连 tflint 都没装。 很多人对 IaC 测试的认知停留在"跑一下 plan 看看输出对不对"。这不叫测试,这叫碰运气。Terraform 不是事务系统——apply 失败后基础设施会停在一个半成品状态,比没改之前更糟。我在多个生产环境中踩过这个坑,最后总结出一套四层验证体系:静态检查 → 安全扫描 → 计划验证 → 集成测试,从代码提交到生产部署逐层拦截问题。本文拆解每一层的工具选型、配置方法和踩坑细节。 本文假设你已经了解 Terraform 基本用法。如果不熟悉,先看 相关文章:Terraform 基础设施即代码入门 和 相关文章:状态文件丢了怎么办:Terraform State 灾难恢复与生产级后端架构。 一、为什么 IaC 需要测试体系 先说清楚一个认知误区:terraform plan 通过 ≠ 代码正确。 terraform plan 只验证两件事:HCL 语法是否合法、资源依赖关系是否合理。它不验证: instance_type 在目标区域是否可用(t2.nano 在某些区域不存在) 安全组规则是否暴露了不该暴露的端口(0.0.0.0/0 开 22 端口) IAM 策略是否过宽(Action: "*", Resource: "*" 这种"上帝权限") 资源命名是否符合团队规范(一个 VPC 叫 prod-vpc 另一个叫 test_vpc_01) 模块间参数传递是否类型匹配 这些全是生产事故的高频原因。我在某电商平台做过统计:37% 的 IaC 相关故障,terraform plan 阶段没有任何报错,是 apply 后才暴露的。...

August 1, 2026 · 11 分钟 · 2227 字 · 徐保金

可靠性度量不是堆指标:用四层模型把'系统稳不稳'变成可决策的数字

概述 凌晨三点,你被告警吵醒。爬起来一看:CPU 正常、内存正常、Pod 也在跑,但用户投诉说"系统卡得用不了"。你打开 Grafana 面板,画了一堆曲线,却说不清楚——这到底算不算故障? 这个场景,我在多个企业客户的 SRE 咨询中反复遇到。核心问题不是监控不够多,而是度量体系设计错了方向:我们一直在监控"系统内部的指标",而不是"用户感受到的服务质量"。 曾经在一次某出行平台的故障复盘中,团队发现一个讽刺的事实:告警系统在故障发生 12 分钟后才触发,而用户在故障发生后 30 秒就已经开始投诉了。原因很简单——告警基于 CPU 使用率超 80% 触发,但实际故障是数据库连接池耗尽,CPU 才 35%,根本没碰阈值。 可靠性度量的本质,是把"系统稳不稳"这个问题,从主观感觉变成可量化的数字。这篇文章不讲 SLI/SLO 的基础概念(这些在 相关文章:SRE核心理念:SLI、SLO与错误预算 中已经讲透了),而是聚焦于:如何从零设计一套完整、可落地、能驱动决策的可靠性度量体系。 为什么传统监控体系不能回答"系统稳不稳" 先说结论:传统监控体系回答不了"系统稳不稳",因为它度量的对象错了。 传统监控的三个盲区 盲区一:监控的是资源,不是用户体验 大多数团队的监控面板长这样:CPU 折线图、内存折线图、磁盘 IO 折线图、网络流量折线图。这些指标反映的是"服务器忙不忙",而不是"用户爽不爽"。 举个真实的例子:某电商平台的订单服务,CPU 使用率常年 70%,运维觉得"不太对劲",计划扩容。但实际上 P99 延迟 120ms,请求成功率 99.97%,用户体验完全没问题。另一个缓存服务,CPU 才 20%,看起来"很健康",但缓存命中率从 95% 掉到 60%,导致数据库被打爆,用户实际体验已经很差了。 盲区二:没有"好"和"坏"的量化边界 “CPU 80% 算好还是算坏?"——这个问题在传统监控体系里没有答案。80% 可能是正常的批处理负载,也可能是即将打满的前兆。没有 SLO 的情况下,80% 就只是一个数字,不是判断依据。 Google SRE Book 里有一段话说得很到位:“如果你不能度量它,你就不能管理它。” 但更准确的说法应该是:如果你度量错了对象,比不度量更危险——因为你会基于错误的信号做决策。 盲区三:告警基于静态阈值,不感知业务影响 传统告警的逻辑是"指标超过阈值就报”。问题是,同样的阈值在不同业务场景下含义完全不同: 场景 CPU 80% 含义 是否需要告警 凌晨 2 点批处理任务 正常负载 不需要 大促期间核心交易服务 即将打满 紧急告警 测试环境压测中 预期行为 不需要 生产环境空闲时段 异常进程 需要排查 静态阈值无法区分这些场景,导致的结果就是:要么告警太多(告警疲劳),要么告警太晚(用户已经投诉了才报)。...

July 30, 2026 · 8 分钟 · 1640 字 · 徐保金

MTTR 从 40 分钟到 8 分钟:用四层防御把故障定位提速 5 倍

概述 凌晨三点,手机震动。告警群炸了 200 条消息,用户投诉已经涌进客服群。你爬起来打开电脑,登录跳板机,发现某个核心接口 P99 飙到 8 秒。接下来 30 分钟你都在翻日志、查 Grafana、问上下游——最终定位到是某个配置中心推了一行错误参数。 这个场景太熟悉了。在我经手的上百次线上故障中,定位环节消耗的时间占 MTTR 的 60% 以上。恢复操作本身可能只要 2 分钟(回滚、重启、切流量),但找到"到底哪里出了问题"往往要花 20-30 分钟。 MTTR(Mean Time To Repair/Recovery)衡量的是从故障发生到服务恢复的平均时间。但这个数字是个黑盒——30 分钟的 MTTR 里,到底哪些环节在拖后腿?检测花了多久?响应花了多久?定位花了多久?恢复花了多久?不拆开看,优化就无从下手。 这篇文章拆解我在某出行项目和某电商项目中实战验证的 MTTR 优化体系——四层防御模型:检测层、响应层、定位层、恢复层。每层有具体的工程手段和度量指标,不是空谈方法论。最终效果:核心服务 MTTR 从 40 分钟降到 8 分钟,故障定位时间从 30 分钟降到 5 分钟。 MTTR 拆解:你优化的是哪个环节 很多人把 MTTR 当成一个整体来优化,这是错的。MTTR 至少要拆成四个阶段: 阶段 全称 含义 典型耗时 优化重点 MTTD Mean Time To Detect 从故障发生到告警触发 1-5 min 监控覆盖、SLO 告警 MTTA Mean Time To Acknowledge 从告警触发到有人开始处理 2-10 min On-Call 机制、告警路由 MTTI Mean Time To Identify 从开始处理到定位根因 10-30 min 可观测性、诊断工具 MTTR Mean Time To Restore 从定位根因到服务恢复 1-5 min 回滚、自愈、预案 注意 MTTR 有两种常见解读:Repair(修复)和 Recovery(恢复)。SRE 语境下我更推荐用 Recovery——目标是恢复服务而非彻底修复 Bug。彻底修复是 Postmortem 之后的事(相关文章:故障复盘改进项跟踪)。...

July 28, 2026 · 9 分钟 · 1722 字 · 徐保金

别被多云忽悠了:从供应商绑架到跨云容灾的架构决策与踩坑实录

概述 凌晨三点,手机震了。告警群一条消息:某云厂商华东 region 存储服务大面积不可用。你负责的核心业务全量部署在这个 region,数据库的主库也在那边。故障已经持续 12 分钟,客户开始投诉,老板在群里问"多久能恢复"。 你心里清楚:跨 region 容灾方案半年前就评审过,但因为"成本太高"被砍了。现在只能硬扛。 这是真实发生过的场景。2023 年阿里云香港机房宕机事件,让不少只做单 region 部署的团队第一次认真思考跨云容灾的问题。但多云架构远不止"把服务部署到两个云"那么简单——网络怎么连通?数据怎么同步?监控怎么统一?成本怎么控制?切换时谁来决策? 这篇文章拆解多云架构设计中的关键决策点,每一层都给出我在实际项目中的选型理由和踩过的坑。不是教科书式的"多云架构有哪些优势",而是一线架构师面对真实约束时做的取舍。 多云 vs 混合云 vs 多区域:先搞清楚你在做哪个 很多人把这三个概念混着用,但它们解决完全不同的问题。 维度 多云(Multi-Cloud) 混合云(Hybrid Cloud) 多区域(Multi-Region) 定义 使用 2+ 个公有云厂商 公有云 + 私有云/本地机房 同一云厂商的不同区域 核心目标 避免厂商绑架、选择性采购 数据合规+弹性扩展 容灾+就近访问 网络复杂度 高(跨厂商 VPC 互联) 中(VPN/专线) 低(厂商内网) 典型场景 A 云跑 AI 推理,B 云跑数据库 核心数据在本地,弹性计算在云 同 region 双活+跨 region 灾备 我的判断:如果你的核心诉求只是"不把鸡蛋放在一个篮子里",先做多区域部署,成本和复杂度远低于跨厂商多云。真正的多云架构应该由业务需求驱动——比如某个云的 GPU 性价比明显更好,或者合规要求特定数据必须在特定云上处理。 我在某出行项目里做过一次"伪多云"的评估:技术团队想用多云来"降低成本",但拆开账单后发现,95% 的成本来自计算和存储资源,跨云迁移后资源单价差异不到 8%,而增加的运维和跨云传输成本吃掉了这块差价。最后改成同厂商多区域 + 预留实例优化,成本反而降了 22%。 别为了多云而多云。先算清楚收益和成本的账。 为什么真的需要多云:四个真实驱动因素 1. 供应商绑架规避 这是最常见的多云驱动因素,但也是最容易被高估的。...

July 25, 2026 · 7 分钟 · 1317 字 · 徐保金

状态文件丢了怎么办:Terraform State 灾难恢复与生产级后端架构

概述 凌晨两点,手机炸了。某出行项目的运维群弹出一连串告警:RDS 主从切换失败、EIP 绑定状态异常、安全组规则缺失。排查了一圈,根因是有人手动在控制台改了安全组规则,Terraform 的 state 文件和云上实际状态不一致,一次 terraform apply 把手动修改的资源全部"纠正"回旧配置——直接覆盖了线上紧急热修复。 这不是个例。Terraform 的 state 文件是整个 IaC 体系的"唯一真相源"(Single Source of Truth),但它同时也是最脆弱的环节。state 文件丢失、锁死、配置漂移,这三个问题我在多个生产环境中全部遇到过。这篇文章不讲 Terraform 基础语法(相关文章:Terraform 基础设施即代码入门 已经讲过),而是聚焦于:生产环境中 state 文件怎么存、怎么锁、怎么迁移、出了事怎么救。 你会看到: state 文件的内部结构和它为什么这么重要 S3 + DynamoDB 远程后端的完整生产级配置(含权限隔离方案) 状态锁卡死的排查和解除方法 配置漂移的检测、修复和预防策略 状态文件拆分迁移的实战步骤(附 terraform state mv 的避坑指南) 一个真实的"state 文件被误删"灾难恢复全过程 state 文件到底是什么 先说人话:state 文件就是 Terraform 的"资产清单"。 你用 Terraform 创建了一台 EC2、一个 RDS、一个 VPC,Terraform 需要记住这些资源的 ID、属性、依赖关系。不然下次 terraform plan 的时候,它怎么知道哪些资源已经创建过、哪些需要更新? state 文件就是一个 JSON 文件,记录了所有被 Terraform 管理的资源的当前状态。每次 terraform apply 后自动更新。 state 文件的内部结构 打开一个 terraform....

July 25, 2026 · 10 分钟 · 2110 字 · 徐保金