工作负载、优雅退出与安全发布 Hands-on
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
本文缩写(英文全称与中文含义)
| 缩写 | 英文全称/名称 | 中文含义 |
|---|---|---|
| API | Application Programming Interface | 应用程序编程接口 |
| CPU | Central Processing Unit | 中央处理器 |
| GitOps | GitOps | 以 Git 保存期望状态、由自动化持续协调实际状态的运维方式 |
| IP | Internet Protocol | 网际协议;IP 地址是网络寻址标识 |
| LB | Load Balancer | 负载均衡器 |
| PDB | Pod Disruption Budget | Pod 中断预算,约束自愿驱逐 |
| PID | Process Identifier | 进程标识符 |
| SIGTERM | Termination Signal | 请求进程正常终止的信号 |
| SLO | Service Level Objective | 服务等级目标 |
前置:企业业务基线、隔离的真实 API/worker;完整发布流程见 渐进发布。
| 对象 | 场景 | 主要风险 |
|---|---|---|
| Deployment | 无状态 API/worker | 新旧版本共存、连接摘流 |
| StatefulSet | 需要稳定身份/独立卷 | 仲裁、卷和数据格式不能随镜像任意回滚 |
| DaemonSet | 节点 Agent | 特权与节点兼容,rollout 会影响全节点 |
| Job/CronJob | 迁移/批处理/周期任务 | 重试或重复调度;业务必须幂等 |
1. 实现正确的退出契约#
API 收到 SIGTERM 后停止接新请求、排空已有请求、关闭连接池;worker 停止取新消息、完成或释放租约后退出。PID 1 必须能收到信号,entrypoint 使用 exec。/healthz 检查自身,不能因共享数据库短暂故障让所有 Pod 一起重启。
基线已有三种探针及 60 秒 grace。实测入口摘流延迟后,按需给 API 增加短 preStop,它占用 grace 时间。以下保存 shutdown-patch.yaml,仅适用于镜像支持 /bin/sleep;distroless 应实现退出等待或使用目标版本支持的 sleep lifecycle action:
spec:
template:
spec:
terminationGracePeriodSeconds: 90
containers:
- name: api
lifecycle:
preStop:
exec:
command: [/bin/sleep, "10"]kubectl -n orders patch deployment orders-api --type=strategic --patch-file shutdown-patch.yaml
kubectl -n orders rollout status deployment/orders-api --timeout=5m2. 带业务流量滚动发布#
记录旧 digest,启动团队的建单/查询/幂等压测;下列 NEW_IMAGE 必须已在预生产验证:
OLD_IMAGE=$(kubectl -n orders get deployment orders-api -o jsonpath='{.spec.template.spec.containers[?(@.name=="api")].image}')
export NEW_IMAGE='REPLACE_REVIEWED_IMAGE_AT_DIGEST'
kubectl -n orders set image deployment/orders-api "api=$NEW_IMAGE"
kubectl -n orders rollout status deployment/orders-api --timeout=10m
kubectl -n orders get rs,pods,endpointslices检查 maxSurge 所需 CPU/内存/IP/卷容量、PDB、LB 健康检查与长连接。progressDeadlineSeconds 只报告失败,不自动回滚。新版本失败且数据格式向后兼容时:
kubectl -n orders set image deployment/orders-api "api=$OLD_IMAGE"
kubectl -n orders rollout status deployment/orders-api --timeout=10mGitOps 场景用 Git revert/sync 完成同一动作,避免控制器马上覆盖手工变更。
3. 周期对账任务#
提供真实对账镜像:/app/reconcile --business-date=previous-day,从 orders-runtime 读取预生产数据库;实现“业务日期+任务类型”唯一键及数据库锁。保存 reconcile.yaml,替换 digest:
apiVersion: batch/v1
kind: CronJob
metadata: {name: orders-reconcile, namespace: orders}
spec:
schedule: "15 2 * * *"
timeZone: Etc/UTC
concurrencyPolicy: Forbid
startingDeadlineSeconds: 600
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
jobTemplate:
spec:
backoffLimit: 2
activeDeadlineSeconds: 1800
ttlSecondsAfterFinished: 86400
template:
spec:
serviceAccountName: orders-api
automountServiceAccountToken: false
restartPolicy: Never
securityContext: {runAsNonRoot: true, seccompProfile: {type: RuntimeDefault}}
containers:
- name: reconcile
image: REPLACE_RECONCILE_IMAGE_AT_DIGEST
command: [/app/reconcile, --business-date=previous-day]
envFrom: [{secretRef: {name: orders-runtime}}]
resources:
requests: {cpu: 250m, memory: 256Mi}
limits: {cpu: "1", memory: 512Mi}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities: {drop: [ALL]}kubectl apply --dry-run=server -f reconcile.yaml
kubectl apply -f reconcile.yaml
JOB="orders-reconcile-$(date +%s)"
kubectl -n orders create job "$JOB" --from=cronjob/orders-reconcile
kubectl -n orders wait --for=condition=complete "job/$JOB" --timeout=31m
kubectl -n orders logs "job/$JOB"重复创建另一个 Job,对账输出一致且不重复记账;Forbid 只约束此 CronJob 的调度,不阻止手工 Job/其他集群重复执行。需暂停时设 .spec.suspend=true,已启动 Job 不会自动终止。
4. 配置与数据库变更#
ConfigMap/Secret 以环境变量注入后不会自动更新运行进程;通过新配置名/checksum 触发 rollout,或使用应用支持的文件热加载。数据库采用 expand→双版本兼容→迁移/对账→下次发布 contract;迁移只由一个受控 Job 执行,不让每个 API 副本并发迁移。
验收:发布与节点排空期间满足 SLO、长请求无异常截断、任务无静默丢失、重复请求无重复副作用。清理实验 CronJob 前保留任务结果和审计证据。
参考:Pod 终止、Deployment、CronJob。