目录
一、Pod控制器及其功用
二、Deployment控制器
三、StatefulSet控制器
四、DaemonSet控制器
五、Job控制器
六、CronJob 控制器
一、Pod控制器及其功用
Pod控制器,又称之为工作负载(workload),是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试进行重启,当根据重启策略无效,则会重新新建pod的资源。
在kubernetes中,有很多类型的Pod控制器,每种都有自己的适合的场景,常见的有下面这些:
- ReplicaSet: 代用户创建指定数量的pod副本,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能。
- Deployment:工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。(ReplicaSet 与Deployment 这两个资源对象逐步替换之前RC的作用。)
- DaemonSet:用于确保集群中的每一个节点只运行特定的pod副本,通常用于实现系统级后台任务。比如ELK服务
- StatefulSet:管理有状态应用
- Job:只要完成就立即退出,不需要重启或重建
- Cronjob:周期性任务控制,不需要持续后台运行
二、Deployment控制器
- 部署无状态应用
- 管理Pod和ReplicaSet
- 具有上线部署、副本设定、滚动升级、回滚等功能
- 提供声明式更新,例如只更新一个新的image
- 应用场景:web服务
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.15.4
name: nginx
ports:
- containerPort: 80
#创建Pod
kubectl create -f nginx-deployment.yaml
#查看
kubectl get pods,deploy,rs
#查看控制器配置
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
......
三、StatefulSet控制器
部署有状态应用需要
- 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
- 稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
- 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
- 有序收缩,有序删除(即从N-1到0)
部署有状态应用的,每个Pod 唯一且不变的,每个Pod 拥有自己专属的持久化的存储(PVC和PV)
在Deployment中,与之对应的服务是service, 而在StatefulSet中与之对应的headless service(headless service,即无头服务) 与service的区别就是它没有Cluster IP,解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。
除此之外,StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod副本创建了一个DNS域名,这个域名的格式为:
$(podname).(headless server name)
FQDN: $(podname).(headless server name).namespace.svc.cluster.local
从上面的应用场景可以发现,statefulset由以下几个部分组成:
- Headless service: 无头服务,用于为pod资源标识符 生成可解析的DNS记录。
- VolumeClaimTemplates: 存储卷的申请模板,基于静态或动态的pv供给方式,为pod资源提供专有的固定存储。
- statefulset: 用于管控pod资源。
为什么要有headless service 无头服务?
- 在deployment中,每一个pod是没有名称,是随机字符串,是无序的。而statefulset中是要求有序的,每一个pod的名称必须是固定的。当节点挂了,重建之后的标识符是不变的,每一个节点的节点名称是不能改变的。pod名称是作为pod识别的唯一标识符,必须保证其标识符的稳定并且唯一。
- 为了实现标识符的稳定,这时候就需要一个headless service 解析直达到pod,还需要给pod配置一个唯一的名称。
为什么要有volumeClainTemplate?
- 大部分有状态副本集都会用到持久存储,比如分布式系统来说,由于数据时不一样的,每个节点都需要自己专用的存储节点。而在deployment 中的pod模板中创建的存储卷是一个共享pod是不适应的,多个pod使用同一个存储卷,而statefulset定义中的每个pod都不能使用同一个存储卷,由此基于pod模板创建pod时不适应 的。
- 这就需要引入volume Clain Template ,当在使用statefulset创建pod时,会自动生成一个PVC,从而请求绑定一个PV,从而请求绑定一个PV,从而有自己的专用的存储卷。
创建statefulset控制器
目前服务器中已经创建好了storageclass 自动创建pv的功能。
下面进行创建statefulset控制器创建pod,在 volumeClaimTemplates 中定义好storageclass的名称,在创建statefulset后,它会自动创建pvc和pv。
vim statefulset.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None #不创建custerip,也就是无头服务的service
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 3 #三个副本
template: #定义容器的模板
metadata:
labels:
app: nginx
spec:
terminationGracePeriodSeconds: 10 #10秒内pod没关闭,就强制杀死
containers:
- name: nginx
image: nginx:1.14.1
ports:
- containerPort: 80
name: web
volumeMounts: #容器内挂载
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates: #存储卷的申请模板
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ] #可读可写,仅能一个节点挂载
storageClassName: "nfs-client-storageclass" #使用动态创建的pv
resources: #设置请求的资源大小
requests:
storage: 2Gi
解析上面: 由于StatefulSet资源依赖于一个实现存在的Headless类型的Service资源,所以需要先定义一个名为nginx的Headless Service资源,用于为关联到每个Pod资源创建DNS资源记录。接着定义了一个名为web的StatefulSet资源,它通过Pod模板创建了3个Pod资源副本,并基于volumeClaimTemplates向存储类进行了请求大小为2Gi的专用存储卷。
下面开始创建
kubectl apply -f statefulset.yaml
#创建service和statefulset。
kubectl get pods -w
kubectl get pvc -w
kubectl get pv -w
滚动更新
kubectl set image statefulset web nginx=nginx:1.17.1
#升级版本
在创建的每一个Pod中,每一个pod自己的名称都是可以被解析的
#从上面的解析,我们可以看到在容器当中可以通过对Pod的名称进行解析到ip。其解析的域名格式如下:
(pod_name).(service_name).(namespace_name).svc.cluster.local
总结:
无状态:
- deployment 认为所有的pod都是一样的
- 不用考虑顺序的要求
- 不用考虑在哪个node节点上运行
- 可以随意扩容和缩容
有状态
- 实例之间有差别,每个实例都有自己的独特性,元数据不同,例如etcd,zookeeper
- 实例之间不对等的关系,以及依靠外部存储的应用。
常规service和无头服务区别
- service: 一组Pod访问策略,提供cluster-IP群集之间通讯,还提供负载均衡和服务发现。
- Headless service: 无头服务,不需要cluster-IP,而是直接以DNS记录的方式解析出被代理Pod的IP地址。
四、DaemonSet控制器
DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
使用 DaemonSet 的一些典型用法:
- 运行集群存储 daemon,例如在每个 Node 上运行 glusterd、ceph。
- 在每个 Node 上运行日志收集 daemon,例如fluentd、logstash。
- 在每个 Node 上运行监控 daemon,例如 Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond。
应用场景:Agent
//官方案例(监控)
https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
示例:
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
kubectl apply -f ds.yaml
//DaemonSet会在每个node节点都创建一个Pod
kubectl get pods
nginx-deployment-4kr6h 1/1 Running 0 35s
nginx-deployment-8jrg5 1/1 Running 0 35s
五、Job控制器
Job分为普通任务(Job)和定时任务(CronJob),常用于运行那些仅需要执行一次的任务
应用场景:数据库迁移、批处理脚本、kube-bench扫描、离线数据处理,视频解码等业务
官方案例:https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/
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
- .spec.template.spec.restartPolicy该属性拥有三个候选值:OnFailure,Never和Always。默认值为Always。它主要用于描述Pod内容器的重启策略。在Job中只能将此属性设置为OnFailure或Never,否则Job将不间断运行。
- .spec.backoffLimit用于设置job失败后进行重试的次数,默认值为6。默认情况下,除非Pod失败或容器异常退出,Job任务将不间断的重试,此时Job遵循 .spec.backoffLimit上述说明。一旦.spec.backoffLimit达到,作业将被标记为失败。
kubectl apply -f job-limit.yaml
kubectl get job,pods
NAME COMPLETIONS DURATION AGE
job.batch/busybox 0/1 4m34s 4m34s
NAME READY STATUS RESTARTS AGE
pod/busybox-dhrkt 0/1 Error 0 4m34s
pod/busybox-kcx46 0/1 Error 0 4m
pod/busybox-tlk48 0/1 Error 0 4m21s
kubectl describe job busybox
......
Warning BackoffLimitExceeded 43s job-controller Job has reached the specified backoff limit
六、CronJob 控制器
周期性任务,像Linux的Crontab一样。
周期性任务
应用场景:通知,备份
官方案例:https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/
vim cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
imagePullPolicy: IfNotPresent
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
kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 0 <none> 25s
kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-1621587180-mffj6 0/1 Completed 0 3m
hello-1621587240-g68w4 0/1 Completed 0 2m
hello-1621587300-vmkqg 0/1 Completed 0 60s
kubectl logs hello-1621587180-mffj6
Fri May 21 09:03:14 UTC 2021
Hello from the Kubernetes cluster
//如果报错: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