跳到主要内容

OpenKruise部署与CloneSet

OpenKruise部署与CloneSet

目录

[TOC]

实验环境

实验环境:
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/1F7mvtbYMCOfqS7Gc_HS7-A?pwd=czge

提取码:czge

2022.3.10-49.OpenKruise部署与CloneSet-实验软件

1、OpenKruise

阿里云开源的

OpenKruise 是一个基于 Kubernetes 的扩展套件,主要聚焦于云原生应用的自动化,比如部署、发布、运维以及可用性防护。OpenKruise 提供的绝大部分能力都是基于 CRD 扩展来定义的,它们不存在于任何外部依赖,可以运行在任意纯净的 Kubernetes 集群中。Kubernetes 自身提供的一些应用部署管理功能,对于大规模应用与集群的场景这些功能是远远不够的,OpenKruise 弥补了 Kubernetes 在应用部署、升级、防护、运维等领域的不足。

OpenKruise 提供了以下的一些核心能力:

  • 增强版本的 Workloads:OpenKruise 包含了一系列增强版本的工作负载,比如 CloneSet、Advanced StatefulSet、Advanced DaemonSet、BroadcastJob等。它们不仅支持类似于 Kubernetes 原生 Workloads 的基础功能,还提供了如原地升级、可配置的扩缩容/发布策略、并发操作等。其中,原地升级是一种升级应用容器镜像甚至环境变量的全新方式,它只会用新的镜像重建 Pod 中的特定容器,整个 Pod 以及其中的其他容器都不会被影响。因此它带来了更快的发布速度,以及避免了对其他 Scheduler、CNI、CSI 等组件的负面影响。

原地升级:这个最近还是提的比较多的,例如我们线上业务能够实现原地升级的话,还是比较有利的。

  • 应用的旁路管理:OpenKruise 提供了多种通过旁路管理应用 sidecar 容器、多区域部署的方式,“旁路” 意味着你可以不需要修改应用的 Workloads 来实现它们。比如,SidecarSet 能帮助你在所有匹配的 Pod 创建的时候都注入特定的 sidecar 容器,甚至可以原地升级已经注入的 sidecar 容器镜像、并且对 Pod 中其他容器不造成影响。而 WorkloadSpread 可以约束无状态 Workload 扩容出来 Pod 的区域分布,赋予单一 workload 的多区域和弹性部署的能力。

  • 高可用性防护:OpenKruise 可以保护你的 Kubernetes 资源不受级联删除机制的干扰,包括 CRD、Namespace、以及几乎全部的 Workloads 类型资源。相比于 Kubernetes 原生的 PDB 只提供针对 Pod Eviction(驱逐) 的防护,PodUnavailableBudget 能够防护 Pod Deletion、Eviction、Update 等许多种 voluntary disruption 场景。

  • 高级的应用运维能力:OpenKruise 也提供了很多高级的运维能力来帮助你更好地管理应用,比如可以通过 ImagePullJob 来在任意范围的节点上预先拉取某些镜像,或者指定某个 Pod 中的一个或多个容器被原地重启。

🍀 OpenKruise官方文档

https://openkruise.io/zh/docs/

2、架构

下图是 OpenKruise 的整体架构:

首先我们要清楚所有 OpenKruise 的功能都是通过 Kubernetes CRD 来提供的:

➜ kubectl get crd | grep kruise.io
advancedcronjobs.apps.kruise.io 2021-09-16T06:02:36Z
broadcastjobs.apps.kruise.io 2021-09-16T06:02:36Z
clonesets.apps.kruise.io 2021-09-16T06:02:36Z
containerrecreaterequests.apps.kruise.io 2021-09-16T06:02:36Z
daemonsets.apps.kruise.io 2021-09-16T06:02:36Z
imagepulljobs.apps.kruise.io 2021-09-16T06:02:36Z
nodeimages.apps.kruise.io 2021-09-16T06:02:36Z
podunavailablebudgets.policy.kruise.io 2021-09-16T06:02:36Z
resourcedistributions.apps.kruise.io 2021-09-16T06:02:36Z
sidecarsets.apps.kruise.io 2021-09-16T06:02:36Z
statefulsets.apps.kruise.io 2021-09-16T06:02:36Z
uniteddeployments.apps.kruise.io 2021-09-16T06:02:37Z
workloadspreads.apps.kruise.io 2021-09-16T06:02:37Z

其中 Kruise-manager 是一个运行控制器和 webhook 的中心组件,它通过 Deployment 部署在 kruise-system 命名空间中。 从逻辑上来看,如 cloneset-controllersidecarset-controller 这些的控制器都是独立运行的,不过为了减少复杂度,它们都被打包在一个独立的二进制文件、并运行在 kruise-controller-manager-xxx 这个 Pod 中。除了控制器之外,kruise-controller-manager-xxx 中还包含了针对 Kruise CRD 以及 Pod 资源的 admission webhook。Kruise-manager 会创建一些 webhook configurations 来配置哪些资源需要感知处理、以及提供一个 Service 来给 kube-apiserver 调用。

webhook它会去做一些校验。

从 v0.8.0 版本开始提供了一个新的 Kruise-daemon 组件,它通过 DaemonSet 部署到每个节点上,提供镜像预热、容器重启等功能。

3、OpenKruise安装

💘 实验:OpenKruise安装

这里我们同样还是使用 Helm 方式来进行安装,需要注意从 v1.0.0 开始,OpenKruise 要求在 Kubernetes >= 1.16 以上版本的集群中安装和使用。

  • 首先添加 charts 仓库:
[root@master1 ~]# helm repo add openkruise https://openkruise.github.io/charts
"openkruise" has been added to your repositories
[root@master1 ~]#helm repo update
Hang tight while we grab the latest from your chart repositories...
……
...Successfully got an update from the "openkruise" chart repository
Update Complete. ⎈Happy Helming!
  • 我这边下载下kruise软件包(下载到本地,方便以后做实验)
[root@master1 ~]#helm fetch openkruise/kruise
Error: Get "https://github.com/openkruise/charts/releases/download/kruise-1.0.1/kruise-1.0.1.tgz": read tcp 172.29.9.51:33422->20.205.243.166:443: read: connection reset by peer
[root@master1 ~]#helm fetch openkruise/kruise
[root@master1 ~]#ls -lh kruise-1.0.1.tgz
-rw-r--r-- 1 root root 37K Mar 10 20:08 kruise-1.0.1.tgz

[root@master1 ~]#tar xf kruise-1.0.1.tgz
[root@master1 ~]#ls kruise
Chart.yaml README.md ci templates values.yaml
  • 然后执行下面的命令安装最新版本的应用:
➜ helm upgrade --install kruise openkruise/kruise --version 1.0.1

该 charts 在模板中默认定义了命名空间为 kruise-system,所以在安装的时候可以不用指定。

如果你的环境访问 DockerHub 官方镜像较慢,则可以使用下面的命令将镜像替换成阿里云的镜像:

➜ helm upgrade --install kruise openkruise/kruise --set manager.image.repository=openkruise-registry.cn-hangzhou.cr.aliyuncs.com/openkruise/kruise-manager --version 1.0.1

注意:我当时安装了第三次才安装成功,多安装几次就OK的。

注意:我们本次是直接使用默认的values.yaml文件里的参数的

  • 应用部署完成后会在 kruise-system 命名空间下面运行2个 kruise-manager 的 Pod,同样它们之间采用 leader-election的方式选主,同一时间只有一个提供服务,达到高可用的目的。此外还会以 DaemonSet 的形式启动 kruise-daemon 组件:
[root@master1 ~]#kubectl get po -nkruise-system         
NAME READY STATUS RESTARTS AGE
kruise-controller-manager-f5c9b55c5-jf4p2 1/1 Running 0 16m
kruise-controller-manager-f5c9b55c5-lbnnz 1/1 Running 0 16m
kruise-daemon-26kvd 1/1 Running 0 16m
kruise-daemon-44ww6 1/1 Running 0 16m
kruise-daemon-kwszd 1/1 Running 0 16m

注意:这里pod启动感觉好慢啊。。。;-->原因是因为这个kruise-manager:v1.0.1镜像要77M呢,拉取比较费时间。。。;

https://github.com/openkruise/charts/tree/master/versions/1.0.1

resources of kruise-manager container这里的值一般是官方测试过的,我们不需要再去修改。

这里可以看到关于values.yaml可配置的一些信息:

实验结束。😘

4、CloneSet

概念

CloneSet 控制器是 OpenKruise 提供的对原生 Deployment 的增强控制器,在使用方式上和 Deployment 几乎一致。

使用

💘 实验:使用CloneSet控制器部署pod

  • 如下所示是我们声明的一个 CloneSet 资源对象:
# 01-cloneset-demo.yaml
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
name: cs-demo
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: cs
template:
metadata:
labels:
app: cs
spec:
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
  • 直接创建上面的这个 CloneSet 对象:
$ kubectl apply -f 01-cloneset-demo.yaml 
cloneset.apps.kruise.io/cs-demo created

[root@master1 ~]#kubectl get cloneset cs-demo
NAME DESIRED UPDATED UPDATED_READY READY TOTAL AGE
cs-demo 3 3 3 3 3 46s

[root@master1 ~]#kubectl describe cloneset cs-demo
Name: cs-demo
Namespace: default
Labels: <none>
Annotations: <none>
API Version: apps.kruise.io/v1alpha1
Kind: CloneSet
……
Updated Replicas: 3
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 69s cloneset-controller succeed to create pod cs-demo-4wz2z
Normal SuccessfulCreate 69s cloneset-controller succeed to create pod cs-demo-cg8bt
Normal SuccessfulCreate 69s cloneset-controller succeed to create pod cs-demo-mdqwn
[root@master1 ~]#

该对象创建完成后我们可以通过 kubectl describe 命令查看对应的 Events 信息,可以发现 cloneset-controller 是直接创建的 Pod,这个和原生的 Deployment 就有一些区别了,Deployment 是通过 ReplicaSet 去创建的 Pod,所以从这里也可以看出来 CloneSet 是直接管理 Pod 的,3个副本的 Pod 此时也创建成功了:

[root@master1 ~]#kubectl get po -l app=cs
NAME READY STATUS RESTARTS AGE
cs-demo-4wz2z 1/1 Running 0 2m30s
cs-demo-cg8bt 1/1 Running 0 2m30s
cs-demo-mdqwn 1/1 Running 0 2m30s

[root@master1 ~]#kubectl get po cs-demo-4wz2z -oyaml
……
ownerReferences:
- apiVersion: apps.kruise.io/v1alpha1
blockOwnerDeletion: true
controller: true
kind: CloneSet #从这里也可以看到pod是由cloneset-controller直接创建出来的!
name: cs-demo
uid: c07bf739-1f89-4ac6-9c1f-401b96350920
……

CloneSet 虽然在使用上和 Deployment 比较类似,但还是有非常多比 Deployment 更高级的功能,下面我们来详细介绍下。

  • 注意:这个volumeClaimTemplates之前不是在statefuleset控制器里出现的吗,这里怎么也出现在了deployment控制里了呢。-->可能还是有一些比较变态的业务场景,它需要只针对这1/2个pod做配置,也就是把这容器当成了传统的业务虚机来看待使用。

实验结束。😘

1.扩缩容

💘 实验:使用CloneSet控制器扩缩容

CloneSet 在扩容的时候可以通过 ScaleStrategy.MaxUnavailable 来限制扩容的步长,这样可以对服务应用的影响最小,可以设置一个绝对值或百分比,如果不设置该值,则表示不限制。

  • 比如我们在上面的资源清单中添加如下所示数据:
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
name: cs-demo
spec:
minReadySeconds: 60
scaleStrategy:
maxUnavailable: 1
replicas: 5
......

上面我们配置 scaleStrategy.maxUnavailable 为1,结合 minReadySeconds 参数,表示在扩容时,只有当上一个扩容出的 Pod 已经 Ready 超过一分钟后,CloneSet 才会执行创建下一个 Pod。

本次测试完整yaml如下:

# 02-cloneset-increase-demo.yaml
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
name: cs-demo
namespace: default
spec:
minReadySeconds: 30 #本次我们设置为30s即可
scaleStrategy:
maxUnavailable: 1
replicas: 5
selector:
matchLabels:
app: cs
template:
metadata:
labels:
app: cs
spec:
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80

注意:deployment控制器滚动升级策略这里有2个配置选项:maxUnavailablemaxSurge。而CloneSet这里只有一个maxUnavailable

  • 部署
$ kubectl apply -f 02-cloneset-increase-demo.yaml 
cloneset.apps.kruise.io/cs-demo configured
  • 比如这里我们扩容成5个副本,更新上面对象后查看 CloneSet 的事件:
[root@master1 ~]#kubectl describe cloneset cs-demo
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 9h cloneset-controller succeed to create pod cs-demo-4wz2z
Normal SuccessfulCreate 9h cloneset-controller succeed to create pod cs-demo-cg8bt
Normal SuccessfulCreate 9h cloneset-controller succeed to create pod cs-demo-mdqwn
Warning ScaleUpLimited 33s cloneset-controller scaleUp is limited because of scaleStrategy.maxUnavailable, limit: 1
Normal SuccessfulCreate 32s cloneset-controller succeed to create pod cs-demo-w4zls
Warning ScaleUpLimited 29s (x5 over 32s) cloneset-controller scaleUp is limited because of scaleStrategy.maxUnavailable, limit: 0
Normal SuccessfulCreate 0s cloneset-controller succeed to create pod cs-demo-h6cfn

可以看到第一时间扩容了一个 Pod,由于我们配置了 minReadySeconds: 60,也就是新扩容的 Pod 创建成功超过1分钟后才会扩容另外一个 Pod,上面的 Events 信息也能表现出来,查看 Pod 的 AGE 也能看出来扩容的2个 Pod 之间间隔了1分钟左右:

[root@master1 ~]#kubectl get po -l app=cs
NAME READY STATUS RESTARTS AGE
cs-demo-4wz2z 1/1 Running 0 9h
cs-demo-cg8bt 1/1 Running 0 9h
cs-demo-h6cfn 1/1 Running 0 56s
cs-demo-mdqwn 1/1 Running 0 9h
cs-demo-w4zls 1/1 Running 0 88s

当 CloneSet 被缩容时,我们还可以指定一些 Pod 来删除,这对于 StatefulSet 或者 Deployment 来说是无法实现的。StatefulSet 是根据序号来删除 Pod,而 Deployment/ReplicaSet 目前只能根据控制器里定义的排序来删除。而 CloneSet 允许用户在缩小 replicas 数量的同时,指定想要删除的 Pod 名字。

  • 如下所示:
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
name: cs-demo
spec:
minReadySeconds: 60
scaleStrategy:
maxUnavailable: 1
podsToDelete:
- cs-demo-79rcx
replicas: 4
......

更新上面的资源对象后,会将应用缩到4个 Pod,如果在 podsToDelete 列表中指定了 Pod 名字,则控制器会优先删除这些 Pod,对于已经被删除的 Pod,控制器会自动从 podsToDelete 列表中清理掉

完整yaml如下:

# 03-cloneset-decrease-demo.yaml
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
name: cs-demo
namespace: default
spec:
minReadySeconds: 30 #本次我们设置为30s即可
scaleStrategy:
maxUnavailable: 1
podsToDelete:
- cs-demo-4wz2z #指定要删除的pod
replicas: 4 #replicas修改为4
selector:
matchLabels:
app: cs
template:
metadata:
labels:
app: cs
spec:
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
  • 比如我们更新上面的资源对象后 cs-demo-79rcx 这个 Pod 会被移除,其余会保留下来:
$ kubectl apply -f 03-cloneset-decrease-demo.yaml
cloneset.apps.kruise.io/cs-demo configured

[root@master1 ~]#kubectl get po -l app=cs
NAME READY STATUS RESTARTS AGE
cs-demo-cg8bt 1/1 Running 0 10h
cs-demo-h6cfn 1/1 Running 0 4m45s
cs-demo-mdqwn 1/1 Running 0 10h
cs-demo-w4zls 1/1 Running 0 5m17s

[root@master1 ~]#kubectl describe cloneset cs-demo
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 10h cloneset-controller succeed to create pod cs-demo-4wz2z
Normal SuccessfulCreate 10h cloneset-controller succeed to create pod cs-demo-cg8bt
Normal SuccessfulCreate 10h cloneset-controller succeed to create pod cs-demo-mdqwn
Warning ScaleUpLimited 5m36s cloneset-controller scaleUp is limited because of scaleStrategy.maxUnavailable, limit: 1
Normal SuccessfulCreate 5m35s cloneset-controller succeed to create pod cs-demo-w4zls
Warning ScaleUpLimited 5m32s (x5 over 5m35s) cloneset-controller scaleUp is limited because of scaleStrategy.maxUnavailable, limit: 0
Normal SuccessfulCreate 5m3s cloneset-controller succeed to create pod cs-demo-h6cfn
Normal SuccessfulDelete 42s cloneset-controller succeed to delete pod cs-demo-4wz2z
  • 如果你只把 Pod 名字加到 podsToDelete,但没有修改 replicas 数量,那么控制器会先把指定的 Pod 删掉,然后再扩一个新的 Pod。

  • 另一种直接删除 Pod 的方式是在要删除的 Pod 上打 apps.kruise.io/specified-delete: true 标签。

相比于手动直接删除 Pod,使用 podsToDeleteapps.kruise.io/specified-delete: true 方式会有 CloneSet 的 maxUnavailable/maxSurge 来保护删除, 并且会触发 PreparingDelete 生命周期的钩子(这里关于生命周期可以看下官方文档,里面有中文,也很详细)。

实验结束。😘

2.升级

pod原地升级概念

  • ReCreate: 删除旧 Pod 和它的 PVC,然后用新版本重新创建出来,这是默认的方式。 (注意:deployment这里默认的升级策略是滚动升级,但这里CloneSet默认的策略是ReCreate。)
  • InPlaceIfPossible: 会优先尝试原地升级 Pod,如果不行再采用重建升级
  • InPlaceOnly: 只允许采用原地升级,因此,用户只能修改上一条中的限制字段,如果尝试修改其他字段会被拒绝

注意:原地升级是只针对你单独一个容器的;

🍀 这里有一个重要概念:原地升级,这也是 OpenKruise 提供的核心功能之一,当我们要升级一个 Pod 中镜像的时候,下图展示了重建升级原地升级的区别:

重建升级时我们需要删除旧 Pod、创建新 Pod:

  • Pod 名字和 uid 发生变化,因为它们是完全不同的两个 Pod 对象(比如 Deployment 升级)
  • Pod 名字可能不变、但 uid 变化,因为它们是不同的 Pod 对象,只是复用了同一个名字(比如 StatefulSet 升级)
  • Pod 所在 Node 名字可能发生变化,因为新 Pod 很可能不会调度到之前所在的 Node 节点
  • Pod IP 发生变化,因为新 Pod 很大可能性是不会被分配到之前的 IP 地址

但是对于原地升级,我们仍然复用同一个 Pod 对象,只是修改它里面的字段:

  • 可以避免如_调度_、分配 IP、_挂载盘_等额外的操作和代价
  • 更快的镜像拉取,因为会复用已有旧镜像的大部分 layer 层,只需要拉取新镜像变化的一些 layer
  • 当一个容器在原地升级时,Pod 中的其他容器不会受到影响,仍然维持运行

所以显然如果能用原地升级方式来升级我们的工作负载,对在线应用的影响是最小的。上面我们提到 CloneSet 升级类型支持 InPlaceIfPossible,这意味着 Kruise 会尽量对 Pod 采取原地升级,如果不能则退化到重建升级,以下的改动会被允许执行原地升级:

  • 更新 workload 中的 spec.template.metadata.*,比如 labels/annotations,Kruise 只会将 metadata 中的改动更新到存量 Pod 上。
  • 更新 workload 中的 spec.template.spec.containers[x].image,Kruise 会原地升级 Pod 中这些容器的镜像,而不会重建整个 Pod。
  • 从 Kruise v1.0 版本开始,更新 spec.template.metadata.labels/annotations 并且 container 中有配置 env from 这些改动的 labels/anntations,Kruise 会原地升级这些容器来生效新的 env 值。

否则,其他字段的改动,比如 spec.template.spec.containers[x].envspec.template.spec.containers[x].resources,都是会回退为重建升级。

注意:[root@master1 ~]#kubectl explain pod.spec.containers

💘 实验:使用CloneSet控制器升级

  • 比如我们将上面的应用升级方式设置为 InPlaceIfPossible,只需要在资源清单中添加 spec.updateStrategy.type: InPlaceIfPossible 即可:
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
name: cs-demo
spec:
updateStrategy:
type: InPlaceIfPossible
......

完整yaml如下:

# 04-cloneset-InPlaceIfPossible-demo.yaml
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
name: cs-demo
namespace: default
spec:
minReadySeconds: 30
updateStrategy:
type: InPlaceIfPossible #修改1:指定为最大限度的原地升级的方式
scaleStrategy:
maxUnavailable: 1
replicas: 4
selector:
matchLabels:
app: cs
template:
metadata:
labels:
app: cs
spec:
containers:
- name: nginx
image: nginx:1.7.9 #修改2:把镜像版本替换了
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80

更新后可以发现 Pod 的状态并没有发生什么大的变化,名称、IP 都一样,唯一变化的是镜像 tag:

$ kubectl apply -f 04-cloneset-InPlaceIfPossible-demo.yaml
cloneset.apps.kruise.io/cs-demo configured

[root@master1 ~]#kubectl get po -l app=cs
NAME READY STATUS RESTARTS AGE
cs-demo-cg8bt 1/1 Running 0 13h
cs-demo-h6cfn 1/1 Running 1 (63s ago) 3h32m
cs-demo-mdqwn 1/1 Running 0 13h
cs-demo-w4zls 1/1 Running 1 (31s ago) 3h33m
[root@master1 ~]#kubectl get po -l app=cs
NAME READY STATUS RESTARTS AGE
cs-demo-cg8bt 1/1 Running 1 (3s ago) 13h
cs-demo-h6cfn 1/1 Running 1 (101s ago) 3h33m
cs-demo-mdqwn 1/1 Running 1 (36s ago) 13h
cs-demo-w4zls 1/1 Running 1 (69s ago) 3h33m


[root@master1 ~]#kubectl describe cloneset cs-demo
……
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulUpdatePodInPlace 2m30s cloneset-controller successfully update pod cs-demo-h6cfn in-place(revision cs-demo-7cb9c88699)
Normal SuccessfulUpdatePodInPlace 118s cloneset-controller successfully update pod cs-demo-w4zls in-place(revision cs-demo-7cb9c88699)
Normal SuccessfulUpdatePodInPlace 85s cloneset-controller successfully update pod cs-demo-mdqwn in-place(revision cs-demo-7cb9c88699)
Normal SuccessfulUpdatePodInPlace 52s cloneset-controller successfully update pod cs-demo-cg8bt in-place(revision cs-demo-7cb9c88699)


[root@master1 ~]#kubectl describe po cs-demo-cg8bt
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Created 3m10s (x2 over 13h) kubelet Created container nginx
Normal Started 3m10s (x2 over 13h) kubelet Started container nginx
Normal Killing 3m10s kubelet Container nginx definition changed, will be restarted
Normal Pulled 3m10s kubelet Container image "nginx:1.7.9" already present on machine

[root@master1 ~]#kubectl get po cs-demo-cg8bt -oyaml|grep image
apps.kruise.io/inplace-update-state: '{"revision":"cs-demo-7cb9c88699","updateTimestamp":"2022-03-11T03:20:45Z","lastContainerStatuses":{"nginx":{"imageID":"docker.io/library/nginx@sha256:eb05700fe7baa6890b74278e39b66b2ed1326831f9ec3ed4bdc6361a4ac2f333"}}}'
- image: nginx:1.7.9
imagePullPolicy: IfNotPresent
image: docker.io/library/nginx:1.7.9
imageID: sha256:35d28df486f6150fa3174367499d1eb01f22f5a410afe4b9581ac0e0e58b3eaf

这就是原地升级的效果。

🍀 原地升级整体工作流程如下图所示:

注意:conditions是在pod的status里面的选项;

注意:kubectl explain cloneset.spec.updateStrategy.type

🍀 ``PreDownloadImageForInPlaceUpdate这个 feature-gate

如果你在安装或升级 Kruise 的时候启用了 PreDownloadImageForInPlaceUpdate 这个 feature-gate,CloneSet 控制器会自动在所有旧版本 pod 所在节点上预热你正在灰度发布的新版本镜像,这对于应用发布加速很有帮助。

默认情况下 CloneSet 每个新镜像预热时的并发度都是 1,也就是一个个节点拉镜像,如果需要调整,你可以在 CloneSet annotation 上设置并发度:

apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
annotations:
apps.kruise.io/image-predownload-parallelism: "5"

注意,为了避免大部分不必要的镜像拉取,目前只针对 replicas > 3 的 CloneSet 做自动预热。

🍀 CloneSet 还支持分批进行灰度

此外 CloneSet 还支持分批进行灰度,在 updateStrategy 属性中可以配置 partition 参数,该参数可以用来保留旧版本 Pod 的数量或百分比,默认为0:

  • 如果是数字,控制器会将 (replicas - partition) 数量的 Pod 更新到最新版本
  • 如果是百分比,控制器会将 (replicas * (100% - partition)) 数量的 Pod 更新到最新版本

比如,我们将上面示例中的的 image 更新为 nginx:latest 并且设置 partition=2:

完整yaml如下:

# 05-cloneset-updateStrategy-partition.yaml
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
metadata:
name: cs-demo
namespace: default
spec:
minReadySeconds: 30
updateStrategy:
type: InPlaceIfPossible
partition: 2 #修改1:保留旧版本pod的数量
scaleStrategy:
maxUnavailable: 1
replicas: 4
selector:
matchLabels:
app: cs
template:
metadata:
labels:
app: cs
spec:
containers:
- name: nginx
image: nginx:latest #修改2:把镜像版本替换了
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80

更新后,过一会查看可以发现只升级了2个 Pod:

$ kubectl apply -f 05-cloneset-updateStrategy-partition.yaml 
cloneset.apps.kruise.io/cs-demo configured

[root@master1 ~]#kubectl get pods -l app=cs -L controller-revision-hash
NAME READY STATUS RESTARTS AGE CONTROLLER-REVISION-HASH
cs-demo-cg8bt 1/1 Running 2 (3m3s ago) 16h cs-demo-7c4d79f5bc #能够看到这个控制器的hash值发生了变化
cs-demo-h6cfn 1/1 Running 1 (3h13m ago) 6h44m cs-demo-7cb9c88699
cs-demo-mdqwn 1/1 Running 2 (2m29s ago) 16h cs-demo-7c4d79f5bc
cs-demo-w4zls 1/1 Running 1 (3h12m ago) 6h45m cs-demo-7cb9c88699

[root@master1 ~]#kubectl describe po cs-demo-cg8bt
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Killing 10m (x2 over 3h18m) kubelet Container nginx definition changed, will be restarted
Normal Pulled 10m kubelet Container image "nginx:latest" already present on machine
Normal Created 10m (x3 over 16h) kubelet Created container nginx
Normal Started 10m (x3 over 16h) kubelet Started container nginx
  • 此外 CloneSet 还支持一些更高级的用法,比如可以定义优先级策略来控制 Pod 发布的优先级规则,还可以定义策略来将一类 Pod 打散到整个发布过程中,也可以暂停 Pod 发布等操作。

kubectl explain cloneset.spec.updateStrategy

https://openkruise.io/zh/docs/

实验结束。😘

关于我

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

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

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

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

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

  1. 个人csdn

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

最后

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

1