目 录
[二、ReplicaSet 的作用](#二、ReplicaSet 的作用)
[2.1 核心职责:维持指定数量的 Pod 副本](#2.1 核心职责:维持指定数量的 Pod 副本)
[2.2 故障自愈](#2.2 故障自愈)
[2.3 控制器工作原理](#2.3 控制器工作原理)
[三、ReplicaSet YAML 编写:Label 与 Selector](#三、ReplicaSet YAML 编写:Label 与 Selector)
[3.1 完整 YAML 结构](#3.1 完整 YAML 结构)
[3.2 Label 与 Selector 的关系](#3.2 Label 与 Selector 的关系)
[3.3 选择器的两种写法](#3.3 选择器的两种写法)
[3.4 选择器的重要特性](#3.4 选择器的重要特性)
[四、ReplicaSet 的扩缩容与删除行为](#四、ReplicaSet 的扩缩容与删除行为)
[4.1 扩缩容](#4.1 扩缩容)
[4.2 删除 ReplicaSet 的行为](#4.2 删除 ReplicaSet 的行为)
[4.3 扩缩容中的滚动更新差异](#4.3 扩缩容中的滚动更新差异)
[五、ReplicaSet 与 Deployment 的关系](#五、ReplicaSet 与 Deployment 的关系)
[5.1 Deployment 底层使用 ReplicaSet](#5.1 Deployment 底层使用 ReplicaSet)
[5.2 滚动更新背后的 RS 切换](#5.2 滚动更新背后的 RS 切换)
[5.3 观察底层 RS](#5.3 观察底层 RS)
[六、为什么生产环境几乎不直接操作 ReplicaSet](#六、为什么生产环境几乎不直接操作 ReplicaSet)
[6.1 核心原因:缺少更新与回滚](#6.1 核心原因:缺少更新与回滚)
[6.2 Deployment 是「带升级能力的 RS 封装」](#6.2 Deployment 是「带升级能力的 RS 封装」)
[6.3 什么时候才会直接接触 RS](#6.3 什么时候才会直接接触 RS)
[七、实操输出:ReplicaSet YAML 案例](#七、实操输出:ReplicaSet YAML 案例)
[7.1 完整案例](#7.1 完整案例)
[7.2 部署与验证](#7.2 部署与验证)
[7.3 动手实验:副本自愈](#7.3 动手实验:副本自愈)
一、回顾与导读
在上一篇中,我们深入了解了 Pod------Kubernetes 中最小的调度与运行单元。但生产环境中我们几乎不会直接创建单个 Pod,因为单 Pod 无法应对节点故障、流量增长等场景。真正在背后保障「始终有足够数量的 Pod 在运行」的,正是控制器(Controller)。
ReplicaSet(简称 RS)是其中最基本的副本控制器,也是 Deployment、StatefulSet 等高级控制器共用的「底层零件」。理解 ReplicaSet,就等于理解了 Kubernetes 声明式副本管理的核心逻辑。本文从作用、YAML、扩缩容、与 Deployment 的关系到生产实践,带你完整吃透这个底层控制器。
阅读建议:文中 YAML 基于 Kubernetes v1.27 编写,与你内网 5 节点集群版本一致,可直接参照修改后 apply 验证。
二、ReplicaSet 的作用
2.1 核心职责:维持指定数量的 Pod 副本
ReplicaSet 的核心目标只有一个------在任何时刻都维持声明数量的 Pod 副本。它通过一个不断循环的调谐(Reconcile)过程实现:
- 当前副本数 < 期望副本数:创建新的 Pod,补齐差额。
- 当前副本数 > 期望副本数:删除多余的 Pod,收缩到期望值。
- 副本数量等于期望值:什么都不做,保持稳定。
这种「声明期望状态,控制器持续趋近」的模型,正是 Kubernetes 声明式 API 的基石:你只需告诉系统想要几个副本,无需关心具体如何创建与回收。
2.2 故障自愈
当某个节点宕机或 Pod 被意外删除时,ReplicaSet 会立即感知副本数不足,并在其他可用节点上重建 Pod,实现自动自愈。这正是它比裸 Pod 可靠的根本原因。
2.3 控制器工作原理
ReplicaSet 控制器通过 selector 持续监视集群中符合标签条件的 Pod 数量,并与 spec.replicas 比对。副本的增删由控制器触发,Pod 的调度仍由 Scheduler 负责,两者分工协作。
三、ReplicaSet YAML 编写:Label 与 Selector
3.1 完整 YAML 结构
一个最简单的 ReplicaSet 由三大部分组成:副本数 spec.replicas、选择器 spec.selector、Pod 模板 spec.template。
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: web-rs
labels:
app: web
version: v1
spec:
replicas: 3 # 期望副本数
selector: # 选择器:控制哪些 Pod 归它管
matchLabels:
app: web
template: # Pod 模板:按此创建副本
metadata:
labels:
app: web # 必须与 selector 匹配!
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 80
3.2 Label 与 Selector 的关系
Label(标签)是挂在 Pod 上的一组 key-value 键值对,用于标识和分组;Selector(选择器)是 ReplicaSet 用来「认领」Pod 的匹配规则。两者配合,ReplicaSet 才知道哪些 Pod 归自己管理。
最关键的约束:template.metadata.labels 必须完整包含 selector 中声明的标签。如果两者不匹配,创建 ReplicaSet 会直接报错,因为控制器无法确认该创建怎样的 Pod 才属于自己。
3.3 选择器的两种写法
- matchLabels:精确匹配指定键值对,写法简洁,最常用。
- matchExpressions:基于表达式匹配,支持 In、NotIn、Exists、DoesNotExist 操作符,更灵活。
spec:
selector:
matchExpressions:
- key: app
operator: In
values: "web", "api"
- key: env
operator: Exists
3.4 选择器的重要特性
- 选择器创建后不可修改------若要调整匹配范围,只能删除重建。
- ReplicaSet 会接管所有符合 selector 的 Pod,即使这些 Pod 不是它创建的。这也是「扩容未声明 Pod」等奇技淫巧的根源。
- selector 通常是 matchLabels 与 matchExpressions 两者逻辑「与」的关系。
四、ReplicaSet 的扩缩容与删除行为
4.1 扩缩容
扩缩容的本质就是修改期望副本数,控制器会自动创建或回收 Pod。常见方式有两种:
- 声明式:编辑 YAML 修改 spec.replicas 后 kubectl apply,推荐用于版本管理。
- 命令式:直接用 kubectl scale 调整,适合临时扩容或快速缩容。
命令式扩缩容:副本数调整为 5
kubectl scale rs web-rs --replicas=5
声明式:修改 replicas 后 apply
kubectl apply -f web-rs.yaml
4.2 删除 ReplicaSet 的行为
默认情况下,kubectl delete rs 删除 ReplicaSet 时,会级联删除它管理的所有 Pod(--cascade 默认为 true)。这是最干净利落的清理方式。
删除 RS 及其管理的全部 Pod
kubectl delete rs web-rs
只删除 RS,保留已存在的 Pod(孤儿模式)
kubectl delete rs web-rs --cascade=orphan
注意:使用 --cascade=orphan 后,遗留的 Pod 不再受任何控制器管理,删除后不会被重建;后续如需接管,需手动创建一个匹配相同 selector 的 ReplicaSet。
4.3 扩缩容中的滚动更新差异
ReplicaSet 本身不具备滚动更新能力------它的扩缩容是「直接增删副本」,没有新旧版本灰度替换的过程。这一能力由 Deployment 在上层提供,这也直接引出下面的主题。
五、ReplicaSet 与 Deployment 的关系
5.1 Deployment 底层使用 ReplicaSet
Deployment 是更高层、面向用户的控制器,但它并不直接管理 Pod------它管理的是 ReplicaSet,由 ReplicaSet 再管理 Pod。完整层级关系如下:
Deployment(期望状态)→ 管理 ReplicaSet(副本数)→ 管理 Pod(实际运行),是一套典型的两层委托结构。
5.2 滚动更新背后的 RS 切换
当你对 Deployment 执行一次镜像版本更新时,Deployment 并不会原地修改现有 RS 的 Pod,而是创建一个新的 ReplicaSet,然后按策略逐步扩新缩旧,直到新 RS 接管全部副本:
- 创建新 RS(replicas 从 0 逐步增加)。
- 旧 RS 的副本数逐步减少至 0。
- 最终新版 RS 保留,旧版 RS 保留历史记录(便于回滚)。
这也解释了为什么每次更新 Deployment 都会产生一个新的 ReplicaSet:RS 的 YAML 是不可变的(selector 不可修改),版本迭代自然依赖「新建 RS」来完成。
5.3 观察底层 RS
通过下面的命令,可以清晰看到 Deployment 名下产生了多个 ReplicaSet:
kubectl get rs -l app=web
输出中 NAME 形如 web-7d5c9f6c89,后半段为 Pod 模板哈希,
每次更新模板都会生成新的哈希后缀
Deployment 的滚动更新策略(maxUnavailable、maxSurge)与回滚功能,全部基于「新旧 ReplicaSet 副本数的此消彼长」实现。
六、为什么生产环境几乎不直接操作 ReplicaSet
理解了 ReplicaSet 的机制后,一个重要问题随之而来:既然它已能维持副本数,为什么生产环境几乎从不直接使用 ReplicaSet,而是使用 Deployment?原因在于 ReplicaSet 缺失了面向生产的一整层能力:
|------------|--------------------|--------------------------------|
| 能力 | ReplicaSet | Deployment |
| 滚动更新 | 不支持,只能整体替换 | 支持,可灰度逐步替换 |
| 版本回滚 | 不支持 | 支持,可回滚到历史版本 |
| 暂停/恢复更新 | 不支持 | 支持 |
| 更新过程控制 | 无 | maxUnavailable / maxSurge 精细控制 |
| 副本管理 | 维持副本数 | 基于 RS 维持副本数(含更新) |
6.1 核心原因:缺少更新与回滚
直接修改 ReplicaSet 的 Pod 模板,不会触发任何滚动过程------它只会直接重建,导致服务短暂中断,且无法回滚。而 Deployment 在底层复用 ReplicaSet 的副本能力,同时补全了滚动更新、回滚、更新控制等生产必备能力。
6.2 Deployment 是「带升级能力的 RS 封装」
可以说,Deployment 就是为 ReplicaSet 叠加了「版本管理」这一层。日常声明式运维用 Deployment;只有在排查底层控制器行为、或做教学实验时,才会直接接触 ReplicaSet。
6.3 什么时候才会直接接触 RS
- 排查问题:观察滚动更新时新旧 RS 的副本变化。
- 精细控制:个别高级场景(如手动控制更新节奏)会直接操作 RS。
- 学习原理:理解副本控制的底层机制。
结论:生产环境用 Deployment,ReplicaSet 作为底层机制被自动管理,几乎无需人工直接操作。
七、实操输出:ReplicaSet YAML 案例
7.1 完整案例
下面是一个可直接 apply 的 ReplicaSet 案例:维持 3 个 nginx 副本,演示标签、选择器、探针与资源限制的组合写法。
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: demo-rs
labels:
app: demo
spec:
replicas: 3
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 15
periodSeconds: 15
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
7.2 部署与验证
kubectl apply -f demo-rs.yaml
kubectl get rs # 查看 RS 状态
kubectl get pods -l app=demo # 查看 RS 管理的 Pod
kubectl describe rs demo-rs # 查看控制器事件
7.3 动手实验:副本自愈
删除一个由 RS 管理的 Pod,观察控制器是否立即补齐副本:
kubectl delete pod <pod-name>
kubectl get pods -l app=demo --watch # 观察新 Pod 自动创建
验证后,可用 kubectl delete rs demo-rs 清理资源(会连带删除其管理的 Pod)。
八、读者收获
通过本文,你应已理解以下核心要点:
- ReplicaSet 的核心职责是「声明期望副本数,持续调谐趋近」,并具备故障自愈能力。
- 能独立编写 RS YAML,理解 Label 与 Selector 的匹配关系,以及 template 标签必须匹配 selector 的约束。
- 掌握 RS 的扩缩容方式与删除行为(默认级联删除、孤儿模式保留)。
- 理解「Deployment → ReplicaSet → Pod」的两层委托结构,以及滚动更新背后新旧 RS 切换的原理。
- 明白生产环境为何使用 Deployment 而非直接操作 ReplicaSet------后者缺少更新与回滚能力。