工作负载型控制器的应用
工作负载控制器(Workload Controllers)时kubernetes的一个抽象概念,用于更高层次对象,部署和管理pod。
常用工作负载控制器:
- Deployment:无状态应用部署
- StatefulSet:有状态应用部署
- DaemonSet:确保所有Node运行同一个Pod
- JOb:一次性服务
- Cronjob:定时任务
控制器的作用:
- 管理pod对象
- 使用标签与Pod关联
- 控制器实现了Pod的运维,例如滚动更新、伸缩、副本管理、维护Pod状态等。
Deployment
基于ReplicaSet之上,可为Pod和ReplicaSet资源提供声明式更新,它具有以下特性:
- 事件和状态查看:可以查看Deployment对象升级的详细进度和状态
- 回滚:当升级操作完成后发现问题时,支持将应用返回到指定的历史版本中
- 版本记录:对Deployment 对象的每一次操作都予以保存
- 暂停和启动:每一次升级,都可以随时暂停和启动
- 多种自动更新方案:Recreate-重建更新、RollingUpdate-滚动更新
应用场景:
- 网站
- 微服务
- APi
Deployment的更新策略描述如下:
RollingUpdate 策略:旧控制器的Pod数量不断减少,同时新控制器的Pod不断增加,以下两个属性:
- maxSurge:升级期间存在的总Pod数量最多可超过期望值的个数,可以是数值或百分比。
- maxUnavailabe:升级期间正常可用的Pod数(新旧版本)最多不能低于期望的个数,可以是数值或百分比。
滚动升级更新策略
spec:
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app:web
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
注意: 在实际应用中,maxSurge: 25% 和maxUnavailable: 25% ,通常都是1 : 1,关几个,跑几个,为保证服务更新时务业服务的可用性。
Recreate 策略:在删除旧的 pod 之后才开始创建新的 pod。 如果你的应用程序不支持多个版本同时对外提供服务, 需要在启动新版本之前完全停用旧版本, 那么需要使用这种策略。 但是使用这种策略的话, 会导致应用程序出现短暂的不可用。
Deployment实现滚动升级
[root@master ~]# vi test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 4
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: xxkk/httpd:v1.0
imagePullPolicy: IfNotPresent
先运行一个v1版本的pods
[root@master ~]# kubectl delete -f test.yaml
deployment.apps "web" deleted
[root@master ~]# kubectl get pods //此时都是v1版本
NAME READY STATUS RESTARTS AGE
web-66dc445c66-5sd42 1/1 Running 0 50s
web-66dc445c66-8fjld 1/1 Running 0 50s
web-66dc445c66-8wdc9 1/1 Running 0 50s
web-66dc445c66-fc9lf 1/1 Running 0 50s
# 更改版本镜像v1-v2
[root@master ~]# vi test.yaml
......
containers:
- name: httpd
image: xxkk/httpd:v2.0
imagePullPolicy: IfNotPresent
......
# 应用部署
[root@master ~]# kubectl apply -f test.yaml
deployment.apps/web configured
[root@master ~]# kubectl get pods
# 发现有五个正在创建或运行的,一个正在关闭,五个运行,其中包括了四个之前就创建过的;
在策略中, replicas: 4(副本的总数量),maxSurge=25%(1/4),maxUnavailable: 25%(1/4)也就是一个,当更新时控制关闭一个pod,然后启动一个pod。所以在运行的pod为:4+1个。
NAME READY STATUS RESTARTS AGE
web-66dc445c66-8gkcv 0/1 ContainerCreating 0 1s
web-66dc445c66-gv6gx 0/1 ContainerCreating 0 1s
web-689dbd69c9-l6t69 1/1 Running 0 2m25s
web-689dbd69c9-p8xtq 1/1 Running 0 2m25s
web-689dbd69c9-prdls 1/1 Running 0 2m23s
# 4的1 /4为一,所以在更新时,关闭了一个
web-689dbd69c9-xbtwl 1/1 Terminating 0 2m22s
# 修改占比,将占比改为50%(1/2)
[root@master ~]# vim test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 4
strategy:
rollingUpdate:
maxSurge: 50% //修改此处
maxUnavailable: 50% //修改此处
type: RollingUpdate
......此处省略n行
spec:
containers:
- name: httpd
image: xxkk/httpd:v1.0 //修改版本
imagePullPolicy: IfNotPresent
# maxSurge: 50% //更新时,启动的Pod数量,占总数量的1/2
# maxUnavailable: 50% //更新时,关闭的Pod数量,占总数量的1/2
# replicas: 4 副本数量
# 重新应用
[root@master ~]# kubectl apply -f test.yaml
Adeployment.apps/web configured
#原来正在运行四个
# 正在在运行 = 启动两个,4+(4*0.5)=6个,关闭两个(4*0.5=2)个,runing:150%,Closing:50%
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-66dc445c66-8gkcv 1/1 Terminating 0 13m
web-66dc445c66-gv6gx 1/1 Terminating 0 13m
web-66dc445c66-mqqdk 1/1 Running 0 13m
web-66dc445c66-rgqqz 1/1 Running 0 13m
web-689dbd69c9-5mkm6 0/1 ContainerCreating 0 1s
web-689dbd69c9-g4px6 0/1 ContainerCreating 0 1s
web-689dbd69c9-hvh86 0/1 ContainerCreating 0 1s
web-689dbd69c9-jc57n 0/1 ContainerCreating 0 1s
# 总共8个
# 等待更新完毕
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-689dbd69c9-5mkm6 1/1 Running 0 13m
web-689dbd69c9-g4px6 1/1 Running 0 13m
web-689dbd69c9-hvh86 1/1 Running 0 13m
web-689dbd69c9-jc57n 1/1 Running 0 13m
版本记录
-
kubectl rollout history deployment/web # 查看历史发布版本
-
kubectl rollout undo deployment/web # 回滚上一个版本
-
kubectl rollout undo deployment/web --to-revision=2 # 回滚历史指定版本
# 先清除之前创建的资源,将版本历史清空
[root@master ~]# kubectl delete -f test.yaml
deployment.apps "web" deleted
[root@master ~]# cat test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 4
revisionHistoryLimit:10 //版本的最大存储版本数
strategy:
rollingUpdate:
maxSurge: 50%
maxUnavailable: 50%
type: RollingUpdate
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: xxkk/httpd:v2.0
imagePullPolicy: IfNotPresent
# 然后重新部署新资源,此时为1版本
[root@master ~]# kubectl apply -f test.yaml
deployment.apps/web created
[root@master ~]# vi test.yaml //变更版本
......
containers:
- name: httpd
image: xxkk/httpd:v1.0 //修改此处
imagePullPolicy: IfNotPresent
......
[root@master ~]# kubectl apply -f test.yaml //重新应用,此时为2版本
deployment.apps/web configured
[root@master ~]# kubectl rollout history deployment/web //查看版本,发现有1,2两个版本
deployment.apps/web
REVISION CHANGE-CAUSE
1 <none> //旧版本,上一个版本
2 <none> //所在版本
[root@master ~]# vi test.yaml
[root@master ~]# kubectl apply -f test.yaml
deployment.apps/web configured
[root@master ~]# kubectl rollout history deployment/web
deployment.apps/web
REVISION CHANGE-CAUSE
2 <none> //上一个版本
3 <none> //所在版本
# revisionHistoryLimit:10,发现并没有继续存储,版本1被2替代。
# 原因在于我们只使用了两个镜像,若镜像一致,系统则会替代
# 回滚到上一个版本
[root@master ~]# kubectl rollout undo deployment/web
deployment.apps/web rolled back
[root@master ~]# kubectl rollout history deployment/web
deployment.apps/web
REVISION CHANGE-CAUSE
3 <none>
4 <none>
# 回滚到指定版本
[root@master ~]# kubectl rollout undo deploy/web --to-revision 3
deployment.apps/web rolled back
[root@master ~]# kubectl rollout history deployment/web
deployment.apps/web
REVISION CHANGE-CAUSE
4 <none>
5 <none>
ReplicaSet
说到ReplicaSet对象,得先说说ReplicationController(简称为RC)。在旧版本的Kubernetes中,只有ReplicationController对象。它的主要作用是确保Pod以你指定的副本数运行,即如果有容器异常退出,会自动创建新的 Pod 来替代;而异常多出来的容器也会自动回收。
ReplicationController、ReplicaSet、Deployment的区别
ReplicaSet是新一代的ReplicationController, 并推荐使用它替代ReplicationController来复制和管理 Pod。
同时,在使用 Deployment 时,实际的 Pod是由Deployment的Replicaset创建和管理的,而不是由Deployment直接创建和管理的。
# 查看RS记录
[root@master ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
web-66dc445c66 0 0 0 32s
web-689dbd69c9 4 4 3 3s
#版本对应RS记录
[root@master ~]# kubectl rollout history deployment web
deployment.apps/web
REVISION CHANGE-CAUSE
1 <none>
2 <none>
[root@master ~]# vi test.yaml //变更版本
......
containers:
- name: httpd
image: xm17671855780/httpd:v2.0 //修改此处
imagePullPolicy: IfNotPresent
......
[root@master ~]# kubectl apply -f test.yaml
deployment.apps/web configured
# 发现每次版本变更时对应一个RS,上一个版本被干掉了,新的版本会生成新的Rs
[root@master ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
web-66dc445c66 4 4 4 2m7s
web-689dbd69c9 0 0 0 98s
[root@master ~]#
DaemonSet
DaemonSet控制器确保集群中的每一个Node只运行一个特定的Pod副本,实现系统级的后台任务,也具有标签选择器。也可以指定部分满足条件的Node运行一个Pod副本,比如监控具有ssd存储的Node节点。
常用来部署一些集群的日志、监控或者其他系统管理应用。典型的应用包括:
- 日志收集,比如fluentd、logstash等。
- 系统监控,比如Prometheus Node Exporter、collectd、New Relic agent、Ganglia gmond等。
- 系统程序,比如kube-proxy、kube-dns、Glusterd、Ceph等
[root@master ~]# kubectl delete deploy/nginx //清除资源
deployment.apps "nginx" deleted
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-689dbd69c9-2stv8 1/1 Terminating 0 6m56s
web-689dbd69c9-7plnz 1/1 Terminating 0 6m56s
web-689dbd69c9-cmngk 0/1 Terminating 0 6m56s
[root@master ~]# kubectl get pods
No resources found in default namespace.
# 修改test.yaml文件
[root@master ~]# vi test.yaml
---
apiVersion: apps/v1
kind: DaemonSet // 指定类型为DaemonSet
metadata:
name: filebeat
namespace: kube-system //指定系统命名空间
spec:
selector:
matchLabels:
name: filebeat
template:
metadata:
labels:
name: filebeat
spec:
containers:
- name: log
image: elastic/filebeat:7.16.2
imagePullPolicy: IfNotPresent
# 容器名:filebeat
[root@master ~]# kubectl apply -f test.yaml
daemonset.apps/filebeat created
[root@master ~]# kubectl get pods -n kube-system -o wide | grep filebeat
filebeat-crlnx 1/1 Running 0 8m1s 10.244.2.119 node02 <none> <none>
filebeat-hplmj 1/1 Running 0 8m1s 10.244.1.64 node01 <none> <none>
# 发现在node01和node02上运行
# 需要在每个节点都运行容器的时候,可以用DameonSet来执行:公共任务
Job控制器
Job控制器用于Pod对象运行一次性任务,容器中的进程在正常运行结束后不会对其进行重启,而是将Pod对象置于"Completed"(完成)状态,若容器中的进程因错误而终止,则需要按照重启策略配置确定是否重启,未运行完成的Pod对象因其所在的节点故障而意外终止后会被调度。 Job控制器的Pod对象的状态转换如下图所示:
Job工作流程及特点:N个作业需要串行运行N次,直至满足期望的次数。如下图所示,这次Job也可以理解为并行度为1的作业执行方式,在某个时刻仅存在一个Pod资源对象。
# 编写一个job.yaml文件
[root@master ~]# vi 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 // 重试次数
[root@master ~]# kubectl apply -f job.yaml //部署
job.batch/pi created
[root@master ~]# kubectl get pods -o wide //此时为正在创建状态
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pi-dtgj6 0/1 ContainerCreating 0 8s <none> node01 <none> <none>
[root@master ~]# kubectl get pods -o wide //当进程运行完成后为完成状态,并不在运行了
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pi-dtgj6 0/1 Completed 0 5m7s 10.244.1.65 node01 <none> <none>
CronJob
CronJob控制器执行周期性任务作业,控制其运行的时间点及重复运行的方式,类似于Linux操作系统的周期性任务作业计划的方式控制其运行的时间点和重复运行的方式
配置项:
- jobTemplate:Job控制器模板。
- schedule:Cron格式的作业调度运行的时间点。
- concurrencyPolicy:并发执行策略,用于定义前一次作业尚未完成时如何执行下一此任务。默认是Allow,即允许前后Job,甚至是属于同一个CrontJob的更多Job同时运行。如果设置为Forbid则禁止前后两个Job同时运行,如果前一个尚未结束,后一个不会启动(跳过),如果设置为Replace,则后一个Job会替代前一个Job,即终止前一个,启动后一个。
- failedJobHistoryLimit:为失败的任务执行保留的历史记录数,默认是1。
- successfulJobsHistoryLimit:为成功的任务执行保留的历史记录数,默认是3。
- startingDeadlineSeconds:因各种原因缺乏执行作业的时间点所导致的启动作业错误的超时时长,会被记入错误历史记录
- suspend:是否挂起后续的任务执行,默认是false。
# 编写cronjob.yaml 文件
[root@master ~]# vi cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *" //每分钟进行一次
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date;echo Hello aliang
restartPolicy: OnFailure
# 部署
[root@master ~]# kubectl apply -f cronjob.yaml
cronjob.batch/hello created
[root@master ~]# kubectl get pods //完成,等待任务执行
NAME READY STATUS RESTARTS AGE
pi-dtgj6 0/1 Completed 0 9m42s
# 记录时间
[root@master ~]# date
2021年 12月 24日 星期五 18:37:12 CST
[root@master ~]# kubectl get pods //此时已经有一个任务了
NAME READY STATUS RESTARTS AGE
hello-27339037-qnvvx 0/1 ContainerCreating 0 14s
pi-dtgj6 0/1 Completed 0 10m
# 我们再等待1分钟查看,任务是否增加
[root@master ~]# date
2021年 12月 24日 星期五 18:38:01 CST
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-27339037-qnvvx 0/1 Completed 0 63s
hello-27339038-9k2mj 0/1 ContainerCreating 0 3s
pi-dtgj6 0/1 Completed 0 11m
# 注意:batch/v1beta1 CronJob 在 v1.21+ 中被弃用,在 v1.25+ 中不可用; 使用批处理/v1 CronJob。