k8s 之调度基础

一、Deployment 无状态调度

1.1 关系

Deployment 与 ReplicaSet 的核心关系

Deployment:一般用于部署公司的无状态服务,这个也是最常用的控制

器,因为企业内部现在都是以微服务为主,而微服务实现无状态化也是最佳

实践,可以利用Deployment的高级功能做到无缝迁移、自动扩容缩容、自动

灾难恢复、一键回滚等功能

  1. Replication Controller:Replication Controller可以确保Pod副本数达到期望值,也就是RC定义的数量。换句话说,Replication Controller可以确保一个Pod或一组同类Pod总是可用的。

ReplicaSet 是 支 持 基 于 集 合 的 标 签 选 择 器 的 下 一 代 Replication

Controller , 它 主 要 用 作 Deployment 协 调 创 建 、 删 除 和 更 新 Pod , 和Replication Controller唯一的区别是,ReplicaSet支持标签选择器

1、Deployment 与 ReplicaSet 的核心关系

你想理清 Deployment、Replication Controller(RC)、ReplicaSet(RS)和 Pod 这四者之间的创建与管理关系,核心是要区分 RC 和 RS 的定位,以及 Deployment 如何通过它们管控 Pod。

2.核心关系总览

首先明确一个关键前提:Replication Controller(RC)是 Kubernetes 早期的 Pod 副本控制器,ReplicaSet(RS)是 RC 的升级版,而

Deployment 是 RS 的控制器(不会直接管理 RC)。四者的核心关系链路是:

复制代码
Deployment → ReplicaSet (取代了 Replication Controller) → Pod

Deployment 不会创建 RC(仅兼容但不主动创建),只会创建 RS;RS 作为 RC 的替代方案,是管理 Pod 副本的核心,具体拆解如下:

  1. Replication Controller(RC):被淘汰的 "前辈"
  • RC 是 Kubernetes 最早的 Pod 副本控制器,核心功能是保证指定数量的 Pod 副本始终运行,支持基于标签的 Pod 选择。
  • 关键缺陷:仅支持等值匹配的标签选择器(如 app=nginx),不支持集合匹配(如 app in (nginx, apache)),灵活性差。
  • Deployment 与 RC 的关系:Deployment 是为 RS 设计的,不会主动创建 RC;如果集群中存在旧的 RC,Deployment 也不会管理它,仅能通过手动方式迁移到 RS/Deployment
  1. ReplicaSet(RS):RC 的 "升级版"+ Deployment 的 "执行层"
  • RS 完全兼容 RC 的所有功能,且新增了集合型标签选择器(更灵活),是 Kubernetes 目前推荐的 Pod 副本控制器。
  • Deployment 是 RS 的 "上层控制器",所有对 Pod 的副本管理、版本更新,都通过创建 / 删除 / 扩缩 RS 来实现,不会直接操作 Pod:
    • 首次创建 Deployment:自动生成一个 RS(命名格式:deployment名-随机哈希),由该 RS 创建指定数量的 Pod
    • 更新 Deployment(如改镜像、资源):Deployment 不会修改现有 RS,而是新建一个 RS,并逐步将 Pod 从旧 RS 迁移到新 RS(滚动更新)
    • 回滚 Deployment:Deployment 会缩容新 RS 的 Pod 数到 0,重新扩容旧 RS 的 Pod 数到目标值
  1. 实操验证:看 Deployment 只创建 RS 不创建 RC

    1. 创建一个 Deployment

    kubectl create deployment nginx-deploy --image=nginx:1.21 --replicas=3

    2. 查看 Deployment、RS、RC、Pod

    kubectl get deploy,rs,rc,pod -l app=nginx-deploy

    输出示例(仅能看到 Deployment、RS、Pod,无 RC)

    NAME READY UP-TO-DATE AVAILABLE AGE
    deployment.apps/nginx-deploy 3/3 3 3 10s

    NAME DESIRED CURRENT READY AGE
    replicaset.apps/nginx-deploy-7f987d6b9 3 3 3 10s

    NAME READY STATUS RESTARTS AGE
    pod/nginx-deploy-7f987d6b9-2x89k 1/1 Running 0 10s
    pod/nginx-deploy-7f987d6b9-5m78z 1/1 Running 0 10s
    pod/nginx-deploy-7f987d6b9-8s27k 1/1 Running 0 10s

    3. 更新 Deployment 镜像,看是否新建 RS

    kubectl set image deployment/nginx-deploy nginx=nginx:1.22
    kubectl get rs -l app=nginx-deploy

    输出示例(新增一个 RS,旧 RS 保留)

    NAME DESIRED CURRENT READY AGE
    nginx-deploy-7f987d6b9 0 0 0 20s # 旧 RS
    nginx-deploy-8d76f897c 3 3 3 5s # 新 RS

核心区别:RC vs RS(为什么 RS 取代 RC)

3.总结

  1. 层级核心:Deployment 只管理 ReplicaSet(RS),不创建 / 管理 Replication Controller(RC);RS 取代 RC 成为管控 Pod 副本的核心,直接创建和维护 Pod。
  2. 版本逻辑:Deployment 通过 "新建 RS + 缩容旧 RS" 实现 Pod 版本更新,旧 RS 保留用于回滚,全程不直接操作 Pod。
  3. RC 定位:RC 是早期产物,功能单一且不灵活,已被 RS 完全取代,与 Deployment 无关联,仅用于兼容旧集群。

1.2 清单示例

Replication Controller

ReplicaSet 示例


Replication Controller和ReplicaSet的创建、删除和Pod并无太大区
别 , Replication Controller 目 前 几 乎 已 经 不 在 生 产 环 境 中 使 用 ,ReplicaSet 也 很 少 单 独 被 使 用 , 都 是 使 用 更 高 级 的 资 源 Deployment 、DaemonSet、StatefulSet管理Pod。

Deployment 示例

从Kubernetes 1.16版本开始,彻底废弃了其他的APIVersion,只能使用

apps/v1,1.16以下的版本可以使用extension等。

1.3 清单使用命令

Deployment 创建

使用kubectl create创建此Deployment

复制代码
kubectl create -f dp-nginx.yaml
deployment.apps/nginx-deployment created

查看此Deployment的状态:

使用kubectl get或者kubectl describe查看此Deployment的状态:

NAME:集群中Deployment的名称。

  • DESIRED:应用程序副本数。
  • CURRENT:当前正在运行的副本数。
  • UP-TO-DATE:显示已达到期望状态的被更新的副本数。
  • AVAILABLE:显示用户可以使用的应用程序副本数,当前为1,因为
    部分Pod仍在创建过程中。
  • AGE:显示应用程序运行的时间。

查看Deployment创建的状态

复制代码
kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out

更新Deployment

当且仅当Deployment的Pod模板(即.spec.template)更改时,才会触发

Deployment更新,例如更改内存、CPU配置或者容器的image。

回滚Deployment

当更新的版本不稳定或配置不合理时,可以对其进行回滚操作,假设我

们又进行了几次更新(此处以更新镜像版本触发更新,更改配置效果类

似)

复制代码
kubectl set image deployment nginx-deployment
nginx=dotbalo/canary:v1 --record
# kubectl set image deployment nginx-deployment
nginx=dotbalo/canary:v2 --record

使用kubectl rollout history查看更新历史:

查看Deployment某次更新的详细信息,使用--revision指定某次更新的

版本号

暂停和恢复Deployment更新

更新Deployment的注意事项

历史版本清理策略:

在默认情况下,revision保留10个旧的ReplicaSet,其余的将在后台进

行垃圾回收,可以在.spec.revisionHistoryLimit设置保留ReplicaSet的个

数。当设置为0时,不保留历史记录。

更新策略:

  • .spec.strategy.type==Recreate:表示重建,先删掉旧的Pod,再
    创建新的Pod。
  • .spec.strategy.type==RollingUpdate:表示滚动更新,可以指定
    maxUnavailable和maxSurge来控制滚动更新过程。
    ◆ .spec.strategy.rollingUpdate.maxUnavailable:指定在回滚
    更新时最大不可用的Pod数量,可选字段,默认为25%,可以设
    置为数字或百分比,如果maxSurge为0,则该值不能为0。
    ◆ .spec.strategy.rollingUpdate.maxSurge:可以超过期望值的
    最大Pod数,可选字段,默认为25%,可以设置成数字或百分
    比,如果maxUnavailable为0,则该值不能为0。
  • Ready策略:
    .spec.minReadySeconds是可选参数,指定新创建的Pod应该在没有任何
    容器崩溃的情况下视为Ready(就绪)状态的最小秒数,默认为0,即一旦被创建就视为可用,通常和容器探针连用。

二、StatefulSet 无状态调度

StatefulSet的基本概念

StatefulSet主要用于管理有状态应用程序的工作负载API对象。比如在

生产环境中,可以部署ElasticSearch集群、MongoDB集群或者需要持久化的

RabbitMQ集群、Redis集群、Kafka集群和ZooKeeper集群等

一般StatefulSet用于有以下一个或者多个需求的应用程序:

  • 需要稳定的独一无二的网络标识符。
  • 需要持久化数据。
  • 需要有序的、优雅的部署和扩展。
  • 需要有序的自动滚动更新。

如果应用程序不需要任何稳定的标识符或者有序的部署、删除或者扩
展 , 应 该 使 用 无 状 态 的 控 制 器 部 署 应 用 程 序 , 比 如 Deployment 或 者
ReplicaSet
。StatefulSet是Kubernetes 1.9版本之前的beta资源,在1.5版

本 之 前 的 任 何 Kubernetes 版 本 都 没 有 。 Pod 所 用 的 存 储 必 须 由

PersistentVolume Provisioner ( 持 久 化 卷 配 置 器 ) 根 据 请 求 配 置

StorageClass,或者由管理员预先配置,当然也可以不配置存储。

为了确保数据安全,删除和缩放StatefulSet不会删除与StatefulSet关

联的卷,可以手动选择性地删除PVC和PV(关于PV和PVC可参考本书8.6节)。

Headless Service

Headless Service命名规则

StatefulSet创建的Pod一般使用Headless Service(无头服务)进行通信,

和 普 通 的 Service 的 区 别 在 于 Headless Service 没 有 ClusterIP , 它 使 用Endpoint进行互相通信,Headless一般的格式为

复制代码
statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local。

配置说明:

  • serviceName为Headless Service的名字,创建StatefulSet时必须
    指定Headless Service名称。
  • 0...N‒1为Pod所在的序号,从0开始到N‒1。
  • statefulSetName为StatefulSet的名字。
  • namespace为服务所在的命名空间。
  • .cluster.local为Cluster Domain(集群域)。

StatefulSet 与Headless Service 关系

域名规则(必考、必用)

Service 名称:nginx-headless

Namespace:default

StatefulSet 名称:nginx-sts

复制代码
nginx-sts-0
nginx-sts-1
nginx-sts-2

它们的稳定域名是:

复制代码
nginx-sts-0.nginx-headless.default.svc.cluster.local
nginx-sts-1.nginx-headless.default.svc.cluster.local
nginx-sts-2.nginx-headless.default.svc.cluster.local

这个域名 Pod 重启、重建都不变 → 这就是 StatefulSet 的 "有状态"。

StatefulSet 必须依赖一个固定的 Service(Headless Service)才能工作。这个 Service 不是用来负载均衡,而是给 Pod 提供稳定的网络标识与域名解析。

Headless Service 是什么?

clusterIP: None

不做负载均衡

作用:直接解析出所有后端 Pod 的 IP 列表

给 StatefulSet 提供稳定域名

2. StatefulSet 为什么必须绑定 Service?

因为 StatefulSet 的 Pod 有两个核心特性:

稳定的网络身份(hostname + 固定域名)

稳定的存储

而稳定域名必须靠 Headless Service 来实现。

  1. 域名 & 网络关系(最核心)

    Headless Service: nginx-sts-svc

    Pod 名称 → 稳定 DNS 域名(永不变化)
    sts-0 → sts-0.nginx-sts-svc.default.svc.cluster.local
    sts-1 → sts-1.nginx-sts-svc.default.svc.cluster.local
    sts-2 → sts-2.nginx-sts-svc.default.svc.cluster.local

一句话背下来(面试必问)

Headless Service = StatefulSet 的网络底座

StatefulSet = 有序、有稳定域名、有独立存储的 Pod 管理器

serviceName 字段必须写,否则 StatefulSet 无法创建稳定网络

资源清单

复制代码
# 1. 必须先有 Headless Service
apiVersion: v1
kind: Service
metadata:
  name: nginx-sts-svc
spec:
  clusterIP: None   # 关键:Headless
  selector:
    app: nginx
  ports:
  - port: 80

---
# 2. StatefulSet 绑定 Headless Service
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-sts
spec:
  serviceName: nginx-sts-svc  # 必须写!
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx

# 3. 可选:对外访问用普通 Service(负载均衡)
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-sts-normal
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
  - port: 80
相关推荐
Mr.小海1 小时前
Docker Swarm 集群实战指南:从搭建到生产落地的完整攻略
运维·docker·容器
云服务器租用费用2 小时前
2026年零基础部署OpenClaw(前身为Clawdbot)+接入微信保姆级教程
服务器·人工智能·云原生·飞书·京东云
l1t2 小时前
利用Docker安装PostgreSQL 19 dev版
docker·postgresql·容器
至此流年莫相忘2 小时前
Kubernetes核心概念
java·容器·kubernetes
匀泪2 小时前
云原生(Keepalived 核心功能配置与实验)
服务器·云原生
Hello.Reader3 小时前
Flink Kerberos 安全接入整体机制、三大安全模块、Standalone/K8s/YARN 部署与 Token 续期策略
安全·flink·kubernetes
@hdd3 小时前
Service 详解:服务发现与负载均衡机制
云原生·kubernetes
Mr.小海3 小时前
Docker+K8s 集成部署实战
docker·容器·kubernetes
叱咤少帅(少帅)3 小时前
基于ELK 收集K8S的日志
elk·容器·kubernetes