关于云原生:OpenKruise-如何实现-K8s-社区首个规模化镜像预热能力

8次阅读

共计 4340 个字符,预计需要花费 11 分钟才能阅读完成。

简介: OpenKruise 是阿里云开源的云原生利用自动化治理套件,也是以后托管在 Cloud Native Computing Foundation (CNCF) 下的 Sandbox 我的项目。它来自阿里巴巴多年来容器化、云原生的技术积淀,是阿里外部生产环境大规模利用的基于 Kubernetes 之上的规范扩大组件,也是紧贴上游社区规范、适应互联网规模化场景的技术理念与最佳实际。

作者 | 王思宇(酒祝)
起源 | 阿里巴巴云原生公众号

前言

OpenKruise 是阿里云开源的云原生利用自动化治理套件,也是以后托管在 Cloud Native Computing Foundation (CNCF) 下的 Sandbox 我的项目。它来自阿里巴巴多年来容器化、云原生的技术积淀,是阿里外部生产环境大规模利用的基于 Kubernetes 之上的规范扩大组件,也是紧贴上游社区规范、适应互联网规模化场景的技术理念与最佳实际。

OpenKruise 在 2021.3.4 公布了最新的 v0.8.0 版本(ChangeLog),其中一个次要变动是新增了 镜像预热 能力。本文由《通过 OpenKruise 实现大规模集群 镜像预热 & 部署公布减速实际》分享整顿为文字,为大家介绍咱们所提供的镜像预热能力的需要起源、实现形式以及应用场景。

背景:为什么镜像预热能力是必要的

“镜像”也算是 Docker 为容器畛域带来的一大翻新。在 Docker 之前,尽管 Linux 曾经提供了 cgroup 隔离,只管阿里巴巴从 2011 年曾经逐步基于 LXC 开始容器化,但都不足镜像这种对运行环境的封装。不过呢,只管镜像为咱们带来了诸多益处,但不可否认在理论场景中咱们也面临各种各样拉镜像带来的问题,其中最常见的一点就是拉镜像的耗时。

咱们过来听到过很多用户对容器化的期待和意识,比方“极致弹性”、“秒级扩容”、“高效公布”等等,但联合 Kubernetes 中一个规范的 Pod 创立过程来看,和用户的冀望还是有肯定差距的(假如 Pod 中蕴含 sidecar、app 两个容器):

失常来说,对于小规模集群中调度、调配 / 挂载近程盘、调配网络等操作耗时较小,对于大规模集群须要做肯定优化,但都还在可控的范畴内。然而对于拉镜像的耗时,在大规模弹性的集群中则尤为辣手,即便采纳了 P2P 等技术手段来优化,对于一个较大的业务镜像还是可能须要较长的工夫来拉取,与用户所冀望的扩容、公布速度不符。

而咱们如果能做到将 sidecar 容器的镜像、以及业务容器的根底镜像提前在节点上拉取好,则 Pod 创立过程能够大幅缩短,其中拉镜像的耗时甚至能优化 70% 以上:

而 Kubernetes 本身是没有提供任何面向镜像的操作能力的,围绕 Kubernetes 的生态来看,目前也没有比拟成熟的规模化镜像预热产品。这是咱们在 OpenKruise 中提供镜像预热的起因,并且这套镜像预热能力曾经在阿里巴巴外部的云原生环境大面积落地,在后文的实际中也会简略介绍咱们的根本用法。

OpenKruise 是如何实现镜像预热的

OpenKruise 实现镜像预热的原理,要先从它的运行架构看起:

从 v0.8.0 开始,装置了 Kruise 之后,有两个在 kruise-system 命名空间下的组件:kruise-manager 与 kruise-daemon。前者是一个由 Deployment 部署的中心化组件,一个 kruise-manager 容器(过程)中蕴含了多个 controller 和 webhook;后者则由 DaemonSet 部署到集群中的节点上,通过与 CRI 交互来绕过 Kubelet 实现一些扩大能力(比方拉取镜像、重启容器等)。

因而,Kruise 会为每个节点(Node)创立一个同名对应的自定义资源:NodeImage,而每个节点的 NodeImage 里写明了在这个节点上须要预热哪些镜像,因而这个节点上的 kruise-daemon 只有依照 NodeImage 来执行镜像的拉取工作即可:

如上图所示,咱们在 NodeImage 中能指定要拉取的镜像名、tag、拉取的策略,比方单次拉取的超时、失败重试次数、工作的 deadline、TTL 工夫等等。

有了 NodeImage,咱们也就领有了最根本的镜像预热能力了,不过还不能齐全满足大规模场景的预热需要。在一个有 5k 个节点的集群中,要用户去一个个更新 NodeImage 资源来做预热显然是不够敌对的。因而,Kruise 还提供了一个更高形象的自定义资源 ImagePullJob:

如上图所示,在 ImagePullJob 中用户能够指定一个镜像要在哪些范畴的节点上批量做预热,以及这个 job 的拉取策略、生命周期等。一个 ImagePullJob 创立后,会被 kruise-manager 中的 imagepulljob-controller 接管到并解决,将其合成并写入到所有匹配节点的 NodeImage 中,以此来实现规模化的预热。

整体的流程如下:

而有了镜像预热能力后,咱们怎么去应用它,或者说什么场景下须要来应用呢?接下来咱们介绍下镜像预热在阿里巴巴中的几种常见应用形式。

常见的镜像预热应用形式有哪些

1. 根底镜像 – 集群维度预热

最常见的预热场景,是在整个集群维度继续预热一些根底镜像:

apiVersion: apps.kruise.io/v1alpha1
kind: ImagePullJob
metadata:
  name: base-image-job
spec:
  image: xxx/base-image:latest
  parallelism: 10
  completionPolicy:
    type: Never
  pullPolicy:
    backoffLimit: 3
    timeoutSeconds: 300

如上述 ImagePullJob 有几个特色:

  1. 不配置 selector 规定,即默认整个集群维度预热

    1. 存量的节点上对立预热
    2. 后续新增(导入)的节点上也会立刻主动做预热
  2. 采纳 Never 的 completionPolicy 策略来长期运行

    1. Never 策略表明这个 job 继续做预热,不会完结(除非被删除)
    2. Never 策略下,ImagePullJob 每隔 24h 左右会触发在所有匹配的节点上重试拉取一次,也就是每天都会确保一次镜像存在

依据咱们的教训,一个集群中预热根底镜像的 ImagePullJob 在 10~30 个左右,具体视集群以及业务场景而定。

2. sidecar 镜像 – 集群维度预热

咱们同样也能够对一些 sidecar 的镜像做预热,尤其是那些基本上每个业务 Pod 中都会带有的根底 sidecar:

apiVersion: apps.kruise.io/v1alpha1
kind: ImagePullJob
metadata:
  name: sidecar-image-job
spec:
  image: xxx/sidecar-image:latest
  parallelism: 20
  completionPolicy:
    type: Always
    activeDeadlineSeconds: 1800
    ttlSecondsAfterFinished: 300
  pullPolicy:
    backoffLimit: 3
    timeoutSeconds: 300

如上述 ImagePullJob 有几个特色:

  1. 不配置 selector,默认整个集群维度预热,这一点与根底镜像相似
  2. 采纳 Always 策略一次性预热

    1. 所有节点做一次预热
    2. 整个 job 预热超时工夫 30min
    3. job 实现后过 5min 主动删除

当然,这里的 sidecar 预热也能够配置为 Never 策略,视场景而定。以咱们的教训来看,尤其在 sidecar 做版本迭代、镜像降级的时候,提前做一次规模化的镜像预热,能够大幅晋升后续 Pod 扩容、公布的速度。

3. 非凡业务镜像 – 资源池维度预热

对于一些多租的 Kubernetes 集群中会存在多个不同的业务资源池,其中可能须要将一些特定的业务镜像按资源池维度来预热:

apiVersion: apps.kruise.io/v1alpha1
kind: ImagePullJob
metadata:
  name: serverless-job
spec:
  image: xxx/serverless-image:latest
  parallelism: 10
  completionPolicy:
    type: Never
  pullPolicy:
    backoffLimit: 3
    timeoutSeconds: 300
  selector:
    matchLabels:
      resource-pool: serverless

如上述 ImagePullJob 有几个特色:

  1. 采纳 Never 策略长期预热
  2. 指定 selector 预热范畴,是匹配 resource-pool=serverless 标签的节点

当然,这里只是以资源池为例,用户能够依据本身的场景来定义在哪些节点上预热某种镜像。

版本前瞻:原地降级与预热的联合

最初,再来介绍下 OpenKruise 的下个版本(v0.9.0)中,咱们会基于以后的镜像预热实现怎么的加强能力呢?

之前对 OpenKruise 理解过的同学肯定晓得,咱们提供的一大个性就是“原地降级”,即突破了 Kubernetes 原生 workload 公布时必须将 Pod 删除、重建的模式,反对在原 Pod 上只更新其中某个容器的镜像。对原地降级原理感兴趣的同学能够读这篇文章:《揭秘:如何为 Kubernetes 实现原地降级?》。

因为原地降级防止了 Pod 删除、重建的过程,它自身曾经能为咱们带来了如下的益处:

  • 节俭了 调度 的耗时,Pod 的地位、资源都不发生变化
  • 节俭了 调配网络 的耗时,Pod 还应用原有的 IP
  • 节俭了 调配、挂载近程盘 的耗时,Pod 还应用原有的 PV(且都是曾经在 Node 上挂载好的)
  • 节俭了 大部分拉取镜像 的耗时,因为节点上曾经存在了利用的旧镜像,当拉取新版本镜像时只须要下载多数的几层 layer
  • 原地降级 Pod 中某个容器时,其余容器 放弃失常运行,网络、存储均不受影响

其中,“节俭了大部分拉取镜像的耗时”后,只须要下载新镜像下层的局部 layer 即可。而咱们有没有可能把这个镜像拉取工夫彻底优化掉呢?答案是必定的。

如上图所示,在下个版本中 OpenKruise 的 CloneSet 将反对公布过程主动镜像预热。当用户还在灰度降级第一批 Pod 的时候,Kruise 会提前在后续 Pod 所在节点上把新版本的镜像预热好。这样一来,在后续批次的 Pod 做原地降级时候,新镜像都曾经在节点上筹备好了,也就节俭了真正公布过程中的拉镜像耗时。

当然,这种“公布 + 预热”的模式也只实用于 OpenKruise 的原地降级场景。对于原生 workload 如 Deployment 而言,因为公布时 Pod 是新建进去的,咱们无奈提前预知到它会被调度到的节点,天然也就没方法提前把镜像预热好了。
原文链接
本文为阿里云原创内容,未经容许不得转载。

正文完
 0