可观测、安全、数据与平台事故¶
可观测链路背压导致“业务故障时恰好没有遥测”¶
相关技术说明
遥测1链路应被当成有容量上限的生产系统:SDK 队列、agent、gateway、网络和后端任一处背压2都会向上游传播。同步导出可能增加业务延迟,无界重试则会耗尽 OpenTelemetry Collector3 内存;尾采样需要缓存完整 trace4,流量激增时尤其危险。设计应有 memory_limiter、有界队列/持久队列、批处理、丢弃优先级和 Collector 自观测,并使业务线程不因遥测失败而阻塞。缺数据本身必须产生独立告警。
实践经验
这是一个复合生产场景。影响:订单 API p99 从 300 ms 升至 4 s,约 12% 请求超时;同时 trace 搜索在故障窗口近乎空白。时间线与证据链:10:02 新促销流量进入;10:05 后端 trace 存储限流;10:07 gateway exporter 重试队列上升、RSS 达限制并 OOM;10:09 应用同步 exporter 超时与业务延迟同向;入口负载均衡指标和数据库指标仍完整,证明并非流量消失。10:13 先关闭正常请求的 trace 导出、保留错误日志和核心指标,限制 Collector 队列并扩 gateway;10:19 业务恢复。
根因是后端限流时无界重试与同步 SDK 共同形成反压;促销容量模型未包含 spans/request 上升、尾采样路由不均和“遥测缺失”告警缺位是促成因素。永久修复:应用改有界异步导出,gateway 启用内存限制和持久队列,错误/高延迟优先采样,按租户限额,并为接收/拒绝/丢弃/排队建立 SLO。验证通过两倍峰值压测和 30 分钟后端断连演练:业务 p99 不恶化、核心指标无缺口、丢弃仅发生在低优先级正常 trace。复盘行动还包括容量 owner、季度故障注入及禁止无界队列的配置测试;副作用是正常 trace 覆盖下降,使用动态采样补足。
CI Runner 泄露发布凭证并造成供应链入侵风险¶
相关技术说明
自托管 Runner5 会执行仓库代码,若复用宿主、缓存或全局工作区,不可信 PR 可能读取上一个作业残留。长期发布 token 一旦泄露,删除日志或关闭 PR 不能使其失效。响应要先吊销身份、限制制品库/云权限并保存 Runner、CI 日志、IdP 与 registry 审计;重建必须从可信基线进行。长期应按信任域拆池、使用一次性计算和 OIDC6 短期凭证,并对生产制品做 digest 签名、provenance7 与准入验证。
实践经验
影响:安全监控发现发布账号在非流水线时段拉取私有包并尝试推送测试镜像,尚无证据表明未知 digest 进入生产,但信任链被视为失守。时间线/证据:02:14 registry 异常源 IP;02:20 会话映射到共享 token;02:27 CI 日志发现调试输出与上个作业残留 .npmrc;审计将 token 访问范围限定到制品库,无云控制面调用。团队先禁用 Runner 池、吊销所有相关 token、冻结晋级、导出不可变审计,并逐一比对生产运行 digest、签名和已知流水线产物;02:55 确认生产制品一致。
根因是 fork PR 与发布作业共享持久宿主及长期凭证;缓存隔离不足、日志脱敏失败和制品库允许 tag 覆盖是促成因素。永久修复为一次性 Runner、网络出口分区、OIDC job 身份、不可变 tag、keyless 签名和部署端 subject/issuer 校验;第三方 action 固定 digest。验证用攻击演练确认外部 PR 无秘密、不能访问内部仓库,且伪造签名被准入拒绝。复盘明确“未发现生产篡改”不等于“无事件”,改进证据保管和 30 分钟内吊销目标;冷启动增加,以预拉无密钥镜像池折中。
根 CA 轮换导致服务间 mTLS 大面积失败¶
相关技术说明
CA8 轮换是分布式兼容变更,安全顺序通常是先让所有客户端信任新旧根,再切换签发,观察旧链使用归零后移除旧根。仅更新服务端证书会让旧客户端无法构链;配置热加载、长连接、时钟偏差和离线节点会延长迁移窗口。双信任提升兼容性,也短期扩大信任面,所以需要精确截止和审计,而不能永久保留旧根。
实践经验
影响:内部结算 RPC 约 18% 握手失败,订单确认延迟并产生积压。时间线/证据:14:00 签发器切到新中间 CA;14:03 TLS 错误率按旧版本实例集中;14:06 抓包和代理日志显示 unknown authority,证书时间有效、名称正确;14:09 发现一组 sidecar 的 trust bundle 只在进程启动时加载。团队停止继续签发、临时恢复旧链签发并将失败版本流量降权,同时发布包含旧、新信任锚的 trust bundle,随后滚动重启代理;14:22 成功率恢复,积压按幂等键排空。
根因是错误的“切签发再铺信任”顺序;未盘点非热加载客户端、预发布环境未覆盖旧代理版本、没有按证书链维度的握手指标是促成因素。永久修复为根/中间/叶轮换 runbook、双信任阶段、客户端资产清单、30/14/7 天预警和合成 mTLS 探测;控制面发布加入旧版本兼容矩阵。验证在隔离环境演练完整轮换及回退,并确认旧链握手连续七天为零后删除。复盘保留有审计的延长窗口,但禁止无期限旧根例外。
PostgreSQL 自动切换形成 Split Brain 与连接风暴¶
相关技术说明
数据库自动切换必须将 leader 选举、数据完整性与 fencing9 绑定。仅因健康检查失联就提升副本,若旧主仍可被部分客户端访问,会形成 split brain10。提升后 RTO 还受代理、DNS 缓存、连接池与重试控制影响;所有实例同时重连会压垮新主。异步复制的 RPO 应用 LSN/时间线量化,不能在事故中假定为零。
实践经验
影响:一个区域网络分区后约 7 分钟存在双写,1.6% 订单状态冲突;新主连接数在一分钟内到上限。时间线/证据:11:41 编排器失去旧主心跳;11:42 提升副本;11:43 部分使用缓存 DNS 的客户端仍写旧主;11:44 时间线分叉、唯一键冲突和连接创建率暴涨。IC 先冻结订单状态写入,在基础设施层 fence 旧主,限制应用重连并保留管理连接;确认新主 LSN 与多数业务事件后将读写统一路由,随后按订单事件日志对账和补偿。
根因是提升流程未强制 fencing;促成因素包括异步复制、客户端直连、DNS TTL/连接寿命过长及无抖动重试。永久修复为“fence 成功才提升”、统一数据库代理、总连接预算、退避重连和关键写路径同步副本;保存旧时间线用于审计,不直接合并物理数据。验证执行网络分区游戏日:旧主无法写、新主在目标 RTO 内可用、峰值连接低于预算、RPO 通过业务序列校验。复盘同时更新手工切换权限和数据冲突处置表,承认同步复制增加提交延迟并按业务分级使用。
Redis 缓存雪崩压垮主数据库¶
相关技术说明
大量 key 同时到期、整组缓存不可用或版本前缀整体变化都可能让回源瞬间超过数据库安全并发。缓存是保护层而不是无限透传开关:需要 TTL 抖动、热点提前刷新、singleflight、回源限流、舱壁和可接受的 stale/降级策略。价格、库存等强业务约束不应随意返回旧值,必须按数据类别定义陈旧窗口和失败语义。
实践经验
影响:促销开始后商品详情错误率 28%,数据库连接满,结算路径也受连带影响。时间线/证据:00:00 新缓存版本上线,所有商品 key 使用相同两小时 TTL;02:00 expired_keys 与 cache miss 同时陡增,回源 QPS 是平时 14 倍;Redis CPU 尚可而数据库池等待超过 10 秒,证实不是 Redis 计算瓶颈。团队先隔离结算数据库连接、限流非登录详情、对描述类数据启用短时 stale,并分批预热热点;库存请求保持失败关闭。02:18 数据库恢复,积压查询被丢弃而非重放。
根因是统一 TTL 与批量版本切换;无回源预算、详情和结算共享连接池、缺少 miss-rate 告警是促成因素。永久修复:TTL 加抖动、逻辑过期与 singleflight、按业务舱壁、热点预热和缓存故障演练;版本迁移采用双读渐进。验证在 100% 缓存冷启动和单节点失效时,数据库连接低于 70%、核心 SLO 达标,非核心降级符合产品约定。复盘指出“提高数据库上限”会放大锁/内存风险,未作为主修复。
Kafka Consumer Rebalance Storm 导致积压与重复副作用¶
相关技术说明
Kafka Consumer11 处理时间超过 max.poll.interval、频繁发布、GC 或网络抖动会使成员反复离组,引发 rebalance12。lag13 要结合最老消息年龄、分区分布和净消费速率;扩容超过分区数无效。至少一次消费下,处理成功但 offset 未提交会重复,因此外部副作用必须幂等,不能靠增加 session timeout 掩盖无限慢任务。
实践经验
影响:通知 topic 最老消息达到 47 分钟,约 3.2 万条短信被重复请求,供应商触发限流。时间线/证据:09:10 发布新富化逻辑;09:14 poll latency 超过间隔;09:15 起 group 每两分钟 rebalance,member removed 日志与 lag 阶梯增长一致;分区数 24、实例已 40,继续扩容无收益。团队回滚富化逻辑,暂停短信 side effect,按业务通知 ID 在供应商和本地记录对账,再以限速模式恢复;offset 未做强行跳转。
根因是同步下游调用把单批处理拉长;缺乏幂等键、发布时同时重启全部消费者、只监控总 lag 是促成因素。永久修复为 inbox 唯一约束、富化异步舱壁、小批轮询、协作式分配与滚动发布,并按分区告警 rebalance、poll 和最老年龄。验证注入下游 10 秒延迟与单实例终止,确认无风暴、重复被去重且 backlog 在目标时间排空。副作用是异步富化产生最终一致性,产品明确允许窗口并展示“处理中”。
自助平台重试造成重复资源与误删¶
相关技术说明
长时间资源创建必须使用稳定 request ID 和幂等语义,浏览器超时不能代表底层失败。工作流每步记录状态、外部资源 ID 和补偿,删除需依赖图、软删除与恢复窗口。若平台以标签查询资源且标签可重复/缺失,重试与清理都可能命中错误目标;资源身份应由不可变 ID 和租户/环境条件共同约束。
实践经验
影响:开发者为生产数据库点击创建三次,产生三个实例;夜间“孤儿清理器”又误删其中正在迁移的目标,迁移延迟六小时,无持久数据丢失。时间线/证据:16:02 前端 30 秒超时;三次调用无幂等键;16:20 第一个完成但目录只登记最后一个 ID;02:00 清理器仅按缺少目录记录判断孤儿。团队立即暂停清理和新建,恢复软删除实例、冻结迁移,并用云审计/工作流日志重建对应关系;随后只保留已验证目标。
根因是同步 API 与无幂等创建;促成因素是目录被误当权威源、删除无依赖检查/等待期、错误信息诱导重试。永久修复为异步工作流 ID、每步幂等、云资源不可变关联、reconcile 对账,以及删除预览、双人审批和七天隔离。验证用超时、重复提交、平台重启和目录延迟故障测试,确保只创建一次且清理不能碰受保护资源。软删除增加短期费用,以风险分级缩短非生产等待期。
跨区流量与日志配置变更引发云成本异常¶
相关技术说明
云成本异常要拆成用量、单价、分配和业务驱动,而不是只看总额。跨区/公网数据传输、NAT 处理、日志摄入与索引常随架构路径成倍增长;按服务、区域、资源和单位交易归一化,再关联部署/配置事件。费用数据通常延迟,工程侧还应使用字节、连接和日志生成率做领先指标,并设绝对金额与变化率双阈值。
实践经验
影响:三天预测月账单增加约 42 万元,业务 SLO 正常。时间线/证据:周一 11:00 服务网格路由变更;网络 flow logs 显示同区请求经跨区集中 egress,跨区字节增 9 倍;同时 DEBUG 配置误扩到全生产,日志 GB/千请求增 6 倍。费用分摊确认 62% 来自传输、31% 来自日志。团队先回滚路由、将 DEBUG 限定单实例 30 分钟并停止非关键索引,保留安全审计日志;四小时内工程用量恢复,次日账单趋势确认。
根因是路由默认值和日志配置范围错误;没有预估差异、跨区字节预算、动态日志到期机制及变更 owner 是促成因素。永久修复:IaC 计划展示流量/成本影响,拓扑测试禁止不必要 hairpin,调试开关强制范围与 TTL,按单位请求建立成本 SLO 和异常 owner。验证以合成流量对比网络路径、日志字节率和账单回填;复盘没有一刀切关日志,因为会破坏安全/事故证据,而是实施热冷分层与采样。
-
遥测(telemetry)是系统自动产生并远程采集的指标、日志、链路等运行数据。 ↩
-
背压(backpressure)是下游处理不过来时把减速或拒绝信号向上游传播的流量控制机制。 ↩
-
OpenTelemetry Collector 是接收、处理并导出 traces、metrics 和 logs 的可观测数据代理。参见 OpenTelemetry Collector 文档。 ↩
-
trace 表示一次请求跨多个服务的端到端调用链,由多个 span 组成。 ↩
-
CI runner 是领取并执行流水线任务的计算环境,会直接运行仓库代码。 ↩
-
OIDC 是 OpenID Connect,一种可用于让 CI 作业以可验证身份换取短期凭证的身份协议。 ↩
-
provenance(来源证明)记录制品由什么源码、身份和构建过程生成,用于验证供应链来源。 ↩
-
CA 是 Certificate Authority(证书颁发机构),负责签发证书并作为证书信任链的锚点。 ↩
-
fencing(隔离)是在提升新主前确保旧主无法继续写入的机制,可通过网络、电源、租约或存储令牌实现。 ↩
-
split brain(脑裂)指多个节点因分区或协调失败同时认为自己是主节点并接受相互冲突的写入。 ↩
-
Kafka Consumer 是从 Kafka topic 分区拉取并处理事件的客户端成员。 ↩
-
rebalance(再均衡)是 Kafka Consumer Group 在成员或分区变化时重新分配分区的过程。 ↩
-
consumer lag(消费滞后)是消费者已处理位置落后于分区最新位置的距离,可按消息数、时间或最老消息年龄衡量。 ↩