mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1896 字
5 分钟
Kubernetes 工作负载:从 Pod 到 Deployment
2023-06-13

当你需要在 Kubernetes 上运行一个应用时,直接创建 Pod 是最简单的方式——但 Pod 不会自动重启、不会自动扩缩、不会滚动更新。生产环境中,你需要更高级的工作负载管理器来确保应用的可靠性。

Kubernetes 提供了多种工作负载类型,每种都有明确的设计意图:Deployment 管理无状态应用,StatefulSet 管理有状态应用,DaemonSet 确保每个节点运行一个实例,Job 处理一次性任务。理解它们的区别和适用场景,是正确使用 Kubernetes 的关键。

一、Pod 生命周期与探针#

Pod 是所有工作负载的基础。理解 Pod 的生命周期和健康检查机制,是掌握上层工作负载的前提。

1.1 Pod 的启动流程#

flowchart TB A["Pod 创建"] --> B["Init 容器依次执行"] B --> C["主容器启动"] C --> D["PostStart Hook"] D --> E["Startup Probe<br/>启动探针"] E -->|"通过"| F["Liveness/Readiness Probe<br/>存活/就绪探针"] E -->|"失败"| G["容器被杀并重启"] F -->|"Liveness 失败"| G F -->|"Readiness 通过"| H["Pod 加入 Service Endpoints"] F -->|"Readiness 失败"| I["Pod 从 Endpoints 移除"] style A fill:#e3f2fd,stroke:#1565c0 style H fill:#c8e6c9,stroke:#2e7d32 style G fill:#ffcdd2,stroke:#c62828

Init 容器用于 Pod 启动前的初始化工作——等待依赖服务就绪、下载配置文件、注册服务发现。它们按顺序执行,全部成功后主容器才启动。

1.2 三种探针#

探针目的失败后果典型配置
Startup Probe判断容器是否已启动重启容器慢启动应用(periodSeconds: 10, failureThreshold: 30
Liveness Probe判断容器是否健康运行重启容器HTTP 健康检查或进程存活检查
Readiness Probe判断容器是否可接收请求从 Service Endpoints 移除检查依赖是否就绪
spec:
containers:
- name: my-app
image: my-app:v1
startupProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
failureThreshold: 30 # 最多等待 300 秒启动
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 15
failureThreshold: 3 # 连续 3 次失败则重启
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
failureThreshold: 3 # 连续 3 次失败则移出 Endpoints
Tip

Startup Probe 是 Kubernetes 1.18 引入的,专门解决慢启动应用的问题。在此之前,开发者只能通过设置较长的 initialDelaySeconds 来等待容器启动,但这会导致快速启动的应用也要等待相同时间。Startup Probe 启用后,Liveness Probe 只在 Startup Probe 成功后才开始检查,两者互不干扰。

1.3 重启策略#

策略说明适用工作负载
Always容器退出后总是重启Deployment、ReplicaSet、StatefulSet
OnFailure只有非零退出码才重启Job
Never从不重启CronJob(一次性任务)

二、ReplicaSet:副本数量管理#

ReplicaSet 确保指定数量的 Pod 副本始终运行。它是 Deployment 的底层实现,通常不直接使用。

apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-rs
spec:
replicas: 3 # 期望副本数
selector:
matchLabels:
app: nginx # 必须匹配 Pod 的 Label
template: # Pod 模板
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25

ReplicaSet 控制器的工作逻辑:

  1. 计算当前匹配 selector 的 Pod 数量
  2. 如果数量 < replicas:按 template 创建新 Pod
  3. 如果数量 > replicas:按优先级删除多余 Pod
  4. 如果 Pod 失败退出:自动重建
Note

ReplicaSet 的 selector 必须匹配 template.metadata.labels,否则 ReplicaSet 无法管理自己创建的 Pod。Kubernetes API 会验证这一约束。

三、Deployment:滚动更新与回滚#

Deployment 是最常用的工作负载类型。它在 ReplicaSet 之上增加了版本管理和滚动更新能力。

3.1 Deployment 与 ReplicaSet 的关系#

graph TB DEPLOY["Deployment<br/>replicas: 3"] RS1["ReplicaSet v1<br/>nginx:1.24<br/>Pod: 0 个"] RS2["ReplicaSet v2<br/>nginx:1.25<br/>Pod: 3 个"] DEPLOY --> RS1 DEPLOY --> RS2 style DEPLOY fill:#e3f2fd,stroke:#1565c0 style RS1 fill:#ffcdd2,stroke:#c62828 style RS2 fill:#c8e6c9,stroke:#2e7d32

每次更新 Deployment 的 Pod 模板(如修改 image 版本),Deployment 会创建一个新的 ReplicaSet,并逐步将流量从旧 ReplicaSet 迁移到新 ReplicaSet。旧 ReplicaSet 不会被删除——它保留着回滚所需的历史版本。

3.2 滚动更新策略#

spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 更新时最多多创建 1 个 Pod(可以是百分比)
maxUnavailable: 0 # 更新时最多允许 0 个 Pod 不可用
参数说明默认值
maxSurge更新过程中超出期望副本数的最大 Pod 数25%
maxUnavailable更新过程中不可用 Pod 的最大数量25%

maxSurge=1, maxUnavailable=0 的更新过程:

flowchart LR S1["3 Pod (v1)"] --> S2["4 Pod (3v1+1v2)"] S2 --> S3["4 Pod (2v1+2v2)"] S3 --> S4["4 Pod (1v1+3v2)"] S4 --> S5["3 Pod (v2)"] style S1 fill:#ffcdd2 style S5 fill:#c8e6c9

整个过程始终保持至少 3 个可用 Pod,服务不中断。

3.3 回滚#

# 查看 Deployment 的历史版本
kubectl rollout history deployment/nginx
# 回滚到上一个版本
kubectl rollout undo deployment/nginx
# 回滚到指定版本
kubectl rollout undo deployment/nginx --to-revision=2
# 查看回滚状态
kubectl rollout status deployment/nginx

Deployment 默认保留 10 个历史 ReplicaSet(通过 revisionHistoryLimit 控制)。回滚时,Deployment 将旧 ReplicaSet 的副本数恢复到期望值,同时缩容当前 ReplicaSet。

四、StatefulSet:有状态应用#

Deployment 适合无状态应用——任何 Pod 都可以处理任何请求,Pod 之间没有区别。但有状态应用(如数据库、消息队列)需要稳定的网络标识、持久化存储和有序的部署/终止。

4.1 StatefulSet 提供的保证#

保证说明Deployment 是否提供
稳定网络标识Pod 名称有序且固定(statefulset-name-0, -1, -2
稳定持久化存储每个 Pod 绑定独立的 PVC,Pod 重建后重新挂载同一 PVC
有序部署Pod 按 0→1→2 的顺序创建,前一个 Ready 后才创建下一个
有序终止Pod 按 2→1→0 的逆序删除
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql # 必须指定 Headless Service
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumeClaimTemplates: # 每个 Pod 自动创建独立 PVC
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi

StatefulSet 必须配合 Headless Service 使用。Headless Service 的 clusterIPNone,DNS 查询直接返回每个 Pod 的 IP,而不是 Service VIP:

apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
clusterIP: None # Headless Service
selector:
app: mysql
ports:
- port: 3306

Pod 的 DNS 名称格式为 mysql-0.mysql.default.svc.cluster.local,无论 Pod 重建多少次,这个名称始终指向同一个 PVC 和同一个数据。

4.2 StatefulSet vs Deployment#

场景选择原因
Web 服务、API 服务Deployment无状态,Pod 之间无区别
MySQL 主从集群StatefulSet主从角色不同,需要稳定标识和持久化
Redis ClusterStatefulSet每个节点有独立数据,需要稳定网络标识
Kafka 集群StatefulSetBroker ID 需要固定,日志目录需要持久化

五、DaemonSet:每个节点一个 Pod#

DaemonSet 确保每个(或特定)Node 上运行一个 Pod 副本。典型用途:

  • 日志收集:每个节点运行 Fluentd/Filebeat
  • 监控代理:每个节点运行 Prometheus Node Exporter
  • 网络插件:每个节点运行 Calico/Cilium CNI agent
  • 存储插件:每个节点运行 CSI node driver
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
tolerations: # 容忍 Master 节点的污点
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
containers:
- name: node-exporter
image: prom/node-exporter
ports:
- containerPort: 9100
hostPort: 9100 # 暴露到宿主机端口

当新 Node 加入集群时,DaemonSet 自动在该 Node 上创建 Pod;当 Node 移除时,Pod 自动被回收。replicas 字段不需要指定——副本数等于匹配的 Node 数量。

六、Job 与 CronJob:批处理任务#

Job 用于运行一次性任务,确保任务成功完成。CronJob 用于定时执行 Job。

6.1 Job#

apiVersion: batch/v1
kind: Job
metadata:
name: data-migration
spec:
completions: 5 # 需要成功完成 5 次
parallelism: 2 # 最多 2 个 Pod 并行执行
backoffLimit: 6 # 最多重试 6 次
template:
spec:
restartPolicy: OnFailure # Job 使用 OnFailure 或 Never
containers:
- name: migrate
image: my-migrate-tool
参数说明
completions需要成功完成的 Pod 总数
parallelism同时运行的 Pod 最大数量
backoffLimit失败重试上限,超过后 Job 标记为 Failed

6.2 CronJob#

apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-backup
spec:
schedule: "0 2 * * *" # 每天 2:00 执行
concurrencyPolicy: Forbid # 禁止并发执行
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: backup
image: my-backup-tool
concurrencyPolicy说明
Allow允许并发执行(默认)
Forbid禁止并发,上次未完成则跳过本次
Replace替换上次未完成的 Job

七、HPA:自动扩缩容#

Horizontal Pod Autoscaler(HPA)根据指标自动调整 Deployment/StatefulSet 的副本数。

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nginx-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50 # CPU 使用率超过 50% 时扩容

HPA 的扩缩逻辑:

  • 当前 CPU 使用率 > 50%:增加副本数
  • 当前 CPU 使用率 < 50%:减少副本数
  • 副本数变化有冷却期(默认 5 分钟),防止频繁抖动
# 查看 HPA 状态
kubectl get hpa
# 输出示例
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
nginx-hpa Deployment/nginx 45%/50% 2 10 3 5m
Note

HPA 需要集群中安装 Metrics Server(kubectl top pods 可用时 HPA 才能工作)。对于自定义指标(如 QPS、队列长度),需要配置 Prometheus Adapter。

总结#

工作负载设计意图关键特性典型场景
Pod最小调度单元容器共享网络/存储手动调试、单次任务
ReplicaSet副本数量管理维持固定副本数Deployment 的底层实现
Deployment无状态应用管理滚动更新、回滚、版本管理Web 服务、API 服务
StatefulSet有状态应用管理稳定标识、持久化、有序部署数据库、消息队列
DaemonSet节点守护进程每个 Node 一个 Pod日志收集、监控代理
Job一次性任务确保成功完成数据迁移、批处理
CronJob定时任务Cron 表达式调度定时备份、报表生成
HPA自动扩缩容基于指标调整副本数流量波动大的服务

下一章将深入 Kubernetes 的服务发现与网络基础——Service 如何为 Pod 提供稳定访问入口,Ingress 如何将外部流量引入集群。

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

Kubernetes 工作负载:从 Pod 到 Deployment
https://blog.souloss.com/posts/kubernetes/k8s-workload/
作者
Souloss
发布于
2023-06-13
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

相关文章 智能推荐
1
Kubernetes 安全:RBAC、Pod 安全与网络策略
云原生 深入 Kubernetes 安全体系——RBAC 权限模型(Role/ClusterRole/RoleBinding/ClusterRoleBinding)、ServiceAccount 身份管理、Pod 安全标准与 Pod Security Admission、SecurityContext 容器安全、NetworkPolicy 网络隔离、Secret 加密与外部密钥管理,构建纵深防御的安全架构。
2
Kubernetes 核心概念:Pod、Node 与控制面
云原生 深入 Kubernetes 核心概念——从控制面组件(API Server、etcd、Scheduler、Controller Manager)到工作节点组件(kubelet、kube-proxy),再到 Pod、Node、Namespace、Label 与 Selector 的设计哲学,理解声明式 API 与控制器模式的协作机制。
3
深度剖析:一个请求从客户端到 Pod 的完整路径
云原生 从底层视角追踪一个 HTTP 请求从外部客户端经过 Ingress Controller、Service、kube-proxy、iptables/IPVS 规则,最终到达 Pod 容器的完整数据路径——理解每一层网络转换、DNAT、conntrack 和路由决策的细节。
4
深度剖析:创建一个 Deployment 时,Kubernetes 底层发生了什么
云原生 从底层视角追踪创建一个 Deployment 的完整流程——kubectl → API Server 认证/鉴权/准入控制 → etcd 持久化 → Deployment Controller 创建 ReplicaSet → ReplicaSet Controller 创建 Pod → Scheduler 调度 → kubelet 启动容器,理解声明式 API 与控制器模式的协作机制。
5
Kubernetes 配置与存储:ConfigMap、Secret 与 PV/PVC
云原生 深入 Kubernetes 配置与存储体系——ConfigMap 配置管理、Secret 敏感信息、Volume 存储卷、PV/PVC 持久化存储、StorageClass 动态供给,理解配置与代码分离的设计哲学和存储的完整生命周期。