k8s-控制器

在学习了 Pod 的原理和一些基本使用后,发现在实际使用的时候并不会直接使用 Pod,而是会使用各种控制器来满足我们的需求,Kubernetes 中运行了一系列控制器来确保集群的当前状态与期望状态保持一致,它们就是 Kubernetes 的大脑。

例如,ReplicaSet 控制器负责维护集群中运行的 Pod 数量;Node 控制器负责监控节点的状态,并在节点出现故障时及时做出响应。总而言之,在 Kubernetes 中,每个控制器只负责某种类型的特定资源。

目录

ReplicaSet控制器

[ReplicaSet 的核心工作机制](#ReplicaSet 的核心工作机制)

如何操作ReplicaSet?

[1. 创建ReplicaSet](#1. 创建ReplicaSet)

[2. 弹性扩缩容](#2. 弹性扩缩容)

[3. 删除ReplicaSet](#3. 删除ReplicaSet)

Deployment控制器

[核心关系:Deployment → ReplicaSet → Pod](#核心关系:Deployment → ReplicaSet → Pod)

滚动更新详解

1.关键控制参数:

2.更新管控与版本回滚

3.进阶概念:更智能的部署策略

[StatefulSet 控制器](#StatefulSet 控制器)

[StatefulSet 的核心:为有状态应用提供身份和存储](#StatefulSet 的核心:为有状态应用提供身份和存储)

[理解有状态 vs. 无状态](#理解有状态 vs. 无状态)

[两个关键设计:Headless Service 与稳定存储](#两个关键设计:Headless Service 与稳定存储)

特性与工作流程

[什么时候该用 StatefulSet?](#什么时候该用 StatefulSet?)

[DaemonSet 控制器](#DaemonSet 控制器)

[DaemonSet 的核心思想:一节点,一守护](#DaemonSet 的核心思想:一节点,一守护)

四大典型应用场景

关键特性与工作原理


ReplicaSet控制器

理解ReplicaSet控制器是掌握Kubernetes自动化运维的关键一步。理解其"自动修复"和"扩缩容"的能力。

ReplicaSet 的核心工作机制

ReplicaSet(RS)的核心目标非常简单:确保与其标签选择器匹配的、正在运行的Pod副本数量,始终等于用户声明的期望数量 。这个过程就是Kubernetes中经典的控制循环 (Control Loop)或调谐循环(Reconcile Loop)。

它通过三个核心部分来实现这一目标:

|---------------------|--------------------------------------|-----------------------------------|---------------------------------------|
| 核心部分 | 作用 | 类比 | YAML |
| 副本数 Replicas | 定义期望的Pod副本数量,即"需要运行多少个完全一样的实例"。 | 餐厅经理计划今晚需要3名服务员上岗 | spec.replicas: 3 |
| 标签选择器Label Selector | 用于识别哪些Pod归自己管理。它会持续扫描集群中带有特定标签的Pod | 经理通过"岗位=服务员"这个标准来识别员工 | spec.selector.matchLabels: app: nginx |
| Pod模板 Pod Template | 当需要创建新的Pod时,就用这个模板来"生成"。它定义了Pod的完整规格 | 经理的"服务员岗位说明书",规定了服务员的制服、工作内容等 | spec.template下的完整Pod定义 |

如何操作ReplicaSet?

1. 创建ReplicaSet

使用你的YAML文件示例,通过命令即可创建:

kubectl apply -f nginx-rs.yaml

创建后,可以查看RS和Pod的状态:

kubectl get rs

kubectl get pods -l app=nginx # -l 用于按标签筛选Pod

2. 弹性扩缩容

调整副本数有两种常用方式:

  • 修改YAML文件 :将 spec.replicas的值改为2,然后重新执行 kubectl apply -f nginx-rs.yaml

  • 使用scale命令(更快捷):

kubectl scale rs nginx-rs --replicas=2

3. 删除ReplicaSet

  • 默认删除:会删除RS对象及其管理的所有Pod。

kubectl delete rs nginx-rs

  • 只删除控制器(保留Pod):使用此命令后,Pod将变成无人管理的"自主式Pod"。

kubectl delete rs nginx-rs --cascade=orphan

Deployment控制器

Deployment 是 Kubernetes 中用于管理应用部署的核心控制器,它通过管理 ReplicaSet 来实现强大的滚动更新版本控制功能,确保应用更新过程平滑、可控。

核心关系:Deployment → ReplicaSet → Pod

Deployment 并不直接创建和管理 Pod。它的工作模式是:

  • Deployment ​ 根据你定义的 Pod 模板创建并管理 ReplicaSet

  • ReplicaSet ​ 负责确保指定数量的 Pod​ 副本正常运行。

  • 当你更新 Pod 模板(如镜像版本)时,Deployment 会创建一个新的 ReplicaSet,并逐步将 Pod 从旧的 ReplicaSet 迁移到新的 ReplicaSet,直至所有 Pod 都符合新模板。

这种层级关系使得 Deployment 能够实现 ReplicaSet 不具备的复杂部署策略。

滚动更新详解

滚动更新是 Deployment 的核心价值所在,它通过精细的控制策略实现服务不中断的更新。

1.关键控制参数

  • maxSurge:允许超出期望副本数的最大 Pod 数量,用于在更新过程中启动新版本 Pod(例如,设置为 1 意味着最多可以有一个额外的 Pod)。

  • maxUnavailable:更新过程中允许不可用 Pod 的最大数量,用于控制旧版本 Pod 的下线速度(例如,设置为 1 意味着最多可以有一个 Pod 暂时无法服务)。

更新过程通常表现为:启动一个新版本 Pod → 终止一个旧版本 Pod → 循环此过程,直到所有 Pod 都替换为新版本。

你可以使用 kubectl rollout status deployment/<deployment-name>实时观察更新状态。

2.更新管控与版本回滚

Deployment 提供了强大的流程控制功能:

  • 暂停与继续 :你可以使用 kubectl rollout pause deployment/<deployment-name>暂停滚动更新,以便在部分 Pod 更新后进行验证。确认无误后,使用 kubectl rollout resume deployment/<deployment-name>继续更新过程。

  • 版本记录与回滚 :每次对 Deployment 的修改都会创建一个新的 修订版本 。你可以使用 kubectl rollout history deployment/<deployment-name>查看所有修订记录。如果更新后发现问题,可以迅速回滚到上一个版本 kubectl rollout undo deployment/<deployment-name>,或回滚到特定版本 kubectl rollout undo deployment/<deployment-name> --to-revision=<revision-number>。Kubernetes 正是通过保留旧 ReplicaSet的对象来实现回滚的。

3.进阶概念:更智能的部署策略

虽然原生 Deployment 的滚动更新已经很强大,但对于需要更精细控制流量或验证新版本稳定性的场景,还有更高级的策略:

  • 蓝绿部署:同时部署新版本和旧版本,测试通过后,一次性将流量从旧版本切换到新版本。

  • 金丝雀发布:仅将一小部分流量引导至新版本,观察一段时间确认稳定后,再逐步扩大新版本的流量比例。

这些策略通常需要借助 Argo Rollouts ​ 或 Flagger​ 等工具来实现,它们提供了基于指标的自动验证和更灵活的流量管理能力。

StatefulSet 控制器

StatefulSet 的核心:为有状态应用提供身份和存储

你可以把 StatefulSet 看作是专门用于管理有状态应用 的 Deployment。它的核心设计目标是确保每个 Pod 都有唯一的、稳定的身份标识和独立的、持久的存储。这与 Deployment 管理的、彼此完全等同的无状态 Pod 形成了鲜明对比。

下面的表格清晰地展示了它与 Deployment 的核心区别:

|------------|--------------------------------------------|----------------------------------------------------------------|
| 特性 | Deployment(无状态) | StatefulSet(有状态) |
| Pod 身份 | 所有 Pod 身份完全一致,名称随机(如 app-7df9cfc97d-xyz) | 每个 Pod 有唯一且稳定的名称,按顺序编号(如 web-0, web-1, web-2) |
| 网络标识 | 共享同一个 Service 的虚拟 IP(VIP),访问会随机转发到某个 Pod | 每个 Pod 有稳定的 DNS 名称:<pod-name>.<service-name>....,可直接访问特定 Pod |
| 存储 | 所有 Pod 共享存储卷(如果定义) | 每个 Pod 拥有独立的持久化存储卷(PV),Pod 重建后仍绑定原数据 |
| 启停顺序 | 并行创建和扩展,无固定顺序 | 顺序操作:按编号升序(0,1,2)创建/扩展,按降序(2,1,0)删除/缩容 |

理解有状态 vs. 无状态

  • 无状态服务(Stateless) :实例本身不保存需要持久化的数据,多个实例完全等价且可互换。例如,一个 Web 前端服务,其会话(Session)数据存储在外部的 Redis 中。适合用 Deployment 管理

  • 有状态服务(Stateful) :实例需要在本地磁盘保存持久化数据,且实例间存在依赖关系(如主从、主备)。例如,MySQL 数据库、ZooKeeper、Etcd 等。必须用 StatefulSet 管理,否则 Pod 重启或调度到新节点会导致数据丢失。

两个关键设计:Headless Service 与稳定存储

1. Headless Service(无头服务)

这是 StatefulSet 网络身份稳定的基础。它与普通 Service 的关键区别在于 clusterIP: None,即没有集群虚拟 IP

  • 作用:它不为 Pod 提供负载均衡,而是为每个 Pod 提供一个稳定的 DNS 域名。

  • 域名格式<pod-name>.<service-name>.<namespace>.svc.cluster.local

    • 例如,对于名为 web的 StatefulSet 和名为 nginx的 Headless Service,第一个 Pod(web-0)的域名是:web-0.nginx.default.svc.cluster.local。通过此域名可以直接解析到 web-0这个 Pod 的 IP 地址。

2. 稳定的持久化存储

这是 StatefulSet 数据不丢失的保障。通过 volumeClaimTemplates(卷申请模板)实现。

  • 工作原理 :当 StatefulSet 创建 Pod 时(如 web-0),会根据模板自动创建一个与之绑定的 PVC(PersistentVolumeClaim,持久化卷申请),命名格式为 <volumeClaimTemplateName>-<statefulsetName>-<ordinal>(如 www-web-0)。这个 PVC 会绑定到一个 PV(PersistentVolume,持久化卷)。

  • 核心优势 :当 Pod web-0被删除并重建后,新 Pod 仍然会绑定到原来那个 名为 www-web-0的 PVC,从而挂载原有的数据卷,实现了数据的持久化。

特性与工作流程

  1. 有序部署与伸缩

    • 创建 :必须等 web-0进入 RunningReady状态后,才会开始创建 web-1

    • 扩容 :扩容到 3 个副本时,会按顺序创建 web-2

    • 缩容:缩容时,则按逆序(2,1,0)终止 Pod。

  2. 更新策略

    • RollingUpdate:默认策略,逆序(从最大序号开始)滚动更新 Pod。

    • OnDelete:手动删除 Pod 后,才会用新模板创建。

    • Partition:可实现灰度发布,仅更新序号大于等于指定分区值的 Pod。

  3. 管理策略

    • OrderedReady:默认策略,遵循上述顺序性保证。

    • Parallel:并行启动或终止所有 Pod,不等待,适用于不需要严格顺序的集群。

什么时候该用 StatefulSet?

当你需要部署满足以下一个或多个条件的应用时:

  • 稳定的、唯一的网络标识

  • 稳定的、持久化的存储

  • 有序的部署、扩缩容和更新

  • 实例间有不平等关系(如主从、主备)。

典型场景:MySQL、PostgreSQL 等数据库集群,ZooKeeper、Etcd、Kafka、Redis Cluster 等中间件集群。

DaemonSet 控制器

Daemon,就是用来部署守护进程的,DaemonSet用于在每个 Kubernetes 节点中将守护进程的副本作为后台进程运行。

DaemonSet 的核心思想:一节点,一守护

DaemonSet ​ 的核心目标非常简单:确保集群中的每一个(符合条件的)节点上,都运行一个指定的 Pod 副本。就像一个尽职的"守护进程"一样。

你的图片完美诠释了这一点:

  • **最上层的 DaemonSet**​ 是控制器本身。

  • 中间层的 Pod ​ 是它管理的对象,每个节点对应一个 Pod

  • **底层的 Node**​ 是这些 Pod 运行的实际位置。

这种"一对一"的绑定关系,使得 DaemonSet 非常适合部署那些需要运行在所有节点上、提供节点级别服务的系统级组件

四大典型应用场景

以下场景是 DaemonSet 的"主场":

|----------|-----------------------------------|------------------------------------|
| 场景 | 典型应用 | 核心原因 |
| 存储插件 | ​glusterd, ceph | 每个节点都需要一个代理来提供或接入分布式存储 |
| 节点监控 | node-exporter(Prometheus) | 需要从每个节点收集硬件和操作系统级别的监控指标 |
| 日志收集 | fluentd, logstash, Filebeat | 需要在每个节点上运行一个代理,统一收集该节点上所有容器的日志 |
| 网络插件 | flannel, calico | 需要在每个节点上运行网络代理/守护进程,以管理 Pod 间的网络通信 |

关键特性与工作原理

  1. 自动绑定节点,绕过调度器

    • 这是 DaemonSet 与 Deployment/ReplicaSet 的根本区别 。DaemonSet 在创建 Pod 时,会直接指定 ​ Pod 运行在哪个节点上(通过 .spec.nodeName),完全不经过 Kubernetes 默认调度器

    • 这意味着:即使节点被标记为 unschedulable(不可调度),DaemonSet 的 Pod 依然可以部署上去。即使集群的调度器(kube-scheduler)还未启动,DaemonSet 的 Pod 也能被创建。

  2. 自动跟随节点生命周期

    • 节点加入集群​ -> 自动在该节点上创建一个 Pod。

    • 节点从集群移除​ -> 自动删除该节点上的 Pod。

    • 删除 DaemonSet 对象​ -> 删除它创建的所有 Pod。

  3. 如何保证"一节点一 Pod"

    • 控制器流程:DaemonSet 控制器持续监听集群中所有节点的变化。

      • 获取所有节点列表。

      • 根据 Pod 模板和节点的污点/容忍等配置,判断 Pod 是否运行在该节点上。

      • 检查节点上是否已有符合要求的 Pod。

        • 没有​ -> 创建。

        • 有且只有一个​ -> 保持。

        • 有多个​ -> 删除多余的(确保唯一)。

      • Pod 损坏时,在原节点上重建。

  4. 更新策略

    • RollingUpdate(默认):滚动更新。更新时,DaemonSet 会按节点顺序(默认随机)逐节点替换 Pod。

    • OnDelete:手动删除 Pod 后,DaemonSet 才会用新模板创建新的 Pod。适用于需要精确控制更新节奏的场景。

一句话总结 :当你需要在集群的每个节点上都运行一个相同的、提供节点级服务 的 Pod 时,就使用 DaemonSet

相关推荐
是火云哦2 小时前
打包你的开发环境:Docker 从入门到上瘾
运维·docker·容器
今晚打佬虎3 小时前
精准阻断 Docker 容器映射端口:流量路径诊断与 iptables 配置
运维·docker·容器
yuezhilangniao3 小时前
K8s优化-大规模集群优化-大规模K8S优化-性能优化速查表-优化顺序-先阻塞瓶颈再性能瓶颈
容器·性能优化·kubernetes
KubeSphere 云原生4 小时前
在 KubeSphere 上运行 Moltbot(Clawdbot):自托管 AI 助手的云原生实践
docker·云原生·容器
你才是臭弟弟4 小时前
生产环境开箱即用的“Flink + Iceberg 数据湖容器搭建”(Docker)
docker·容器·jar
_运维那些事儿4 小时前
GitLabCI-CD入门
运维·ci/cd·容器·云计算·k8s·运维开发
Clarence Liu5 小时前
k8s 1.35 使用kubeadm部署高可用集群
云原生·容器·kubernetes
boy快快长大5 小时前
Docker简单服务迁移
运维·docker·容器
qq_428389045 小时前
尚硅谷k8s自己实践步骤
spring cloud·kubernetes