一、Pod控制器概述
Pod 控制器(Controller) 又称为 工作负载(Workload) ,是 Kubernetes 中用于 管理 Pod 的中间层。 它的职责是确保集群中的 Pod 资源始终符合用户定义的"期望状态"。
功能
-
保证 Pod 副本数量与期望一致
-
Pod 异常退出时,自动根据重启策略重建
-
支持伸缩(扩容/缩容)、滚动更新、回滚
二、Pod控制器的类型
控制器 | 功能 | 应用场景 |
---|---|---|
ReplicaSet | 保证指定数量的 Pod 副本存在,支持滚动扩缩容。通常不直接使用,由 Deployment 管理。 | 无状态应用 |
Deployment | 管理 ReplicaSet,实现声明式部署、滚动升级、回滚等。 | Web 服务 |
StatefulSet | 管理有状态应用,提供稳定的网络标识与存储。 | 数据库、Zookeeper |
DaemonSet | 每个 Node 上运行一个 Pod。 | 日志、监控、Agent |
Job | 执行一次性任务。 | 批处理、数据库迁移 |
CronJob | 周期性任务(类似 Crontab)。 | 定期备份、通知 |
三、Deployment控制器
3.1 特点
-
管理无状态应用
-
支持滚动更新与回滚
-
声明式配置更新
-
与 ReplicaSet 协作使用
3.2 案例
bash
vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.15.4
ports:
- containerPort: 80
kubectl create -f nginx-deployment.yaml
kubectl get pods,deploy,rs

3.3 查看控制器配置
bash
kubectl edit deployment/nginx-deployment
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2021-04-19T08:13:50Z"
generation: 1
labels:
app: nginx #Deployment资源的标签
name: nginx-deployment
namespace: default
resourceVersion: "167208"
selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/nginx-deployment
uid: d9d3fef9-20d2-4196-95fb-0e21e65af24a
spec:
progressDeadlineSeconds: 600
replicas: 3 #期望的pod数量,默认是1
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25% #升级过程中会先启动的新Pod的数量不超过期望的Pod数量的25%,也可以是一个绝对值
maxUnavailable: 25% #升级过程中在新的Pod启动好后销毁的旧Pod的数量不超过期望的Pod数量的25%,也可以是一个绝对值
type: RollingUpdate #滚动升级
template:
metadata:
creationTimestamp: null
labels:
app: nginx #Pod副本关联的标签
spec:
containers:
- image: nginx:1.15.4 #镜像名称
imagePullPolicy: IfNotPresent #镜像拉取策略
name: nginx
ports:
- containerPort: 80 #容器暴露的监听端口
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always #容器重启策略
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
......
##查看历史版本
[root@master01 ~]# kubectl rollout history deployment nginx-deployment
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
1 <none>
四、StatefulSet控制器(有状态)
4.1 特点
- 稳定存储:基于 PVC 实现,每个 Pod 独立存储
- 稳定网络标识:Pod 名称和 DNS 名称固定
- 有序部署/删除 :从
0 → N-1
创建,从N-1 → 0
删除 - 依赖 Headless Service
4.2 三个核心组件
-
Headless Service(无头服务):用于为Pod资源标识符生成可解析的DNS记录。
-
volumeClaimTemplates(存储卷申请模板):基于静态或动态PV供给方式为Pod资源提供专有的固定存储。
-
StatefulSet:用于管控Pod资源。
为什么要有headless?
在deployment中,每一个pod是没有名称,是随机字符串,是无序的。而statefulset中是要求有序的,每一个pod的名称必须是固定的。当节点挂了,重建之后的标识符是不变的,每一个节点的节点名称是不能改变的。pod名称是作为pod识别的唯一标识符,必须保证其标识符的稳定并且唯一。为了实现标识符的稳定,这时候就需要一个headless service 解析直达到pod,还需要给pod配置一个唯一的名称。
为什么要有volumeClainTemplate?
大部分有状态副本集都会用到持久存储,比如分布式系统来说,由于数据是不一样的,每个节点都需要自己专用的存储节点。而在 deployment中pod模板中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,而statefulset定义中的每一个pod都不能使用同一个存储卷,由此基于pod模板创建pod是不适应的,这就需要引入volumeClainTemplate,当在使用statefulset创建pod时,会自动生成一个PVC,从而请求绑定一个PV,从而有自己专用的存储卷。
4.3 StatefulSet+NFS持久卷(案例)
4.3.1 定义Headless Service
bash
vim stateful-headless.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: myapp-pod
kubectl apply -f stateful-headless.yaml
4.3.2 定义StatefulSet动态
bash
vim stateful-demo.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: myapp
spec:
serviceName: myapp-svc
replicas: 3
selector:
matchLabels:
app: myapp-pod
template:
metadata:
labels:
app: myapp-pod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: myappdata
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: myappdata
annotations: #动态PV创建时,使用annotations在PVC里声明一个StorageClass对象的标识进行关联
volume.beta.kubernetes.io/storage-class: nfs-client-storageclass
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 2Gi
解析上例:由于 StatefulSet 资源依赖于一个实现存在的 Headless 类型的 Service 资源,所以需要
先定义一个名为 myapp-svc 的 Headless Service 资源,用于为关联到每个 Pod 资源创建 DNS 资源记
录。接着定义了一个名为 myapp 的 StatefulSet 资源,它通过 Pod 模板创建了 3 个 Pod 资源副本,
并基于 volumeClaimTemplates 向前面创建的PV进行了请求大小为 2Gi 的专用存储卷。
4.3.3 创建与验证
bash
kubectl apply -f stateful-demo.yaml
kubectl get sts,pvc,pv,pods
4.3.4 滚动更新
bash
//StatefulSet 控制器将在 StatefulSet 中删除并重新创建每个 Pod。它将以与 Pod 终止相同
的顺序进行(从最大的序数到最小的序数),每次更新一个 Pod。在更新其前身之前,它将等待正
在更新的 Pod 状态变成正在运行并就绪。如下操作的滚动更新是按照2-0的顺序更新。
# 修改镜像版本
kubectl edit sts myapp
kubectl get pods -w # 观察按序更新 2→1→0
4.3.5 pod的名称解析
bash
kubectl exec -it myapp-0 /bin/sh
Name: myapp-0.myapp-svc.default.svc.cluster.local
Address 1: 10.244.2.27 myapp-0.myapp-svc.default.svc.cluster.local
/ # nslookup myapp-1.myapp-svc.default.svc.cluster.local
nslookup: can't resolve '(null)': Name does not resolve
Name: myapp-1.myapp-svc.default.svc.cluster.local
Address 1: 10.244.1.14 myapp-1.myapp-svc.default.svc.cluster.local
/ # nslookup myapp-2.myapp-svc.default.svc.cluster.local
nslookup: can't resolve '(null)': Name does not resolve
Name: myapp-2.myapp-svc.default.svc.cluster.local
Address 1: 10.244.2.26 myapp-2.myapp-svc.default.svc.cluster.local
//从上面的解析,我们可以看到在容器当中可以通过对Pod的名称进行解析到ip。其解析的域名格式如下:
(pod_name).(service_name).(namespace_name).svc.cluster.local
//总结
无状态:
1)deployment 认为所有的pod都是一样的
2)不用考虑顺序的要求
3)不用考虑在哪个node节点上运行
4)可以随意扩容和缩容
有状态
1)实例之间有差别,每个实例都有自己的独特性,元数据不同,例如etcd,zookeeper
2)实例之间不对等的关系,以及依靠外部存储的应用。
常规service和无头服务区别
service:一组Pod访问策略,提供cluster-IP群集之间通讯,还提供负载均衡和服务发现。
Headless service:无头服务,不需要cluster-IP,而是直接以DNS记录的方式解析出被代理Pod的IP地址。
五、DaemonSet控制器
5.1 功能
确保每个 Node 上都运行一个 Pod 副本,常用于运行系统级后台任务(守护进程)。
典型场景:
-
Fluentd / Logstash 日志收集
-
Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond 监控代理
-
存储服务如 Ceph、GlusterFS
5.2 案例
bash
vim ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-daemonSet
labels:
app: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.15.4
ports:
- containerPort: 80
DaemonSet会在每个node节点都创建一个Pod
kubectl get pods
六、Job控制器
6.1 功能
用于执行一次性任务,任务完成后即退出。
应用场景:
-
数据迁移
-
批处理
-
安全扫描
-
离线数据处理
6.2 案例1
bash
vim job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
kubectl apply -f job.yaml
kubectl logs job/pi
#参数解释
.spec.template.spec.restartPolicy该属性拥有三个候选值:OnFailure,Never和Always。默认值
为Always。它主要用于描述Pod内容器的重启策略。在Job中只能将此属性设置为OnFailure或Never,否
则Job将不间断运行。
.spec.backoffLimit用于设置job失败后进行重试的次数,默认值为6。默认情况下,除非Pod失败或容器
异常退出,Job任务将不间断的重试,此时Job遵循 .spec.backoffLimit上述说明。旦.spec.backoffLimit
达到,作业将被标记为失败。
//在所有node节点下载perl镜像,因为镜像比较大,所以建议提前下载好
docker pull perl
kubectl apply -f job.yaml
kubectl get pods
pi-bqtf7 0/1 Completed 0 41s
//结果输出到控制台
kubectl logs pi-bqtf7
3.14159265......
//清除job资源
kubectl delete -f job.yaml
6.3 案例2
bash
//backoffLimit
vim job-limit.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: busybox
spec:
template:
spec:
containers:
- name: busybox
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "sleep 10;date;exit 1"]
restartPolicy: Never
backoffLimit: 2
kubectl apply -f job-limit.yaml
command: ["/bin/sh", "-c", "sleep 10;date;exit 1"]
容器启动后执行的命令:
sleep 10 → 先睡眠 10 秒
date → 打印当前日期
exit 1 → 以 退出码 1 结束容器(即任务失败)
七、CronJob控制器
7.1 功能
周期性任务(类似 Linux Crontab)。
应用场景:
-
定期备份
-
定时通知
-
日志清理
7.2 案例
bash
# 每分钟打印hello
vim cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
//cronjob其它可用参数的配置
spec:
concurrencyPolicy: Allow #要保留的失败的完成作业数(默认为1)
schedule: '*/1 * * * *' #作业时间表。在此示例中,作业将每分钟运行一次
startingDeadlineSeconds: 15 #pod必须在规定时间后的15秒内开始执行,若超过该时间未执行,则任务将不运行,且标记失败
successfulJobsHistoryLimit: 3 #要保留的成功完成的作业数(默认为3)
terminationGracePeriodSeconds: 30 #job存活时间 默认不设置为永久
jobTemplate: #作业模板。这类似于工作示例
kubectl create -f cronjob.yaml
//如果报错:Error from server (Forbidden): Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) ( pods/log hello-1621587780-c7v54)
//解决办法:绑定一个cluster-admin的权限
kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous
八、无状态vs有状态应用对比
对比项 | 无状态(Deployment) | 有状态(StatefulSet) |
---|---|---|
Pod 名称 | 随机生成 | 固定、有序(0→N-1) |
存储 | 共享存储或无持久卷 | 每个 Pod 独立 PVC |
网络标识 | 不固定 | 稳定 DNS 名称 |
扩缩容顺序 | 无序 | 有序(依次创建/删除) |
应用示例 | Web、API | MySQL、ZooKeeper |
九、常规Service与Headless Service对比
类型 | 是否有 ClusterIP | 访问方式 | 作用 |
---|---|---|---|
Service | 有 | 负载均衡 + 服务发现 | 集群统一访问入口 |
Headless Service | 无 | 直接解析到 Pod IP | StatefulSet 中 DNS 定位 |
十、服务发现机制
Kubernetes 内置 DNS 机制:
-
1.3 以前:SkyDNS
-
1.3 ~ 1.11:KubeDNS
-
1.11 以后:CoreDNS
Pod 间通信域名格式:(pod_name).(service_name).(namespace).svc.cluster.local
十一、总结
控制器 | 是否有状态 | 功能简述 |
---|---|---|
Deployment | ❌ | 无状态应用部署、滚动升级 |
ReplicaSet | ❌ | 保证副本数量,通常由 Deployment 管理 |
StatefulSet | ✅ | 有状态应用,稳定网络与存储 |
DaemonSet | ❌ | 每个节点运行一个 Pod |
Job | ❌ | 一次性任务 |
CronJob | ❌ | 周期性任务 |