OpenKruise 是 Kubernetes 的一个标准扩展,它能够配合原生 Kubernetes 使用,并为管理应用容器、sidecar、镜像分发等方面提供更增强大和高效的能力。html
原地升级
原地升级是一种能够避免删除、新建 Pod 的升级镜像能力。它比原生 Deployment/StatefulSet 的重建 Pod 升级更快、更高效,而且避免对 Pod 中其余不须要更新的容器形成干扰。node
Sidecar 管理
支持在一个单独的 CR 中定义 sidecar 容器,OpenKruise 可以帮你把这些 Sidecar 容器注入到全部符合条件的 Pod 中。这个过程和 Istio 的注入很类似,可是你能够管理任意你关心的 Sidecar。nginx
跨多可用区部署
定义一个跨多个可用区的全局 workload,容器,OpenKruise 会帮你在每一个可用区建立一个对应的下属 workload。你能够统一管理他们的副本数、版本、甚至针对不一样可用区采用不一样的发布策略。git
CloneSet 提供更加高效、肯定可控的应用管理和部署能力,支持优雅原地升级、指定删除、发布顺序可配置、并行/灰度发布等丰富的策略,能够知足更多样化的应用场景。 Advanced StatefulSet 基于原生 StatefulSet 之上的加强版本,默认行为与原生彻底一致,在此以外提供了原地升级、并行发布(最大不可用)、发布暂停等功能。 SidecarSet 对 sidecar 容器作统一管理,在知足 selector 条件的 Pod 中注入指定的 sidecar 容器。 UnitedDeployment 经过多个 subset workload 将应用部署到多个可用区。 BroadcastJob 配置一个 job,在集群中全部知足条件的 Node 上都跑一个 Pod 任务。 Advanced DaemonSet 基于原生 DaemonSet 之上的加强版本,默认行为与原生一致,在此以外提供了灰度分批、按 Node label 选择、暂停、热升级等发布策略。 AdvancedCronJob 一个扩展的 CronJob 控制器,目前 template 模板支持配置使用 Job 或 BroadcastJob。
以上在官方文档都有介绍,本文主要着重实战,先讲CloneSet,其余控制器后面会陆续更新。。。github
这里使用helm来安装Kruise
一、如今kruise Chartshell
wget https://github.com/openkruise/kruise/releases/download/v0.7.0/kruise-chart.tgz tar -zxf kruise-chart.tgz cd kruise [root@ kruise]# ls -l total 16 -rw-r--r-- 1 root root 311 Dec 20 15:09 Chart.yaml -rw-r--r-- 1 root root 4052 Dec 20 15:09 README.md drwxr-xr-x 2 root root 4096 Dec 23 10:18 templates -rw-r--r-- 1 root root 659 Dec 20 15:09 values.yaml
二、修改values.yaml,默认不用修改也行
三、执行部署json
[root@qd01-stop-k8s-master001 kruise]# kubectl create ns kruise namespace/kruise created [root@qd01-stop-k8s-master001 kruise]# helm install kruise -n kruise -f values.yaml . W1223 10:22:13.562088 1589994 warnings.go:67] apiextensions.k8s.io/v1beta1 CustomResourceDefinition is deprecated in v1.16+, unavailable in v1.22+; use apiextensions.k8s.io/v1 CustomResourceDefinition 。。。。。。。 NAME: kruise LAST DEPLOYED: Wed Dec 23 10:22:12 2020 NAMESPACE: kruise STATUS: deployed REVISION: 1 TEST SUITE: None 这里会看到一堆的deprecated信息,由于新版的kubernetes对CRD的版本会淘汰,能够根据本身的集群版本修改CRD的API版本便可
四、检查kruise部署状态api
[root@qd01-stop-k8s-master001 kruise]# helm ls -n kruise NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION kruise kruise 1 2020-12-23 10:22:12.963651877 +0800 CST deployed kruise-0.7.0 能够看到,集群中有的kruise crd类型 [root@qd01-stop-k8s-master001 kruise]# kubectl get crd|grep kruise advancedcronjobs.apps.kruise.io 2020-12-23T02:22:13Z broadcastjobs.apps.kruise.io 2020-12-23T02:22:13Z clonesets.apps.kruise.io 2020-12-23T02:22:13Z daemonsets.apps.kruise.io 2020-12-23T02:22:13Z sidecarsets.apps.kruise.io 2020-12-23T02:22:13Z statefulsets.apps.kruise.io 2020-12-23T02:22:13Z uniteddeployments.apps.kruise.io 2020-12-23T02:22:13Z
下面咱们开始来使用这些管理器app
CloneSet 控制器提供了高效管理无状态应用的能力,它能够对标原生的 Deployment,但 CloneSet 提供了不少加强功能。
一、咱们先建立一个简单的CloneSet,yaml以下ide
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
二、部署
[root@qd01-stop-k8s-master001 demo]# kubectl apply -f CloneSet.yaml cloneset.apps.kruise.io/nginx-alpine created [root@qd01-stop-k8s-master001 demo]# kubectl get po |grep nginx nginx-alpine-29g7n 1/1 Running 0 45s nginx-alpine-bvgqm 1/1 Running 0 45s nginx-alpine-q9tlw 1/1 Running 0 45s nginx-alpine-s2t46 1/1 Running 0 44s nginx-alpine-sslvf 1/1 Running 0 44s 从输出结果看,和原生的Deployment没有啥区别 #注意,这里若是get deployment是看不到nginx-alpine这个应用的,须要get cloneset才能看到 [root@qd01-stop-k8s-master001 demo]# kubectl get deployment [root@qd01-stop-k8s-master001 demo]# kubectl get cloneset NAME DESIRED UPDATED UPDATED_READY READY TOTAL AGE nginx-alpine 5 5 5 5 5 2m16s
CloneSet 容许用户配置 PVC 模板 volumeClaimTemplates,用来给每一个 Pod 生成独享的 PVC,这是 Deployment 所不支持的。 若是用户没有指定这个模板,CloneSet 会建立不带 PVC 的 Pod。
三、如今来建立一个带有 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-master001 demo]# kubectl apply -f CloneSet.yaml cloneset.apps.kruise.io/nginx-2 created [root@qd01-stop-k8s-master001 demo]# kubectl get pv|grep data-vol pvc-0fde19f3-ea4b-47e0-81be-a8e43812e47b 2Gi RWO Delete Bound default/data-vol-nginx-2-t55h8 rbd 83s pvc-72accf10-57a6-4418-a1bc-c64633b84434 2Gi RWO Delete Bound default/data-vol-nginx-2-t49mk rbd 82s pvc-8fc8b9a5-afe8-446a-9190-08fcee0ec9f6 2Gi RWO Delete Bound default/data-vol-nginx-2-jw2zp rbd 84s pvc-c9fba396-e357-43e8-9510-616f698da765 2Gi RWO Delete Bound default/data-vol-nginx-2-b5fdd rbd 84s pvc-e5302eab-a9f2-4a71-a5a3-4cd43205e8a0 2Gi RWO Delete Bound default/data-vol-nginx-2-l54dz rbd 84s [root@qd01-stop-k8s-master001 demo]# kubectl get po|grep nginx nginx-2-b5fdd 1/1 Running 0 97s nginx-2-jw2zp 1/1 Running 0 97s nginx-2-l54dz 1/1 Running 0 97s nginx-2-t49mk 1/1 Running 0 96s nginx-2-t55h8 1/1 Running 0 96s
从部署结果能够看到,每一个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 被 CloneSet controller 缩容删除时,这个 Pod 关联的 PVC 都会被一块儿删掉。 若是一个 Pod 被外部直接调用删除或驱逐时,这个 Pod 关联的 PVC 还都存在;而且 CloneSet controller 发现数量不足从新扩容时,新扩出来的 Pod 会复用原 Pod 的 instance-id 并关联原来的 PVC。 当 Pod 被重建升级时,关联的 PVC 会跟随 Pod 一块儿被删除、新建。 当 Pod 被原地升级时,关联的 PVC 会持续使用。
四、指定 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-master001 demo]# kubectl apply -f CloneSet.yaml cloneset.apps.kruise.io/nginx-2 configured [root@qd01-stop-k8s-master001 demo]# kubectl get po|grep nginx nginx-2-b5fdd 1/1 Running 0 11m nginx-2-jw2zp 1/1 Running 0 11m nginx-2-l54dz 1/1 Running 0 11m nginx-2-t49mk 1/1 Running 0 11m
如今看输入结果,已经没有nginx-2-t55h8
这个Pod了
这个功能很实用,好比某台机器故障了,或者负载过高,你想删除指定的pod。
五、升级功能
CloneSet 提供了和 Advanced StatefulSet 相同的 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-master001 demo]# kubectl apply -f CloneSet.yaml cloneset.apps.kruise.io/nginx-2 configured 使用 kubectl describe查看升级过程 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 59m default-scheduler 0/22 nodes are available: 22 pod has unbound immediate PersistentVolumeClaims. Warning FailedScheduling 59m default-scheduler 0/22 nodes are available: 22 pod has unbound immediate PersistentVolumeClaims. Warning FailedScheduling 59m default-scheduler 0/22 nodes are available: 22 pod has unbound immediate PersistentVolumeClaims. Normal Scheduled 59m default-scheduler Successfully assigned default/nginx-2-l54dz to qd01-stop-k8s-node007.ps.easou.com Normal SuccessfulAttachVolume 59m attachdetach-controller AttachVolume.Attach succeeded for volume "pvc-e5302eab-a9f2-4a71-a5a3-4cd43205e8a0" Normal Pulling 58m kubelet Pulling image "nginx:alpine" Normal Pulled 58m kubelet Successfully pulled image "nginx:alpine" in 6.230045975s Normal Killing 55s kubelet Container nginx definition changed, will be restarted Normal Pulling 55s kubelet Pulling image "nginx" Normal Pulled 26s kubelet Successfully pulled image "nginx" in 29.136659264s Normal Created 23s (x2 over 58m) kubelet Created container nginx Normal Started 23s (x2 over 58m) kubelet Started container nginx
从输出能够看到,Container nginx definition changed, will be restarted
,Pod并无删除在重建,而是在原来的基础上直接更新了镜像文件,并重启了服务。
原地升级减小了删除重建环节,节省了升级时间和资源调度频率。。。
六、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: Available Replicas: 5 Collision Count: 0 Label Selector: app=nginx-2 Observed Generation: 6 Ready Replicas: 5 Replicas: 5 Update Revision: nginx-2-7b44cb9c8 Updated Ready Replicas: 2 Updated Replicas: 2 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulUpdatePodInPlace 45m cloneset-controller successfully update pod nginx-2-l54dz in-place(revision nginx-2-5879fd9f7) Normal SuccessfulUpdatePodInPlace 44m cloneset-controller successfully update pod nginx-2-t49mk in-place(revision nginx-2-5879fd9f7) Normal SuccessfulUpdatePodInPlace 43m cloneset-controller successfully update pod nginx-2-b5fdd in-place(revision nginx-2-5879fd9f7) Normal SuccessfulUpdatePodInPlace 43m cloneset-controller successfully update pod nginx-2-jw2zp in-place(revision nginx-2-5879fd9f7) Normal SuccessfulCreate 22m cloneset-controller succeed to create pod nginx-2-zpp8z Normal SuccessfulUpdatePodInPlace 5m22s cloneset-controller successfully update pod nginx-2-zpp8z in-place(revision nginx-2-7b44cb9c8) Normal SuccessfulUpdatePodInPlace 4m55s cloneset-controller successfully update pod nginx-2-jw2zp in-place(revision nginx-2-7b44cb9c8) [root@qd01-stop-k8s-master001 demo]# kubectl get pod -L controller-revision-hash NAME READY STATUS RESTARTS AGE CONTROLLER-REVISION-HASH nginx-2-b5fdd 1/1 Running 1 99m nginx-2-5879fd9f7 nginx-2-jw2zp 1/1 Running 2 99m nginx-2-7b44cb9c8 nginx-2-l54dz 1/1 Running 1 99m nginx-2-5879fd9f7 nginx-2-t49mk 1/1 Running 1 99m nginx-2-5879fd9f7 nginx-2-zpp8z 1/1 Running 1 19m nginx-2-7b44cb9c8
从输出信息咱们能够看到,Update Revision已经更新为nginx-2-7b44cb9c8
,而Pod中只有两个Pod升级了。
因为咱们设置了 partition=3,控制器只升级了 2 个 Pod。
Partition 分批灰度功能完善了原生的Pod升级方式,使得升级可以进行更灵活,可以进行灰度上线。超赞。。。
七、最后再演示下发布暂停
用户能够经过设置 paused 为 true 暂停发布,不过控制器仍是会作 replicas 数量管理:
[root@qd01-stop-k8s-master001 demo]# kubectl get po -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,
[root@qd01-stop-k8s-master001 demo]# kubectl get po -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
spec: replicas: 10 updateStrategy: paused: true type: InPlaceIfPossible inPlaceUpdateStrategy: gracePeriodSeconds: 10
[root@qd01-stop-k8s-master001 demo]# kubectl get po -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-master001 demo]# kubectl get po -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,
以上就是整个发布暂停的演示,这个功能好处就是;咱们在升级的过程当中能够随时中断升级。
除此以外,CloneSet还有不少特性,例如:MaxUnavailable 最大不可用数量、MaxSurge 最大弹性数量、升级顺序、打散策略、生命周期钩子等,鉴于文章篇幅,这些特性再也不演示了,有须要的能够查看官方文档。