资讯详情

持续交付 vs 持续部署:CD流水线架构与发布模式全解析

📅 2026/10/11 6:08:53 | 华诺云谱 👁 阅读
持续交付 vs 持续部署:CD流水线架构与发布模式全解析
我经常在技术面试里问候选人一个问题你们团队用的是持续交付还是持续部署得到的回答里十个有八个会愣一下然后补一句反正就是自动上线CD嘛。这个理解不算全错但漏掉了CD体系里最关键的工程哲学。更要命的是当你打开搜索引擎输入CD这个词能看到的结果至少横跨五个完全不相干的领域软件研发里的持续交付/持续部署、Linux下切换目录的cd命令、已经快进博物馆的CD光盘、银行里的大额可转让定期存单甚至还有人搜抄底cd热门系列。本文聊的是软件工程语境下的那个CD——持续交付Continuous Delivery与持续部署Continuous Deployment。这两个概念的区别一句话就能说完持续交付让软件始终处于随时可以上生产的状态但最后一步由人来按持续部署连最后这一步都自动化了代码通过全部检查后直接进生产。但围绕这句话展开的工程体系、风险策略、流程架构和团队能力要求差别比大多数人以为的大得多。这篇我打算从定义差异讲到流水线架构再讲透蓝绿、金丝雀、滚动这三种交付模式的选型逻辑最后分享一些落地时的实战经验和坑。1. CD这个词被用乱了先分清持续交付、持续部署和另外那些CD1.1 从持续集成到持续交付补上自动发布之前的那些环节很多人习惯把CI/CD连在一起喊好像这是一件事。严格说不是。持续集成Continuous Integration解决的核心问题是代码频繁合入主干且每次都自动验证。它最早被提出是为了终结集成地狱——多个开发分支各自跑得欢一合并就炸然后再花几天时间修冲突。持续集成把编译、单测、静态检查自动化之后大家发现自己站在一个新的台阶上代码每天合主干质量有自动化把关主干基本是绿的。接下来顺理成章的诉求是——既然主干天天绿能不能让任何一个绿的主干提交都自动部署到测试环境让测试人员随时有东西可验这一步就是持续交付的雏形。持续交付的定义业界公认的版本来自Martin Fowler那套理论软件构建、测试、部署到类生产环境的整个过程全部自动化保证任何一个通过验证的构建产物都能在几分钟内一键部署到生产环境。注意关键词一键部署但没有说系统自动部署。这就是持续交付和持续部署最微妙的边界。持续部署则更进一步通过所有验证的代码自动发布到生产环境全程无人干预。从代码提交到用户可见没有一个人为审批节点。1.2 定义精读持续交付和持续部署只差一个按钮把两个定义放在一起对比差异点就非常明确维度持续交付Continuous Delivery持续部署Continuous Deployment自动化范围测试、构建、部署到类生产环境全自动在持续交付基础上生产发布也自动生产发布动作人工点击发布按钮系统自动执行核心状态软件随时可发布Release Ready软件自动发布Auto Release人为介入点保留最终发布决策权无任何人为决策节点风险兜底人在最后一刻把控完全依赖自动化质量体系一句话总结持续部署 持续交付 自动发布。但这句话背后是两条完全不同的工程路线。没有了最后那个人工审批环节意味着测试覆盖率、监控告警、回滚机制、配置管理都必须达到机器可以信任的级别。这个差异我后面专门展开。1.3 同一缩写多个语境搜索引擎里的CD到底什么意思写这篇的时候我特意去搜了一下CD相关热词结果相当混乱有人搜shell命令cd有人搜cd机有人搜usb网卡接上出现cd驱动器错误还有人搜concierto de aranjuez hiderto kanai quintet three blind mice tmb cd这种音乐专辑。同一个时间线上CD这个词至少承载着五种完全不同的含义。如果你是为了搞懂持续交付和持续部署来搜CD的建议先把语境锁死在技术社区里CD前面通常会有CI/USB/I之分或者直接写全称Continuous Delivery/Continuous Deployment。搜索引擎的结果里如果出现cd ~/downloads sudo apt install ./spark-store*.deb这种带路径切换命令的内容那是Linux命令行教学跟软件工程里的CD没有任何关系。划清楚这个边界能帮你省掉不少无效信息筛选时间。下面正式进入持续交付和持续部署的深度拆解。2. 分水岭在前方那个上生产按钮到底留给人还是交给机器2.1 按钮背后的风险模型人为判断的价值在哪里持续交付理念里那个发布按钮是有意保留的。为什么因为自动化测试无法覆盖所有风险。想象一个业务场景银行月底结算前两小时一笔重要对账任务正在跑批这时代码刚好通过了全部自动化检查按流程可以发布了。一个有经验的发布负责人会看一眼日历说今天不适合发。自动化系统很难做出这种基于上下文的风险判断。这不是说自动化不可信而是说软件发布不只是技术动作它还牵扯业务节奏、合规窗口、外部依赖状态。持续交付支持随时可发布但把什么时候真发这个决策权留给有全局信息的人。对强监管行业、金融核心系统、医疗系统来说这个按钮几乎是红线。持续部署反过来它信任全部的自动化质量链路认为只要测试、监控、灰度机制足够完善人点按钮引入的延迟和错误比自动化更大。这不无道理——人工操作最经典的失误就是点了发布忘了看日志等到业务报警才发现版本有问题。机器虽然也会犯错但错得比人有规律且更容易快速修正。2.2 持续部署对工程体系的硬性要求我不会劝每个团队都冲持续部署。但如果你真打算把那个按钮交给机器下面这些能力缺一项都可能出事测试可信度单元测试、接口测试、端到端测试的覆盖率要到一个擅长持续部署的团队才会有的水平而且测试套件必须稳定不抖动不能有大量flaky test偶发失败的那种测试。否则机器自动发布时跑到一个不稳定的测试用例门禁误拦还好最怕误放。观测体系日志、指标、链路追踪必须齐全且要能自动对比发布前后的核心业务指标。没有指标对比新版本上线后用户已经在报错了监控上还是一潭死水。回滚自动化发布失败后系统要能在几分钟内自动或一键回滚到上一个可用版本。这里要注意代码回滚容易数据库回滚难后面第五章我会讲。配置一致性测试环境和生产环境的差异要降到最低否则在预发环境验得好好的一上生产就崩持续部署的自动化就变成了自动闯祸。上面四条做不到持续部署就是在放大缺陷而不是提升效率。这也是为什么很多一线大厂把CI做到了极致但生产发布依然保留人工审批特别是涉及核心链路的版本变更。2.3 两种模式的取舍决策表做技术选型的时候别听别人说持续部署是趋势就硬上。我按团队规模、业务形态、基础设施成熟度列了一个对照表你可以拿自己的情况去对决策维度更适合持续交付更适合持续部署团队规模小到中型团队DevOps人力有限有专职平台/DevOps团队的较大团队业务类型强监管、低频大版本、合同制交付互联网产品、高频迭代、快速试错测试能力覆盖率中等关键路径有验证覆盖率很高质量门禁稳定可信监控能力有基础告警发布后人工盯大盘发布后能自动对比业务指标回滚能力有回滚预案手动执行可接受回滚已脚本化、自动化且演练过发布频率每周到每月一次每天多次甚至几十次合规要求要求人工审批留痕无强人工审批要求或可用自动化审计替代没有哪个选项更高贵。我见过一家做企业服务的公司产品两个月发布一次大版本硬上了持续部署结果一半精力花在应对自动化发布失败上效率反而更低。他们的问题不是工具不够好而是选型跟业务节奏不匹配。2.4 部署Deployment和发布Release不能混为一谈聊CD绕不开两个词Deployment和Release。很多人把它们当成同义词但在发布工程里它们是两个不同动作。部署Deployment把新版本代码装到目标环境并运行起来。这个动作面向的是服务器。发布Release让新功能对外部用户可见通常通过流量切换、DNS解析、功能开关等动作实现。这个动作面向的是用户。蓝绿部署就是典型的先部署、后发布新版本先部署到备用环境跑起来确认没问题再通过负载均衡把流量切换过去。那一刻才是发布。如果切换后发现有问题切回旧环境即可这个回滚动作不影响用户因为部署和发布被刻意拆开了。搞清楚这个区别再看持续交付和持续部署的争议会发现大家吵的其实是部署动作是否自动化而发布动作无论哪种模式都牵扯流量策略。这两个概念混在一起讨论就很难有结果。3. 从git提交到生产环境CD流水线的工程架构拆解3.1 一条合格CD流水线至少要有的六个阶段很多团队把CD流水线理解成CI跑完了自动部署一下这其实只是最粗糙的脚本不是架构。一条能稳定支撑业务的CD流水线至少包含下面六个环节提交触发与变更识别开发者推送代码到主干或指定分支流水线被触发同时记录本次变更对应的Commit ID、改动文件列表。静态检查与单元测试跑lint、代码规范检查、安全扫描SAST、单元测试并计算覆盖率。这一环节速度要快让开发者尽早得到反馈。构建不可变制品把代码构建成容器镜像、JAR包或二进制产物并推送到制品仓库。这里的关键要求是不可变——同一个构建产物在测试环境验过什么在生产环境就跑什么不允许发布时重新编译。部署到类生产环境自动把制品部署到staging预发环境执行冒烟测试、契约测试、端到端测试。这个环节的目的是用最接近生产的条件验证制品。质量门禁校验与准入汇总所有测试结果、覆盖率、安全扫描报告、性能基线对比全部达标才允许进入发布管道。任何一个门禁不过流水线直接红灯。生产发布执行根据选择人工点击发布按钮持续交付或系统自动执行灰度/蓝绿/滚动发布持续部署。环节5极其重要但不是所有人都设计了。质量门禁不是把测试跑完就算而是要有一个汇总判定的节点——就像高考录取单科成绩再好总分不过线一样不录。3.2 环境分层设计pre-production为什么是CD的命门CD流水线的天敌是环境漂移——测试环境和生产环境存在肉眼可见的差异导致测试结果失真。常见的环境分层是dev环境开发者本地调试用数据随意配置随意。test/集成环境团队共享跑自动化测试和联调数据是脱敏过的脏数据或造数工具生成的合成数据。staging/pre-production预发环境配置尽量与生产一致数据用脱敏但结构完整的生产拷贝专门做发布前的最后验收。production生产环境真实流量真实数据。CD体系里staging环境的质量决定了整个流水线的可信度。如果staging和生产差距太大流水线跑得再顺也是自欺欺人。我见过最典型的反面案例staging环境用了老旧的脱敏数据生产环境的数据结构已经因为业务迭代加了新字段结果所有staging上的自动化测试都通过一发布到生产就报SQL字段不存在。要缓解环境漂移核心手段是基础设施即代码IaC——用Terraform、Ansible、CloudFormation这类工具把环境定义成代码保证各个环境从同一个模板创建再配合配置中心把环境差异收敛到显式的配置文件中而不是靠运维手工改服务器。3.3 质量门禁与不可变制品没有它们CD就是裸奔不可变制品的核心价值是可复现。打个比方你不可能让厨师把试吃时的那盘菜跟端给顾客的那盘菜分别做一遍——口味一定会有差别。正确做法是同一个盘子里做了三份试吃一份上菜一份留样一份。CD流水线里的制品仓库就是那个盘子一个构建产物比如Docker镜像打上唯一版本号在测试、预发、生产三个环境用同一个镜像。质量门禁可参考的几个具体指标单元测试覆盖率低于80%不允许进入构建阶段。安全扫描依赖漏洞、密钥泄漏、镜像基础层漏洞发现高危项不允许部署。关键接口的契约测试失败不允许部署。性能基线对比P99响应时间、吞吐量劣化超过阈值不允许发布。这些门禁的设置原则是宁可误杀不可放水。门禁多了必然增加等待时间所以要把能并行的检查并行掉尽量缩短流水线总耗时。3.4 最小可用的Python项目CD流水线讲理论太多容易飘我用一个Python项目的GitLab CI配置作为例子演示一个最小可用的CD流水线长什么样。这个项目用FastAPI写了一个HTTP服务构建成Docker镜像部署到staging环境。stages: - test - build - deploy variables: APP_NAME: fastapi-demo IMAGE_TAG: $CI_COMMIT_SHORT_SHA test: stage: test image: python:3.11-slim script: - pip install -r requirements-dev.txt - pytest --covapp --cov-fail-under80 -q only: - main build: stage: build image: docker:24 services: - docker:24-dind script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker build -t $CI_REGISTRY_IMAGE:$IMAGE_TAG . - docker push $CI_REGISTRY_IMAGE:$IMAGE_TAG only: - main deploy-staging: stage: deploy image: alpine:latest before_script: - apk add --no-cache openssh-client - eval $(ssh-agent -s) - echo $STAGING_SSH_PRIVATE_KEY | ssh-add - script: - ssh deploystaging-server docker pull $CI_REGISTRY_IMAGE:$IMAGE_TAG - ssh deploystaging-server docker stop $APP_NAME || true docker rm $APP_NAME || true - ssh deploystaging-server docker run -d --name $APP_NAME -p 8080:8080 $CI_REGISTRY_IMAGE:$IMAGE_TAG environment: name: staging only: - main这个配置里值得注意的细节镜像tag用$CI_COMMIT_SHORT_SHA保证每个提交对应唯一镜像版本可追溯。deploy阶段依赖SSH密钥不要用明文密码密钥存到GitLab CI/CD Variables里。部署完只起到了容器启动的程度严谨的做法还要加一个健康检查步骤等待接口返回200再标记部署成功。再往外延伸一步如果要把staging切换到生产环境就是在deploy-staging后面再加一个deploy-production阶段并在其中根据你的发布模式实现流量切换逻辑——比如蓝绿模式下切换负载均衡后端金丝雀模式下调整流量比例。3.5 流水线中最容易翻车的三个环节第一构建阶段的网络依赖不稳定。很多Python项目用pip装依赖只要requirements.txt里写了不精确的版本号比如numpy1.20某天pip解析到一个不兼容的新版本构建就挂了或者在测试通过后构建出了个假版本。解决办法用pip-tools或poetry锁定依赖版本生成requirements.lock让构建完全可复现。第二测试阶段偶发失败。一次端到端测试包含大量异步操作、外部依赖某个接口偶发超时就会让流水线红灯。红灯多了团队就会习惯性重跑一下最后测试门禁形同虚设。解决办法先识别哪些是flaky test把稳定的用例放门禁不稳定的用例单独放一夜跑逐步修复。第三部署阶段的密钥和权限问题。SSH密钥过期、sudo权限不足、防火墙规则变更都可能让部署脚本半路失败。这个问题不复杂但很烦人我的建议是建立一个部署环境健康检查前置任务每次部署前先验证密钥连通性、磁盘空间、目标服务状态提前暴露问题。4. 蓝绿、金丝雀、滚动三类交付模式的运行逻辑和选型4.1 三种模式的运行机制与直观类比交付模式解决的是新版本怎么替换旧版本的问题。三种主流模式各有各的脾气蓝绿部署Blue-Green Deployment准备两套完全相同的环境蓝色跑旧版本绿色跑新版本。先把新版本部署到绿色环境并全面验证再把流量从蓝色整体切到绿色完成发布。直观类比就是双通道换水先在新管道里蓄好净水确认合格后直接切换阀门。金丝雀发布Canary Release先让新版本服务一小部分用户或流量比如先放5%观察一段时间没有异常再逐步扩大比例直到100%。类比就是矿井里的金丝雀——先让一小部分冒险探明风险后再全体跟进。滚动更新Rolling Update本质上就是分批替换。在负载均衡后的一组服务器中一批一批地停止旧实例、启动新实例滚动过程中新旧版本共存直到全部替换完。类比是逐节更换火车车厢一节换新、一节验收、再换下一节整列车一直在线运行。4.2 为什么部署和发布在这一章必须分开第2.4节我提过部署和发布的区别在交付模式这里会体现得非常清晰。蓝绿部署是典型的先部署后发布绿色环境的部署动作跟流量完全隔离部署完成不代表用户能看到新版本只有负载均衡切换那一刻才是发布。金丝雀和滚动则是部署即发布的渐进过程新版本实例一启动就有一部分流量被导过去部署的动作本身就是发布动作的一部分。这个区分直接影响你的回滚设计。蓝绿部署的回滚就是一次流量切换把负载均衡重新指回蓝色环境秒级完成。滚动的回滚则要重新走一遍替换流程把新实例逐个替换成旧镜像耗时更长。选模式之前先想清楚你能接受多快、多复杂的回滚动作。4.3 选型决策按团队、按业务、按基础设施打分不同模式对基础设施的要求差异很大选型时可以按下面这张表对照决策维度蓝绿部署金丝雀发布滚动更新基础设施要求高需要双倍资源中高需要流量控制能力低基本所有编排平台都支持实施复杂度中主要是环境切换逻辑高需要灰度策略和指标对比低平台原生能力多回滚速度极快秒级切流量快调流量比例到零较慢需反向滚动替换资源成本发布期间双倍资源低增量成本无额外成本适合场景核心系统、数据强一致性要求高流量互联网服务、快速验证弹性伸缩的云原生应用典型工具支持Kubernetes、SLB、DNSIstio、Nginx InfluxDB、K8s原生Kubernetes、云平台弹性组我给一个务实的建议刚起步的团队别一上来就金丝雀先把滚动更新玩明白。Kubernetes原生支持滚动更新配置一个strategy参数就能用成本最低。等到发布频率高了、业务规模大了再逐步引入蓝绿或金丝雀。金丝雀的门槛不在于技术而在于怎么判断新版本好不好——你需要一套能快速对比新旧版本业务指标的观测系统没有这套东西灰度比例调大调小完全靠拍脑袋。4.4 灰度发布在真实系统里的落地细节灰度发布金丝雀的一个变体在实际落地时至少可以从三个维度切分流量按实例比例比如Kubernetes中设置10%的Pod运行新版本90%运行旧版本。这个方式最简单但对多租户系统不够精细。按用户维度按IP段、用户ID哈希、地域、设备类型、内部员工标签等维度分流。实现上依赖API网关的规则引擎或服务网格的流量策略。按功能维度结合Feature Flag特征开关同一个Pod里新代码已部署但只有特定功能开关打开的用户能看到新功能。这个方式把部署和发布彻底拆开了团队可以随时通过开关调整用户可见范围是大型系统高频发布的主流手段。灰度发布最怕两件事一是指标对比口径不对新旧版本的流量特征本身有差异没做同维度对比就误判二是灰度放量过快5%没扛住就直接放到50%事故规模瞬间放大。我个人的经验是前5%验证功能正确性15%验证稳定性40%验证容量再逐步到100%每一档停留时间根据指标观察结果灵活伸缩没有异常就快有异常立即止损。5. 把CD真正跑起来的实战账环境、回滚、权限和推进路线5.1 环境漂移CD最隐蔽的敌人在我接触过的团队里CD流水线搭得漂漂亮亮最后毁在环境漂移上的例子实在太多。最典型的场景测试环境通过、预发环境通过、一上生产就挂。根因通常是这几类配置漂移预发环境配了缓存集群生产环境忘了配或者配置中心的key对不上。依赖漂移两个环境的依赖版本不一致测试环境装到了新版本生产环境还在旧版本。数据漂移生产环境的数据量级、分布特征跟测试环境完全不是一回事测试环境几千行数据跑得好好的SQL生产环境几亿行数据直接慢查询拖垮数据库。对策层面我反复跟团队强调三件事一是坚持IaC环境定义写进代码仓库版本可追溯二是构建镜像只使用锁定版本的依赖杜绝环境里各装各的三是staging环境的数据要大最好是脱敏后的生产快照且定期刷新。做不到这三点CD流水线就是在一条飘忽不定的公路上跑车技术再好的司机也拦不住翻车。5.2 回滚设计数据是前进的代码才叫回滚很多人设计回滚方案时脑子里只有切换旧版本镜像这一个动作等到发布事故真的发生时才发现代码可以回滚数据回不滚。比方说新版本上线了一个数据库迁移给用户表加了一个字段并回填了数据。运行两天后发现有问题要回滚代码切回旧版本但旧版本不认这个新字段吗或者这个回填的数据已经影响了下游统计怎么处理这就是经典的数据前滚问题——数据库变更本质上是单向前进的版本回退后数据库结构往往不能直接跟着倒退。现实中的解决思路是设计时要求所有数据库变更向前兼容。加字段只加可空字段删字段先停用不物理删除回填数据用可逆策略补偿。配合功能开关这种逻辑回滚手段——代码不滚只把新功能关掉——很多时候根本不需要物理回滚镜像。在写CD流水线之前先跟DBA约定好兼容性变更的军规比临时抱佛脚管用得多。另一个被低估的点是制品保留策略。回滚需要旧版本还在所以制品仓库要保留足够多的历史版本。我的经验是容器镜像至少保留最近100个版本或30天同时保证每个镜像是不可变且可复现的。很多人只保留最近一两个版本结果发布后第3天才发现性能问题想回退时发现旧镜像早被清理了。5.3 权限、审批和密钥安全边界不该被自动化抹掉持续交付和持续部署可以提高发布频率但安全意识不能跟着自动化一起自动化掉。实际落地时这几个问题要提前想清楚谁有权限触发生产部署建议按角色分权开发者的权限到预发环境为止生产发布权限由发布负责人或平台管理员持有。人工审批怎么留痕即使是持续交付的人工按钮也要有明确的审批记录谁、什么时间、部署了哪个版本、部署到哪个环境。全程审计日志是合规底线。密钥管理怎么做流水线里的SSH密钥、云厂商AccessKey、镜像仓库密码一律不要硬编码在仓库里统一放到CI/CD平台的加密变量或专用密钥管理系统里定期轮换。紧急发布通道要不要要但紧急通道不能变成日常通道。团队要约定清楚什么级别的事故可以走紧急发布事后必须补审计记录。有一次我们客户的生产环境出了紧急事故需要立即发布热修复结果发现发布负责人密钥过期了流程被卡在SSH认证这一步。后来我们做了一次复盘给所有核心密钥加了自动到期提醒并把发布账号密钥有效性纳入环境健康检查。这种细节不踩过一次坑很难有体感。5.4 团队推进CD的建议落地顺序最后分享一条我认为比较稳妥的落地路径。如果你所在团队还没跑通完整的CD别一上来就追求全自动部署。我的推荐顺序是先追版本可追溯每个提交对应唯一制品能说清楚生产环境跑的是哪个Commit的什么镜像。再追环境一致性用IaC管理环境锁定依赖版本staging数据接近生产。然后补质量门禁从单测覆盖率、契约测试、安全扫描这几个最基础的指标开始逐步增加门禁项。接着实现持续交付做到一键发布到生产但保留人工按钮先把发布节奏稳定下来。最后才考虑持续部署或灰度自动化当上述能力都稳定了再把最后那个按钮交给机器。这套顺序背后有一条主线每一步都在为下一步增加对自动化的信任。发布工程本质上不是一个纯技术问题而是一个自动化程度与信任程度相匹配的工程决策。我个人在实际操作中的体会是很多团队卡住的不是工具和技术而是没有按这个顺序渐进跳级推进导致翻车然后又缩回全手动发布的老路。CD这个词在技术圈里被讨论了十几年到今天依然有大量团队还停在CI很完善、CD很骨感的阶段。希望这篇把定义差异、流程架构、交付模式这几个关键维度讲清楚之后能帮你少走一点弯路。如果有机会下次面试里再遇到你们用持续交付还是持续部署你可以试着把那个按钮背后的风险模型讲给面试官这比背一遍定义有意思得多。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑