六个控制器谐音记忆

1. Deployment —— "地铺门特" → "地铺"

谐音:Deployment ≈ "地铺门特",取前两个字 "地铺"

联想:打地铺的人,谁睡都一样,坏了换一个。

作用:管理无状态服务,保证副本数量,支持滚动更新和回滚。

口诀:地铺随便睡,谁睡都一样 → 无状态、可替换


2. StatefulSet —— "四抬佛赛特" → "四抬佛"

谐音:StatefulSet ≈ "四抬佛赛特",取前三个字 "四抬佛"

联想:四抬大轿抬一尊佛,每尊佛都有名字,不能乱换。

作用:管理有状态服务,Pod 有固定名字、固定存储、有序启动。

口诀:四抬佛,认人不认号 → 有状态、身份固定


3. DaemonSet —— "大门赛特" → "大门"

谐音:DaemonSet ≈ "大门赛特",取前两个字 "大门"

联想:每栋楼的大门口,都得站一个保安。

作用:保证每个节点都运行一个 Pod,新节点自动补上。

口诀:大门保安,一楼一个 → 每台机器都要有


4. Job —— "找不" → "找活"

谐音:Job 本身就是"工作",谐音记成 "找活"

联想:临时工找活干,干完就走。

作用:一次性任务,保证成功完成指定次数后结束。

口诀:找活干,干完就撤 → 一次性任务


5. CronJob —— "克隆找活" → "闹钟找活"

谐音:CronJob ≈ "克隆找活",联想成 "闹钟找活"

联想:闹钟一响,定时去找活干。

作用:定时任务,按 cron 表达式周期性执行。

口诀:闹钟一响,定时找活 → 定时任务


6. ReplicaSet —— "瑞普利卡赛特" → "瑞普"

谐音:ReplicaSet ≈ "瑞普利卡赛特",取前两个字 "瑞普"

联想:"瑞普"像个复读机,只负责数数,保证数量对。

作用:保证指定数量的 Pod 副本运行,一般被 Deployment 管着,不直接用。

口诀:瑞普复读机,只数数 → 保证副本数量

一、Pod 资源控制器

Pod 是 K8s 最小调度单元,但直接创建的 Pod 不具备自愈和扩缩容能力。因此实际生产中用控制器来管理 Pod。

1. ReplicaSet(RS)

  • 保证指定数量的 Pod 副本始终运行

  • 支持标签选择器(selector)匹配 Pod

  • 一般不直接使用,而是通过 Deployment 管理

2. Deployment(最常用)

  • 管理 ReplicaSet,实现滚动更新和版本回滚

  • 无状态服务的首选控制器

 apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: nginx-deploy
 spec:
   replicas: 3
   selector:
     matchLabels:
       app: nginx
   template:
     metadata:
       labels:
         app: nginx
     spec:
       containers:
       - name: nginx
         image: nginx:1.25
         ports:
         - containerPort: 80

常用操作:

 kubectl set image deploy/nginx-deploy nginx=nginx:1.26   # 滚动更新
 kubectl rollout status deploy/nginx-deploy               # 查看更新状态
 kubectl rollout undo deploy/nginx-deploy                 # 回滚
 kubectl rollout history deploy/nginx-deploy              # 查看历史版本

3. StatefulSet(有状态)

  • 为每个 Pod 提供稳定的网络标识和持久存储

  • Pod 名称有序:web-0、web-1、web-2

  • 配合 Headless Service 和 PVC 使用

4. DaemonSet

  • 保证每个节点(或指定节点)都运行一个 Pod

  • 典型场景:日志采集(fluentd)、监控(node-exporter)、网络插件(calico)

5. Job / CronJob

  • Job:一次性任务,保证成功完成指定次数

  • CronJob:定时任务,按 cron 表达式周期执行

控制器对比

控制器

适用场景

Pod 身份

典型用途

Deployment

无状态

可替换

Web 服务、API

StatefulSet

有状态

稳定唯一

数据库、消息队列

DaemonSet

每节点一个

与节点绑定

日志、监控

Job

一次性

临时

批处理

CronJob

定时

临时

定时备份


二、有状态 vs 无状态服务

无状态服务(Stateless)

  • 每个请求不依赖之前的会话,实例可随意替换/扩缩

  • 不保存本地数据,数据存外部(DB、Redis、对象存储)

  • Pod 名称、IP 可变化,无顺序要求

  • 用 Deployment 管理

  • 例子:Nginx、前端 Web、REST API

有状态服务(Stateful)

  • 实例有唯一身份,需要持久化数据,实例间可能有主从/集群关系

  • 需要:稳定网络标识、稳定持久存储、有序启停

  • 用 StatefulSet 管理,需配合 Headless Service

  • 例子:MySQL 主从、Kafka、ZooKeeper、etcd、Elasticsearch

StatefulSet 三大核心特性

  1. 稳定网络标识:pod-name.service-name.namespace.svc.cluster.local

  2. 稳定存储:每个 Pod 绑定独立 PVC(volumeClaimTemplates)

  3. 有序部署/伸缩:创建按 0→N-1,删除按 N-1→0

 apiVersion: apps/v1
 kind: StatefulSet
 metadata:
   name: web
 spec:
   serviceName: "nginx-headless"   # 关联 Headless Service
   replicas: 3
   selector:
     matchLabels:
       app: nginx
   template:
     metadata:
       labels:
         app: nginx
     spec:
       containers:
       - name: nginx
         image: nginx
         volumeMounts:
         - name: www
           mountPath: /usr/share/nginx/html
   volumeClaimTemplates:            # 每个 Pod 独立 PVC
   - metadata:
       name: www
     spec:
       accessModes: ["ReadWriteOnce"]
       resources:
         requests:
           storage: 1Gi

对比总结

维度

无状态

有状态

实例身份

无差别

唯一固定

存储

外部共享

独立持久卷

扩缩容

任意顺序

有序

控制器

Deployment

StatefulSet

典型

Web/API

DB/MQ


三、HPA(Horizontal Pod Autoscaler)

HPA 实现 Pod 水平自动扩缩容:根据负载指标自动增减 Pod 副本数。

工作原理

 HPA Controller 周期(默认15s)查询指标
         ↓
 对比目标值与当前值,计算期望副本数
         ↓
 desiredReplicas = ceil(currentReplicas × (currentMetric / targetMetric))
         ↓
 调整 Deployment/StatefulSet 的 replicas

指标来源

  • 资源指标:CPU、内存(依赖 metrics-server)

  • 自定义指标:QPS、连接数等(依赖 Prometheus Adapter)

  • 外部指标:云服务队列长度等

前置条件

需要安装 metrics-server:

 kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
 kubectl top nodes
 kubectl top pods

HPA 示例

命令式创建:

 kubectl autoscale deployment nginx-deploy --cpu-percent=50 --min=2 --max=10

声明式(推荐):

 apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
 metadata:
   name: nginx-hpa
 spec:
   scaleTargetRef:
     apiVersion: apps/v1
     kind: Deployment
     name: nginx-deploy
   minReplicas: 2
   maxReplicas: 10
   metrics:
   - type: Resource
     resource:
       name: cpu
       target:
         type: Utilization
         averageUtilization: 50
   - type: Resource
     resource:
       name: memory
       target:
         type: Utilization
         averageUtilization: 70
   behavior:                    # 控制扩缩容行为
     scaleDown:
       stabilizationWindowSeconds: 300   # 缩容冷却5分钟

关键要点

  • 必须设置 resources.requests,否则 CPU 利用率无法计算

  • 扩容快、缩容慢(默认缩容有 5 分钟稳定窗口,防止抖动)

  • 需要配合 Cluster Autoscaler 才能实现节点层面的扩缩容

  • v2 版本支持多指标、behavior 精细控制

查看 HPA

 kubectl get hpa
 kubectl describe hpa nginx-hpa

NAME        REFERENCE              TARGETS         MINPODS  MAXPODS  REPLICAS
nginx-hpa   Deployment/nginx-deploy 30%/50%        2        10       3

模拟案例

1. Deployment(地铺)—— 部署 3 个 Nginx 副本

场景:跑一个无状态的 Web 服务,坏了自动补,升级不断服。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: "100m"
            memory: "64Mi"

操作与验证:

kubectl apply -f nginx-deploy.yaml
kubectl get deploy
kubectl get pods -o wide   # 看到 3 个 Pod
kubectl scale deploy/nginx-deployment --replicas=5   # 扩到 5 个
kubectl set image deploy/nginx-deployment nginx=nginx:1.26   # 滚动升级               
kubectl rollout status deploy/nginx-deployment
kubectl rollout undo deploy/nginx-deployment   # 出问题回滚

关键点:必须设置 resources.requests.cpu,否则后面 HPA 算不出利用率 。

2. StatefulSet(四抬佛)—— 部署单实例 MySQL

场景:数据库这种“认人”的服务,数据要存在自己的卷上,名字不能变。

apiVersion: v1
kind: Service
metadata:
  name: mysql-headless
spec:
  clusterIP: None      # 关键:Headless Service
  selector:
    app: mysql
  ports:
  - port: 3306
    targetPort: 3306
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-headless   # 必须和上面 Service 同名
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "root123"
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:         # 每个 Pod 自动生成独立 PVC
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi

操作与验证:

kubectl apply -f mysql-sts.yaml
kubectl get pods   # 看到 mysql-0,名字固定
kubectl get pvc    # 看到 data-mysql-0,独立存储卷

关键点:clusterIP: None 是 Headless Service,它不分配 ClusterIP,而是直接返回 Pod 的 DNS 记录。这样其他应用可以通过 mysql-0.mysql-headless.default.svc.cluster.local 访问到固定 Pod 。

3. DaemonSet(大门)—— 每台机器跑一个日志采集器

场景:集群里每台节点都需要一个“保安”,负责收集本机日志。

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: log-collector
  labels:
    app: logging
spec:
  selector:
    matchLabels:
      app: logging
  template:
    metadata:
      labels:
        app: logging
    spec:
      containers:
      - name: collector
        image: busybox
        command: ["/bin/sh", "-c", "while true; do echo 'Collecting...'; sleep 30; done"]

操作与验证:

kubectl apply -f daemonset.yaml
kubectl get ds
kubectl get pods -o wide   # 每个节点上都有一个 log-collector

关键点:DaemonSet 不需要写 replicas,Pod 数量自动跟节点数量一致。加了新节点,自动补一个;删了节点,自动撤走 。

4. Job(找活)—— 一次性数据处理任务

场景:跑一个一次性任务,干完就结束,不常驻。

apiVersion: batch/v1
kind: Job
metadata:
  name: data-process
spec:
  completions: 1
  template:
    spec:
      containers:
      - name: processor
        image: busybox
        command: ["/bin/sh", "-c", "echo 'Processing data...'; sleep 5; echo 'Done!'"]
      restartPolicy: Never

操作与验证:

kubectl apply -f job.yaml
kubectl get jobs
kubectl get pods   # 看到 Pod 状态从 Running → Completed
kubectl logs job/data-process   # 看任务输出

关键点:restartPolicy 必须是 Never 或 OnFailure,不能是 Always。Job 完成后 Pod 不会自动删除,可以留着看日志,手动清理即可 。

5. CronJob(闹钟找活)—— 每天凌晨 3 点备份

场景:定时任务,每天半夜跑一次“备份”。

apiVersion: batch/v1
kind: CronJob
metadata:
  name: daily-backup
spec:
  schedule: "0 3 * * *"        # 每天凌晨 3 点
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: busybox
            command: ["/bin/sh", "-c", "echo 'Backing up...'; date"]
          restartPolicy: OnFailure

操作与验证:

kubectl apply -f cronjob.yaml
kubectl get cronjob
kubectl get jobs   # 到点后会自动创建一个 Job

Cron 表达式速记:

* * * * *
│ │ │ │ └── 星期几(0-6)
│ │ │ └──── 月(1-12)
│ │ └────── 日(1-31)
│ └──────── 时(0-23)
└────────── 分(0-59)

常用宏:@daily = 每天午夜,@hourly = 每小时 。

6. ReplicaSet(瑞普)—— 手动保证 4 个 Nginx

场景:了解 ReplicaSet 的底层逻辑。生产一般不直接用,但用来理解“副本数保证”机制很好。

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-rs
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx-rs
  template:
    metadata:
      labels:
        app: nginx-rs
    spec:
      containers:
      - name: nginx
        image: nginx

操作与验证:

kubectl apply -f rs.yaml
kubectl get rs
kubectl get pods -l app=nginx-rs   # 看到 4 个
kubectl delete pod <其中一个>       # 删除后 RS 自动补一个
kubectl scale rs/nginx-rs --replicas=2   # 缩到 2 个

关键点:ReplicaSet 只管“数量对不对”,不管“版本升级”。Deployment 其实是“管着 ReplicaSet 的包工头”,升级时创建新 RS、慢慢替换旧的 。

串起来练一遍(推荐动手顺序)

 # 1. 先跑 Deployment,体验自愈和扩缩容
 kubectl apply -f nginx-deploy.yaml
 kubectl delete pod <任意一个>   # 观察自动补回来
 kubectl scale deploy/nginx-deployment --replicas=5
 ​
 # 2. 跑 Job,体验一次性任务
 kubectl apply -f job.yaml
 kubectl get pods   # 看到 Completed
 ​
 # 3. 跑 CronJob,等一分钟看自动创建 Job
 kubectl apply -f cronjob.yaml
 ​
 # 4. 跑 DaemonSet,看每个节点是不是都有一个
 kubectl apply -f daemonset.yaml
 kubectl get pods -o wide
 ​
 # 5. 跑 StatefulSet + Headless Service(MySQL),看固定名字和独立 PVC
 kubectl apply -f mysql-sts.yaml
 kubectl get pvc