首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >聊聊发布的那点事,零停机是不是神话?

聊聊发布的那点事,零停机是不是神话?

作者头像
IT运维技术圈
发布2025-10-09 12:25:22
发布2025-10-09 12:25:22
1370
举报
文章被收录于专栏:IT运维技术圈IT运维技术圈

0. 写在前面:为什么你需要“神器”而非“常用命令

大家好,欢迎来到干货、技术、专业全方位遥遥领先的老杨的博客.

帮老杨点赞、转发、在看以及打开小星标哦

攒今世之功德,修来世之福报


零停机就是用户无感知的发布。 请求不断。 连接不中断。 服务平稳切换到新版本。 重要的是用户体验不变。

听起来好听,但它不是魔法。 它靠方法、流程和反复演练。

先聊基本原则

改动要向后兼容。 流量要可控。 实例要能优雅下线。 数据库变更要可回滚。 步骤要自动化并可审计。

常见的发布策略与取舍

Blue-Green(蓝绿)

我会把新版本部署到绿环境。 验证无误再切流量到绿。 回滚只需把流量切回蓝。 缺点是需要额外资源。

示例:切流量命令和校验输出如下。

代码语言:javascript
复制
$ kubectl patch svc myservice -n prod -p '{"spec":{"selector":{"app":"green"}}}'
service/myservice patched
代码语言:javascript
复制
$ kubectl get endpoints myservice -n prod -o wide
NAME        ENDPOINTS
myservice   10.244.1.12:8080,10.244.2.15:8080

这适合能承受双倍容量的场景。


Canary(金丝雀)

把少量真实流量先丢给新版本。 观察指标后逐步放量。 我建议把错误率和 95% 延迟作为准入门槛。 用服务网格能精细控制权重。

示例:把 Canary 配置应用后的反馈。

代码语言:javascript
复制
$ kubectl apply -f virtualservice-canary.yaml -n prod
virtualservice.networking.istio.io/myservice configured

金丝雀适合风险较高的功能变更。


Rolling Update(滚动升级)

在资源有限时使用它。 Kubernetes 按策略替换 Pod。 关键是 readiness 要做得严一点。

更新和观察命令如下。

代码语言:javascript
复制
$ kubectl set image deployment/myapp mycontainer=myapp:2025-09-01 -n prod
deployment.apps/myapp image updated
$ kubectl rollout status deployment/myapp -n prod
Waiting for rollout to finish: 2 of 3 updated...
deployment "myapp" successfully rolled out

滚动时要保证旧实例能处理未完成的请求。


Probe 与优雅下线

readiness 决定实例是否能接流量。 liveness 决定容器是否需要重启。 preStop 用来给应用清理并排尽连接。

下面是常见的配置片段(示例保留)。

代码语言:javascript
复制
readinessProbe:
  httpGet:
    path: /health/ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5
lifecycle:
  preStransform: translateY(
    exec:
      command: ["/bin/sh", "-c", "sleep 10"]

preStop 常用来关闭监听、等待连接数降到 0。 这样能避免半条请求在替换时被中断。

应用配置后,用下面命令部署并查看状态。

代码语言:javascript
复制
$ kubectl apply -f deployment.yaml -n prod
deployment.apps/myapp configured

排干连接的操作

下线节点前先把流量排干。 Kubernetes 的 drain 可以把 Pod 驱逐并迁移。

命令与示例输出如下。

代码语言:javascript
复制
$ kubectl drain node-node01 --ignore-daemonsets --delete-local-data
node/node01 cordoned
evicting pod myapp-abcde...
pod/myapp-abcde evicted
node/node01 drained

对外部负载均衡器亦同理。 先从后端池移出实例。 观察活跃连接为 0 再做维护。


数据库模式变更:分阶段、安全为王

数据库变更最容易翻车。 原则是小步快跑,保证可回滚。 步骤我常用三段走法:新增字段→双写回填→切读旧字段→删旧字段。

在线变更工具会把热表分片拷贝再切换。 gh-ost 的示例如下。

代码语言:javascript
复制
$ gh-ost \
  --user="ghuser" --password="ghpass" \
  --host="db-master" --database="mydb" --table="orders" \
  --alter="ADD COLUMN new_flag TINYINT(1) DEFAULT 0" \
  --allow-on-master --execute

模拟输出示例:

代码语言:javascript
复制
INFO Migrating table orders
INFO Ghost table created: _orders_gho
INFO Applying row-copy...
INFO Cut-over completed.

工具会逐步复制行并最小化锁定窗口。 不要在高峰期做大范围结构变更。


回滚要提前演练

每次发布都要有秒级回滚方案。 Kubernetes 支持 rollout undo。

命令和反馈示例:

代码语言:javascript
复制
$ kubectl rollout undo deployment/myapp -n prod
deployment.apps/myapp rolled back
$ kubectl rollout status deployment/myapp -n prod
deployment "myapp" successfully rolled out

回滚前要确认目标镜像、配置和 probe 都存在并可用。 回滚也要走健康检查流程,别跳过验证。


CI/CD 自动化要点(实务)

把发布流程写成 pipeline。 允许人工暂停和审查。 关键是把发布操作可审计、可回溯。

示例 GitLab CI 片段(占位):

代码语言:javascript
复制
deploy_canary:
  stage: deploy
  script:
    - kubectl apply -f k8s/canary.yaml -n prod
    - kubectl rollout status deployment/myapp-canary -n prod
  when: manual

手动触发能减少误发。 自动化里也要内置告警触发回滚的逻辑。


验证与流量测试

上线前做压力和功能验证。 对比错误率、延迟、连接数这三项。

一个常用的压力测试示例:

代码语言:javascript
复制
$ wrk -t2 -c200 -d30s http://myservice.prod/health
Running 30s test @ http://myservice.prod/health
  2 threads and 200 connections
Requests/sec: 12000
Latency  25ms

在 Canary 上重复同样测试。 对比指标差异决定是否放量。


常见陷阱(一句话一条)

改非兼容字段会出错。 probe 配置太宽松会把未就绪实例拉入流量池。 未排干连接就下线会造成错误。 忘记清理旧指标会误导后续分析。 缺回滚路径会拉长故障恢复时间。


最简单的安全发布脚本(示例)

这段脚本适合小团队快速发布并检查就绪。

代码语言:javascript
复制
#!/bin/bash
set -e

DEPLOY=deployment/myapp
NAMESPACE=prod
NEW_IMAGE=myapp:2025-09-01

echo "更新镜像..."
kubectl set image $DEPLOY mycontainer=$NEW_IMAGE -n $NAMESPACE

echo "等待 rollout..."
kubectl rollout status $DEPLOY -n $NAMESPACE

echo "检查 readiness..."
kubectl get pods -l app=myapp -n $NAMESPACE -o jsonpath='{range .items[*]}{.metadata.name} {.status.phase} {.status.containerStatuses[0].ready}{"\n"}{end}'

echo "发布完成"

输出如下。

代码语言:javascript
复制
更新镜像...
deployment.apps/myapp image updated
等待 rollout...
deployment "myapp" successfully rolled out
myapp-abcde Running true
myapp-fghij Running true
发布完成

这只是基础版。 复杂场景要接入流量网格、灰度控制和审计系统。

习惯性水结尾

评论区等你们!

老杨时间

这里老杨先声明一下,日常生活中大家都叫老杨波哥,跟辈分没关系,主要是岁数大了.就一个代称而已. 老杨的00后小同事老杨喊都是带哥的.张哥,李哥的. 但是这个称呼呀,在线下参加一些活动时.金主爸爸也这么叫就显的不太合适. 比如上次某集团策划总监,公司开大会来一句:“今个咱高兴!有请IT运维技术圈的波哥讲两句“ 这个氛围配这个称呼在互联网这行来讲就有点对不齐! 每次遇到这个情况老杨老杨周末浅聊服务器开在公网的那些坑老杨干了,你们随意!” 所以以后咱们改叫老杨,即市井又低调.还挺亲切,老杨觉得挺好.

运维X档案系列文章:

从告警到CTO:一个P0故障的11小时生死时速

企业级 Kubernetes 集群安全加固全攻略( 附带一键检查脚本)

看完别走.修行在于点赞、转发、在看.攒今世之功德,修来世之福报

老杨AI的号: 98dev

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT运维技术圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 先聊基本原则
  • 常见的发布策略与取舍
    • Blue-Green(蓝绿)
    • Canary(金丝雀)
    • Rolling Update(滚动升级)
  • Probe 与优雅下线
  • 排干连接的操作
  • 数据库模式变更:分阶段、安全为王
  • 回滚要提前演练
  • CI/CD 自动化要点(实务)
  • 验证与流量测试
  • 常见陷阱(一句话一条)
  • 最简单的安全发布脚本(示例)
  • 习惯性水结尾
  • 老杨时间
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档