Kubernetes 工作负载与发布方式
Kubernetes 工作负载
下文 YAML 是独立结构示例,未执行;demo/observability 命名空间、registry.example.com 镜像和 fast-rwo StorageClass 需由目标平台实际提供或替换,代码块不能串成部署项目。完整源码与资源见单副本计数项目。
控制器选型
| 对象 | 适用场景 | 不适用场景 |
|---|---|---|
| Pod | 最小调度单元、短期调试 | 直接管理长期服务 |
| Deployment | 无状态长期服务、滚动发布 | 稳定网络身份或有序存储 |
| StatefulSet | 数据库、队列等需要稳定身份/存储的应用 | 普通无状态 API |
| DaemonSet | 每节点日志、网络、存储代理 | 固定副本数的业务服务 |
| Job | 有完成语义的批处理 | 常驻进程 |
| CronJob | 周期性创建 Job | 严格实时调度或仅执行一次 |
| ReplicaSet | Deployment 的下层实现 | 通常不应直接创建 |
Pod:生命周期边界
Pod 中容器共享网络命名空间,可通过 localhost 通信;也可共享声明的 Volume。Pod 是短暂对象,重建后 UID 和 IP 可变化。
apiVersion: v1
kind: Pod
metadata:
name: web
namespace: demo
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.29.0
ports:
- name: http
containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256MiPod phase(Pending、Running、Succeeded、Failed、Unknown)是粗粒度摘要,不能代替容器状态和 Conditions。Running Pod 也可能未 Ready 或持续重启。
Init Container 与 Sidecar
- Init Container 按顺序运行并成功退出后,普通容器才开始。
- 使用
restartPolicy: Always的原生 Sidecar Init Container 可先启动并伴随 Pod 生命周期运行。 - Sidecar 适合代理、适配和辅助功能,但会增加资源、启动/终止顺序与排障复杂度。
- 不要用 Init Container 无限等待脆弱依赖;为等待逻辑设置超时并让失败可见。
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: demo
spec:
replicas: 3
revisionHistoryLimit: 5
minReadySeconds: 10
progressDeadlineSeconds: 600
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
terminationGracePeriodSeconds: 30
containers:
- name: web
image: registry.example.com/web:2.4.1
ports:
- name: http
containerPort: 8080
readinessProbe:
httpGet:
path: /readyz
port: http
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
memory: 512MimaxUnavailable: 0 不代表绝对零中断:节点故障、应用错误、容量不足和连接终止仍可能造成中断。需结合多副本、反亲和/拓扑分布、PDB、探针和优雅关闭。
kubectl -n demo apply -f deployment.yaml
kubectl -n demo rollout status deployment/web --timeout=5m
kubectl -n demo rollout history deployment/webRecreate 与 RollingUpdate
RollingUpdate:新旧 ReplicaSet 并存一段时间,应用和数据库必须兼容滚动窗口。Recreate:先删旧 Pod 再建新 Pod,会中断服务,适合无法并行运行的少数应用。- 蓝绿/金丝雀通常需要多个 Deployment 配合 Service、Gateway/Ingress 或渐进交付控制器,原生 Deployment 不提供按比例流量管理。
StatefulSet
StatefulSet 提供稳定序号、网络身份和 volumeClaimTemplates:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: db
namespace: demo
spec:
serviceName: db-headless
replicas: 3
podManagementPolicy: OrderedReady
updateStrategy:
type: RollingUpdate
selector:
matchLabels:
app: db
template:
metadata:
labels:
app: db
spec:
terminationGracePeriodSeconds: 60
containers:
- name: db
image: registry.example.com/db:16.4
volumeMounts:
- name: data
mountPath: /var/lib/db
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
memory: 2Gi
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ReadWriteOnce]
storageClassName: fast-rwo
resources:
requests:
storage: 100Gi还需同名 Headless Service(clusterIP: None)。删除或缩容 StatefulSet 默认不会自动删除 PVC,以保护数据;必须规划保留策略、备份和回收。
partition 可分段更新,但操作不当会让版本长期分裂。数据库升级还要遵循数据库自身的成员、复制和 Schema 规则,不能只依赖 StatefulSet 顺序。
DaemonSet
DaemonSet 保证符合选择条件的每个节点运行一个 Pod,常用于节点级代理:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-agent
namespace: observability
spec:
selector:
matchLabels:
app: node-agent
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 10%
template:
metadata:
labels:
app: node-agent
spec:
containers:
- name: agent
image: registry.example.com/node-agent:1.8.0
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
memory: 256Mi访问宿主机路径、PID/网络命名空间或特权模式会显著扩大攻击面。节点代理应使用最小挂载和权限,并单独审计。
Job
apiVersion: batch/v1
kind: Job
metadata:
name: report-20260812
namespace: demo
spec:
backoffLimit: 3
activeDeadlineSeconds: 1800
ttlSecondsAfterFinished: 86400
template:
spec:
restartPolicy: Never
containers:
- name: report
image: registry.example.com/report:4.2.0
args: ["generate", "--date=2026-08-12"]
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
memory: 1GiJob 可能重试或在节点故障时产生重复执行,业务必须幂等。restartPolicy 只能是 Never 或 OnFailure。并行任务可使用 completions、parallelism 和 Indexed Job;对外部系统的唯一性不能仅依赖 Pod 名。
CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-report
namespace: demo
spec:
schedule: "15 2 * * *"
timeZone: "Asia/Shanghai"
concurrencyPolicy: Forbid
startingDeadlineSeconds: 900
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: Never
containers:
- name: report
image: registry.example.com/report:4.2.0- CronJob 调度是近似的,不保证严格一次;任务必须幂等。
Forbid跳过重叠,Replace会替换旧 Job,Allow允许并发。- 明确
timeZone,避免控制面时区和夏令时歧义。 - 临时暂停用
spec.suspend: true,恢复时关注错过的执行和 deadline。
PodDisruptionBudget
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web
namespace: demo
spec:
minAvailable: 2
selector:
matchLabels:
app: webPDB 只约束通过 Eviction API 的自愿中断,如 drain;不防节点宕机、Pod 崩溃或直接删除。minAvailable 太严格会阻塞节点维护,副本数、容量和 PDB 必须一起设计。
工作负载检查
kubectl -n demo get deployment,statefulset,daemonset,job,cronjob
kubectl -n demo get pods -o wide
kubectl -n demo get pod <pod> -o jsonpath='{.metadata.ownerReferences}{"\n"}'
kubectl -n demo get pdb生产工作负载至少明确:镜像版本、资源请求、健康检查、终止时限、安全上下文、拓扑目标、可用性预算、日志方式和变更负责人。
识别 Pod 就绪与故障状态
补充来源:jekyall_blog 的 Kubernetes Pod、Kubernetes Deployment 笔记(2023-11-24)。基础定义已合并到上文。
kubectl get pods 的 READY 列以 X/Y 显示已就绪与容器总数。例如 0/1 表示容器尚未就绪,2/2 表示两个容器均已就绪。Running 只是 Pod 阶段,仍需结合 Ready 条件、容器状态、事件和日志判断服务是否可接流量。
| 显示状态 | 优先检查 |
|---|---|
| Pending | 调度事件、requests、污点、亲和性和 PVC |
| ContainerCreating | 镜像、初始化、卷挂载和节点资源 |
| ErrImagePull / ImagePullBackOff | 镜像名称、标签、仓库凭据和节点到仓库的网络 |
| CrashLoopBackOff | 上次容器日志、退出码、入口命令、配置、探针和 OOM |
| Failed / Unknown | 容器终止原因、节点通信及控制面状态 |
CrashLoopBackOff、ContainerCreating 和 ImagePullBackOff 是常见显示状态,不是 Pod phase 的新增取值。完整诊断步骤见排障手册。
滚动、金丝雀与蓝绿发布
| 方式 | 核心过程 |
|---|---|
| 滚动发布 | 分批替换实例,逐步完成版本更新 |
| 金丝雀发布 | 先让少量实例或流量使用新版本,验证后扩大范围 |
| 蓝绿发布 | 同时保留新旧环境,通过流量切换完成发布 |
Deployment 的 maxSurge 和 maxUnavailable 控制滚动更新时额外副本数与不可用副本数。原稿把固定值直接对应三种发布方式,缺少工作负载和容量条件;这些参数本身不能定义金丝雀流量分配或蓝绿环境切换。
继续阅读
- 命令
- 故障排查
- 故障排查