Kubernetes 核心资源ReplicaSet 控制器详解

目 录

一、回顾与导读

[二、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------后者缺少更新与回滚能力。
相关推荐
μθημα2 小时前
Kubernetes 微服务网络实践:Service 与 Ingress 从入门到灰度发布
网络·微服务·kubernetes
众人皆醒我独醉2 小时前
Kubernetes GPU 调度与管理的完整机制——从节点上架到 Pod 拿到 GPU
面试·kubernetes·gpu
池以遇2 小时前
云原生——k8s中的微服务
微服务·云原生·kubernetes
分布式存储与RustFS2 小时前
用 RustFS 原生 CLI `rc` 管对象存储:从 alias 到 cp 的完整玩法
云原生·开源·对象存储·分布式存储·s3·rustfs·性能基准
梦之美丽生活2 小时前
【本地部署及docker部署】yolov8_detect
yolo·docker·容器
分布式存储与RustFS2 小时前
用 RPM/DEB 包在 Linux 上安装 RustFS:生产落地第一步
云原生·开源·对象存储·分布式存储·s3·rustfs·性能基准
^酸酸3 小时前
Kubernetes 运维实战:临时容器、端口转发与资源管理详解
运维·容器·kubernetes
奇特認3 小时前
kubernetes 微服务
微服务·容器·kubernetes
专注仿真4 小时前
Go操作Kubernetes API
贪心算法·golang·kubernetes