Kubernetes
在Kubernetes里使用openkruise实现服务原地升级功能
为什么需要原地升级?
在Kubernetes里原生的deployment在升级的时候都是先创建新的Pod,然后删除旧的Pod;而StatefulSet则是先删除旧的Pod,然后创建同名的新的Pod。如果副本数较多,那么在这个过程中就存在多次Pull镜像、多次调度、多次分配网络、挂载PV,如果采用原地升级的方式进行应用的更新,将会大大提升应用的发布效率。
OpenKruise安装
OpenKruise 要求 Kubernetes 版本高于 1.13+,注意在 1.13 和 1.14 版本中必须先在 kube-apiserver 中打开 CustomResourceWebhookConversion feature-gate。
根据官方文档,采用Helm方式安装:
# Kubernetes 1.13 或 1.14 版本 helm install kruise https://github.com/openkruise/kruise/releases/download/v0.9.0/kruise-chart.tgz --disable-openapi-validation # Kubernetes 1.15 和更新的版本 helm install kruise https://github.com/openkruise/kruise/releases/download/v0.9.0/kruise-chart.tgz
镜像加速的方法,可加上参数:--set manager.image.repository=openkruise-registry.cn-hangzhou.cr.aliyuncs.com/openkruise/kruise-manager
安装的时候支持一些特殊配置,可以查阅官方文档。
升级方法:
# Kubernetes 1.13 and 1.14 helm upgrade kruise https://github.com/openkruise/kruise/releases/download/v0.9.0/kruise-chart.tgz --disable-openapi-validation # Kubernetes 1.15 and newer versions helm upgrade kruise https://github.com/openkruise/kruise/releases/download/v0.9.0/kruise-chart.tgz
卸载方法:
$ helm uninstall kruise release "kruise" uninstalled
原地升级配置
这里采用Openkruise里的CloneSet控制器来用来验证,CloneSet 控制器提供了高效管理无状态应用的能力,它可以对标原生的 Deployment,但 CloneSet 提供了很多增强功能。
Openkruise提供了三种升级方式,默认为 ReCreate:
ReCreate: 控制器会删除旧 Pod 和它的 PVC,然后用新版本重新创建出来。
InPlaceIfPossible: 控制器会优先尝试原地升级 Pod,如果不行再采用重建升级。目前只有修改 spec.template.metadata.* 和spec.template.spec.containers[x].image 这些字段才可以走原地升级。
InPlaceOnly: 控制器只允许采用原地升级。因此,用户只能修改上一条中的限制字段,如果尝试修改其他字段会被 Kruise 拒绝。
其他的一些常见参数简单说明:
gracePeriodSeconds:控制器在原地升级的过程中会先把 Pod status 改为 not-ready,然后等一段时间(gracePeriodSeconds),最后再去修改 Pod spec 中的镜像版本。 这样,就为 endpoints-controller 这些控制器留出了充足的时间来将 Pod 从 endpoints 端点列表中去除
partition:如果是数字,控制器会将 (replicas - partition) 数量的 Pod 更新到最新版本。如果是百分比,控制器会将 (replicas * (100% - partition)) 数量的 Pod 更新到最新版本。注意:在Advanced StatefulSet里这个是表示order序号。
MaxUnavailable:CloneSet 限制下属最多不可用的 Pod 数量。 它可以设置为一个绝对值或者百分比,如果不填 Kruise 会设置为默认值 20%。
MaxSurge:CloneSet 控制最多能扩出来超过 replicas 的 Pod 数量。 它可以设置为一个绝对值或者百分比,如果不填 Kruise 会设置为默认值 0。
一个支持原地升级的CloneSet的yaml文件如下:
apiVersion: apps.kruise.io/v1alpha1 kind: CloneSet metadata: labels: app: sample name: sample spec: replicas: 5 selector: matchLabels: app: sample updateStrategy: type: InPlaceIfPossible inPlaceUpdateStrategy: gracePeriodSeconds: 10 partition: 3 maxUnavailable: 20% template: metadata: labels: app: sample spec: containers: - name: nginx image: nginx:1.20
注意下:若首次执行部署上面的yaml,将会全量部署,只有升级过程才执行原地升级机制。
使用上面的yaml进行nginx的版本原地升级,将会只有2个(replicas-partition)Pod执行了升级,并且旧的Pod没有被重建,达到了预期的效果。
这里有些问题需要注意下:
原地升级只有修改 spec.template.metadata.* 和spec.template.spec.containers[x].image 这些字段才可以走原地升级
如果镜像的hash值没有改变也是无法触发原地升级机制
可以基于控制partition参数来达到分批升级的机制
同时openkruise也提供了新镜像预热功能,需要在安装的时候开启PreDownloadImageForInPlaceUpdate,默认是未开启的。开启这个特性后将在节点上创建NodeImage,用户创建ImagePullJob来做镜像预热,详细说明可以参考ImagePulljob
相关文章
- 吾八哥学k8s(十一):kubernetes里Pod的调度机制
- 吾八哥学k8s(十):kubernetes里Service和Ingress
- kubernetes中服务自定义Prometheus的metrics的方法
- k8s集群安装Prometheus监控以及Grafana面板的方法
- kubernetes集群证书过期的解决方法
- kubelet启动失败报failed to find cgroups of kubelet的解决方法
- 吾八哥学k8s(九):kubernetes里持久化存储
- macOs和Linux环境下kubectl命令自动补齐的方法
- 吾八哥学k8s(八):kubernetes里Secret的用法
- apps/v1版本下使用client-go实现kubernetes回滚的方法