Kubernetes 零损发布实战:Pod 全绿背后的 23 个丢失请求

简介: 订单服务滚动发布看似成功,实则因Pod优雅终止与业务请求时序错配,导致23笔订单状态不明、7笔重复支付。根本在于未协同流量摘除、在途请求排空与幂等设计,零损发布需以业务语义而非K8s状态为验收标准。

订单服务做滚动发布,Deployment 显示更新成功,Pod 没有 CrashLoop,发布平台也全绿。半小时后对账却发现:23 个创建订单请求在发布窗口没有形成明确结果,其中 7 个被客户端重试后生成了重复支付意图。

组件都没有明显“坏掉”,事故发生在 Pod 下线、流量摘除、长请求执行和客户端超时之间的竞态里。

image.png

Kubernetes 管理生命周期,不理解你的业务提交点

Pod 被删除时会进入终止流程,端点状态变化、容器生命周期钩子和终止信号共同参与优雅关闭。但应用是否还能接受请求、一个请求何时产生不可逆副作用、失败后能否恢复,只有业务代码知道。

如果收到终止信号后立刻退出,正在支付的请求会被切断;如果继续对外保持 ready,上游在收敛期间还会送来新请求;如果只 sleep 20 秒,却没有统计在途任务,团队只是把问题推迟了 20 秒。

image.png

正确顺序是:摘流量、停入口、排在途、再退出

应用收到终止信号后,应先进入 draining 状态,让 readiness 返回失败;HTTP 入口拒绝新的高成本请求,消息消费者停止拉取新任务,定时任务不再领取租约;已经开始的请求继续执行,直到完成或进入可恢复状态。

下面是一个简化的 Python 状态控制器,核心在于显式跟踪在途请求,而不是固定等待:

import asyncio
from contextlib import asynccontextmanager

class DrainState:
    def __init__(self):
        self.draining = False
        self.inflight = 0
        self.done = asyncio.Event()
        self.done.set()

    @asynccontextmanager
    async def request(self):
        if self.draining:
            raise RuntimeError("instance_draining")
        self.inflight += 1
        self.done.clear()
        try:
            yield
        finally:
            self.inflight -= 1
            if self.inflight == 0:
                self.done.set()

    async def drain(self, timeout_seconds=35):
        self.draining = True
        await asyncio.wait_for(self.done.wait(), timeout=timeout_seconds)

真实服务还要防止“检查 draining 后、inflight 加一前”出现竞争,可用同一个异步锁保护状态切换。网关或服务网格的连接排空也要与应用宽限期对齐。

订单类请求必须能回答“到底提交了吗”

最棘手的时序是数据库已提交,响应还没返回,Pod 就被终止。客户端只看到超时,无法知道订单是否存在,随后重试可能生成第二单。

因此创建订单要使用业务幂等键,查询接口能按该键返回既有结果;支付、库存等后续动作也要有独立状态与恢复机制。优雅下线只能减少中断,不能替代副作用幂等。

CREATE UNIQUE INDEX uq_order_request
ON orders(tenant_id, client_request_id);

-- 重试时先按 tenant_id + client_request_id 查询已有终态

配置要为应用的最坏完成时间留空间

如果业务请求 P99 为 12 秒,支付超时上限 20 秒,terminationGracePeriodSeconds 却只有 15 秒,那么“正常最坏路径”在发布时必然被杀死。宽限期应覆盖停止接流量、上游传播和在途请求完成,并留有安全余量。

配置示例:

spec:
  terminationGracePeriodSeconds: 45
  containers:
    - name: order-api
      lifecycle:
        preStop:
          httpGet:
            path: /internal/drain
            port: 8080
      readinessProbe:
        httpGet:
          path: /ready
          port: 8080
        periodSeconds: 2
        failureThreshold: 1

preStop 接口应幂等,并立即切换 draining;不要把固定 sleep 当作唯一动作。还要确保探针失败后,应用不会继续从其他入口领取新任务。

image.png

零损发布应该怎样测试

持续按真实到达率发送创建、查询、取消三类请求,在每次发布的随机时刻删除 Pod。把请求按“终止前开始、终止中到达、终止后重试”分桶,最后对账数据库、支付和客户端结果。

验收不只看 5xx:每个 client_request_id 最多一个订单;每个已扣款请求都有可查询订单;每个客户端超时都有明确恢复路径;终止中的新请求快速失败并带可重试语义;Pod 在宽限期内完成退出。再主动让下游支付延迟到 25 秒,验证最坏路径。

生产监控增加 draining 实例数、终止时在途请求、强制结束次数、终止窗口的未知结果数和幂等命中数。它们比 Deployment 成功状态更接近用户事实。

滚动发布真正的“成功”,不是新 Pod 都 Ready,而是旧 Pod 离开的过程中,每一个业务请求都能说明自己完成、拒绝,还是可恢复。

相关文章
|
6天前
|
人工智能 运维 BI
阿里云千问办公QwenWork深度解析:基于Qwen3.8,六大核心能力重构企业全自动化工作流与计费选型指南
传统AI办公工具大多停留在对话问答、文档摘要、简单文案生成层面,只能完成单点碎片化任务,无法自主拆解复杂业务流程,很难串联多工具、多文档、外部业务系统完成端到端完整工作交付。很多企业在落地AI办公的时候,需要组合多款不同工具,来回切换界面,手动复制粘贴中间结果,智能化改造落地门槛居高不下。千问办公QwenWork是整合多款智能体产品能力打造的一体化企业办公智能体平台,底层基座依托Qwen3.8大模型,打通桌面端Agent、云端Agent、企业协同Agent三种运行形态,不再局限简单问答,接收业务目标之后自主拆解任务步骤,调用各类工具,处理文档、表格、浏览器自动化、数据查询,直接输出可交付的办公
1520 0
|
6天前
|
人工智能 自然语言处理 安全
阿里云AI数智鉴密:AI 生成内容如何拿到一张"防篡改的身份证"
隐形水印 + C2PA签名:让AI生成内容“持证上岗”。
1134 0
|
15天前
|
人工智能 自然语言处理 安全
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
本文聚焦阿里云2026年推出的三款自研AI办公产品,清晰拆解千问办公、Qoder Teams、Qoder CN的差异化定位与能力边界:千问办公主打职场全场景提效,支持自然语言指令一键完成PPT生成、数据分析等高频办公任务;Qoder Teams面向程序员团队,深度整合AI代码生成、团队协同与企业知识库能力;Qoder CN则专为金融、政务等强合规场景打造,实现数据不出境与VPC私有化部署。文章同步给出分场景选型指南与最新活动定价,帮助不同类型的企业按需组合产品,实现业务岗、研发岗与强合规场景的AI能力全覆盖。
3799 4
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
|
3天前
|
SQL 人工智能 前端开发
QoderWake 1.0 正式发布:从桌面里的 Agent,到工作现场的数字员工
QoderWake v1.0正式发布:企业级数字员工团队平台。支持“一句话建岗”,预置10类特训岗位;Waker常驻钉钉/飞书群,@即响应、自动协作、跨任务记忆;具备定时/事件/API多触发方式与统一任务看板;已沉淀27.6万条记忆、12.3万项技能,助力组织实现人机协同增效。
655 0
|
2天前
|
人工智能 API 内存技术
刚刚 DeepSeek V4.1 Flash 开启内测,1 分钟教你用上!
刚刚 DeepSeek 内测群发布了 DeepSeek V4.1 Flash 中间版本内测的消息,这次的模型采用了新的结构,原生支持多模态、能力更强、速度更快、且成本更低。
1449 2
|
7天前
|
网络协议 Linux iOS开发
【2026实测】Wireshark下载+安装+汉化+使用教程(图文版,巨详细)
Wireshark 是一款免费开源的网络协议分析工具,可实时捕获、解析并可视化数据包,助你诊断网络故障、分析通信协议(如HTTP、DNS、TCP等)。支持Windows/macOS/Linux,含中文界面,新手入门便捷。(239字)