Kubernetes 工作负载
工作负载控制器是什么
工作负载控制器(Workload Controllers)是K8s的一个抽象概念,用于更高级层次对象,部署和管理Pod。
常用工作负载控制器:
- Deployment:无状态应用部署
- StatefulSet:有状态应用部署
- DaemonSet:确保所有Node运行同一个Pod
- Job:一次性任务
- Cronjob:定时任务
控制器的作用:
- 管理Pod对象
- 使用标签与Pod关联
- 控制器实现了Pod的运维,例如滚动更新、伸缩、副本管理、维护Pod状态等
Deployment
基于ReplicaSet之上,可为Pod和ReplicaSet资源提供声明式更新,它具有以下特性:
- 事件和状态查看:可以查看Deployment对象升级的详细进度和状态
- 回滚:当升级操作完成后发现问题时,支持将应用返回到指定的历史版本中
- 版本记录:对Deployment 对象的每一次操作都予以保存
- 暂停和启动:每一次升级,都可以随时暂停和启动
- 多种自动更新方案:Recreate-重建更新、RollingUpdate-滚动更新
应用场景:
- 网站
- 微服务
- APi
Deployment 应用流程如下:
Deployment的更新策略描述如下:
RollingUpdate 策略:旧控制器的Pod数量不断减少,同时新控制器的Pod不断增加,以下两个属性:
- maxSurge:升级期间存在的总Pod数量最多可超过期望值的个数,可以是数值或百分比。
- maxUnavailabe:升级期间正常可用的Pod数(新旧版本)最多不能低于期望的个数,可以是数值或百分比。
滚动升级更新策略
spec:
replicas: 3
revisionHistoryLimit: 10 // 历史版本保存数量,保存数量基于镜像数量
selector:
matchLabels:
app:web
strategy:
rollingUpdate:
maxSurge: 25% //更新时,启动的Pod数量,占总数量的1/4
maxUnavailable: 25% //更新时,关闭的Pod数量,占总数量的1/4
type: RollingUpdate
注意: 在实际应用中,maxSurge: 25% 和maxUnavailable: 25% ,通常都是1 : 1,关几个,跑几个,为保证服务更新时务业服务的可用性。
Recreate 策略:在删除旧的 pod 之后才开始创建新的 pod。 如果你的应用程序不支持多个版本同时对外提供服务, 需要在启动新版本之前完全停用旧版本, 那么需要使用这种策略。 但是使用这种策略的话, 会导致应用程序出现短暂的不可用。
实例
// 本地有镜像
[root@master ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
gaofan1225/httpd v0.2 f61bbd041ba4 11 days ago 89.2MB
// 创建四个httpd容器。名字都叫web
[root@master ~]# cat test2.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: default
spec:
replicas: 4
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: gaofan1225/httpd:v0.2
imagePullPolicy: IfNotPresent
[root@master ~]# kubectl apply -f test2.yaml
deployment.apps/web created
[root@master ~]# kubectl get pods
web-5d688b9745-7gx4g 1/1 Running 0 100s
web-5d688b9745-9hnxz 1/1 Running 0 100s
web-5d688b9745-ft6w9 1/1 Running 0 100s
web-5d688b9745-vmcbv 1/1 Running 0 100s
// 再次编写test2.yaml文件,设置maxSurge、maxUnavaliable
[root@master ~]# cat test2.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: default
spec:
replicas: 4
strategy: // 策略
rollingUpdate: // 滚动更新
maxSurge: 25% // 最大可超出25% // 这两个参数可以一起使用也可以分开使用,根据需求决定
maxUnavailable: 25% // 最大不可用25%
type: RollingUpdate
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: gaofan1225/httpd:v0.2
imagePullPolicy: IfNotPresent
// 应用
[root@master ~]# kubectl apply -f test2.yaml
deployment.apps/web configured
// 查看发现暂未发生变化
[root@master ~]# kubectl get pods
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
// 我们去test2.yaml里面修改一下镜像
[root@master ~]# vim test2.yaml
image: httpd // 镜像修改就会更新
// 修改完之后应用
[root@master ~]# kubectl apply -f test2.yaml
deployment.apps/web configured
// 发现停止了三个旧的web,启动了两个新的web和一个旧的web,还有两个新web正在创建
[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
// 最后变为四个新的web
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-f8bcfc88-bcvcd 1/1 Running 0 92s
web-f8bcfc88-kkx4f 1/1 Running 0 92s
web-f8bcfc88-w4dxx 1/1 Running 0 65s
web-f8bcfc88-x6q5z 1/1 Running 0 47s
版本记录
-
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: xm17671855780/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: xm17671855780/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>
Deployment:水平扩锁容
水平扩充容(启动多实例,提高并发)
- 修改yanl里replicas值,再apply
- kubectl scale deployment web --replicas=10
注:replicas参数控制Pod副本数量
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-f8bcfc88-bcvcd 1/1 Running 0 92s
web-f8bcfc88-kkx4f 1/1 Running 0 92s
web-f8bcfc88-w4dxx 1/1 Running 0 65s
web-f8bcfc88-x6q5z 1/1 Running 0 47s
// 创建10个容器
[root@master ~]# cat test2.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: default
spec:
replicas: 10 // 复制成10个
strategy:
rollingUpdate:
maxSurge: 55% // 最大可超出55%
maxUnavailable: 50% // 最大不可用50%
type: RollingUpdate
selector:
matchLabels:
app: httpd
template:
metadata:
labels:
app: httpd
spec:
containers:
- name: httpd
image: gaofan1225/httpd:v0.2
imagePullPolicy: IfNotPresent
// 应用
[root@master ~]# kubectl apply -f test2.yaml
deployment.apps/web created
// 查看,发现10个容器已经创建好了,都已经运行了
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-5d688b9745-6dqcl 1/1 Running 0 63s
web-5d688b9745-bkmbf 1/1 Running 0 63s
web-5d688b9745-cpxkx 1/1 Running 0 63s
web-5d688b9745-gxjf6 1/1 Running 0 63s
web-5d688b9745-k2l2b 1/1 Running 0 63s
web-5d688b9745-ll5cc 1/1 Running 0 63s
web-5d688b9745-sqckx 1/1 Running 0 63s
web-5d688b9745-t578c 1/1 Running 0 63s
web-5d688b9745-txwh9 1/1 Running 0 63s
web-5d688b9745-z25kc 1/1 Running 0 63s
// 修改replicas值,实现水平扩缩容
#其余内容不变
[root@master ~]# vim test2.yaml
replicas: 3
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-5d688b9745-6dqcl 1/1 Running 0 63s
web-5d688b9745-bkmbf 1/1 Running 0 63s
web-5d688b9745-cpxkx 1/1 Terminating 0 63s
web-5d688b9745-gxjf6 1/1 Terminating 0 63s
web-5d688b9745-k2l2b 1/1 Terminating 0 63s
web-5d688b9745-ll5cc 1/1 Terminating 0 63s
web-5d688b9745-sqckx 1/1 Terminating 0 63s
web-5d688b9745-t578c 1/1 Terminating 0 63s
web-5d688b9745-txwh9 1/1 Terminating 0 63s
web-5d688b9745-z25kc 1/1 Terminating 0 63s
web-f8bcfc88-hb8dz 0/1 ContainerCreating 0 5s
web-f8bcfc88-ldqt5 0/1 ContainerCreating 0 5s
web-f8bcfc88-r8zn7 0/1 ContainerCreating 0 5s
// 最后结果只剩3个
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-f8bcfc88-hb8dz 1/1 Running 0 3m44s
web-f8bcfc88-ldqt5 1/1 Running 0 3m44s
web-f8bcfc88-r8zn7 1/1 Running 0 3m44s
Deployment:ReplicaSet
ReplicaSet控制器用途:
- Pod副本数量管理,不断对比当前Pod数量与期望Pod数量
- Deployment每次发布都会创建一个RS作为记录,用于实现回滚
ReplicationController、ReplicaSet、Deployment的协调流程
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
DameonSet
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 和 CronJob
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。