目录

Replication Controller(RC)

什么是RC

RC应用

RC滚动更新

Replication Set(RS)

什么是RS

RS应用

Deployment

什么是Deployment

更新节奏和更新逻辑

自定义滚动更新策略

Deployment应用

扩缩容Pod应用

滚动更新应用

更新

回滚

其他操作

DaemonSet

什么是DaemonSet

DaemonSet应用

StatefulSet

有状态服务

什么是StatefulSet

无头服务(Headless service)

StatefulSet应用

扩容缩容

删除

级联删除

非级联删除

任务

一次性任务(Job)

周期性任务(Cronjob)


Replication Controller(RC)

什么是RC

        前面我们的课程中学习了Pod的一些基本使用方法,而且前面我们都是直接来操作的Pod,假如我们现在有一个Pod正在提供线上的服务,我们来想想一下我们可能会遇到的一些场景:

        某次运营活动非常成功,网站访问量突然暴增,运行当前Pod的节点发生故障了,Pod不能正常提供服务了。

        第一种情况,可能比较好应对,一般活动之前我们会大概计算下会有多大的访问量,提前多启动几个Pod,活动结束后再把多余的Pod杀掉,虽然有点麻烦,但是应该还是能够应对这种情况的。

        第二种情况,可能某天夜里收到大量报警说服务挂了,然后起来打开电脑在另外的节点上重新启动一个新的Pod,问题也很好的解决了。

        如果我们都人工的去解决遇到的这些问题,似乎又回到了以前刀耕火种的时代了是吧,如果有一种工具能够来帮助我们管理Pod就好了,Pod不够了自动帮我新增一个,Pod挂了自动帮我在合适的节点上重新启动一个Pod,这样是不是遇到上面的问题我们都不需要手动去解决了。

        幸运的是,Kubernetes就为我们提供了这样的资源对象:

Replication Controller:用来部署、升级Pod

Replica Set:下一代的Replication Controller

Deployment:可以更加方便的管理Pod和Replica Set

        Replication Controller简称RC,RC是Kubernetes系统中的核心概念之一,简单来说,RC可以保证在任意时间运行Pod的副本数量,能够保证Pod总是可用的。如果实际Pod数量比指定的多那就结束掉多余的,如果实际数量比指定的少就新启动一些Pod,当Pod失败、被删除或者挂掉后,RC都会去自动创建新的Pod来保证副本数量,所以即使只有一个Pod,我们也应该使用RC来管理我们的Pod。

        我们想想如果现在我们遇到上面的问题的话,可能除了第一个不能做到完全自动化,其余的我们是不是都不用担心了,运行Pod的节点挂了,RC检测到Pod失败了,就会去合适的节点重新启动一个Pod就行,不需要我们手动去新建一个Pod了。如果是第一种情况的话在活动开始之前我们给Pod指定10个副本,结束后将副本数量改成2,这样是不是也远比我们手动去启动、手动去关闭要好得多,而且我们后面还会给大家介绍另外一种资源对象HPA可以根据资源的使用情况来进行自动扩缩容,这样以后遇到这种情况,我们就真的可以安心的去睡觉了。

RC应用

现在我们来编写一个yaml文件来创建RC。

# kind:ReplicationController
# spec.replicas: 指定Pod副本数量,默认为1
# spec.selector: RC通过该属性来筛选要控制的Pod
# spec.template: 这里就是我们之前的Pod的定义的模块,但是不需要apiVersion和kind了
# spec.template.metadata.labels: 注意这里的Pod的labels要和spec.selector相同,这样RC就可以来控制当前这个Pod了。
#这个YAML文件中的意思就是定义了一个RC资源对象,它的名字叫rc-demo,保证一直会有3个Pod运行,Pod的镜像是nginx镜像。
[root@master ~]# cat nginx_rc.yaml 
apiVersion: v1
kind: ReplicationController
metadata:
  name: rc-demo
  labels:
    name: rc
spec:
  replicas: 3
  selector:
    name: rc
  template:
    metadata:
     labels:
       name: rc
    spec:
     containers:
     - name: nginx-demo
       image: nginx:1.20
       ports:
       - containerPort: 80

[root@master ~]# kubectl apply -f nginx_rc.yaml 
replicationcontroller/rc-demo created

[root@master ~]# kubectl get pod
NAME            READY   STATUS              RESTARTS   AGE
rc-demo-tv7tc   0/1     ContainerCreating   0          4s
rc-demo-vprgq   0/1     ContainerCreating   0          4s
rc-demo-w7lw8   0/1     ContainerCreating   0          4s

你也可以使用尝试删除一个pod,会发现删除以后又会启动一个pod。

# 查看rc
[root@master ~]# kubectl get rc
NAME      DESIRED   CURRENT   READY   AGE
rc-demo   3         3         3       4m3s

RC滚动更新

# rolling-update在1.11版开始过时的,控制Pod副本数量后面我们主要使用Deployment
kubectl rolling-update rc-demo --image=nginx:1.21

Replication Set(RS)

什么是RS

        Replication Set简称RS,随着Kubernetes的高速发展,官方已经推荐我们使用RS和Deployment来代替RC了,实际上RS和RC的功能基本一致,目前唯一的一个区别就是RC只支持基于等式的selector(env=dev或environment!=qa),但RS还支持基于集合的selector(version in (v1.0, v2.0)),这对复杂的运维管理就非常方便了。

        kubectl命令行工具中关于RC的大部分命令同样适用于我们的RS资源对象。不过我们也很少会去单独使用RS,它主要被Deployment这个更加高层的资源对象使用,除非用户需要自定义升级功能或根本不需要升级Pod,在一般情况下,我们推荐使用Deployment而不直接使用Replica Set。

        最后我们总结下关于RC/RS的一些特性和作用吧:

大部分情况下,我们可以通过定义一个RC实现的Pod的创建和副本数量的控制

RC中包含一个完整的Pod定义模块(不包含apiversion和kind)

RC是通过label selector机制来实现对Pod副本的控制的

通过改变RC里面的Pod副本数量,可以实现Pod的扩缩容功能

通过改变RC里面的Pod模板中镜像版本,可以实现Pod的滚动升级功能(但是不支持一键回滚,需要用相同的方法去修改镜像地址)

RS应用

[root@master ~]# cat nginx_rs.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.20

[root@master ~]# kubectl apply -f nginx_rs.yaml 
replicaset.apps/nginx created

[root@master ~]# kubectl get rs
NAME    DESIRED   CURRENT   READY   AGE
nginx   3         3         3       7m15s
[root@master ~]# kubectl get pod
NAME          READY   STATUS    RESTARTS   AGE
nginx-jfw4d   1/1     Running   0          7m17s
nginx-kwpbr   1/1     Running   0          7m17s
nginx-x6bls   1/1     Running   0          7m17s

Deployment

什么是Deployment

        Deployment同样也是Kubernetes系统的一个核心概念,主要职责和RC、RS一样的都是保证Pod的数量和健康,通过定义一个Deployment控制器会创建一个新的ReplicaSet控制器,通过ReplicaSet创建pod,删除Deployment控制器,也会删除Deployment控制器下对应的ReplicaSet控制器和pod资源。二者大部分功能都是完全一致的,我们可以看成是一个升级版的RC、RS控制器,那Deployment又具备那些新特性呢?

        RC的全部功能:Deployment具备上面描述的RC的全部功能

事件和状态查看:可以查看Deployment的升级详细进度和状态

回滚:当升级Pod的时候如果出现问题,可以使用回滚操作回滚到之前的任一版本

版本记录:每一次对Deployment的操作,都能够保存下来,这也是保证可以回滚到任一版本的基础

暂停和启动:对于每一次升级都能够随时暂停和启动

        作为对比,我们知道Deployment作为新一代的RC,不仅在功能上更为丰富了,同时我们也说过现在官方也都是推荐使用Deployment来管理Pod的,比如一些官方组件kube-dns、kube-proxy也都是使用的Deployment来管理的,所以当大家在使用的使用也最好使用Deployment来管理Pod。一般无状态服务都是使用Deployment来进行管理。

什么是无状态服务:

  • 服务不依赖自身的状态,实例的状态数据可以维护在内存中。
  • 任何一个请求都可以被任意一个实例处理。
  • 不存储状态数据,实例可以水平拓展,通过负载均衡将请求分发到各个节点。
  • 在一个封闭的系统中,只存在一个数据闭环。
  • 通常存在于单体架构的集群中。

更新节奏和更新逻辑

        比如说Deployment控制5个pod副本,pod的期望值是5个,但是升级的时候需要额外多几个pod,那我们控制器可以控制在5个pod副本之外还能再增加几个pod副本;比方说能多一个,但是不能少,那么升级的时候就是先增加一个,再删除一个,增加一个删除一个,始终保持pod副本数是5个;还有一种情况,最多允许多一个,最少允许少一个,也就是最多6个,最少4个,第一次加一个,删除两个,第二次加两个,删除两个,依次类推,可以自己控制更新方式,这种滚动更新需要加readinessProbe和livenessProbe探测,确保pod中容器里的应用都正常启动了才删除之前的pod。

        启动第一步,刚更新第一批就暂停了也可以;假如目标是5个,允许一个也不能少,允许最多可以10个,那一次加5个即可;这就是我们可以自己控制节奏来控制更新的方法。

        通过Deployment对象,你可以轻松的做到以下事情:

1、创建ReplicaSet和Pod

2、滚动升级(不停止旧服务的状态下升级)和回滚应用(将应用回滚到之前的版本)

3、平滑地扩容和缩容

4、暂停和继续Deployment

自定义滚动更新策略

maxSurge和maxUnavailable用来控制滚动更新的更新策略

maxUnavailable:和期望ready的副本数比,不可用副本数最大比例(或最大值),这个值越小,越能保证服务稳定,更新越平滑;

maxSurge:和期望ready的副本数比,超过期望副本数最大比例(或最大值),这个值调的越大,副本更新速度越快。

取值范围

数值

  1. maxUnavailable: [0, 副本数]

  2. maxSurge: [0, 副本数]

     注意:两者不能同时为0

比例

  1. maxUnavailable: [0%, 100%] 向下取整,比如10个副本,5%的话==0.5个,但计算按照0个;

  2. maxSurge: [0%, 100%] 向上取整,比如10个副本,5%的话==0.5个,但计算按照1个;

     注意:两者不能同时为0

建议配置

  1. maxUnavailable == 0

  2. maxSurge == 1

Deployment应用

[root@master ~]# cat nginx_deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata: 
  name: nginx
  labels: 
    app: nginx
spec:
  replicas: 6
  selector:
    matchLabels:
      app: nginx
  # 用于将现有 Pod 替换为新 Pod 的部署策略。
  strategy:
    rollingUpdate: 
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.20
        imagePullPolicy: IfNotPresent
[root@master ~]# kubectl apply -f nginx_deployment.yaml 
deployment.apps/nginx created
[root@master ~]# kubectl get deployment
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   6/6     6            6           63s
[root@master ~]# kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
nginx-795ff9d4cc-8hjqr   1/1     Running   0          11s
nginx-795ff9d4cc-fr9dx   1/1     Running   0          14s
nginx-795ff9d4cc-ldvb4   1/1     Running   0          9s
nginx-795ff9d4cc-mpdx5   1/1     Running   0          13s
nginx-795ff9d4cc-mwccx   1/1     Running   0          8s
nginx-795ff9d4cc-wxrs9   1/1     Running   0          6s

扩缩容Pod应用

# 修改yaml文件中的replicas配置,然后重新应用yaml文件
# replicas的值修改的比之前多就是扩容,比之前少就是缩容
[root@master ~]# vi nginx_deployment.yaml 
[root@master ~]# kubectl apply -f nginx_deployment.yaml 
deployment.apps/nginx configured
# 还可以使用edit直接修改
[root@master ~]# kubectl get deployment
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   8/8     8            8           4m7s
# 找到replicas配置修改完以后保存退出即可
[root@master ~]# kubectl edit deployment nginx
deployment.apps/nginx edited
[root@master ~]# kubectl get deployment
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   9/9     9            9           5m33s
# 使--replicas指定数量即可
[root@master ~]# kubectl scale deployment nginx --replicas=2
deployment.apps/nginx scaled

滚动更新应用

更新

# 编写yaml文件中image,然后重新应用yaml文件
[root@master ~]# vi nginx_deployment.yaml 
[root@master ~]# kubectl apply -f nginx_deployment.yaml 
deployment.apps/nginx configured
[root@master ~]# kubectl get pod
NAME                     READY   STATUS              RESTARTS   AGE
nginx-5ff79c7ff8-865kg   0/1     ContainerCreating   0          0s
nginx-5ff79c7ff8-lttfr   1/1     Running             0          2s
nginx-795ff9d4cc-29z2t   1/1     Running             0          32s
nginx-795ff9d4cc-dxst6   1/1     Running             0          32s
nginx-795ff9d4cc-grmwm   1/1     Running             0          32s
nginx-795ff9d4cc-kpdzl   1/1     Terminating         0          32s
nginx-795ff9d4cc-xtwbc   1/1     Running             0          32s
nginx-795ff9d4cc-xztdg   1/1     Running             0          32s
nginx-795ff9d4cc-z2cxn   1/1     Running             0          32s
nginx-795ff9d4cc-zh5gn   1/1     Running             0          32s

# 使用该命令可以查看发布历史
[root@master ~]# kubectl rollout history deployment nginx
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

# 使用--revision可以查看某个发布历史的具体信息
[root@master ~]# kubectl rollout history deployment nginx --revision=1
deployment.apps/nginx with revision #1
Pod Template:
  Labels:	app=nginx
	pod-template-hash=795ff9d4cc
  Containers:
   nginx:
    Image:	nginx:1.20
    Port:	<none>
    Host Port:	<none>
    Environment:	<none>
    Mounts:	<none>
  Volumes:	<none>

[root@master ~]# kubectl rollout history deployment nginx --revision=2
deployment.apps/nginx with revision #2
Pod Template:
  Labels:	app=nginx
	pod-template-hash=5ff79c7ff8
  Containers:
   nginx:
    Image:	nginx:1.21
    Port:	<none>
    Host Port:	<none>
    Environment:	<none>
    Mounts:	<none>
  Volumes:	<none>

# 可以使用kubectl set image命令来进行滚动更新
[root@master ~]# kubectl get deployment
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   8/8     8            8           6m50s
[root@master ~]# kubectl set image deployment nginx nginx=nginx:1.22
deployment.apps/nginx image updated
[root@master ~]# kubectl get pod
NAME                     READY   STATUS              RESTARTS   AGE
nginx-5ff79c7ff8-778cz   1/1     Running             0          7m40s
nginx-5ff79c7ff8-865kg   1/1     Running             0          7m43s
nginx-5ff79c7ff8-c8ccl   1/1     Running             0          7m42s
nginx-5ff79c7ff8-cx9g4   1/1     Running             0          7m38s
nginx-5ff79c7ff8-hcj4d   1/1     Running             0          7m41s
nginx-5ff79c7ff8-lttfr   1/1     Running             0          7m45s
nginx-5ff79c7ff8-srmdq   1/1     Running             0          7m39s
nginx-5ff79c7ff8-zq9nk   1/1     Running             0          7m37s
nginx-7c8489bfcf-n2kkw   0/1     ContainerCreating   0          5s

# 查看发布状态
[root@master ~]# kubectl rollout status deployment nginx
deployment "nginx" successfully rolled out

回滚

# 查看上线历史
[root@master ~]# kubectl rollout history deployment nginx
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>
4         <none>

# 回滚到上一个版本
[root@master ~]# kubectl rollout undo deployment nginx
deployment.apps/nginx rolled back

# 回滚到指定版本
[root@master ~]# kubectl rollout undo deployment nginx --to-revision=1
deployment.apps/nginx rolled back

# 查看回滚状态
[root@master ~]# kubectl rollout status deployment nginx
deployment "nginx" successfully rolled out

其他操作

# 暂停deployment更新
[root@master ~]# kubectl rollout pause deployment nginx
deployment.apps/nginx paused

# 恢复deployment更新
[root@master ~]# kubectl rollout resume deployment nginx
deployment.apps/nginx resumed

DaemonSet

什么是DaemonSet

        通过该控制器的名称我们可以看出它的用法:Daemon,就是用来部署守护进程的,DaemonSet用于在每个Kubernetes节点中将守护进程的副本作为后台进程运行,说白了就是在每个节点部署一个Pod副本,当节点加入到Kubernetes集群中,Pod会被调度到该节点上运行,当节点从集群只能够被移除后,该节点上的这个Pod也会被移除,当然,如果我们删除DaemonSet,所有和这个对象相关的Pods都会被删除。

        在哪种情况下我们会需要用到这种业务场景呢?其实这种场景还是比较普通的,比如:

集群存储守护程序,如glusterd、ceph要部署在每个节点上以提供持久性存储;

节点监视守护进程,如Prometheus监控集群,可以在每个节点上运行一个node-exporter进程来收集监控节点的信息;

日志收集守护程序,如fluentd或logstash,在每个节点上运行以收集容器的日志

DaemonSet应用

[root@master ~]# cat nginx_ds.yaml 
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.20
        imagePullPolicy: IfNotPresent
[root@master ~]# kubectl apply -f nginx_ds.yaml 
daemonset.apps/nginx created
[root@master ~]# kubectl get ds
NAME    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
nginx   2         2         2       2            2           <none>          66s

# 可查看到node节点都运行了一个nginx的pod
[root@master ~]# kubectl get pod -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE    NOMINATED NODE   READINESS GATES
nginx-hck9g   1/1     Running   0          30s   10.244.2.37   node2   <none>           <none>
nginx-kskbm   1/1     Running   0          30s   10.244.1.39   node1   <none>           <none>

# 仔细观察会发现master节点并没有运行pod,因为这涉及到污点,关于污点我们后面会讲到
[root@master ~]# kubectl get node
NAME     STATUS   ROLES                  AGE   VERSION
master   Ready    control-plane,master   43h   v1.23.0
node1    Ready    <none>                 43h   v1.23.0
node2    Ready    <none>                 43h   v1.23.0

StatefulSet

在学习StatefulSet这种控制器之前,我们就得先弄明白一个概念:什么是有状态服务?

有状态服务

        有状态服务(Stateful Service):该服务运行的实例需要在本地存储持久化数据,比如上面的MySQL数据库,你现在运行在节点A,那么他的数据就存储在节点A上面的,如果这个时候你把该服务迁移到节点B去的话,那么就没有之前的数据了,因为他需要去对应的数据目录里面恢复数据,而此时没有任何数据。

有状态服务的特点:

  • 服务本身依赖或者存在局部的状态数据,这些数据需要自身持久化或者可以通过其他节点恢复。
  • 一个请求只能被某个节点(或者同等状态下的节点)处理。
  • 存储状态数据,实例的拓展需要整个系统参与状态的迁移。
  • 在一个封闭的系统中,存在多个数据闭环,需要考虑这些闭环的数据一致性问题。
  • 通常存在于分布式架构中。

什么是StatefulSet

        StatefulSet 是用来管理有状态应用的工作负载 API 对象。和 Deployment 类似, StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同的是, StatefulSet 为它们的每个 Pod 维护了一个有粘性的 ID。这些 Pod 是基于相同的规约来创建的, 但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。

        StatefulSet类似于ReplicaSet,但是它可以处理Pod的启动顺序,为保留每个Pod的状态设置唯一标识,同时具有以下功能:

  • 稳定的、唯一的网络标识符
  • 稳定的、持久化的存储
  • 有序的、优雅的部署和缩放
  • 有序的、优雅的删除和终止
  • 有序的、自动滚动更新

无头服务(Headless service)

        Headless service不分配clusterIP,headless service可以通过解析service的DNS,返回所有Pod的dns和ip地址 (statefulSet部署的Pod才有DNS),普通的service,只能通过解析service的DNS返回service的ClusterIP。

为什么要用headless service(没有service ip的service)?

        在使用Deployment时,创建的Pod名称是没有顺序的,是随机字符串,在用statefulset管理pod时要求pod名称必须是有序的 ,每一个pod不能被随意取代,pod重建后pod名称还是一样的。因为pod IP是变化的,所以要用Pod名称来识别。pod名称是pod唯一性的标识符,必须持久稳定有效。这时候要用到无头服务,它可以给每个Pod一个唯一的名称。

headless service会为service分配一个域名,域名格式如下:

<service name>.$<namespace name>.svc.cluster.local

K8s中资源的全局FQDN格式:

Service_NAME.NameSpace_NAME.Domain.LTD.
Domain.LTD.=svc.cluster.local.     #这是默认k8s集群的域名。

StatefulSet会为关联的Pod分配一个dnsName

$<Pod Name>.$<service name>.$<namespace name>.svc.cluster.local

StatefulSet应用

[root@master ~]# cat nginx_sts.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  clusterIP: None
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80 
[root@master ~]# kubectl apply -f nginx_sts.yaml 
statefulset.apps/nginx created
[root@master ~]# kubectl get sts
NAME    READY   AGE
nginx   2/2     6m45s
[root@master ~]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
nginx-0   1/1     Running   0          6m50s
nginx-1   1/1     Running   0          6m49s

扩容缩容

# --replicas选项可以调整副本数量
[root@master ~]# kubectl scale sts nginx --replicas=4
statefulset.apps/nginx scaled

删除

        删除StatefulSet有两种方式:级联删除和非级联删除。

        使用非级联方式删除StatefulSet时,StatefulSet的Pod不会被删除。使用级联方式删除StatefulSet时,StatefulSet和它的Pod都会被删除。

级联删除

[root@master ~]# kubectl delete sts nginx
statefulset.apps "nginx" deleted

非级联删除

[root@master ~]# kubectl delete sts nginx --cascade=false
warning: --cascade=false is deprecated (boolean value) and can be replaced with --cascade=orphan.
statefulset.apps "nginx" deleted
[root@master ~]# kubectl get sts
No resources found in default namespace.
[root@master ~]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
nginx-0   1/1     Running   0          38s
nginx-1   1/1     Running   0          36s

任务

        我们在日常的工作中经常都会遇到一些需要进行批量数据处理和分析的需求,当然也会有按时间来进行调度的工作,在我们的Kubernetes集群中为我们提供了Job和CronJob两种资源对象来应对我们的这种需求。

        Job负责处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束。而CronJob则就是在Job上加上了时间调度。

一次性任务(Job)

我们用Job这个资源对象来创建一个任务,我们定一个Job来执行一个倒计时的任务,定义YAML文件:

#注意Job的RestartPolicy仅支持Never和OnFailure两种,不支持Always,我们知道Job就相当于来执行一个批处理任务,执行完就结束了,如果支持Always的话是不是就陷入了死循环了?
[root@master ~]# cat job-demo.yaml 
apiVersion: batch/v1
kind: Job
metadata:
  name: job-demo
spec:
  template:
    metadata:
      name: job-demo
    spec:
      restartPolicy: Never
      containers:
      - name: counter
        image: busybox
        command:
        - "bin/sh"
        - "-c"
        - "for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 1; done"
[root@master ~]# kubectl apply -f job-demo.yaml 
job.batch/job-demo created

[root@master ~]# kubectl get job
NAME       COMPLETIONS   DURATION   AGE
job-demo   1/1           31s        92s

[root@master ~]# kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE
job-demo-qqq8j   1/1     Running   0          27s

# job运行完以后,pod的状态是Completed   
[root@master ~]# kubectl get pod
NAME             READY   STATUS      RESTARTS   AGE
job-demo-qqq8j   0/1     Completed   0          42s

# 使用kubectl logs可以查看日志
[root@master ~]# kubectl logs job-demo-qqq8j 
9
8
7
6
5
4
3
2
1

周期性任务(Cronjob)

        CronJob其实就是在Job的基础上加上了时间调度,我们可以:在给定的时间点运行一个任务,也可以周期性地在给定时间点运行。这个实际上和我们Linux中的crontab就非常类似了。

        一个CronJob对象其实就对应中crontab文件中的一行,它根据配置的时间格式周期性地运行一个Job,格式和crontab也是一样的。

crontab的格式如下:

分 时 日 月 星期 要运行的命令 
第1列分钟0~59 
第2列小时0~23 
第3列日1~31 
第4列月1~12 
第5列星期0~7(0和7表示星期天) 
第6列要运行的命令

现在,我们用CronJob来管理我们上面的Job任务

[root@master ~]# cat cronjob-demo.yaml 
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjob-demo
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: hello
            image: busybox
            args:
            - "bin/sh"
            - "-c"
            - "for i in 9 8 7 6 5 4 3 2 1; do echo $i;sleep 1; done"
[root@master ~]# kubectl apply -f cronjob-demo.yaml 
cronjob.batch/cronjob-demo created

[root@master ~]# kubectl get cronjob
NAME           SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob-demo   */1 * * * *   False     0        16s             101s

[root@master ~]# kubectl get pod
NAME                          READY   STATUS      RESTARTS   AGE
cronjob-demo-28356682-hv7z4   0/1     Completed   0          94s
cronjob-demo-28356683-t5h59   0/1     Completed   0          34s

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐