kubernetes-1

目录

部署并发布简单的应用

Deployment控制器伸缩 

Deployment控制器回滚

DaemonSet控制器


部署并发布简单的应用

1.创建deployment

[root@master ~]# kubectl  create deployment  test-nginx  --image=nginx

deployment.apps/test-nginx created

2.查看创建后的deployment

[root@master ~]# kubectl  get deployment

NAME         READY   UP-TO-DATE   AVAILABLE   AGE

test-nginx   1/1     1            1           38s

3.查看pod状态

[root@master ~]# kubectl  get pod

NAME                         READY   STATUS    RESTARTS       AGE

test-nginx-59ffd87f5-mqvjq   1/1     Running   0              58s

testpod                      1/1     Running   12 (24m ago)   24h

[root@master ~]# kubectl  describe pod test-nginx-59ffd87f5-mqvjq

Name:         test-nginx-59ffd87f5-mqvjq

Namespace:    default

Priority:     0

Node:         worker1/192.168.200.12

Start Time:   Tue, 15 Nov 2022 22:08:29 -0500

Labels:       app=test-nginx

              pod-template-hash=59ffd87f5

Annotations:  <none>

Status:       Running

IP:           10.244.1.7

IPs:

  IP:           10.244.1.7

Controlled By:  ReplicaSet/test-nginx-59ffd87f5

Containers:

  nginx:

    Container ID:   docker://9f66b66ff9cfe9511b8c248346f62ae872c16aca53d54003f345ab7df09e13a8

    Image:          nginx

    Image ID:       docker-pullable://nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31

    Port:           <none>

    Host Port:      <none>

    State:          Running

      Started:      Tue, 15 Nov 2022 22:08:53 -0500

    Ready:          True

    Restart Count:  0

    Environment:    <none>

    Mounts:

      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-l29hm (ro)

Conditions:

  Type              Status

  Initialized       True

  Ready             True

  ContainersReady   True

  PodScheduled      True

Volumes:

  kube-api-access-l29hm:

    Type:                    Projected (a volume that contains injected data from multiple sources)

    TokenExpirationSeconds:  3607

    ConfigMapName:           kube-root-ca.crt

    ConfigMapOptional:       <nil>

    DownwardAPI:             true

QoS Class:                   BestEffort

Node-Selectors:              <none>

Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s

                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s

Events:              

  Type    Reason     Age   From               Message

  ----    ------     ----  ----               -------

  Normal  Scheduled  103s  default-scheduler  Successfully assigned default/test-nginx-59ffd87f5-mqvjq to worker1

  Normal  Pulling    101s  kubelet            Pulling image "nginx"

  Normal  Pulled     79s   kubelet            Successfully pulled image "nginx" in 22.047909579s

  Normal  Created    79s   kubelet            Created container nginx

  Normal  Started    79s   kubelet            Started container nginx

[root@master ~]# kubectl  get pod -o wide

NAME                         READY   STATUS    RESTARTS       AGE     IP           NODE      NOMINATED NODE   READINESS GATES

test-nginx-59ffd87f5-mqvjq   1/1     Running   0              3m18s   10.244.1.7   worker1   <none>           <none>

4.发布服务

K8S暴露服务的方式有三种:loadblancer nodeport ingress

[root@master ~]# kubectl  expose deployment  test-nginx --port=80  --type=NodePort

service/test-nginx exposed

[root@master ~]# kubectl  get svc

NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE

kubernetes   ClusterIP   10.1.0.1     <none>        443/TCP        6d

test-nginx   NodePort    10.1.31.72   <none>        80:32465/TCP   14s

暴露服务之后可以使用“任意节点IP+暴露的端口进行访问”,:

5.Pod动态伸缩

[root@master ~]# kubectl  scale deployment test-nginx --replicas=5   //增加pod副本数

deployment.apps/test-nginx scaled

[root@master ~]# kubectl  get pods

NAME                         READY   STATUS    RESTARTS       AGE

test-nginx-59ffd87f5-7pjwk   1/1     Running   0              56s

test-nginx-59ffd87f5-8d229   1/1     Running   0              56s

test-nginx-59ffd87f5-ff4gg   1/1     Running   0              56s

test-nginx-59ffd87f5-mqvjq   1/1     Running   0              10m

test-nginx-59ffd87f5-nzft5   1/1     Running   0              56s

testpod                      1/1     Running   12 (34m ago)   24h

[root@master ~]# kubectl  scale deployment test-nginx --replicas=2   //设置副本的缩容

deployment.apps/test-nginx scaled

[root@master ~]# kubectl  get pods

NAME                         READY   STATUS    RESTARTS       AGE

test-nginx-59ffd87f5-7pjwk   1/1     Running   0              117s

test-nginx-59ffd87f5-mqvjq   1/1     Running   0              11m

testpod                      1/1     Running   12 (35m ago)   24h

[root@master ~]# kubectl  autoscale deployment test-nginx --min=1 --max=10    //设置pod自动伸缩

horizontalpodautoscaler.autoscaling/test-nginx autoscaled

1.调度master节点

[root@master ~]# kubectl  get nodes

NAME      STATUS   ROLES                  AGE     VERSION

master    Ready    control-plane,master   6d21h   v1.22.2

worker1   Ready    <none>                 6d20h   v1.22.2

[root@master ~]# kubectl  describe node master

......

Taints:             node-role.kubernetes.io/master:NoSchedule

//处于安全性考虑,默认配置下的k8s集群不会将pod调度在master节点上

[root@master ~]# kubectl  taint node master node-role.kubernetes.io/master-   //将master作为调度节点使用

node/master untainted

[root@master ~]# kubectl  describe node master    //再次查看已经恢复master节点的调度角色

......

Taints:             <none>

2.node节点的隔离与恢复

(1)隔离Node

为什么要隔离node?在硬件升级、维护的情况下,需要将某些node隔离。使用kubectl cordon <node_name>可以禁止pod调度在此节点上,在他上面运行的Pod不会去自动的停止,管理员需要手动的停止在该node上运行pod。

[root@master ~]# kubectl  cordon  worker1

node/worker1 cordoned

[root@master ~]# kubectl  get nodes

NAME      STATUS                     ROLES                  AGE     VERSION

master    Ready                      control-plane,master   6d21h   v1.22.2

worker1   Ready,SchedulingDisabled   <none>                 6d20h   v1.22.2

//查看node状态可以观察到在node状态中增加了一项SchedulingDisabled,对于后续创建的pod,系统将不会再向这个worker1节点进行调度

(2)恢复node

[root@master ~]# kubectl  uncordon  worker1

node/worker1 uncordoned

[root@master ~]# kubectl  get nodes

NAME      STATUS   ROLES                  AGE     VERSION

master    Ready    control-plane,master   6d21h   v1.22.2

worker1   Ready    <none>                 6d20h   v1.22.2

//可以看出node节点已经恢复调度,允许pod调度到该节点上

(3)驱逐node

通过kubectl drain <node_name>可以实现对node节点的驱逐,这条命令会删除该节点上的所有pod,并且在其他的node节点上重新启动。

3.node节点的扩容

为什么要进行node扩容?

在实际的生产系统中会经常遇到服务器容量不足的情况,这个时候就需要加入新的服务器,然后将应用系统进行水平扩展来完成对系统的扩容。

在k8s集群中对于新的node加入集群是非常简单的,可以在Node节点上安装docker、Kubelet和kube-proxy服务,然后将这两个启动参数中的master URL指定为当前k8s集群masyter地址,最后启动。Master节点在接受到了新的node注册之后,会自动地将它纳入当前的集群调度范围。

(1)准备新的节点,并且安装k8s所需的所有服务

安装过程省略,可以结合前面的文档进行操作

(2)启动k8s组件

[root@worker2 ~]# systemctl  enable kubelet

[root@worker2 ~]# systemctl  start  kubelet

//此时启动不成功,后面加入集群后可以成功

(3)生成token

[root@master ~]# kubeadm token create --ttl 0

fphus0.pmi8894iwf30i202

//k8s默认的token有效期为24h,过期之后,该token不可用,登录到master节点获取一条永久有效的token

(4)获取hash值

[root@master ~]# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

9f59f022a74578f9803f875add7c2b4f7995888528ef376c49f9593e2bc9369e

(5)worker2加入集群

[root@worker2 ~]# kubeadm  join 192.168.200.11:6443 --token fphus0.pmi8894iwf30i202 --discovery-token-ca-cert-hash sha256:9f59f022a74578f9803f875add7c2b4f7995888528ef376c49f9593e2bc9369e

//将上面获取到的token值和hash值使用命令加入到集群

[preflight] Running pre-flight checks

[preflight] Reading configuration from the cluster...

[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'

[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"

[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"

[kubelet-start] Starting the kubelet

[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:

* Certificate signing request was sent to apiserver and a response was received.

* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

(6)查看集群节点

[root@master ~]# kubectl  get nodes

NAME      STATUS     ROLES                  AGE     VERSION

master    Ready      control-plane,master   6d22h   v1.22.2

worker1   Ready      <none>                 6d21h   v1.22.2

worker2   Ready   <none>                 6m43s   v1.22.2


控制器-pod管理

2.创建deployment

[root@master ~]# vi testdeployment.yaml

apiVersion: apps/v1                          //k8s API稳定版本

kind: Deployment                          //创建的资源对象

metadata:                               //资源对象的元数据

  name: testdeployment                 //资源的名称

spec:                                //具体资源的设置

  replicas: 3                       //表示在控制器下托管的pod需要保持的副本数量

  selector:                        //用于定义一个或者多个标签,其形式为键值对。它对pod起筛选作用,会选择与标签定义相匹配的pod

    matchLabels:

      example: deploymentnginx

  template:                        //pod模板

    metadata:

      labels:

        example: deploymentnginx

    spec:

      containers:

      - name: nginx

        image: nginx:1.7.9

        ports:

        - containerPort: 80

[root@master ~]# kubectl  apply -f testdeployment.yaml --record

Flag --record has been deprecated, --record will be removed in the future

deployment.apps/testdeployment created

//--record参数,会把每次修改控制器时所使用的命令记录到备注字段中,以便在查看deployment控制器变更历史或进行回滚时可以辨别每次修改的内容

[root@master ~]# kubectl  get deployments

NAME             READY   UP-TO-DATE   AVAILABLE   AGE

testdeployment   3/3     3            3           116s

[root@master ~]# kubectl  get pod -o wide

NAME                              READY   STATUS    RESTARTS         AGE     IP            NODE      NOMINATED NODE   READINESS GATES

testdeployment-58779f7cd8-jwwtm   1/1     Running   0                3m9s    10.244.1.30   worker1   <none>           <none>

testdeployment-58779f7cd8-m6q5g   1/1     Running   0                3m9s    10.244.1.31   worker1   <none>           <none>

testdeployment-58779f7cd8-ssdrx   1/1     Running   0                3m9s    10.244.0.22   master    <none>           <none>

//在上面的案例中deployment会创建三个pod,每个pod后面都有两个有两个随机生成的字符串,用于表示各自的身份(例如58779f7cd8是replicaset随机生成的标识字符串,后面的jwwtm是pod随机表示字符串)

[root@master ~]# kubectl  describe deployments testdeployment

Name:                   testdeployment

Namespace:              default

CreationTimestamp:      Sun, 20 Nov 2022 20:10:19 -0500

Labels:                 <none>

Annotations:            deployment.kubernetes.io/revision: 1

                        kubernetes.io/change-cause: kubectl apply --filename=testdeployment.yaml --record=true

Selector:               example=deploymentnginx

Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable

StrategyType:           RollingUpdate

MinReadySeconds:        0

RollingUpdateStrategy:  25% max unavailable, 25% max surge

Pod Template:

  Labels:  example=deploymentnginx

  Containers:

   nginx:

    Image:        nginx:1.7.9

    Port:         80/TCP

    Host Port:    0/TCP

    Environment:  <none>

    Mounts:       <none>

  Volumes:        <none>

Conditions:

  Type           Status  Reason

  ----           ------  ------

  Available      True    MinimumReplicasAvailable

  Progressing    True    NewReplicaSetAvailable

OldReplicaSets:  <none>

NewReplicaSet:   testdeployment-58779f7cd8 (3/3 replicas created)

Events:

  Type    Reason             Age    From                   Message

  ----    ------             ----   ----                   -------

  Normal  ScalingReplicaSet  8m36s  deployment-controller  Scaled up replica set testdeployment-58779f7cd8 to 3

测试删除pod和node关机

[root@master ~]# kubectl  delete pod testdeployment-58779f7cd8-jwwtm

pod "testdeployment-58779f7cd8-jwwtm" deleted

[root@master ~]# kubectl  get deployments

NAME             READY   UP-TO-DATE   AVAILABLE   AGE

test-nginx       2/2     2            2           4d22h

testdeployment   3/3     3            3           11m

//删除完毕之后等待一段时间之后会发现reay数量仍为3/3,这是因为deployment控制器启用了新的pod来维持replicas中设置的数量

//下面关闭worker1节点

[root@master ~]# kubectl  get deployments    //关闭机器之后,会发现控制器的ready数量已经变为1/3

NAME             READY   UP-TO-DATE   AVAILABLE   AGE

test-nginx       0/2     2            0           4d22h

testdeployment   1/3     3            1           17m

[root@master ~]# kubectl  get pod    //调度在worker1节点上的pod已经变为Terminating,但是过一段时间之后会发现有两个pod正在重新创建

NAME                              READY   STATUS              RESTARTS         AGE

test-nginx-59ffd87f5-2g86v        0/1     ContainerCreating   0                4s

test-nginx-59ffd87f5-7pjwk        1/1     Terminating         2 (2d17h ago)    4d22h

test-nginx-59ffd87f5-mqvjq        1/1     Terminating         2 (2d17h ago)    4d22h

test-nginx-59ffd87f5-wzmt4        0/1     ContainerCreating   0                4s

testdeployment-58779f7cd8-m6q5g   1/1     Terminating         0                20m

testdeployment-58779f7cd8-qx2td   1/1     Terminating         0                9m25s

testdeployment-58779f7cd8-ssdrx   1/1     Running             0                20m

testdeployment-58779f7cd8-v7xbz   1/1     Running             0                4s

testdeployment-58779f7cd8-zddrr   1/1     Running             0                4s

testpod                           1/1     Terminating         52 (2d17h ago)   5d22h

testpodforliveness                1/1     Terminating         16 (2d17h ago)   3d22h

testpodforreadiness               1/1     Terminating         3 (2d17h ago)    3d

[root@master ~]# kubectl  get deployments

NAME             READY   UP-TO-DATE   AVAILABLE   AGE

test-nginx       2/2     2            2           4d22h

testdeployment   3/3     3            3           22m

//deployment控制器保证在集群中部署的pod数量与配置中的pod数量保持一致,如果主机出现故障会自动的进行启动新的pod进行补充


Deployment控制器伸缩 

1.Deployment控制器伸缩

假设现有的业务需求变更,需要将pod副本数设置为5。

[root@master ~]# vi testdeployment.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: testdeployment

spec:

  replicas: 5           //将副本数量设置为5

......

[root@master ~]# kubectl  apply -f testdeployment.yaml  --record

Flag --record has been deprecated, --record will be removed in the future

deployment.apps/testdeployment configured

//上面命令执行完毕后,会进入到pod创建的过程,等待pod创建完毕后,可以通过下面的命令查看状态

[root@master ~]# kubectl  get deployment

NAME             READY   UP-TO-DATE   AVAILABLE   AGE

testdeployment   5/5     5            5           47h

[root@master ~]# kubectl  get pod

NAME                              READY   STATUS    RESTARTS      AGE

testdeployment-58779f7cd8-c492j   1/1     Running   0             116s

testdeployment-58779f7cd8-mt65r   1/1     Running   0             116s

testdeployment-58779f7cd8-ssdrx   1/1     Running   1 (21h ago)   47h

testdeployment-58779f7cd8-v7xbz   1/1     Running   1 (21h ago)   47h

testdeployment-58779f7cd8-zddrr   1/1     Running   1 (21h ago)   47h

//从以上结果可以发现pod数量也变成了5个,通过相同的方法,也可以减少pod副本的数量

2.Deployment控制器更新

Deployment控制器的更新有两种方法:

Recreate:所有现有的pod都会创建在新的pod之前被终止

RollingUpdate:表示以滚动更新的方式更新pod,并且可以设置maxUnavailable和maxSurge参数来控制滚动更新的过程

(1)Recreate方式

[root@master ~]# vi testdeployment2.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: testdeployment

spec:

  replicas: 5

  selector:

    matchLabels:

      example: deploymentnginx

  template:

    metadata:

      labels:

        example: deploymentnginx

    spec:

      containers:

      - name: nginx

        image: nginx:1.8.1

        ports:

        - containerPort: 80

  strategy:

    type: Recreate

~

"testdeployment2.yaml" [New] 21L, 372C written

[root@master ~]# kubectl  apply -f testdeployment2.yaml  --record

Flag --record has been deprecated, --record will be removed in the future

deployment.apps/testdeployment configured

[root@master ~]# kubectl  get deployments

NAME             READY   UP-TO-DATE   AVAILABLE   AGE

test-nginx       2/2     2            2           6d22h

testdeployment   5/5     5            5           2d

[root@master ~]# kubectl  get pod

NAME                              READY   STATUS    RESTARTS      AGE

chinaskill-mall                   5/5     Running   5 (21h ago)   46h

test-nginx-59ffd87f5-2g86v        1/1     Running   1 (21h ago)   47h

test-nginx-59ffd87f5-wzmt4        1/1     Running   1 (21h ago)   47h

testdeployment-5c4b8d64df-7z49v   1/1     Running   0             2m25s

testdeployment-5c4b8d64df-9mh7q   1/1     Running   0             2m25s

testdeployment-5c4b8d64df-mrptg   1/1     Running   0             2m25s

testdeployment-5c4b8d64df-nnkwl   1/1     Running   0             2m25s

testdeployment-5c4b8d64df-xnwkd   1/1     Running   0             2m25s

//在使用Recreate执行更新时,我们应用了新的模板文件后最开始会看到READY数量时0/5,AVAILABLE数量为0,UP-TO-DATE为0,表示没有一个pod执行更新,如果此时再去查询pod状态会发现之前的pod状态为Terminating,,稍等一段时间之后,我们会发现所有的pod都是可用的状态,并且deployment ready数量为5/5,UP-TO-DATE数量为5,表示更新了5个pod

[root@master ~]# kubectl  describe pod testdeployment-5c4b8d64df-7z49v   //随便找一个pod查看详细信息会发现我们的nginx镜像已经变为1.8.1版本

Name:         testdeployment-5c4b8d64df-7z49v

Namespace:    default

Priority:     0

Node:         master/192.168.200.11

Start Time:   Tue, 22 Nov 2022 20:17:21 -0500

Labels:       example=deploymentnginx

              pod-template-hash=5c4b8d64df

Annotations:  <none>

Status:       Running

IP:           10.244.0.40

IPs:

  IP:           10.244.0.40

Controlled By:  ReplicaSet/testdeployment-5c4b8d64df

Containers:

  nginx:

    Container ID:   docker://611a648c2e7f8939ab62d291d7d6f334ac59e0e98e496a2f2c1b19384eb4ec77

    Image:          nginx:1.8.1

[root@master ~]# kubectl  get rs -o wide

NAME                        DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES        SELECTOR

testdeployment-58779f7cd8   0         0         0       2d      nginx        nginx:1.7.9   example=deploymentnginx,pod-template-hash=58779f7cd8

testdeployment-5c4b8d64df   5         5         5       9m48s   nginx        nginx:1.8.1   example=deploymentnginx,pod-template-hash=5c4b8d64df

//此时再查看ReplicaSet控制器的变化情况,可以看到之前的1.7.9的版本已经停用,新的版本已经创建

(2)RollingUpdate(滚动更新)

这种更新方式会比较实用,是一种平滑的升级方式,不会中断整个pod集群提供的服务。

maxUnavailable:表示再更新的过程中能够进入不可用状态的pod的最大值或相对于总副本数的最大百分比

maxSurge:表示能够额外创建的pod数或相对于总副本数的百分比

[root@master ~]# vi testdeployment3.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

  name: testdeployment

spec:

  replicas: 3

  selector:

    matchLabels:

      example: deploymentnginx

  template:

    metadata:

      labels:

        example: deploymentnginx

    spec:

      containers:

      - name: nginx

        image: nginx:1.9.0

        ports:

        - containerPort: 80

  strategy:

    type: RollingUpdate

    rollingUpdate:

      maxUnavailable: 1    //表示最多只允许一个pod不可用,所以会先终止掉一个pod,使另外两个pod处于运行状态

      maxSurge: 0      //表示最多创建0个额外的副本,再更新的过程中有1个正在创建更新的pod和两个正在运行的旧pod,符合副本的数量为3和零个额外的副本

[root@master ~]# kubectl  apply -f testdeployment3.yaml  --record

Flag --record has been deprecated, --record will be removed in the future

deployment.apps/testdeployment configured

[root@master ~]# kubectl  get deployments

NAME             READY   UP-TO-DATE   AVAILABLE   AGE

test-nginx       2/2     2            2           6d22h

testdeployment   3/3     3            3           2d

//在不同的时间段去执行上方的命令会发现Ready数量和UP-TO-DATE数量都会有变化,但是更新的时间不会过长

[root@master ~]# kubectl  get pod

NAME                              READY   STATUS    RESTARTS      AGE

testdeployment-5c5458b87c-22hnc   1/1     Running   0             2m18s

testdeployment-5c5458b87c-45js4   1/1     Running   0             2m20s

testdeployment-5c5458b87c-fhlcw   1/1     Running   0             2m49s

//此时再执行查询pod命令会发现,拥有了新的三个pod

3.更新的暂停与恢复

假设现有的业务需要变动更新升级,计划将所有的副本nginx镜像都要升级到1.9.1的版本,此次升级不仅要平滑的过度,还要进行金丝雀发布,也就是说先确认其中的一个pod没有问题之后在进行剩余的更新。

完成上述内容可以以yaml文件的方式实现,但是比较复杂,我们可以采用简单的命令进行实现。

# kubectl  rollout pause deploy [deployment name]

# kubectl  rollout resume deploy [deployment name]

[root@master ~]# kubectl  set image deploy testdeployment nginx=nginx:1.9.1  --record

Flag --record has been deprecated, --record will be removed in the future

deployment.apps/testdeployment image updated

[root@master ~]# kubectl  rollout pause deploy testdeployment

deployment.apps/testdeployment paused

[root@master ~]# kubectl  get pod

NAME                              READY   STATUS    RESTARTS      AGE

testdeployment-5c5458b87c-22hnc   1/1     Running   0             61m

testdeployment-5c5458b87c-45js4   1/1     Running   0             61m

testdeployment-8587689fb6-bfcnp   1/1     Running   0             68s

//上面的两条命令会升级deployment中的nginx版本,但是紧接着执行暂停命令会使更新第一个pod时就停止了后续的操作

[root@master ~]# kubectl  get deployments

NAME             READY   UP-TO-DATE   AVAILABLE   AGE

testdeployment   3/3     1            3           2d1h

//上述可以发现ready和 AVAILABLE都为3,但是UP-TO-DATE为1,此时可以对新更新的pod进行验证,没有问题就可以继续让其他的pod更新

[root@master ~]# kubectl  rollout resume deploy testdeployment   //结束暂停

deployment.apps/testdeployment resumed

[root@master ~]# kubectl  get deployments

NAME             READY   UP-TO-DATE   AVAILABLE   AGE

test-nginx       2/2     2            2           6d23h

testdeployment   3/3     3            3           2d1h

[root@master ~]# kubectl  get pods

NAME                              READY   STATUS    RESTARTS      AGE

testdeployment-8587689fb6-bfcnp   1/1     Running   0             8m

testdeployment-8587689fb6-hm8td   1/1     Running   0             41s

testdeployment-8587689fb6-rxsth   1/1     Running   0             42s

//上述命令可以发现所有的pod均更新完毕


Deployment控制器回滚

如果更新之后,发现pod有严重的问题,需要回滚到之前的版本,可以使用命令查看历史变更记录 

[root@master ~]# kubectl  get deployments

NAME             READY   UP-TO-DATE   AVAILABLE   AGE

testdeployment   3/3     3            3           2d23h

[root@master ~]# kubectl  rollout history deployment testdeployment

deployment.apps/testdeployment

REVISION  CHANGE-CAUSE

1         kubectl apply --filename=testdeployment.yaml --record=true

2         kubectl apply --filename=testdeployment2.yaml --record=true

3         kubectl apply --filename=testdeployment3.yaml --record=true

4         kubectl set image deploy testdeployment nginx=nginx:1.9.1 --record=true

[root@master ~]# kubectl  get rs -o wide     //查看Deployment控制器下所有的ReplicaSet控制器

NAME                        DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES        SELECTOR

test-nginx-59ffd87f5        2         2         2       7d21h   nginx        nginx         app=test-nginx,pod-template-hash=59ffd87f5

testdeployment-58779f7cd8   0         0         0       2d23h   nginx        nginx:1.7.9   example=deploymentnginx,pod-template-hash=58779f7cd8

testdeployment-5c4b8d64df   0         0         0       23h     nginx        nginx:1.8.1   example=deploymentnginx,pod-template-hash=5c4b8d64df

testdeployment-5c5458b87c   0         0         0       23h     nginx        nginx:1.9.0   example=deploymentnginx,pod-template-hash=5c5458b87c

testdeployment-8587689fb6   3         3         3       22h     nginx        nginx:1.9.1   example=deploymentnginx,pod-template-hash=8587689fb6

如何进行回滚?

语法:# kubectl  rollout undo deployment [deployment名称]  --to-revision=[REVERSION编号]

[root@master ~]# kubectl  rollout undo deployment testdeployment  --to-revision=2   //将控制器回滚到1.8.1版本

deployment.apps/testdeployment rolled back

[root@master ~]# kubectl  rollout history deployment testdeployment   //再次查看更新历史记录

deployment.apps/testdeployment

REVISION  CHANGE-CAUSE

1         kubectl apply --filename=testdeployment.yaml --record=true

3         kubectl apply --filename=testdeployment3.yaml --record=true

4         kubectl set image deploy testdeployment nginx=nginx:1.9.1 --record=true

5         kubectl apply --filename=testdeployment2.yaml --record=true

[root@master ~]# kubectl  get rs -o wide     //再次查看replicaset控制器的状态,发现已回滚到1.8.1的版本

NAME                        DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES        SELECTOR

test-nginx-59ffd87f5        2         2         2       7d21h   nginx        nginx         app=test-nginx,pod-template-hash=59ffd87f5

testdeployment-58779f7cd8   0         0         0       2d23h   nginx        nginx:1.7.9   example=deploymentnginx,pod-template-hash=58779f7cd8

testdeployment-5c4b8d64df   3         3         3       23h     nginx        nginx:1.8.1   example=deploymentnginx,pod-template-hash=5c4b8d64df

testdeployment-5c5458b87c   0         0         0       23h     nginx        nginx:1.9.0   example=deploymentnginx,pod-template-hash=5c5458b87c

testdeployment-8587689fb6   0         0         0       22h     nginx        nginx:1.9.1   example=deploymentnginx,pod-template-hash=8587689fb6

[root@master ~]# kubectl  get pods

NAME                              READY   STATUS    RESTARTS      AGE

chinaskill-mall                   5/5     Running   5 (45h ago)   2d21h

test-nginx-59ffd87f5-2g86v        1/1     Running   1 (45h ago)   2d23h

test-nginx-59ffd87f5-wzmt4        1/1     Running   1 (45h ago)   2d23h

testdeployment-5c4b8d64df-9xsnb   1/1     Running   0             4m26s

testdeployment-5c4b8d64df-jbt42   1/1     Running   0             4m20s

testdeployment-5c4b8d64df-npgsl   1/1     Running   0             4m22s

[root@master ~]# kubectl  describe pod testdeployment-5c4b8d64df-9xsnb

Name:         testdeployment-5c4b8d64df-9xsnb

Namespace:    default

Priority:     0

Node:         worker1/192.168.200.12

Start Time:   Wed, 23 Nov 2022 19:57:46 -0500

Labels:       example=deploymentnginx

              pod-template-hash=5c4b8d64df

Annotations:  <none>

Status:       Running

IP:           10.244.1.48

IPs:

  IP:           10.244.1.48

Controlled By:  ReplicaSet/testdeployment-5c4b8d64df

Containers:

  nginx:

    Container ID:   docker://21ca5ee96ae37b1ad5ed0b7ef4bf8e1d9a85092881dc67a682cf53c2c9e3c344

    Image:          nginx:1.8.1

    Image ID:       docker-pullable://nginx@sha256:9b3e9f189890ef9d6713c3384da3809731bdb0bff84e7b68da330ebadf533085

    Port:           80/TCP

    Host Port:      0/TCP

    State:          Running

      Started:      Wed, 23 Nov 2022 19:57:49 -0500

    Ready:          True

    Restart Count:  0

    Environment:    <none>

    Mounts:

      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-khlqr (ro)

Conditions:

  Type              Status

  Initialized       True

  Ready             True

  ContainersReady   True

  PodScheduled      True

Volumes:

  kube-api-access-khlqr:

    Type:                    Projected (a volume that contains injected data from multiple sources)

    TokenExpirationSeconds:  3607

    ConfigMapName:           kube-root-ca.crt

    ConfigMapOptional:       <nil>

    DownwardAPI:             true

QoS Class:                   BestEffort

Node-Selectors:              <none>

Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s

                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s

Events:

  Type    Reason     Age    From               Message

  ----    ------     ----   ----               -------

  Normal  Scheduled  4m39s  default-scheduler  Successfully assigned default/testdeployment-5c4b8d64df-9xsnb to worker1

  Normal  Pulled     4m36s  kubelet            Container image "nginx:1.8.1" already present on machine

  Normal  Created    4m36s  kubelet            Created container nginx

  Normal  Started    4m36s  kubelet            Started container nginx


DaemonSet控制器

它会在集群中的各个节点上运行单一的Pod副本,比较适合部署那些为节点本身提供服务或者执行维护的pod。

DaemonSet控制器的一些典型用法包括但不限于以下几个方面:

  1. 运行集群存储Daemon控制器,比如在每个node上运行ceph等
  2. 在每个node上运行日志收集Daemon控制器,比如logstash
  3. 在每个node上运行监控Daemon控制器,比如Prometheus Node Exporter。

在每一台节点上都启动http服务,并将它作为DaaemonSet控制器进行部署。

1.创建daemonset控制器

[root@master ~]# vi testdaemonset.yaml

[root@master ~]# vi testdaemonset.yaml

apiVersion: apps/v1   #表示使用的API版本,此处用的是K8s的稳定版

kind: DaemonSet       #表示创建的资源对象,此处创建的是DaemonSet

metadata:             #资源对象的元数据,一个资源对象可以包含多个元数据,此处采用的元数据为name

  name: testdaemonset #表示当前资源的名称

spec:                 #表示资源对象的具体设置

  selector:           #自定义一个或多个标签,对Pod起到筛选作用,会选择与标签定义相匹配的Pod

    matchLabels:

      example: deploymenthttp

  template:           #Pod模板

    metadata:

      labels:

        example: deploymenthttp

    spec:

      containers:

      - name: httpd

        image: httpd:2.2

        ports:

        - containerPort: 80   #通过Container的属性将80端口进行暴露

          hostPort: 8081      #映射到宿主机的8081端口

          protocol: TCP

[root@master ~]# kubectl  apply -f testdaemonset.yaml

daemonset.apps/testdaemonset created

[root@master ~]# kubectl  get daemonset

NAME(控制器名称)            DESIRED(预期pod数)   CURRENT(当前的pod数)   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE

testdaemonset   2         2         2       2            2           <none>          56s

[root@master ~]# kubectl  get pods -o wide

NAME                              READY   STATUS    RESTARTS      AGE     IP            NODE      NOMINATED NODE   READINESS GATES

testdaemonset-4crzq               1/1     Running   0             2m29s   10.244.0.42   master    <none>           <none>

testdaemonset-7vs2l               1/1     Running   0             2m29s   10.244.1.50   worker1   <none>           <none>

//在前的结果中可以看到pod数量为2,但是我们并没有指定pod副本数,因为我们的node节点数量是两个,Daemonset会为每一台node分配一个pod,此时通过两个节点访问http发现均可以访问

[root@master ~]# kubectl  get daemonset --namespace=kube-system    //查看k8s系统本身的命名空间

NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE

kube-proxy   3         3         3       3            3           kubernetes.io/os=linux   13d

[root@master ~]# kubectl  get daemonset kube-proxy --namespace=kube-system -o yaml   //获取运行pod的配置,查看k8s系统级的daemonset控制器需要加上--namespace=kube-system

apiVersion: apps/v1

kind: DaemonSet

metadata:

  annotations:

    deprecated.daemonset.template.generation: "1"

  creationTimestamp: "2022-11-10T03:05:02Z"

  generation: 1

  labels:

    k8s-app: kube-proxy

  name: kube-proxy

  namespace: kube-system

  resourceVersion: "332127"

  uid: c41a1d6c-5248-42c5-97f8-bbc9bb50a678

spec:

  revisionHistoryLimit: 10

  selector:

    matchLabels:

      k8s-app: kube-proxy

  template:

    metadata:

      creationTimestamp: null

      labels:

        k8s-app: kube-proxy

    spec:

      containers:

      - command:

        - /usr/local/bin/kube-proxy

        - --config=/var/lib/kube-proxy/config.conf

        - --hostname-override=$(NODE_NAME)

        env:

        - name: NODE_NAME

          valueFrom:

            fieldRef:

              apiVersion: v1

              fieldPath: spec.nodeName

        image: registry.aliyuncs.com/google_containers/kube-proxy:v1.22.2

        imagePullPolicy: IfNotPresent

        name: kube-proxy

        resources: {}

        securityContext:

          privileged: true

        terminationMessagePath: /dev/termination-log

        terminationMessagePolicy: File

        volumeMounts:

        - mountPath: /var/lib/kube-proxy

          name: kube-proxy

        - mountPath: /run/xtables.lock

          name: xtables-lock

        - mountPath: /lib/modules

          name: lib-modules

          readOnly: true

      dnsPolicy: ClusterFirst

      hostNetwork: true

      nodeSelector:

        kubernetes.io/os: linux

      priorityClassName: system-node-critical

      restartPolicy: Always

      schedulerName: default-scheduler

      securityContext: {}

      serviceAccount: kube-proxy

      serviceAccountName: kube-proxy

      terminationGracePeriodSeconds: 30

      tolerations:

      - operator: Exists

      volumes:

      - configMap:

          defaultMode: 420

          name: kube-proxy

        name: kube-proxy

      - hostPath:

          path: /run/xtables.lock

          type: FileOrCreate

        name: xtables-lock

      - hostPath:

          path: /lib/modules

          type: ""

        name: lib-modules

  updateStrategy:

    rollingUpdate:

      maxSurge: 0

      maxUnavailable: 1

    type: RollingUpdate

status:

  currentNumberScheduled: 3

  desiredNumberScheduled: 3

  numberAvailable: 3

  numberMisscheduled: 0

  numberReady: 3

  observedGeneration: 1

  updatedNumberScheduled: 3

2.daemonset控制器的更新

它的更新方式也有两种:

(1)RollingUpdate:当使用这种方式进行更新时,在更新Daemonset控制器模板后,旧的daemonset pod将被终止,并且将以受控方式自动创建DaemonSet pod,只支持maxUnavailable

(2)OnDelete:这是向后兼容的默认更新方式。当使用这种方式更新时,在更新DaemonSet控制器模板后,只有手动删除旧的控制器POD后,才会创建新的pod.

以OnDelete的方式进行更新,将http的版本更新至2.4

[root@master ~]# vi testdaemonset.yaml

apiVersion: apps/v1

kind: DaemonSet

metadata:

  name: testdaemonset

spec:

  selector:

    matchLabels:

      example: deploymenthttp

  template:

    metadata:

      labels:

        example: deploymenthttp

    spec:

      containers:

      - name: httpd

        image: httpd:2.4

        ports:

        - containerPort: 80

          hostPort: 8081

          protocol: TCP

  updateStrategy:

    type: OnDelete

[root@master ~]# kubectl  apply -f testdaemonset.yaml

daemonset.apps/testdaemonset configured

[root@master ~]# kubectl  get daemonset   //可以发现目前的更新还是为0,依旧是旧版本

NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE

testdaemonset   2         2         2       0            2           <none>          50m

[root@master ~]# kubectl  get  pods -o wide   //会发现此时的pod也依旧为旧版

NAME                              READY   STATUS    RESTARTS      AGE     IP            NODE      NOMINATED NODE   READINESS GATES

testdaemonset-4crzq               1/1     Running   0             52m     10.244.0.42   master    <none>           <none>

testdaemonset-7vs2l               1/1     Running   0             52m     10.244.1.50   worker1   <none>           <none>

[root@master ~]# kubectl  delete pod  testdaemonset-7vs2l   //删除pod触发更新

pod "testdaemonset-7vs2l" deleted

[root@master ~]# kubectl  get  pods -o wide    //删除完毕之后,会发现有一个新的pod正在创建

NAME                              READY   STATUS    RESTARTS      AGE     IP            NODE      NOMINATED NODE   READINESS GATES

testdaemonset-4crzq               1/1     Running   0             54m     10.244.0.42   master    <none>           <none>

testdaemonset-5887h               1/1     Running   0             28s     10.244.1.51   worker1   <none>           <none>

[root@master ~]# kubectl  get daemonset    //再次查看控制器发现已经更新的了一个pod

NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE

testdaemonset   2         2         2       1            2           <none>          55m

//我们可以重复上述的操作继续更新剩下的pod

[root@master ~]# kubectl  delete  pod testdaemonset-4crzq 

pod "testdaemonset-4crzq" deleted

[root@master ~]# kubectl  get  pods -o wide

NAME                              READY   STATUS    RESTARTS      AGE     IP            NODE      NOMINATED NODE   READINESS GATES

testdaemonset-5887h               1/1     Running   0             2m51s   10.244.1.51   worker1   <none>           <none>

testdaemonset-wnkkb               1/1     Running   0             24s     10.244.0.43   master    <none>           <none>

[root@master ~]# kubectl  get daemonset

NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE

testdaemonset   2         2         2       2            2           <none>          57m

//由上可以看出所有的pod均已被更新


(3)并发式任务:同一时间并发多次执行任务,可以通过spec.parallelism指定并发数量,也可以配合spec.completions属性来指定总任务的执行次数。

1.一次性任务执行

[root@master ~]# vi testjobv1.yaml

apiVersion: batch/v1          #表示API的使用版本,Job位于batch/v1中,v1表示K8S API的稳定版本

kind: Job                     #创建的资源对象类型

metadata:                     #资源对象的元数据

  name: testjobv1             #当前的资源对象名称

spec:

  ttlSecondsAfterFinished: 30      #执行job任务后,等待30s中将执行玩的pod删除

  template:                    #pod模板,需要创建一个pod,pod在启动之后,要执行一串命令

    spec:

      restartPolicy: Never    #容器的重启策略

      containers:

      - name: testjobcontainer

        image: busybox

        imagePullPolicy: IfNotPresent

        command: ['sh','-c']

        args: ['echo "start Job!"; sleep 30; echo "Job Done!"']

[root@master ~]# kubectl  apply -f testjobv1.yaml    //创建pod

job.batch/testjobv1 created

[root@master ~]# kubectl  get job      //获取任务列表

NAME        COMPLETIONS   DURATION   AGE

testjobv1   1/1           33s        53s

[root@master ~]# kubectl  get pod -o wide     //获取pod状态

NAME                              READY   STATUS      RESTARTS       AGE     IP            NODE      NOMINATED NODE   READINESS GATES

testjobv1--1-hf5bk                0/1     Completed   0              71s     10.244.1.66   worker2   <none>           <none>

[root@master ~]# kubectl  logs testjobv1--1-hf5bk

start Job!

Job Done!

注意:Job执行完毕后,不会被自动删除,保留pod的好处是方便后期查看日志,或者在出现问题的时候及时了解pod所处的状态。但是缺点在于,如果执行的次数越来越多,并且不删除,这种垃圾式的job会越来越多,人工删除会越来越麻烦,我们可以采取修改yaml文件增加参数信息的方式来将job执行完毕后,等待一段时间进行删除。增加参数:ttlSecondsAfterFinished

在k8s中这个功能默认是关闭的状态,需要我们手动的开启,修改的组件包括 apiserver、controller和scheduler。我们需要直接修改/etc/kubernetes/manifests/kube-apiserver.yaml,加入- --feature-gates=TTLAfterFinished=true参数即可。

2.串行式任务

[root@master ~]# vi testjobv2.yaml

apiVersion: batch/v1

kind: Job

metadata:

  name: testjobv2

spec:

  completions: 5

  template:

    spec:

      restartPolicy: Never

      containers:

      - name: testjobv2

        image: busybox

        imagePullPolicy: IfNotPresent

        command: ['sh','-c']

        args: ['echo "start Job!"; sleep 30; echo "Job Done!"']

[root@master ~]# kubectl  get pod -o wide    //从结果可知现在增加completions参数后任务已经执行了5次

testjobv2--1-8lrqv                0/1     Completed   0              96s     10.244.1.70   worker2   <none>           <none>

testjobv2--1-cm4px                0/1     Completed   0              2m40s   10.244.1.68   worker2   <none>           <none>

testjobv2--1-hcbdh                0/1     Completed   0              65s     10.244.1.71   worker2   <none>           <none>

testjobv2--1-lgtgd                0/1     Completed   0              34s     10.244.1.72   worker2   <none>           <none>

testjobv2--1-whsf7                0/1     Completed   0              2m7s    10.244.1.69   worker2   <none>           <none>

[root@master ~]# kubectl  get job

NAME        COMPLETIONS   DURATION   AGE

testjobv2   5/5           2m38s      3m39s

3.并行式任务

[root@master ~]# vi testjobv3.yaml

apiVersion: batch/v1

kind: Job

metadata:

  name: testjobv3

spec:

  completions: 10

  parallelism: 5

  template:

    spec:

      restartPolicy: Never

      containers:

      - name: testjobv3

        image: busybox

        imagePullPolicy: IfNotPresent

        command: ['sh','-c']

        args: ['echo "start Job!"; sleep 30; echo "Job Done!"']

[root@master ~]# kubectl  get pod -o wide  |grep testjobv3

testjobv3--1-4dcpb                0/1     Completed   0                2m24s   10.244.2.57   worker1   <none>           <none>

......

注意:一开始会同时创建5个pod同时运行,然后等待某一个pod运行结束之后,继续创建后续的pod,保持5个pod同时处于running的状态,直到达到设置的执行总数10次为止。

4.Job的异常处理

在job任务中,只能定义restartPolicy的值为Never或OnFailure其中一种。

(1)设置OnFailure时的状态

[root@master ~]# vi testjobv4.yaml

apiVersion: batch/v1

kind: Job

metadata:

  name: testjobv4

spec:

  backoffLimit: 6    #重启次数的上限,默认次数就是6次

  template:

    spec:

      restartPolicy: OnFailure

      containers:

      - name: testjobv4

        image: busybox

        imagePullPolicy: IfNotPresent

        command: ['sh','-c']

        args: ['This is erro command!!!']

[root@master ~]# kubectl  apply -f testjobv4.yaml

job.batch/testjobv4 created

[root@master ~]# kubectl  get pod -o wide  |grep testjobv4

testjobv4--1-xnh2g                0/1     CrashLoopBackOff   4 (67s ago)    2m44s   10.244.1.78   worker2   <none>           <none>

//执行完毕创建后,Pod的创建状态一直处于error或者是CrashLoopBackOff,在此期间Pod会不断的重启,RESTART的值一直在不断地增加,

Pod会以递增延迟的方式尝试重新启动(10s,20s,40s...)上限时间为6分钟,当延迟的时间增加到6分钟后,要再次等待6分钟才会重启,在我们的模板文件中设定了重启的次数上限,默认为6次,如果6次以内没有出现失败,则会重新计数,但是如果达到了重启次数的上限,则这个job对应的容器将会被终止删除。

[root@master ~]# kubectl  get pod -o wide  |grep testjobv4

*这个结果什么也没有了,pod到达重启上限后被删除*

(2)设置Never时的状态

[root@master ~]# vi testjobv5.yaml

apiVersion: batch/v1

kind: Job

metadata:

  name: testjobv5

spec:

  backoffLimit: 6    #重启次数的上限,默认次数就是6次

  template:

    spec:

      restartPolicy: Never

      containers:

      - name: testjobv5

        image: busybox

        imagePullPolicy: IfNotPresent

        command: ['sh','-c']

        args: ['This is erro command!!!']

[root@master ~]# kubectl  apply -f testjobv5.yaml

job.batch/testjobv5 created

[root@master ~]# kubectl  get pod

testjobv5--1-5m7pj                0/1     Error       0              2s

testjobv5--1-dcwnp                0/1     Error       0              52s

testjobv5--1-kf2hn                0/1     Error       0              42s

testjobv5--1-t22f7                0/1     Error       0              53s

//从以上结果可知,pod不会重新启动,因为设置了never并且job任务并没有执行成功,所以job会不停的新建pod,直到pod执行成功。

在这个过程中和onfailure相同的是,Never也会增加启动延迟的时间,同样也是由backoffLimit来控制重启的上限次数,在经过6次重启之后(等于7次启动),pod还是失败的状态那么此时就不会在启新的pod了。

(3)不明显异常处理

除了可以发现的异常现象之外,job在执行的过程中,还一种难以发觉的异常情况,比如任务陷入了死循环卡死不动,看起来是正常状态但是执行任务没有任何结果。

对于这类异常情况job也提供了spec.activeDeadlineSeconds属性,指定任务的上限时间(以秒为单位),如果超过上限时间,任务将被强制终止并删除。

[root@master ~]# vi testjobv6.yaml

apiVersion: batch/v1

kind: Job

metadata:

  name: testjobv6

spec:

  activeDeadlineSeconds: 10

  template:

    spec:

      restartPolicy: Never

      containers:

      - name: testjobv6

        image: busybox

        imagePullPolicy: IfNotPresent

        command: ['sh','-c']

        args: ['echo "Hello weizhihua"; sleep 3600']

[root@master ~]# kubectl  apply -f testjobv6.yaml

job.batch/testjobv6 created

[root@master ~]# kubectl  get pod

NAME                              READY   STATUS      RESTARTS       AGE

testjobv6--1-frrm7                1/1     Terminating   0              23s

//我们因为由运行时间限制10秒钟,所以在最开始的十秒钟内,Pod是处于运行的状态,10秒钟后Pod就被终止掉了,直到后面被删除(不管重启策略设置的值是OnFailure还是Never)

[root@master ~]# kubectl  get pod |grep testjov6

*此处以为空*

  • 在K8S集群中还有一种叫做job工作负载的对象,基于某一特定的任务运行,当运行任务的容器完成工作后,就会成功退出。

    Cronjob的任务就是在job的基础上增加了时间调度,可以在给定的时间点运行一个任务,并且也可以定期的运行。

    Job控制器可以执行三种类型的操作:

  • 一次性任务:通常只会去启动一个pod(除非pod失败),一旦pod成功终止,job任务就完成了。
  • 串行式任务:连续的、多次执行某一任务。当上一次任务执行完毕,接着执行下一个任务,直至所有的任务执行完毕,可以通过spec.completions属性指定执行次数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值