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)