七、pod控制器

一、rc控制器和rs控制器

1.1rc控制器(ReplicationController)

bash 复制代码
# ============================================================
# ReplicationController(RC)控制器配置
# 作用:确保集群中始终运行指定数量的 Pod 副本
# 注意:RC 是较老版本的控制器,新版本推荐使用 ReplicaSet 或 Deployment
# ============================================================

apiVersion: v1                    # RC 使用 v1 版本的 API(不是 apps/v1)
kind: ReplicationController       # 资源类型:ReplicationController

metadata:
  name: rc-demo                   # RC 自身名称,全局唯一

spec:

  # ----- 副本数量配置 -----
  replicas: 3                     # 期望运行的 Pod 数量(集群会始终维持 3 个)

  # ----- 选择器(重要!) -----
  # 作用:定义 RC 管理哪些 Pod(通过标签筛选)
  # 注意:与 ReplicaSet 不同,RC 的 selector 只支持简单的标签匹配,不支持 matchLabels/matchExpressions
  # 这里的标签必须与 template.metadata.labels 完全一致
  selector:
    app: rc-demo                  # 筛选出所有标签为 app=rc-demo 的 Pod

  # ----- Pod 模板(蓝图) -----
  # 作用:当需要创建新 Pod 时,就按照这个模板生成
  template:
    metadata:
      labels:                     # 为 Pod 打上标签(必须覆盖 selector 中的标签)
        app: rc-demo              # 这行就是 selector 要找的标签

    spec:                         # Pod 内部规格定义
      containers:
      - name: rc-demo-container   # 容器名称
        image: wangyanglinux/myapp:v1.0  # 容器镜像

        # ----- 环境变量(注入到容器内部) -----
        # 作用:将配置信息以 key-value 形式注入容器,应用可通过 process.env 读取
        env:
        - name: GET_HOSTS_FROM    # 环境变量名 ①
          value: "dns"            # 取值:dns 表示服务发现优先使用 DNS
        - name: zhangsan          # 环境变量名 ②(示例:自定义变量)
          value: "123"            # 取值:字符串 "123"

        # ----- 容器端口声明 -----
        # 作用:声明容器监听哪个端口(仅起文档/可视化作用,不影响实际网络通信)
        ports:
        - containerPort: 80       # 应用监听 80 端口(如 myapp 的 Web 服务)

1.2、rs控制器(ReplicaSet)

bash 复制代码
# ============================================================
# ReplicaSet 控制器配置
# 作用:确保集群中始终运行指定数量的 Pod 副本
# ============================================================

apiVersion: apps/v1          # 使用 apps 组 v1 版本的 API
kind: ReplicaSet             # 资源类型:副本集控制器

metadata:
  name: rs-ml-demo           # ReplicaSet 自身名称,全局唯一

spec:
  # ----- 副本数量配置 -----
  replicas: 3                # 期望运行的 Pod 数量(集群会始终维持 3 个)

  # ----- 选择器(重要!) -----
  # 作用:定义 ReplicaSet 管理哪些 Pod(通过标签筛选)
  # 注意:此处的 labels 必须与 template 中定义的 labels 完全一致
  selector:
    matchLabels:             # 匹配标签规则(只能使用 matchLabels,不支持复杂的 matchExpressions)
      app: rs-ml-demo        # 筛选出所有标签为 app=rs-ml-demo 的 Pod

  # ----- Pod 模板(蓝图) -----
  # 作用:当需要创建新 Pod 时,就按照这个模板生成
  template:
    metadata:
      labels:                # 为 Pod 打上标签(必须覆盖 selector 中的标签)
        app: rs-ml-demo      # 这行就是 selector 要找的标签

    spec:                    # Pod 内部规格定义
      containers:
      - name: rs-ml-demo-container   # 容器名称
        image: wangyanglinux/myapp:v1.0  # 容器镜像

        # ----- 环境变量(注入到容器内部) -----
        # 作用:将配置信息以 key-value 形式注入容器,应用可通过 process.env 读取
        env:
        - name: GET_HOSTS_FROM      # 环境变量名
          value: "dns"              # 取值:dns 表示服务发现优先使用 DNS(常见于旧版 k8s 示例)
                                    # 备注:此变量在较新版本的 Kubernetes 中已非必需,属于历史遗留配置

        # ----- 容器端口声明 -----
        # 作用:声明容器监听哪个端口(仅起文档/可视化作用,不影响实际网络通信)
        ports:
        - containerPort: 80         # 应用监听 80 端口(如 myapp 的 Web 服务)

1.3、两者差别

官方推荐使用rs控制器

对比维度 ReplicationController(旧) ReplicaSet(新)
API 版本 apiVersion: v1 apiVersion: apps/v1
标签选择器能力 ❌ 仅支持等值匹配 (key=value) ✅ 支持等值匹配 + 集合式匹配
selector 写法 直接写 app: rc-demo 支持 matchLabels 和 matchExpressions 两种方式
官方推荐 ❌ 已弃用,不建议使用 ✅ 推荐使用(但通常由 Deployment 自动管理)
实际用途 历史遗留,仅用于理解旧版概念 作为 Deployment 的底层组件,不单独使用

1.4、rs控制器优势

RS 除了支持 matchLabels(等值匹配)外,还支持 matchExpressions,提供更灵活的标签筛选能力。支持的 4 种操作符:

操作符 含义 示例
In 标签的值在指定的列表中 筛选 env 为 prod 或 test 的 Pod
NotIn 标签的值不在指定的列表中 筛选 env 不为 prod 或 test 的 Pod
Exists 只要标签存在就匹配(不关心值) 筛选所有带有 disktype 标签的 Pod
DoesNotExist 标签不存在才匹配 筛选所有不带 disktype 标签的 Pod

下面是rs的特性演示:

举例:

bash 复制代码
# ============================================================
# ReplicaSet 示例 1:使用 Exists 操作符
# 作用:匹配所有带有 app 标签的 Pod(不管值是什么)
# ============================================================
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: rs-me-exists-demo
spec:
  selector:
    matchExpressions:
      - key: app
        operator: Exists
  template:
    metadata:
      labels:
        app: spring-k8s
    spec:
      containers:
        - name: rs-me-exists-demo-container
          image: wangyanglinux/myapp:v1.0
          ports:
            - containerPort: 80
---
# ============================================================
# ReplicaSet 示例 2:使用 In 操作符
# 作用:匹配 app 标签值在 [spring-k8s, hahahah] 列表中的 Pod
# 注意:当前 template 中 labels 为 app: sg-k8s,不在 values 列表中,
#       因此该 RS 实际无法匹配任何 Pod(内容未改,保持原样)
# ============================================================
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: rs-me-in-demo
spec:
  selector:
    matchExpressions:
      - key: app
        operator: In
        values:
          - spring-k8s
          - hahahah
  template:
    metadata:
      labels:
        app: spring-k8s
    spec:
      containers:
        - name: rs-me-in-demo-container
          image: wangyanglinux/myapp:v1.0
          ports:
            - containerPort: 80

所以问题来了,为什么pod有标签了,还需要使用控制器的标签

因为:

现实角色 K8s 组件 它关心什么 标签的作用 不匹配的后果
前台 Service 哪些员工能接待客户 用标签找到"能接客"的 Pod,把流量导给它 Pod 收不到任何流量,但容器仍在运行
人事经理 ReplicaSet 我负责的岗位有没有招满 3 个人 用标签找到"归我管"的 Pod,少一个就补一个 RS 认为自己没有 Pod,会不断创建新的 Pod
员工 Pod 自己是什么身份 用标签(template.labels)表明"我是谁" 没有标签的 Pod 就是"孤儿",没人管

二、Deployment控制器

Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义(declarative)方法,用来替代以前的 ReplicationController 来方便的管理应用。典型的应用场景包括:

➢ 定义 Deployment 来创建 Pod 和 ReplicaSet(deployment管理rs)

➢ 滚动升级和回滚应用

➢ 扩容和缩容

➢ 暂停和继续 Deployment

声明式和命令式是对立的:

  • 声明性的东西是对终结果的陈述,表明意图而不是实现它的过程。在Kubernetes中,这就是说"应该有一个包含三个 Pod 的 ReplicaSet"。

  • 命令式充当命令。声明式是被动的,而命令式是主动且直接的:"创建一个包含三个 Pod 的 ReplicaSet"。

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # 1. 命令式:强制替换(不推荐) # 作用:用 YAML 里的内容,直接强制替换集群中现有的 Deployment。 # 特点:如果资源不存在会报错。它会直接删除旧对象并创建新对象,容易导致服务短暂中断。 kubectl replace -f deployment.yaml | | # 2. 声明式:计算差异并更新(最推荐,企业生产标准) # 作用:对比 YAML 期望状态与集群实际状态,只更新有差异的部分。 # 特点:如果不存在则创建,如果存在则平滑更新(触发滚动更新)。这是你之前遇到"警告"时用的命令,补全了配置后就能正常用。 kubectl apply -f deployment.yaml |
| # 3. 辅助命令:查看差异(安全预检) # 作用:只显示 YAML 文件和集群中实际运行的资源有哪些区别,不执行真正的修改。 # 特点:相当于"预演"一下 apply,方便你确认无误后再执行真正的应用。 $ kubectl diff -f deployment.yaml |

命令式和声明式区别:

复制代码
# ============================================================
# 实验:kubectl apply vs kubectl replace
# 演示:apply 保留未在 YAML 中声明的注解,replace 会删除它
# ============================================================

# 1. 初始创建(用 apply,让它记录 last-applied-configuration)
kubectl apply -f 1.dplmt.yaml

# 2. 手动给 Deployment 加一个额外注解(模拟"YAML 中未声明的字段")
kubectl annotate deployment myapp-deploy test-annotation="hello" --overwrite

# 3. 修改 YAML 中的镜像为 v2.0
sed -i 's/v1.0/v2.0/' 1.dplmt.yaml

# 4. 用 apply 更新,并检查注解是否存在
kubectl apply -f 1.dplmt.yaml
echo "===== apply 之后的注解情况 ====="
kubectl get deployment myapp-deploy -o jsonpath='{.metadata.annotations}'
echo ""

# 5. 重新加上注解,修改 YAML 镜像为 v3.0,再用 replace 更新
kubectl annotate deployment myapp-deploy test-annotation="hello" --overwrite
sed -i 's/v2.0/v3.0/' 1.dplmt.yaml
kubectl replace -f 1.dplmt.yaml
echo "===== replace 之后的注解情况 ====="
kubectl get deployment myapp-deploy -o jsonpath='{.metadata.annotations}'
echo ""

# 6. 结论:
#    apply 之后注解仍然存在(保留未声明字段)
#    replace 之后注解消失(YAML 中没有就删除)

diff对比命令

通过diff对比pod实体与yaml的区别

复制代码
[root@k8s-master01 deployment]# kubectl diff -f 1.dplmt.yaml 
diff -u -N /tmp/LIVE-3445901412/apps.v1.Deployment.default.myapp-deploy /tmp/MERGED-604905406/apps.v1.Deployment.default.myapp-deploy
--- /tmp/LIVE-3445901412/apps.v1.Deployment.default.myapp-deploy	2026-09-14 10:27:15.676236826 +0800
+++ /tmp/MERGED-604905406/apps.v1.Deployment.default.myapp-deploy	2026-09-14 10:27:15.678236825 +0800
@@ -4,7 +4,7 @@
   annotations:
     deployment.kubernetes.io/revision: "3"
   creationTimestamp: "2026-09-14T02:01:49Z"
-  generation: 4
+  generation: 5
   labels:
     app: myapp-deploy
   name: myapp-deploy
@@ -30,7 +30,7 @@
         app: myapp-deploy
     spec:
       containers:
-      - image: wangyanglinux/myapp:v3.0
+      - image: wangyanglinux/myapp:v4.0
         imagePullPolicy: IfNotPresent
         name: myapp
         resources: {}
[root@k8s-master01 deployment]# 

deployment更新策略

分为两种:

  1. RollingUpdate(滚动更新) :默认策略。先起新 Pod,Ready 后删旧 Pod,逐步替换,服务不中断。

  2. Recreate(重建) :先删掉所有旧 Pod,再创建新 Pod,服务会短暂中断。适合无法同时运行新旧版本的应用(如数据库变更)。

Deployment 在升级时,为了保证服务不中断(零宕机),会采用"滚动更新"的方式,确保在升级过程中,总是有一定数量的 Pod 保持可用。

rollingUpdate的核心参数

数 含义 通俗解释
maxSurge 指定超出期望副本数的 Pod 最大数量。支持数字 和百分比。 "多出来"的 Pod:升级时最多允许比期望数量多启动几个新 Pod。
maxUnavailable 指定最多有几个 Pod 不可用。 "少掉"的 Pod:升级时最多允许同时停掉几个旧 Pod。

案例:

复制代码
案例1:
#不写 strategy 字段时,默认就是 RollingUpdate,maxSurge: 25%,maxUnavailable: 25%。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
spec:
  replicas: 10
  selector:
    matchLabels:
      app: myapp-deploy
  template:
    metadata:
      labels:
        app: myapp-deploy
    spec:
      containers:
      - image: wangyanglinux/myapp:v3.0
        name: myapp

案例2:
# 每次最多多起 1 个新 Pod,保证服务绝对不中断
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
spec:
  replicas: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1           # 每次最多多起 1 个新 Pod
      maxUnavailable: 0     # 保证服务绝对不中断
  selector:
    matchLabels:
      app: myapp-deploy
  template:
    metadata:
      labels:
        app: myapp-deploy
    spec:
      containers:
      - image: wangyanglinux/myapp:v2.0
        name: myapp


案例3:指定重建策略,服务会中断
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
spec:
  replicas: 10
  strategy:
    type: Recreate           # 指定重建策略
  selector:
    matchLabels:
      app: myapp-deploy
  template:
    metadata:
      labels:
        app: myapp-deploy
    spec:
      containers:
      - image: wangyanglinux/myapp:v1.0
        name: myapp
~                     

deployment常用命令

bash 复制代码
创建 Deployment,record是记录更新操作的
kubectl create -f deployment.yaml --record

手动扩缩容
kubectl scale deployment nginx-deployment --replicas 10

自动扩缩容 (HPA)
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
--min=10:指定 Pod 副本数的最小值为 10。
--max=15:指定 Pod 副本数的最大值为 15。
--cpu-percent=80:设置目标 CPU 使用率阈值为 80%。当deployment的所有pod使用率超过 80% 时触发扩容,低于时触发缩容。

更新镜像 (滚动更新)
kubectl set image deployment/nginx-deployment nginx-deployment-container=wangyanglinux/myapp:v2.0

版本回滚
kubectl rollout undo deployment/nginx-deployment

构建过程中的命令

bash 复制代码
# 1. 创建 Deployment
kubectl apply -f 1.dplmt.yaml

# 2. 查看初始状态(1 个 RS,10 个 Pod)
kubectl get rs
kubectl get pod

# 3. 修改 YAML:把镜像 v1.0 改成 v2.0
sed -i 's/v1.0/v2.0/' 1.dplmt.yaml

# 4. 应用更新(触发滚动更新)
kubectl apply -f 1.dplmt.yaml

# 5. 实时观察滚动更新过程
kubectl rollout status deployment/myapp-deploy

# 6. 查看 RS 变化(会出现两个 RS:旧的 v1.0 和新的 v2.0)
kubectl get rs

# 7. 查看 Pod 变化(旧 Pod 逐个减少,新 Pod 逐个增加)
kubectl get pod -w

# 8. 查看滚动更新历史
kubectl rollout history deployment/myapp-deploy

# 9. 验证新 Pod 的镜像版本
kubectl get pod -o jsonpath='{.items[*].spec.containers[*].image}'

金丝雀更新策略

金丝雀部署是"把新版本先给 1% 的人用,如果没问题,再逐步扩大给 100% 的人用"

bash 复制代码
#1.0版本
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-demo
spec:
  replicas: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1           # 每次最多多起 1 个新 Pod
      maxUnavailable: 0     # 保证服务绝对不中断
  selector:
    matchLabels:
      app: myapp-deploy
  template:
    metadata:
      labels:
        app: myapp-deploy
    spec:
      containers:
      - image: wangyanglinux/myapp:v1.0
        name: myapp

#apply启动
kubectl apply -f 3.deployment.yaml

#金丝雀更新,本来是10个老pod,新增一个2.0的新pod,然后停止(意思就是:新增一个2.0pod后就停止)
#如果更新策略是默认的25%:25%,需要设置一下更新策略为1:0
kubectl patch deployment deployment-demo -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'


#开始金丝雀部署,部署完会发现多一个2.0
kubectl patch deployment deployment-demo --patch '{"spec":{"template":{"spec":{"containers":[{"name":"myapp","image":"wangyanglinux/myapp:v2.0"}]}}}}' && kubectl rollout pause deploy deployment-demo

#如果2.0没问题,我就可以批量把那10个都设置为2.0了
kubectl rollout resume deploy deployment-demo

#现在我有10个2.0,我现在再弄个10个2.0,1个3。0
#然后发现3.0有问题,必须全部升级到3.0才可以回滚,感觉这一块好傻
kubectl rollout resume deployment deployment-demo
#回滚到2.0
kubectl rollout undo deployment deployment-demo --to-revision=2   # 直接回到 v2.0
kubectl rollout undo deployment deployment-demo --to-revision=1   # 直接回到 v1.0
注意:
1、2、是 Deployment 的历史版本序号,不是镜像1.0和2.0编号。
如果不指定 --to-revision,kubectl rollout undo 默认只会回滚到当前版本的前一个 Revision,并不会自动一路退到最早的 1.0。

三、DaemonSet控制器

DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。

使用 DaemonSet 的一些典型用法:

  • 运行集群存储 daemon,例如在每个 Node 上运行 glusterd、ceph

  • 在每个 Node 上运行日志收集 daemon,例如 fluentd、logstash

  • 在每个 Node 上运行监控 daemon,例如 Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond

    #DaemonSet就是让每个node节点有一个pod

    指定 K8s API 版本,DaemonSet 属于 apps/v1 组

    apiVersion: apps/v1

    资源类型:DaemonSet(守护进程集)

    kind: DaemonSet

    元数据:描述 DaemonSet 自身的信息

    metadata:
    name: daemonset-demo # DaemonSet 的名字(正确拼写)
    labels: # 给 DaemonSet 自己打的标签(用于管理分类)
    app: daemonset-demo

    规格:定义 DaemonSet 的行为

    spec:
    # 选择器:定义 DaemonSet 要管理哪些 Pod
    selector:
    matchLabels:
    name: deamonset-demo #这里必须与下面 template 里的 labels 完全一致!
    # 模板:定义要在每个节点上创建的 Pod 长什么样
    template:
    metadata:
    labels:
    name: deamonset-demo # 必须与上面的 selector 保持一致
    spec:
    containers:
    - name: daemonset-demo-container # 容器的名字
    image: wangyanglinux/myapp:v1.0 # 容器使用的镜像

    #生成pod
    [root@k8s-master01 daemonSet]# kubectl apply -f 1.DaemonSet.yaml
    daemonset.apps/daemonset-demo created
    [root@k8s-master01 daemonSet]#

    #查看每个机器上有一个pod

    [root@k8s-master01 daemonSet]# kubectl get pod -o wide
    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    daemonset-demo-5q7t2 1/1 Running 0 11s 10.244.85.206 k8s-node01
    daemonset-demo-n76h4 1/1 Running 0 11s 10.244.58.222 k8s-node02

四、Job 控制器

Job 是 Kubernetes 中用于运行一次性任务 的控制器。它确保指定数量的 Pod 成功完成,而不是像 Deployment 那样持续保持运行。

核心特点:

  • Pod 执行完任务后正常退出 (状态变为 Completed),Job 不会重新创建它。

  • 如果 Pod 失败,Job 会根据 restartPolicy 决定是否重试。

  • 适用于批处理、数据迁移、备份、报表生成等一次性的工作。

特殊说明:

spec.template 格式同 Pod

RestartPolicy 仅支持 Never(永不重启) 或 OnFailure(重启,直到成功返回0)

单个 Pod 时,默认 Pod 成功运行后 Job 即结束

spec.completions 标志 Job 结束需要成功运行的 Pod 个数,默认为 1

spec.parallelism 标志并行运行的 Pod 的个数,默认为 1

spec.activeDeadlineSeconds 标志失败 Pod 的重试最大时间,超过这个时间不会继续重试

五、cronjob控制器

CronJob

周期性的创建Job,典型的场景:数据库的周期性备份.·

复制代码
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjob-demo
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: cronjob-demo-container
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the kubernetes cluster
          restartPolicy: OnFailure

六、控制器区别

守护进程类型控制器

  • RC 控制器

    • 保障当前的 Pod 数量与期望值一致
  • RS 控制器

    • 功能与 RC 控制器类似,但是多了标签选择的运算方式
  • Deployment

    • 支持了声明式表达

    • 支持滚动更新和回滚

    • 原理:deployment > RS > pod

  • DaemonSet

    • 保障每个节点有且只有一个 Pod 的运行,动态

批处理任务的类型

Job

保障批处理任务一个或多个成功为止

CronJob

周期性的创建Job,典型的场景:数据库的周期性备份.·

控制器 核心职责(干什么的) 理发店系统中的对应场景
ReplicaSet (RS) 只保证 Pod 数量够,不管更新 基本不用,被 Deployment 替代
Deployment 管无状态应用(Web、API),支持滚动更新/回滚 前端、后端 API 服务
DaemonSet 保证每个节点跑一个 Pod 日志收集、监控 Agent、网络插件
Job / CronJob 一次性任务、定时任务 每日销售报表、数据库备份
相关推荐
空空dream12 小时前
03 | 离线部署 FastAPI + Ollama(qwen2:0.5b):从 Docker 联调到 Kubernetes 验收
docker·ai·kubernetes·fastapi
Linux实战笔记14 小时前
K8s 滚动部署失效?maxUnavailable 参数没搞透
kubernetes·readinessprobe·零停机·滚动部署·maxunavailable
张洛闻Eren16 小时前
Ansible【第一课】:Ansible介绍
运维·数据库·云原生·kubernetes·github·ansible
杰克尼17 小时前
Kubernetes
云原生·容器·kubernetes
张洛闻Eren18 小时前
Ansible【第二课】:实施 Ansible Playbook
linux·运维·服务器·云原生·kubernetes·k8s·ansible
东城绝神19 小时前
《Kubernetes部署篇:基于x86_64+aarch64架构CPU+containerd一键离线部署容器版K8S1.36.4高可用集群》
容器·架构·kubernetes
池佳齐20 小时前
【软考高级架构师案例】容器化改造:Docker + K8s,如何用云原生视角重构传统多层架构?
docker·云原生·kubernetes
骑着蜗牛撵大象32721 小时前
云原生存储进阶:CSI 演进与 AI 工作负载的存储架构设计
人工智能·ai·云原生·kubernetes·csi·并行文件系统
kuroomi21 小时前
K8s集群升级与etcd备份恢复实战
容器·kubernetes·etcd