一、控制器核心概念
1.1 控制器的作用
自主创建的 Pod 在进程退出或节点异常后不会自动重建。控制器在用户声明期望副本数后将目标状态写入 etcd,kube-apiserver 持续比对实际状态与期望状态,驱动 kubelet 完成调谐(reconcile)循环。
| 对比维度 | 自主式 Pod | 控制器管理 Pod |
|---|---|---|
| 故障自愈 | 无 | 自动重建 |
| 扩缩容 | 手动逐个操作 | 一条命令调整 replicas |
| 版本更新 | 删除重建 | 滚动更新/回滚 |
| 适用场景 | 临时调试 | 生产环境 |
1.2 控制器类型总览
| 控制器 | API Group | 核心职责 |
|---|---|---|
| ReplicationController | core/v1 | 已废弃,被 ReplicaSet 替代 |
| ReplicaSet | apps/v1 | 维持指定数量 Pod 副本 |
| Deployment | apps/v1 | 管理 ReplicaSet,提供声明式更新 |
| DaemonSet | apps/v1 | 每个节点运行一个 Pod 副本 |
| StatefulSet | apps/v1 | 有状态应用管理 |
| Job | batch/v1 | 一次性批处理任务 |
| CronJob | batch/v1 | 基于时间调度的 Job |
| HPA | autoscaling/v2 | 基于指标自动扩缩容 |
二、ReplicaSet
2.1 功能与参数
ReplicaSet 通过 spec.selector.matchLabels 关联 Pod,通过 spec.template 定义 Pod 模板。标签必须一致,否则控制器无法接管已有 Pod。
| 参数路径 | 说明 |
|---|---|
| spec.replicas | 期望副本数 |
| spec.selector.matchLabels | 标签选择器 |
| spec.template.metadata.labels | Pod 模板标签,须与 selector 匹配 |
| spec.template.spec.containers | 容器定义列表 |
2.2 实验记录
生成 YAML:
kubectl create deployment webcluster --image myapp:v1 --dry-run=client -o yaml > repset.yml
repset.yml:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: webcluster
labels:
app: webcluster
spec:
replicas: 2
selector:
matchLabels:
app: webcluster
template:
metadata:
labels:
app: webcluster
spec:
containers:
- name: myapp
image: myapp:v1
创建与验证:
kubectl apply -f repset.yml
kubectl get pods --show-labels
输出:
NAME READY STATUS LABELS
webcluster-tbxq4 1/1 Running app=webcluster
webcluster-jna23 1/1 Running app=webcluster
伸缩测试:
kubectl scale replicaset webcluster --replicas 4
kubectl get pods --show-labels
# 输出4个Pod,均带 app=webcluster 标签
kubectl scale replicaset webcluster --replicas 2
kubectl get pods --show-labels
# 缩减回2个
标签篡改触发自愈:
kubectl label pod webcluster-tbxq4 app=webcluster-tmp --overwrite
kubectl get pods --show-labels
输出:
webcluster-jna23 1/1 Running app=webcluster
webcluster-tbxq4 1/1 Running app=webcluster-tmp
webcluster-tr5qk 1/1 Running app=webcluster
原 Pod 标签被改后脱离控制器管理,ReplicaSet 立即新建一个 Pod 补足副本数。
删除 Pod 自愈验证:
kubectl delete pod webcluster-jna23
kubectl get pods --show-labels
# 新的 webcluster-9km2p 被创建
恢复原标签并清理:
kubectl label pod webcluster-tbxq4 app=webcluster --overwrite
kubectl delete -f repset.yml
三、Deployment
3.1 架构关系
Deployment → ReplicaSet(v1) → Pod
↓
ReplicaSet(v2) → Pod(滚动更新期间)
Deployment 不直接管理 Pod,每个 ReplicaSet 对应一个镜像版本。更新时创建新 ReplicaSet,逐步扩容新 RS 同时缩容旧 RS。
3.2 滚动更新参数
| 参数 | 默认值 | 含义 |
|---|---|---|
| maxSurge | 25% | 更新期间可超出期望副本数的最大数量 |
| maxUnavailable | 25% | 更新期间允许低于期望副本数的最大数量 |
| minReadySeconds | 0 | 新 Pod 就绪后等待时间,防止过早判定可用 |
3.3 实验记录
dep.yml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: webcluster
labels:
app: webcluster
spec:
minReadySeconds: 5
replicas: 2
selector:
matchLabels:
app: webcluster
template:
metadata:
labels:
app: webcluster
spec:
containers:
- name: myapp
image: myapp:v1
创建与暴露服务:
kubectl apply -f dep.yml
kubectl expose deployment webcluster --port 80 --target-port 80
curl 10.107.142.60
# Hello MyApp | Version: v1 | ...
升级到 v2:
修改 image: myapp:v2 后重新 apply,验证:
curl 10.107.142.60
# Hello MyApp | Version: v2 | ...
kubectl get replicasets.apps
# webcluster-77c87d9946 0 0 0(旧)
# webcluster-7f4786db9c 2 2 2(新)
回滚到 v1:
修改 image: myapp:v1 后重新 apply,验证版本恢复为 v1。
自定义滚动策略:
spec:
replicas: 6
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
kubectl apply -f dep.yml
kubectl describe deployment webcluster | grep RollingUpdate
# RollingUpdateStrategy: 0 max unavailable, 1 max surge
暂停与恢复:
kubectl rollout pause deployment webcluster
# 修改 dep.yml 中 image 和 resources 后 apply,不会触发更新
kubectl rollout history deployment webcluster # 无新 revision
kubectl rollout resume deployment webcluster
kubectl rollout history deployment webcluster # 新增 revision 3
清理:
kubectl delete -f dep.yml
kubectl delete service webcluster
四、DaemonSet
4.1 调度行为
| 场景 | 行为 |
|---|---|
| 新节点加入集群 | 自动在新节点创建 Pod |
| 节点被删除 | 回收该节点上的 Pod |
| 设置 nodeSelector | 仅在匹配标签的节点上运行 |
4.2 实验记录
daemonset.yml:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: daemonset
labels:
app: daemonset
spec:
selector:
matchLabels:
app: daemonset
template:
metadata:
labels:
app: daemonset
spec:
containers:
- name: myapp
image: myapp:v1
创建验证:
kubectl apply -f daemonset.yml
kubectl get pods -o wide
输出(3节点集群):
daemonset-87h6s 10.244.0.8 k8s-master
daemonset-n4vs4 10.244.2.38 k8s-node2
daemonset-vhxmq 10.244.1.40 k8s-node1
加入 node3 后自动调度:
kubectl get pods -o wide
# 新增 daemonset-pq9km 10.244.3.2 node3
清理:
kubectl delete -f daemonset.yml
五、Job
5.1 重启策略对照
| restartPolicy | Pod 失败行为 | 适用场景 |
|---|---|---|
| OnFailure | 容器重启,Pod 不重建 | 任务可重试 |
| Never | 创建新 Pod,原 Pod 保留 Completed 状态 | 需查看失败日志 |
| Always | 持续重启 | 不适用于 Job |
5.2 实验记录
job.yml:
apiVersion: batch/v1
kind: Job
metadata:
name: testjob
spec:
completions: 6
parallelism: 2
backoffLimit: 4
template:
spec:
restartPolicy: Never
containers:
- name: testjob
image: busybox
command: ["/bin/sh", "-c"]
args:
- |
echo this is testjob message
sleep 10
创建与验证:
kubectl apply -f job.yml
kubectl get pods
# 看到多个 testjob-xxxxx Pod,状态依次为 Completed
kubectl logs testjob-4cdlr
# this is testjob message
| 字段 | 值 | 含义 |
|---|---|---|
| completions | 6 | 总共需要成功完成 6 次 |
| parallelism | 2 | 同时最多运行 2 个 Pod |
| backoffLimit | 4 | 失败重试上限 |
六、CronJob
6.1 调度格式
与 Linux cron 一致:
分钟 小时 日 月 星期
6.2 实验记录
cronjob.yml:
apiVersion: batch/v1
kind: CronJob
metadata:
name: cronjob
spec:
schedule: "* * * * *"
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: cronjob
image: busybox
command: ["/bin/sh", "-c"]
args:
- echo "hello timinglee"
创建与验证:
kubectl apply -f cronjob.yml
kubectl get cronjobs.batch
# NAME SCHEDULE ACTIVE LAST SCHEDULE AGE
# cronjob * * * * * 0 17s 70s
kubectl get pods
# cronjob-29598241-pxggh 0/1 Completed 0 2m
kubectl logs cronjob-29598241-pxggh
# hello timinglee
清理:
kubectl delete -f cronjob.yml
七、问题排查速查表
| 现象 | 排查命令 |
|---|---|
| Pod 一直 Pending | kubectl describe pod <name> 查看 Events |
| Pod 反复重启 | kubectl logs <pod> --previous |
| 滚动更新卡住 | kubectl rollout status deployment <name> |
| 标签不匹配导致 Pod 不被接管 | kubectl get pods --show-labels 对比 selector |
| DaemonSet Pod 未调度到新节点 | 检查节点污点 kubectl describe node <node> |
| Job 不执行 | 检查 restartPolicy 是否为 Never 或 OnFailure |
| CronJob 未触发 | 检查 schedule 格式及控制器时间同步 |