16.3.3 控制器类型与适用场景

在Kubernetes中,控制器负责维持期望状态与实际状态一致。选择合适控制器会直接影响发布策略、可用性与运维成本。下文按“适用场景→原理草图→示例→排错→练习”组织,确保可直接落地。

控制器原理草图(统一视角)

文章图片

1. ReplicaSet:无状态副本维持
- 适用场景:仅需保证固定副本数的无状态服务。
- 关键点:标签选择器精确匹配,副本数固定。

示例:创建ReplicaSet并验证副本数

# rs-nginx.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: rs-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: rs-nginx
  template:
    metadata:
      labels:
        app: rs-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
kubectl apply -f rs-nginx.yaml
kubectl get rs rs-nginx
kubectl get pods -l app=rs-nginx -o wide

预期效果:Pod数量保持3个,手动删除Pod会自动拉起。

排错要点

kubectl describe rs rs-nginx
kubectl get events --sort-by=.lastTimestamp | tail
# 若Pod未创建,检查selector与template.labels是否一致

练习
- 将replicas从3改为5并观察变化。
- 手动删除1个Pod,验证副本恢复。

2. Deployment:无状态应用的主力控制器
- 适用场景:Web/API/微服务等无状态业务。
- 关键点:滚动更新、回滚、发布历史。

示例:滚动更新与回滚

# deploy-web.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  revisionHistoryLimit: 5
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:1.25
        ports:
        - containerPort: 80
kubectl apply -f deploy-web.yaml
kubectl set image deploy/web web=nginx:1.26 --record
kubectl rollout status deploy/web
kubectl rollout history deploy/web
kubectl rollout undo deploy/web  # 回滚到上一个版本

排错要点

kubectl describe deploy/web
kubectl get rs -l app=web
# 若卡在更新,检查镜像拉取、探针或资源不足

练习
- 将镜像改为不存在的tag,观察Rollout失败并回滚。

3. StatefulSet:有状态应用
- 适用场景:数据库、中间件、有序集群。
- 关键点:稳定网络标识、持久化卷、按序扩缩。

示例:最小StatefulSet(配合Headless Service)

# svc-headless.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql-headless
spec:
  clusterIP: None
  selector:
    app: mysql
  ports:
  - port: 3306
---
# sts-mysql.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-headless
  replicas: 2
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "Passw0rd!"
        ports:
        - containerPort: 3306
kubectl apply -f svc-headless.yaml
kubectl apply -f sts-mysql.yaml
kubectl get pods -l app=mysql -o wide
# 访问示例:mysql-0.mysql-headless.default.svc.cluster.local

排错要点

kubectl describe sts/mysql
kubectl get pod mysql-0 -o yaml | grep -A5 -n "volumes"
# 若Pending,多为存储类或PVC未绑定

练习
- 将replicas从2改为3,观察Pod创建顺序。

4. DaemonSet:节点级服务
- 适用场景:日志/监控/网络/存储插件等每节点一份。
- 关键点:在每个节点(或匹配节点)运行一个Pod。

示例:部署节点日志采集(示例用busybox模拟)

# ds-logger.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-logger
spec:
  selector:
    matchLabels:
      app: node-logger
  template:
    metadata:
      labels:
        app: node-logger
    spec:
      containers:
      - name: logger
        image: busybox:1.36
        command: ["sh","-c","tail -n+1 -F /var/log/messages"]
        volumeMounts:
        - name: varlog
          mountPath: /var/log
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
          type: Directory
kubectl apply -f ds-logger.yaml
kubectl get ds node-logger
kubectl get pods -l app=node-logger -o wide

排错要点

kubectl describe ds/node-logger
# 若某节点无Pod,检查节点污点/容忍或选择器

练习
- 给某节点加污点,观察Pod是否被驱逐并验证容忍配置。

5. Job:一次性批处理
- 适用场景:数据初始化、迁移、离线计算。
- 关键点:完成即退出,失败重试。

示例:Job执行一次性计算

# job-pi.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job-pi
spec:
  completions: 1
  backoffLimit: 3
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: pi
        image: perl:5.34
        command: ["perl","-Mbignum=bpi","-wle","print bpi(50)"]
kubectl apply -f job-pi.yaml
kubectl get jobs
kubectl logs job/job-pi

排错要点

kubectl describe job/job-pi
# 若失败重试过多,关注backoffLimit与错误日志

练习
- 将命令改为退出码1,观察Job重试次数。

6. CronJob:周期性任务
- 适用场景:定时备份、清理、归档。
- 关键点:Cron表达式与并发策略。

示例:每5分钟打印时间

# cron-time.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cron-time
spec:
  schedule: "*/5 * * * *"
  successfulJobsHistoryLimit: 2
  failedJobsHistoryLimit: 2
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: time
            image: busybox:1.36
            command: ["sh","-c","date; echo hello from cron"]
kubectl apply -f cron-time.yaml
kubectl get cronjob cron-time
kubectl get jobs --watch

排错要点

kubectl describe cronjob/cron-time
# 若未触发,检查集群时间、Cron表达式或控制器是否正常

练习
- 将schedule改为"/1 * * * ",观察1分钟执行一次。

7. HPA/VPA:弹性伸缩
- 适用场景:负载波动明显的服务。
- 关键点:HPA按指标调副本,VPA调资源请求/限制。

示例:HPA基于CPU自动扩缩

# 需要metrics-server,未安装先安装
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# hpa-web.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-web
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web
  minReplicas: 2
  maxReplicas: 6
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
kubectl apply -f hpa-web.yaml
kubectl get hpa hpa-web
# 压测触发扩容(示例)
kubectl run -it --rm load --image=busybox:1.36 -- \
  sh -c "while true; do wget -q -O- http://web; done"

排错要点

kubectl describe hpa hpa-web
# 若指标为空,检查metrics-server是否可用:
kubectl top nodes
kubectl top pods

练习
- 将averageUtilization从50改为20,观察扩缩速度变化。

控制器选择快速对照
- 无状态、需滚动更新:Deployment
- 有状态、稳定标识与持久化:StatefulSet
- 每节点一个服务:DaemonSet
- 一次性/周期性任务:Job/CronJob
- 需自动扩缩容:HPA(配合Deployment/StatefulSet)