gtxyzz

Kubernetes应用管理器OpenKruise

gtxyzz 运维技术 2022-11-07 429浏览 0

Kubernetes应用管理器OpenKruise

OpenKruise

OpenKruise 是 Kubernetes 的一个标准扩展,它可以配合原生 Kubernetes 使用,并为管理应用容器、sidecar、镜像分发等方面提供更加强大和高效的能力。

核心功能

原地升级

原地升级是一种可以避免删除、新建 Pod 的升级镜像能力。它比原生 Deployment/StatefulSet 的重建 Pod 升级更快、更高效,并且避免对 Pod 对其他不需要更新的容器造成干扰。

Sidecar 管理

支持在一个单独的 CR 中定义 sidecar 容器,OpenKruise 能够帮你把这些 Sidecar 容器注入到所有符合条件的 Pod 中。这个过程和 Istio 的注入很相似,但是你可以管理任意你关心的 Sidecar。

跨多可用区部署

定义一个跨多个可用区的全局 workload,容器,OpenKruise 会帮你在每个可用区创建一个对应的下属 workload。你可以统一管理他们的副本数、版本、甚至针对不同可用区采用不同的发布策略。

CRD 列表

CloneSet
提供更加高效、确定可控的应用管理和部署能力,支持优雅原地升级、指定删除、发布顺序可配置、并行/灰度发布等丰富的策略,可以满足更多样化的应用场景。

AdvancedStatefulSet
基于原生StatefulSet之上的增强版本,默认行为与原生完全一致,在此之外提供了原地升级、并行发布(最大不可用)、发布暂停等功能。

SidecarSet
对sidecar容器做统一管理,在满足selector条件的Pod中注入指定的sidecar容器。

UnitedDeployment
通过多个subsetworkload将应用部署到多个可用区。

BroadcastJob
配置一个job,在集群中所有满足条件的Node上都跑一个Pod任务。

AdvancedDaemonSet
基于原生DaemonSet之上的增强版本,默认行为与原生一致,在此之外提供了灰度分批、按Nodelabel选择、暂停、热升级等发布策略。

AdvancedCronJob
一个扩展的CronJob控制器,目前template模板支持配置使用Job或BroadcastJob。

以上在官方文档都有介绍,本文主要着重实战,先讲CloneSet,其他控制器后面会陆续更新。。。

部署Kruise到Kubernetes集群

这里使用helm来安装Kruise

1、现在kruise Chart

wgethttps://github.com/openkruise/kruise/releases/download/v0.7.0/kruise-chart.tgz
tar-zxfkruise-chart.tgz
cdkruise
[root@kruise]#ls-l
total16
-rw-r--r--1rootroot311Dec2015:09Chart.yaml
-rw-r--r--1rootroot4052Dec2015:09README.md
drwxr-xr-x2rootroot4096Dec2310:18templates
-rw-r--r--1rootroot659Dec2015:09values.yaml

2、修改values.yaml,默认不用修改也行

3、执行部署

[root@qd01-stop-k8s-master001kruise]#kubectlcreatenskruise
namespace/kruisecreated
[root@qd01-stop-k8s-master001kruise]#helminstallkruise-nkruise-fvalues.yaml.
W122310:22:13.5620881589994warnings.go:67]apiextensions.k8s.io/v1beta1CustomResourceDefinitionisdeprecatedinv1.16+,unavailableinv1.22+;useapiextensions.k8s.io/v1CustomResourceDefinition
。。。。。。。
NAME:kruise
LASTDEPLOYED:WedDec2310:22:122020
NAMESPACE:kruise
STATUS:deployed
REVISION:1
TESTSUITE:None
这里会看到一堆的deprecated信息,因为新版的kubernetes对CRD的版本会淘汰,可以根据自己的集群版本修改CRD的API版本即可

4、检查kruise部署状态

[root@qd01-stop-k8s-master001kruise]#helmls-nkruise
NAMENAMESPACEREVISIONUPDATEDSTATUSCHARTAPPVERSION
kruisekruise12020-12-2310:22:12.963651877+0800CSTdeployedkruise-0.7.0

可以看到,集群中有的kruisecrd类型
[root@qd01-stop-k8s-master001kruise]#kubectlgetcrd|grepkruise
advancedcronjobs.apps.kruise.io2020-12-23T02:22:13Z
broadcastjobs.apps.kruise.io2020-12-23T02:22:13Z
clonesets.apps.kruise.io2020-12-23T02:22:13Z
daemonsets.apps.kruise.io2020-12-23T02:22:13Z
sidecarsets.apps.kruise.io2020-12-23T02:22:13Z
statefulsets.apps.kruise.io2020-12-23T02:22:13Z
uniteddeployments.apps.kruise.io2020-12-23T02:22:13Z

下面我们开始来使用这些管理器

CloneSet

CloneSet 控制器提供了高效管理无状态应用的能力,它可以对标原生的 Deployment,但 CloneSet 提供了很多增强功能。

1、我们先创建一个简单的CloneSet,yaml如下

apiVersion:apps.kruise.io/v1alpha1
kind:CloneSet
metadata:
labels:
app:nginx-alpine
name:nginx-alpine
spec:
replicas:5
selector:
matchLabels:
app:nginx-alpine
template:
metadata:
labels:
app:nginx-alpine
spec:
containers:
-name:nginx
image:nginx:alpine

2、部署

[root@qd01-stop-k8s-master001demo]#kubectlapply-fCloneSet.yaml
cloneset.apps.kruise.io/nginx-alpinecreated

[root@qd01-stop-k8s-master001demo]#kubectlgetpo|grepnginx
nginx-alpine-29g7n1/1Running045s
nginx-alpine-bvgqm1/1Running045s
nginx-alpine-q9tlw1/1Running045s
nginx-alpine-s2t461/1Running044s
nginx-alpine-sslvf1/1Running044s
从输出结果看,和原生的Deployment没有啥区别
#注意,这里如果getdeployment是看不到nginx-alpine这个应用的,需要getcloneset才能看到
[root@qd01-stop-k8s-master001demo]#kubectlgetdeployment
[root@qd01-stop-k8s-master001demo]#kubectlgetcloneset
NAMEDESIREDUPDATEDUPDATED_READYREADYTOTALAGE
nginx-alpine555552m16s

CloneSet 允许用户配置 PVC 模板 volumeClaimTemplates,用来给每个 Pod 生成独享的 PVC,这是 Deployment 所不支持的。 如果用户没有指定这个模板,CloneSet 会创建不带 PVC 的 Pod。

3、现在来创建一个带有 PVC 模板的例子

apiVersion:apps.kruise.io/v1alpha1
kind:CloneSet
metadata:
labels:
app:nginx-2
name:nginx-2
spec:
replicas:5
selector:
matchLabels:
app:nginx-2
template:
metadata:
labels:
app:nginx-2
spec:
containers:
-name:nginx
image:nginx:alpine
volumeMounts:
-name:data-vol
mountPath:/usr/share/nginx/html
volumeClaimTemplates:
-metadata:
name:rbd
spec:
accessModes:["ReadWriteOnce"]
storageClassName:rbd
resources:
requests:
storage:2Gi

部署

[root@qd01-stop-k8s-master001demo]#kubectlapply-fCloneSet.yaml
cloneset.apps.kruise.io/nginx-2created
[root@qd01-stop-k8s-master001demo]#kubectlgetpv|grepdata-vol
pvc-0fde19f3-ea4b-47e0-81be-a8e43812e47b2GiRWODeleteBounddefault/data-vol-nginx-2-t55h8rbd83s
pvc-72accf10-57a6-4418-a1bc-c64633b844342GiRWODeleteBounddefault/data-vol-nginx-2-t49mkrbd82s
pvc-8fc8b9a5-afe8-446a-9190-08fcee0ec9f62GiRWODeleteBounddefault/data-vol-nginx-2-jw2zprbd84s
pvc-c9fba396-e357-43e8-9510-616f698da7652GiRWODeleteBounddefault/data-vol-nginx-2-b5fddrbd84s
pvc-e5302eab-a9f2-4a71-a5a3-4cd43205e8a02GiRWODeleteBounddefault/data-vol-nginx-2-l54dzrbd84s
[root@qd01-stop-k8s-master001demo]#kubectlgetpo|grepnginx
nginx-2-b5fdd1/1Running097s
nginx-2-jw2zp1/1Running097s
nginx-2-l54dz1/1Running097s
nginx-2-t49mk1/1Running096s
nginx-2-t55h81/1Running096s

从部署结果可以看到,每个pod都创建了一个PVC,这个是原生的Deployment不能实现的。

注意:

每个被自动创建的PVC会有一个ownerReference指向CloneSet,因此CloneSet被删除时,它创建的所有Pod和PVC都会被删除。
每个被CloneSet创建的Pod和PVC,都会带一个apps.kruise.io/cloneset-instance-id:xxx的label。关联的Pod和PVC会有相同的instance-id,且它们的名字后缀都是这个instance-id。
如果一个Pod被CloneSetcontroller缩容删除时,这个Pod关联的PVC都会被一起删掉。
如果一个Pod被外部直接调用删除或驱逐时,这个Pod关联的PVC还都存在;并且CloneSetcontroller发现数量不足重新扩容时,新扩出来的Pod会复用原Pod的instance-id并关联原来的PVC。
当Pod被重建升级时,关联的PVC会跟随Pod一起被删除、新建。
当Pod被原地升级时,关联的PVC会持续使用。

4、指定 Pod 缩容

当一个 CloneSet 被缩容时,有时候用户需要指定一些 Pod 来删除。这对于 StatefulSet 或者 Deployment 来说是无法实现的,因为 StatefulSet 要根据序号来删除 Pod,而 Deployment/ReplicaSet 目前只能根据控制器里定义的排序来删除。

CloneSet 允许用户在缩小 replicas 数量的同时,指定想要删除的 Pod 名字。

现在我们来修改上面例子的部署文件,指定删除nginx-2-t55h8这个Pod

apiVersion:apps.kruise.io/v1alpha1
kind:CloneSet
metadata:
labels:
app:nginx-2
name:nginx-2
spec:
replicas:4
scaleStrategy:
podsToDelete:
-nginx-2-t55h8

然后更新yaml文件

[root@qd01-stop-k8s-master001demo]#kubectlapply-fCloneSet.yaml
cloneset.apps.kruise.io/nginx-2configured

[root@qd01-stop-k8s-master001demo]#kubectlgetpo|grepnginx
nginx-2-b5fdd1/1Running011m
nginx-2-jw2zp1/1Running011m
nginx-2-l54dz1/1Running011m
nginx-2-t49mk1/1Running011m

现在看输入结果,已经没有nginx-2-t55h8这个Pod了

这个功能很实用,比如某台机器故障了,或者负载太高,你想删除指定的pod。

5、升级功能

CloneSet提供了和AdvancedStatefulSet相同的3个升级方式,默认为ReCreate:

ReCreate:控制器会删除旧Pod和它的PVC,然后用新版本重新创建出来。
InPlaceIfPossible:控制器会优先尝试原地升级Pod,如果不行再采用重建升级。目前,只有修改spec.template.metadata.*和spec.template.spec.containers[x].image这些字段才可以走原地升级。
InPlaceOnly:控制器只允许采用原地升级。因此,用户只能修改上一条中的限制字段,如果尝试修改其他字段会被Kruise拒绝。

现在我们来尝试原地升级Pod功能,把nginx镜像由nginx:alpine 升级为 nginx:latest

首先修改yaml文件,这里只粘贴出文件的修改的部分

apiVersion:apps.kruise.io/v1alpha1
kind:CloneSet
...
spec:
replicas:4
updateStrategy:
type:InPlaceIfPossible
inPlaceUpdateStrategy:
gracePeriodSeconds:10
......
spec:
containers:
-name:nginx
image:nginx

执行升级

[root@qd01-stop-k8s-master001demo]#kubectlapply-fCloneSet.yaml
cloneset.apps.kruise.io/nginx-2configured
使用kubectldescribe查看升级过程
Events:
TypeReasonAgeFromMessage
-------------------------
WarningFailedScheduling59mdefault-scheduler0/22nodesareavailable:22podhasunboundimmediatePersistentVolumeClaims.
WarningFailedScheduling59mdefault-scheduler0/22nodesareavailable:22podhasunboundimmediatePersistentVolumeClaims.
WarningFailedScheduling59mdefault-scheduler0/22nodesareavailable:22podhasunboundimmediatePersistentVolumeClaims.
NormalScheduled59mdefault-schedulerSuccessfullyassigneddefault/nginx-2-l54dztoqd01-stop-k8s-node007.ps.easou.com
NormalSuccessfulAttachVolume59mattachdetach-controllerAttachVolume.Attachsucceededforvolume"pvc-e5302eab-a9f2-4a71-a5a3-4cd43205e8a0"
NormalPulling58mkubeletPullingimage"nginx:alpine"
NormalPulled58mkubeletSuccessfullypulledimage"nginx:alpine"in6.230045975s
NormalKilling55skubeletContainernginxdefinitionchanged,willberestarted
NormalPulling55skubeletPullingimage"nginx"
NormalPulled26skubeletSuccessfullypulledimage"nginx"in29.136659264s
NormalCreated23s(x2over58m)kubeletCreatedcontainernginx
NormalStarted23s(x2over58m)kubeletStartedcontainernginx

从输出可以看到,Container nginx definition changed, will be restarted,Pod并没有删除在重建,而是在原来的基础上直接更新了镜像文件,并重启了服务。

原地升级减少了删除重建环节,节省了升级时间和资源调度频率。。。

6、Partition 分批灰度

Partition 的语义是 保留旧版本 Pod 的数量或百分比,默认为 0。这里的 partition 不表示任何 order 序号。

在发布过程中设置了partition:
如果是数字,控制器会将(replicas-partition)数量的Pod更新到最新版本。
如果是百分比,控制器会将(replicas*(100%-partition))数量的Pod更新到最新版本。

现在我将上面的例子的 image 更新为 nginx:1.19.6-alpine 并且设置 partition=3

kind:CloneSet
metadata:
labels:
app:nginx-2
name:nginx-2
spec:
replicas:5
updateStrategy:
type:InPlaceIfPossible
inPlaceUpdateStrategy:
gracePeriodSeconds:10
partition:3
selector:
matchLabels:
app:nginx-2
template:
metadata:
labels:
app:nginx-2
spec:
containers:
-name:nginx
image:nginx:1.19.6-alpine

查看结果

Status:
AvailableReplicas:5
CollisionCount:0
LabelSelector:app=nginx-2
ObservedGeneration:6
ReadyReplicas:5
Replicas:5
UpdateRevision:nginx-2-7b44cb9c8
UpdatedReadyReplicas:2
UpdatedReplicas:2
Events:
TypeReasonAgeFromMessage
-------------------------
NormalSuccessfulUpdatePodInPlace45mcloneset-controllersuccessfullyupdatepodnginx-2-l54dzin-place(revisionnginx-2-5879fd9f7)
NormalSuccessfulUpdatePodInPlace44mcloneset-controllersuccessfullyupdatepodnginx-2-t49mkin-place(revisionnginx-2-5879fd9f7)
NormalSuccessfulUpdatePodInPlace43mcloneset-controllersuccessfullyupdatepodnginx-2-b5fddin-place(revisionnginx-2-5879fd9f7)
NormalSuccessfulUpdatePodInPlace43mcloneset-controllersuccessfullyupdatepodnginx-2-jw2zpin-place(revisionnginx-2-5879fd9f7)
NormalSuccessfulCreate22mcloneset-controllersucceedtocreatepodnginx-2-zpp8z
NormalSuccessfulUpdatePodInPlace5m22scloneset-controllersuccessfullyupdatepodnginx-2-zpp8zin-place(revisionnginx-2-7b44cb9c8)
NormalSuccessfulUpdatePodInPlace4m55scloneset-controllersuccessfullyupdatepodnginx-2-jw2zpin-place(revisionnginx-2-7b44cb9c8)

[root@qd01-stop-k8s-master001demo]#kubectlgetpod-Lcontroller-revision-hash
NAMEREADYSTATUSRESTARTSAGECONTROLLER-REVISION-HASH
nginx-2-b5fdd1/1Running199mnginx-2-5879fd9f7
nginx-2-jw2zp1/1Running299mnginx-2-7b44cb9c8
nginx-2-l54dz1/1Running199mnginx-2-5879fd9f7
nginx-2-t49mk1/1Running199mnginx-2-5879fd9f7
nginx-2-zpp8z1/1Running119mnginx-2-7b44cb9c8

从输出信息我们可以看到,Update Revision已经更新为nginx-2-7b44cb9c8,而Pod中只有两个Pod升级了。

由于我们设置了 partition=3,控制器只升级了 2 个 Pod。

Partition 分批灰度功能完善了原生的Pod升级方式,使得升级能够进行更灵活,能够进行灰度上线。超赞。。。

7、最后再演示下发布暂停

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

  • 首先,我们将示例中image改为nginx:1.18.0 并设置副本数为10,修改后更新yaml,运行结果如下:
[root@qd01-stop-k8s-master001demo]#kubectlgetpo-o=jsonpath='{range.items[*]}{"\n"}{.metadata.name}{":\t"}{range.spec.containers[*]}{.image}{","}{end}{end}'|sort
nginx-2-7lzx9:nginx:1.18.0,
nginx-2-b5fdd:nginx:1.18.0,
nginx-2-jw2zp:nginx:1.18.0,
nginx-2-l54dz:nginx:1.18.0,
nginx-2-nknrt:nginx:1.18.0,
nginx-2-rgmsc:nginx:1.18.0,
nginx-2-rpr5z:nginx:1.18.0,
nginx-2-t49mk:nginx:1.18.0,
nginx-2-v2bpx:nginx:1.18.0,
nginx-2-zpp8z:nginx:1.18.0,
  • 现在我们修改yaml文件,将image修改为nginx:alpine 执行更新,运行如下
[root@qd01-stop-k8s-master001demo]#kubectlgetpo-o=jsonpath='{range.items[*]}{"\n"}{.metadata.name}{":\t"}{range.spec.containers[*]}{.image}{","}{end}{end}'|sort
nginx-2-7lzx9:nginx:1.18.0,
nginx-2-b5fdd:nginx:1.18.0,
nginx-2-jw2zp:nginx:1.18.0,
nginx-2-l54dz:nginx:1.18.0,
nginx-2-nknrt:nginx:alpine,
nginx-2-rgmsc:nginx:alpine,
nginx-2-rpr5z:nginx:alpine,
nginx-2-t49mk:nginx:1.18.0,
nginx-2-v2bpx:nginx:alpine,
nginx-2-zpp8z:nginx:1.18.0,
  • 现在看到,有4个pod的image已经更新为nginx:alpine 然后我们再次修改yaml文件,添加paused: true
spec:
replicas:10
updateStrategy:
paused:true
type:InPlaceIfPossible
inPlaceUpdateStrategy:
gracePeriodSeconds:10
  • 再次执行apply,更新yaml,再次查看更新进度,发现pod并没有继续更新了,已经暂停升级image了
[root@qd01-stop-k8s-master001demo]#kubectlgetpo-o=jsonpath='{range.items[*]}{"\n"}{.metadata.name}{":\t"}{range.spec.containers[*]}{.image}{","}{end}{end}'|sort
nginx-2-7lzx9:nginx:1.18.0,
nginx-2-b5fdd:nginx:1.18.0,
nginx-2-jw2zp:nginx:1.18.0,
nginx-2-l54dz:nginx:1.18.0,
nginx-2-nknrt:nginx:alpine,
nginx-2-rgmsc:nginx:alpine,
nginx-2-rpr5z:nginx:alpine,
nginx-2-t49mk:nginx:1.18.0,
nginx-2-v2bpx:nginx:alpine,
nginx-2-zpp8z:nginx:1.18.0,
  • 最后把paused: true取消,再次apply yaml文件,升级会继续。。。
[root@qd01-stop-k8s-master001demo]#kubectlgetpo-o=jsonpath='{range.items[*]}{"\n"}{.metadata.name}{":\t"}{range.spec.containers[*]}{.image}{","}{end}{end}'|sort
nginx-2-7lzx9:nginx:alpine,
nginx-2-b5fdd:nginx:alpine,
nginx-2-jw2zp:nginx:alpine,
nginx-2-l54dz:nginx:alpine,
nginx-2-nknrt:nginx:alpine,
nginx-2-rgmsc:nginx:alpine,
nginx-2-rpr5z:nginx:alpine,
nginx-2-t49mk:nginx:alpine,
nginx-2-v2bpx:nginx:alpine,
nginx-2-zpp8z:nginx:alpine,

继续浏览有关 系统运维 的文章
发表评论