image-20220311153731890

目录

实验环境

实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
   k8s version:v1.22.2
   containerd://1.5.5

实验软件

链接:https://pan.baidu.com/s/1IH3renNk0kK7nErd_0YbaA?pwd=55wf
提取码:55wf
2022.3.11-50.OpenKruise通用控制器-实验软件

image-20220312084022964

1、Advanced StatefulSet

该控制器在原生的 StatefulSet 基础上增强了发布能力,比如 maxUnavailable 并行发布、原地升级等,该对象的名称也是 StatefulSet,但是 apiVersion 是 apps.kruise.io/v1beta1,这个 CRD 的所有默认字段、默认行为与原生 StatefulSet 完全一致,除此之外还提供了一些 optional 字段来扩展增强的策略。因此,用户从原生 StatefulSet 迁移到 Advanced StatefulSet,只需要把 apiVersion 修改后提交即可:😂

-  apiVersion: apps/v1
+  apiVersion: apps.kruise.io/v1beta1
   kind: StatefulSet
   metadata:
     name: sample
   spec:
     #...

1.最大不可用

💘 实验:最大不可用(测试成功)

Advanced StatefulSet 在滚动更新策略中新增了 maxUnavailable 来支持并行 Pod 发布,它会保证发布过程中最多有多少个 Pod 处于不可用状态。⚠️ 注意,maxUnavailable 只能配合 podManagementPolicy 为 Parallel 来使用

这个策略的效果和 Deployment 中的类似,但是可能会导致发布过程中的 order 顺序不能严格保证,如果不配置 maxUnavailable,它的默认值为 1,也就是和原生 StatefulSet 一样只能串行发布 Pod即使把 podManagementPolicy 配置为 Parallel 也是这样

  • 比如现在我们创建一个如下所示的 Advanced StatefulSet:
#01-sts-RollingUpdate-Parallel.yaml
apiVersion: apps.kruise.io/v1beta1
kind: StatefulSet
metadata:
  name: web
  namespace: default
spec:
  serviceName: "nginx-headless"
  podManagementPolicy: Parallel
  replicas: 5
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 3
      # partition: 4
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx  # @
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - name: web
          containerPort: 80
  • 直接创建该对象,由于对象名称也是 StatefulSet,所以不能直接用 get sts 来获取了,要通过 get asts 获取:
$ kubectl apply -f 01-sts-RollingUpdate-Parallel.yaml 
statefulset.apps.kruise.io/web created

[root@master1 ~]#kubectl get asts
NAME   DESIRED   CURRENT   UPDATED   READY   AGE
web    5         5         5         5       24s

[root@master1 ~]#kubectl get po  -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          33s
web-1   1/1     Running   0          33s
web-2   1/1     Running   0          32s
web-3   1/1     Running   0          32s
web-4   1/1     Running   0          32s

注意:查看advanced statsfulset的简写

[root@master1 ~]#kubectl get crd|grep kruise      
advancedcronjobs.apps.kruise.io            2022-03-10T13:09:22Z
broadcastjobs.apps.kruise.io               2022-03-10T13:09:22Z
clonesets.apps.kruise.io                   2022-03-10T13:09:22Z
containerrecreaterequests.apps.kruise.io   2022-03-10T13:09:22Z
daemonsets.apps.kruise.io                  2022-03-10T13:09:22Z
imagepulljobs.apps.kruise.io               2022-03-10T13:09:22Z
nodeimages.apps.kruise.io                  2022-03-10T13:09:22Z
podunavailablebudgets.policy.kruise.io     2022-03-10T13:09:22Z
resourcedistributions.apps.kruise.io       2022-03-10T13:09:22Z
sidecarsets.apps.kruise.io                 2022-03-10T13:09:22Z
statefulsets.apps.kruise.io                2022-03-10T13:09:22Z
uniteddeployments.apps.kruise.io           2022-03-10T13:09:22Z
workloadspreads.apps.kruise.io             2022-03-10T13:09:22Z

[root@master1 ~]#kubectl get crd statefulsets.apps.kruise.io -oyaml|less

image-20220311160901455

🍀 该应用下有五个 Pod,假设应用能容忍 3 个副本不可用,当我们把 StatefulSet 里的 Pod 升级版本的时候,可以通过以下步骤来做:

    1. 设置 maxUnavailable=3
    1. (可选) 如果需要灰度升级,设置 partition=4,Partition 默认的意思是 order 大于等于这个数值的 Pod 才会更新,在这里就只会更新 P4,即使我们设置了 maxUnavailable=3。
    1. 在 P4 升级完成后,把 partition 调整为 0,此时,控制器会同时升级 P1、P2、P3 三个 Pod。注意,如果是原生 StatefulSet,只能串行升级 P3、P2、P1。
    1. 一旦这三个 Pod 中有一个升级完成了,控制器会立即开始升级 P0。😥

🍀 比如这里我们把上面应用的镜像版本进行修改,更新后查看 Pod 状态,可以看到有3个 Pod 并行升级的:

修改镜像版本:

……
image: nginx:latest  #修改为nginx:latest
……

image-20220311161149639

#部署
$ kubectl apply -f 01-sts-RollingUpdate-Parallel.yaml
statefulset.apps.kruise.io/web configured

#查看
➜ kubectl get pods -l app=nginx
NAME    READY   STATUS              RESTARTS   AGE
web-0   1/1     Running             0          2m41s
web-1   1/1     Running             0          2m41s
web-2   0/1     ContainerCreating   0          10s
web-3   0/1     ContainerCreating   0          10s
web-4   0/1     ContainerCreating   0          10s

[root@master1 ~]#kubectl get po  -l app=nginx
NAME    READY   STATUS              RESTARTS   AGE
web-0   1/1     Running             0          7m5s
web-1   1/1     Running             0          7m5s
web-2   0/1     ContainerCreating   0          4s
web-3   0/1     ContainerCreating   0          4s
web-4   0/1     ContainerCreating   0          4s

[root@master1 ~]#kubectl get po  -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          34s
web-1   1/1     Running   0          35s
web-2   1/1     Running   0          52s
web-3   1/1     Running   0          52s
web-4   1/1     Running   0          52s

[root@master1 ~]#kubectl describe po web-0
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  56s   default-scheduler  Successfully assigned default/web-0 to node2
  Normal  Pulling    55s   kubelet            Pulling image "nginx:latest"
  Normal  Pulled     26s   kubelet            Successfully pulled image "nginx:latest" in 29.501447739s
  Normal  Created    26s   kubelet            Created container nginx
  Normal  Started    25s   kubelet            Started container nginx

实验结束。😘

2.原地升级

💘 实验:原地升级(测试成功)

Advanced StatefulSet 增加了 podUpdatePolicy 来允许用户指定重建升级还是原地升级。此外还在原地升级中提供了 graceful period 选项,作为优雅原地升级的策略。用户如果配置了 gracePeriodSeconds 这个字段,控制器在原地升级的过程中会先把 Pod status 改为 not-ready,然后等一段时间(gracePeriodSeconds),最后再去修改 Pod spec 中的镜像版本。这样,就为 endpoints-controller 这些控制器留出了充足的时间来将 Pod 从 endpoints 端点列表中去除。

如果使用 InPlaceIfPossibleInPlaceOnly 策略,必须要增加一个 InPlaceUpdateReady readinessGate,用来在原地升级的时候控制器将 Pod 设置为 NotReady。

  • 比如设置上面的应用为原地升级的方式:
#02-sts-RollingUpdate-InPlaceIfPossible.yaml
apiVersion: apps.kruise.io/v1beta1
kind: StatefulSet
metadata:
  name: web
  namespace: default
spec:
  serviceName: "nginx-headless"
  podManagementPolicy: Parallel
  replicas: 5
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      podUpdatePolicy: InPlaceIfPossible  # 尽可能执行原地升级
      maxUnavailable: 3 # 允许并行更新,最大不可以实例数为3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      readinessGates:
      - conditionType: InPlaceUpdateReady # 一个新的条件,可确保 Pod 在发生原地更新时保持在 NotReady 状态
      containers:
      - name: nginx
        image: nginx:1.7.9 #这里把镜像修改为1.7.9
        ports:
        - name: web
          containerPort: 80

这里我们设置 updateStrategy.rollingUpdate.podUpdatePolicyInPlaceIfPossible 模式,表示尽可能使用原地升级的方式进行更新。此外在 Pod 模板中我们还添加了一个 readinessGates 属性,可以用来确保 Pod 在发生原地更新时保持在 NotReady 状态。

  • 先来查看下当前pod信息(等会原地升级后,我们再核对下pod信息)
[root@master1 ~]#kubectl get po -l app=nginx -owide
NAME    READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          56s   10.244.2.46    node2   <none>           2/2
web-1   1/1     Running   0          56s   10.244.1.162   node1   <none>           2/2
web-2   1/1     Running   0          56s   10.244.2.47    node2   <none>           2/2
web-3   1/1     Running   0          55s   10.244.1.163   node1   <none>           2/2
web-4   1/1     Running   0          55s   10.244.2.48    node2   <none>           2/2
  • 比如我们现在使用上面资源清单更新应用,然后重新修改镜像的版本更新,则会进行原地升级:
$ kubectl apply -f 02-sts-RollingUpdate-InPlaceIfPossible.yaml 
statefulset.apps.kruise.io/web configured

[root@master1 ~]#kubectl get po -l app=nginx -owide
NAME    READY   STATUS    RESTARTS      AGE    IP             NODE    NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0             106s   10.244.2.46    node2   <none>           1/2
web-1   1/1     Running   1 (17s ago)   106s   10.244.1.162   node1   <none>           2/2
web-2   1/1     Running   0             106s   10.244.2.47    node2   <none>           1/2
web-3   1/1     Running   1 (21s ago)   105s   10.244.1.163   node1   <none>           2/2
web-4   1/1     Running   1 (21s ago)   105s   10.244.2.48    node2   <none>           2/2
[root@master1 ~]#kubectl get po -l app=nginx -owide #可以看到采用原地升级后,pod ip和所在node节点信息都没发生改变
NAME    READY   STATUS    RESTARTS      AGE     IP             NODE    NOMINATED NODE   READINESS GATES
web-0   1/1     Running   1 (50s ago)   2m34s   10.244.2.46    node2   <none>           2/2
web-1   1/1     Running   1 (65s ago)   2m34s   10.244.1.162   node1   <none>           2/2
web-2   1/1     Running   1 (69s ago)   2m34s   10.244.2.47    node2   <none>           2/2
web-3   1/1     Running   1 (69s ago)   2m33s   10.244.1.163   node1   <none>           2/2
web-4   1/1     Running   1 (69s ago)   2m33s   10.244.2.48    node2   <none>           2/2


[root@master1 ~]#kubectl describe asts web
Events:
  Type    Reason                      Age    From                    Message
  ----    ------                      ----   ----                    -------
  Normal  SuccessfulCreate            3m32s  statefulset-controller  create Pod web-0 in StatefulSet web successful
  Normal  SuccessfulCreate            3m32s  statefulset-controller  create Pod web-1 in StatefulSet web successful
  Normal  SuccessfulCreate            3m32s  statefulset-controller  create Pod web-2 in StatefulSet web successful
  Normal  SuccessfulCreate            3m31s  statefulset-controller  create Pod web-3 in StatefulSet web successful
  Normal  SuccessfulCreate            3m31s  statefulset-controller  create Pod web-4 in StatefulSet web successful
  Normal  SuccessfulUpdatePodInPlace  2m7s   statefulset-controller  successfully update pod web-4 in-place(revision web-67975fc8c9)
  Normal  SuccessfulUpdatePodInPlace  2m7s   statefulset-controller  successfully update pod web-3 in-place(revision web-67975fc8c9)
  Normal  SuccessfulUpdatePodInPlace  2m7s   statefulset-controller  successfully update pod web-2 in-place(revision web-67975fc8c9)
  Normal  SuccessfulUpdatePodInPlace  2m3s   statefulset-controller  successfully update pod web-1 in-place(revision web-67975fc8c9)
  Normal  SuccessfulUpdatePodInPlace  108s   statefulset-controller  successfully update pod web-0 in-place(revision web-67975fc8c9)
  • 同样的 Advanced StatefulSet 也支持原地升级自动预热。

  • 也可以通过设置 paused 为 true 来暂停发布,不过控制器还是会做 replicas 数量管理:

apiVersion: apps.kruise.io/v1beta1
kind: StatefulSet
spec:
  # ...
  updateStrategy:
    rollingUpdate:
      paused: true
  • 另外 Advanced StatefulSet 还支持序号保留功能,通过在 reserveOrdinals 字段中写入需要保留的序号,Advanced StatefulSet 会自动跳过创建这些序号的 Pod,如果 Pod 已经存在,则会被删除。

注意,spec.replicas 是期望运行的 Pod 数量,spec.reserveOrdinals 是要跳过的序号。

apiVersion: apps.kruise.io/v1beta1
kind: StatefulSet
spec:
  # ...
  replicas: 4
  reserveOrdinals:
  - 1

比如上面的描述 replicas=4, reserveOrdinals=[1] 的 Advanced StatefulSet,表示实际运行的 Pod 序号为 [0,2,3,4]。

  • 如果要把 Pod-3 做迁移并保留序号,则把 3 追加到 reserveOrdinals 列表中,控制器会把 Pod-3 删除并创建 Pod-5(此时运行中 Pod 为 [0,2,4,5])。
  • 如果只想删除 Pod-3,则把 3 追加到 reserveOrdinals 列表并同时把 replicas 减一修改为 3。控制器会把 Pod-3 删除(此时运行中 Pod 为 [0,2,4])。

🍀 为了避免在一个新 Advanced StatefulSet 创建后有大量失败的 pod 被创建出来,从 Kruise v0.10.0 版本开始引入了在 scale strategy 中的 maxUnavailable 策略。

apiVersion: apps.kruise.io/v1beta1
kind: StatefulSet
spec:
  # ...
  replicas: 100
  scaleStrategy:
    maxUnavailable: 10% # percentage or absolute number

当这个字段被设置之后,Advanced StatefulSet 会保证创建 pod 之后不可用 pod 数量不超过这个限制值。比如说,上面这个 StatefulSet 一开始只会一次性创建 100*10%=10 个 pod,在此之后,每当一个 pod 变为 running、ready 状态后,才会再创建一个新 pod 出来。

注意,这个功能只允许在 podManagementPolicy 是 Parallel 的 StatefulSet 中使用。

实验结束。😘

2、Advanced DaemonSet

这个控制器基于原生 DaemonSet 上增强了发布能力,比如灰度分批、按 Node label 选择、暂停、热升级等。同样的该对象的 Kind 名字也是 DaemonSet,只是 apiVersion 是 apps.kruise.io/v1alpha1,这个 CRD 的所有默认字段、默认行为与原生 DaemonSet 完全一致,除此之外还提供了一些 optional 字段来扩展增强的策略。

因此,用户从原生 DaemonSet 迁移到 Advanced DaemonSet,只需要把 apiVersion 修改后提交即可:

-  apiVersion: apps/v1
+  apiVersion: apps.kruise.io/v1alpha1
   kind: DaemonSet
   metadata:
     name: sample-ds
   spec:
     #...

1.升级

💘 实验:升级(测试成功)

Advanced DaemonSet 在 spec.updateStrategy.rollingUpdate 中有一个 rollingUpdateType 字段,标识了如何进行滚动升级:

  • Standard: 对于每个节点,控制器会先删除旧的 daemon Pod,再创建一个新 Pod,和原生 DaemonSet 行为一致。
  • Surging: 对于每个 node,控制器会先创建一个新 Pod,等它 ready 之后再删除老 Pod。

🍀 创建如下所示的资源对象:

#03-daemonset-demo.yaml
apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
metadata:
  name: nginx
  namespace: default
spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      rollingUpdateType: Standard
  selector:
    matchLabels:
      k8s-app: nginx
  template:
    metadata:
      labels:
        k8s-app: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        name: nginx
        ports:
        - name: http
          containerPort: 80
  • 创建后需要通过 get daemon 来获取该对象:
#部署
$ kubectl apply -f 03-daemonset-demo.yaml
daemonset.apps.kruise.io/nginx created

[root@master1 ~]#kubectl get daemon
NAME    DESIREDNUMBER   CURRENTNUMBER   UPDATEDNUMBERSCHEDULED   AGE
nginx   2               2               2                        11s

[root@master1 ~]#kubectl get pods -l k8s-app=nginx -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
nginx-gbz5h   1/1     Running   0          17s   10.244.2.49    node2   <none>           1/1
nginx-hgx4b   1/1     Running   0          17s   10.244.1.164   node1   <none>           1/1

我们这里只有两个 Work 节点,所以一共运行了2个 Pod,每个节点上一个,和默认的 DaemonSet 行为基本一致。

  • 此外这个策略还支持用户通过配置 node 标签的 selector,来指定灰度升级某些特定类型 node 上的 Pod。比如现在我们只升级 node1 节点的应用,则可以使用 selector 标签来标识:

注意:这个功能还是比较实用的,在恢复发布方面,可以把故障域缩小到一定区间。

apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
spec:
# ...
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      rollingUpdateType: Standard
      selector: #添加节点selector
        matchLabels: #只会针对node1节点做做更新
          kubernetes.io/hostname: node1
# ...

完整yaml代码如下:

#04-daemonset-demo2.yaml
apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
metadata:
  name: nginx
  namespace: default
spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      rollingUpdateType: Standard
      selector: #修改点1:添加节点selector
        matchLabels: #只会针对node1节点做做更新
          kubernetes.io/hostname: node1      
  selector:
    matchLabels:
      k8s-app: nginx
  template:
    metadata:
      labels:
        k8s-app: nginx
    spec:
      containers:
      - image: nginx #修改点2:修改nginx镜像
        name: nginx
        ports:
        - name: http
          containerPort: 80
  • 更新应用后可以看到只会更新 node1 节点上的 Pod:
#部署
$ kubectl apply -f 04-daemonset-demo2.yaml
daemonset.apps.kruise.io/nginx configured

[root@master1 ~]#kubectl get pods -l k8s-app=nginx -o wide
NAME          READY   STATUS    RESTARTS   AGE     IP             NODE    NOMINATED NODE   READINESS GATES
nginx-d67ms   1/1     Running   0          17s     10.244.1.165   node1   <none>           1/1
nginx-gbz5h   1/1     Running   0          6m24s   10.244.2.49    node2   <none>           1/1


[root@master1 ~]#kubectl describe daemon nginx
......
Events:
  Type    Reason            Age    From                  Message
  ----    ------            ----   ----                  -------
  Normal  SuccessfulCreate  7m22s  daemonset-controller  Created pod: nginx-hgx4b
  Normal  SuccessfulCreate  7m22s  daemonset-controller  Created pod: nginx-gbz5h
  Normal  SuccessfulDelete  76s    daemonset-controller  Deleted pod: nginx-hgx4b
  Normal  SuccessfulCreate  75s    daemonset-controller  Created pod: nginx-d67ms
  • 和前面两个控制器一样,Advanced DaemonSet 也支持分批灰度升级,使用 Partition 进行配置,Partition 的语义是保留旧版本 Pod 的数量,默认为 0,如果在发布过程中设置了 partition,则控制器只会将 (status.DesiredNumberScheduled - partition) 数量的 Pod 更新到最新版本。
apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
spec:
  # ...
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 10 #如果大于期望运行的pod数量,则不会更新。
      paused: true  # 暂停发布
  • 同样 Advanced DaemonSet 也是支持原地升级的,只需要设置 rollingUpdateType 为支持原地升级的类型即可,比如这里我们将上面的应用升级方式设置为 InPlaceIfPossible 即可:
apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
spec:
  # ...
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      rollingUpdateType: InPlaceIfPossible #设置为尽可能地原地升级。

完整yam代码如下:

#05-daemonset-demo3.yaml
apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
metadata:
  name: nginx
  namespace: default
spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      rollingUpdateType: InPlaceIfPossible   #修改点1
  selector:
    matchLabels:
      k8s-app: nginx
  template:
    metadata:
      labels:
        k8s-app: nginx
    spec:
      containers:
      - image: nginx:1.7.9 #修改点2:修改nginx镜像,只修改镜像的版本会当成原地升级的场景
        name: nginx
        ports:
        - name: http
          containerPort: 80
  • 在测试之前,我们准备下当前环境:
#清空下当前环境,然后重新部署下05-daemonset-demo3.yaml,并查看下当前pod信息
[root@master1 ~]#kubectl delete daemon nginx 
daemonset.apps.kruise.io "nginx" deleted

$ kubectl apply -f 05-daemonset-demo3.yaml
daemonset.apps.kruise.io/nginx created

[root@master1 ~]#kubectl get po -owide
NAME          READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
nginx-7h2nw   1/1     Running   0          4s    10.244.1.168   node1   <none>           2/2
nginx-bmzcq   1/1     Running   0          4s    10.244.2.52    node2   <none>           2/2


#然后把05-daemonset-demo3.yaml里面的镜像改下,再部署下,观察下效果
……
- image: nginx
……
  • 更新后可以通过查看控制器的事件来验证是否是通过原地升级方式更新应用:
$ kubectl apply -f 05-daemonset-demo3.yaml
daemonset.apps.kruise.io/nginx configured

[root@master1 ~]#kubectl get po -owide
NAME          READY   STATUS    RESTARTS      AGE     IP             NODE    NOMINATED NODE   READINESS GATES
nginx-7h2nw   1/1     Running   1 (10s ago)   2m13s   10.244.1.168   node1   <none>           2/2
nginx-bmzcq   1/1     Running   1 (13s ago)   2m13s   10.244.2.52    node2   <none>           2/2

[root@master1 ~]#kubectl describe daemon nginx
......
Events:
  Type     Reason                            Age                From                  Message
  ----     ------                            ----               ----                  -------
  Normal   SuccessfulCreate                  2m29s              daemonset-controller  Created pod: nginx-bmzcq
  Normal   SuccessfulCreate                  2m29s              daemonset-controller  Created pod: nginx-7h2nw
  Normal   SuccessfulUpdatePodInPlace        29s                daemonset-controller  successfully update pod nginx-bmzcq in-place 
  Warning  numUnavailable >= maxUnavailable  27s (x7 over 29s)  daemonset-controller  default/nginx number of unavailable DaemonSet pods: 1, is equal to or exceeds allowed maximum: 1
  Normal   SuccessfulUpdatePodInPlace        26s                daemonset-controller  successfully update pod nginx-7h2nw in-place 
  • 注意:这里使用daemon就好。
[root@master1 ~]#kubectl get crd|grep kruise
advancedcronjobs.apps.kruise.io            2022-03-10T13:09:22Z
broadcastjobs.apps.kruise.io               2022-03-10T13:09:22Z
clonesets.apps.kruise.io                   2022-03-10T13:09:22Z
containerrecreaterequests.apps.kruise.io   2022-03-10T13:09:22Z
daemonsets.apps.kruise.io                  2022-03-10T13:09:22Z
imagepulljobs.apps.kruise.io               2022-03-10T13:09:22Z
nodeimages.apps.kruise.io                  2022-03-10T13:09:22Z
podunavailablebudgets.policy.kruise.io     2022-03-10T13:09:22Z
resourcedistributions.apps.kruise.io       2022-03-10T13:09:22Z
sidecarsets.apps.kruise.io                 2022-03-10T13:09:22Z
statefulsets.apps.kruise.io                2022-03-10T13:09:22Z
uniteddeployments.apps.kruise.io           2022-03-10T13:09:22Z
workloadspreads.apps.kruise.io             2022-03-10T13:09:22Z
[root@master1 ~]#kubectl get crd daemonsets.apps.kruise.io -oyaml
……
spec:
  conversion:
    strategy: None
  group: apps.kruise.io
  names:
    kind: DaemonSet
    listKind: DaemonSetList
    plural: daemonsets
    shortNames:
    - daemon
    singular: daemonset
……

实验结束。😘

3、BroadcastJob

这个控制器将 Pod 分发到集群中每个节点上,类似于 DaemonSet,但是 BroadcastJob 管理的 Pod 并不是长期运行的 daemon 服务,而是类似于 Job 的任务类型 Pod,在每个节点上的 Pod 都执行完成退出后,BroadcastJob 和这些 Pod 并不会占用集群资源。 这个控制器非常有利于做升级基础软件、巡检等过一段时间需要在整个集群中跑一次的工作

💘 实验:BroadcastJob(测试成功)

  • 比如我们声明一个如下所示的 BroadcastJob 对象:
#06-BroadcastJob.yaml
apiVersion: apps.kruise.io/v1alpha1
kind: BroadcastJob
metadata:
  name: bcj-demo
  namespace: default
spec:
  template:
    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; done"
  • 直接创建上面的资源对象,
$ kubectl apply -f 06-BroadcastJob.yaml  
broadcastjob.apps.kruise.io/bcj-demo created

[root@master1 ~]#kubectl get bcj
NAME       DESIRED   ACTIVE   SUCCEEDED   FAILED   AGE
bcj-demo   2         0        2           0        87s

[root@master1 ~]#kubectl get po -owide
NAME             READY   STATUS      RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
bcj-demo-48b8q   0/1     Completed   0          90s   10.244.1.169   node1   <none>           1/1
bcj-demo-w9m79   0/1     Completed   0          90s   10.244.2.53    node2   <none>           1/1

我们可以看到创建了一个 BroadcastJob 对象后,同时启动了两个 Pod 任务,每个节点上一个,这和原生的 Job 是不太一样的

创建的 BroadcastJob 一共有以下几种状态:

  • Desired : 期望的 Pod 数量(等同于当前集群中匹配的节点数量)
  • Active: 运行中的 Pod 数量
  • SUCCEEDED: 执行成功的 Pod 数量
  • FAILED: 执行失败的 Pod 数量

🍀 此外在 BroadcastJob 对象中还可以配置任务完成后的一些策略,比如配置 completionPolicy.ttlSecondsAfterFinished: 30,表示这个 job 会在执行结束后 30s 被删除。

apiVersion: apps.kruise.io/v1alpha1
kind: BroadcastJob

spec:
  completionPolicy:
    type: Always
    ttlSecondsAfterFinished: 30
  # ......

🍀 配置 completionPolicy.activeDeadlineSeconds 为 10,表示这个 job 会在运行超过 10s 之后被标记为失败,并把下面还在运行的 Pod 删除掉。

apiVersion: apps.kruise.io/v1alpha1
kind: BroadcastJob

spec:
  completionPolicy:
    type: Always
    activeDeadlineSeconds: 10
  # ......

🍀 completionPolicy 类型除了 Always 之外还可以设置为 Never,表示这个 job 会持续运行即使当前所有节点上的 Pod 都执行完成了。这里老师当时说,好像没看到具体效果……

apiVersion: apps.kruise.io/v1alpha1
kind: BroadcastJob

spec:
  completionPolicy:
    type: Never
  # ......

4、AdvancedCronJob

💘 实验:AdvancedCronJob(成功测试)

AdvancedCronJob 是对于原生 CronJob 的扩展版本,根据用户设置的 schedule 规则,周期性创建 Job 执行任务,而 AdvancedCronJob 的 template 支持多种不同的 job 资源:

apiVersion: apps.kruise.io/v1alpha1
kind: AdvancedCronJob
spec:
  template:
    # Option 1: use jobTemplate, which is equivalent to original CronJob
    jobTemplate:
      # ...
    # Option 2: use broadcastJobTemplate, which will create a BroadcastJob object when cron schedule triggers
    broadcastJobTemplate:
      # ...
  • jobTemplate:与原生 CronJob 一样创建 Job 执行任务
  • broadcastJobTemplate:周期性创建 BroadcastJob 执行任务

AdvancedCronJob

  • 写一个yaml
#07-acj-demo1.yaml
apiVersion: apps.kruise.io/v1alpha1
kind: AdvancedCronJob
metadata:
  name: acj-test
spec:
  schedule: "*/1 * * * *"
  template:
    broadcastJobTemplate:
      spec:
        completionPolicy:
          type: Always
          ttlSecondsAfterFinished: 30
        template:
          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; done"

上述 YAML 定义了一个 AdvancedCronJob,每分钟创建一个 BroadcastJob 对象,这个 BroadcastJob 会在所有节点上运行一个 job 任务。

  • 部署并查看
$ kubectl apply -f 07-acj-demo1.yaml     
advancedcronjob.apps.kruise.io/acj-test created

[root@master1 ~]#kubectl get acj
NAME       SCHEDULE      TYPE           LASTSCHEDULETIME   AGE
acj-test   */1 * * * *   BroadcastJob                      25s

[root@master1 ~]#kubectl get bcj
NAME                  DESIRED   ACTIVE   SUCCEEDED   FAILED   AGE
acj-test-1647045420   2         0        2           0        18s
acj-test-1647045480   2         1        1           0        5s

[root@master1 ~]#kubectl get po
NAME                        READY   STATUS      RESTARTS   AGE
acj-test-1647045420-56x7j   0/1     Completed   0          33s
acj-test-1647045420-nkrx4   0/1     Completed   0          33s

实验结束。😘

关于我

我的博客主旨:我希望每一个人拿着我的博客都可以做出实验现象,先把实验做出来,然后再结合理论知识更深层次去理解技术点,这样学习起来才有乐趣和动力。并且,我的博客内容步骤是很完整的,也分享源码和实验用到的软件,希望能和大家一起共同进步!

各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人免费帮您解决问题:

  1. 个人微信二维码:x2675263825 (舍得), qq:2675263825。

    image-20211002091450217

  2. 个人微信公众号:云原生架构师实战

    image-20211002141739664

  3. 个人博客地址:www.onlyonexl.cn

    image-20211002092057988

  4. 个人csdn

    https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

    image-20211002092344616

  5. 个人已开源干货😘

    名称链接
    01 实战:打造一款王者云笔记:typora+坚果云+阿里云oss(永久开源)https://www.jianguoyun.com/p/DXS6qiIQvPWVCRiS0qoE
    02 实战:定制宇宙中最美的typora主题皮肤(永久开源)https://www.jianguoyun.com/p/DeUK9u0QvPWVCRib0qoE
    03 玩转vscode(永久开源)https://www.jianguoyun.com/p/DZe8gmsQvPWVCRid0qoE
    04 陈果的幸福哲学课(永久开源)https://www.jianguoyun.com/p/Db0kM7gQvPWVCRj2q6YE

最后

好了,关于OpenKruise通用控制器实验就到这里了,感谢大家阅读,最后贴上我女神的photo,祝大家生活快乐,每天都过的有意义哦,我们下期见!

image-20220312084139245

Logo

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

更多推荐