容器镜像加速指南:探索 Kubernetes 缓存最佳实践
介绍
将容器化应用程序部署到 Kubernetes 集群时,由于从 registry 中提取必要的容器镜像需要时间,因此可能会出现延迟。在应用程序需要横向扩展或处理高速实时数据的情况下,这种延迟尤其容易造成问题。幸运的是,有几种工具和策略可以改善 Kubernetes 中容器镜像的可用性和缓存。在本篇文章中,我们将全面介绍这些工具和策略,包括 kube-fledged、kuik、Kubernetes 内置的镜像缓存功能、本地缓存以及监控和清理未使用的镜像。

前提
将工作负载部署到 Kubernetes 时,某个 Pod 中的容器自然会基于 OCI 容器镜像。这些镜像可以从多种私有/公共存储库中提取。Kubernetes 会在拉取镜像的每个节点上本地缓存镜像,以便其他 Pod 使用相同的镜像。

然而在大多数用例中,这还不够。如今,大多数云 Kubernetes 集群都需要自动扩展,并根据客户的使用情况动态分配节点。如果多个节点必须多次调用同一个镜像怎么办?如果这个镜像很重,那可能需要几分钟时间。在应用自动伸缩的情况下,需要相对较长的时间。
现有解决方案
预期的解决方案需要在 Kubernetes 上建立一个缓存层,这样 Kubernetes 就有了一个集中的镜像缓存,所有节点都能从其中 "提取 "镜像。但是,由于缓存需要非常快,因此缓存解决方案需要位于 Kubernetes 内部,所有节点都应该以最快的延迟到达缓存。
要解决从 registry 中提取容器镜像的延迟问题,广泛使用的方法是在集群内运行 registry 镜像。
两种广泛使用的解决方案是集群内自托管 registry 和推送缓存 (pull-through cache)。
在前一种解决方案中,本地 registry 在 Kubernetes 集群内运行,并在容器运行时配置为镜像 registry。任何镜像拉取请求都会指向集群内的 registry。在后一种解决方案中,容器镜像的缓存直接在工作节点上构建和管理。
其他现有解决方案包括使用 kuik 等可靠的缓存解决方案、在 Kubernetes 中启用镜像缓存、使用本地缓存、优化容器镜像构建以及监控和清理未使用的镜像。
Harbor
Harbor 是一个 CNCF 毕业项目,它的功能是容器 registry ,但最重要的是它还是一个推送代理缓存 (Pull Through Proxy Cache)。
推送代理缓存是一种缓存机制,旨在优化容器 registry 环境中容器镜像的分发和检索。它充当用户端(如容器运行时或构建系统)和上游容器 registry 之间的中介。
当用户端请求容器镜像时,直通式代理缓存会检查它是否已经拥有所请求镜像的本地副本。如果镜像存在,代理缓存会直接将其提供给客户端,而无需从上游 registry 下载。这样可以减少网络延迟并节省带宽。
如果本地缓存中没有请求的镜像,代理缓存就会充当普通代理,将请求转发到上游 registry。然后,代理缓存会从 registry 中检索镜像,并将其提供给客户端。此外,代理缓存还会在其本地缓存中存储一份镜像副本,以备将来请求之用。

kube-fledged
kube-fledged 是一个 K8s 附加组件或 operator,用于直接在 Kubernetes 集群的工作节点上创建和管理容器镜像缓存。它允许用户定义镜像列表,并将这些镜像缓存到哪个工作节点上。kube-fledged 提供了 CRUD API 来管理镜像缓存的生命周期,并支持多个可配置参数,以便根据个人需求定制功能。
kube-fledged 是为管理 Kubernetes 中的镜像缓存而设计和构建的通用解决方案。虽然主要用例是实现 Pod 的快速启动和扩展,但该解决方案支持下列的各种实例。
工作原理

kube-fledged 定义了一种名为 “ImageCache” 的自定义资源,并实现了一个自定义控制器(名为 kubefledged-controller)。用户可以使用 kubectl 命令创建和删除 ImageCache 资源。
Kubernetes-image-puller
为了缓存镜像,Kubernetes Image Puller 会在所需集群上创建一个 Daemonset,然后在集群中的每个节点上创建一个 pod,其中包含一个命令 sleep 720h 的容器列表。这样就能确保集群中的所有节点都缓存了这些镜像。使用的 sleep 二进制基于 golang(请参阅 Scratch Images:https://github.com/che-incubator/kubernetes-image-puller#scratch-images)。
我们还会定期检查守护进程集的健康状况,并在必要时重新创建它。
可以通过 Helm 或处理和应 OpenShift 模板来部署应用程序。此外,OperatorHub 上还有一个社区支持的 Operator。

kubernetes-image-puller 部署了大量容器(每个镜像和每个节点一个容器,缓存机制使用 daemonset),以实现缓存功能。
举个例子:缓存中有 5 个节点和 10 个镜像,而我们在集群中已经有 50 个容器专门用于缓存功能。
Tugger
Tugger 使用单一配置文件,通过其 Helm 文件值定义。它不允许我们将“系统”配置(例如:从缓存系统中排除特定图片)和 “用户”配置分开。
Tugger 使用通过 Helm 文件值定义的单一配置文件。它不允许分离 "系统 "配置,比如从缓存系统中排除特定镜像,和 "用户 "配置。
kube-image-keeper (kuik)
kube-image-keeper(又名 kuik,类似于 “quick”)是 Kubernetes 的容器镜像缓存系统。它能将 pod 使用的容器镜像保存在自己的本地 registry 中,这样在原始镜像不可用时,这些镜像仍可使用。
工作原理
创建 pod 时,kuik 的 webhook 会即时重写其镜像,并添加 localhost:{port}/ 前缀(默认 port 为 7439,可配置)。
在 localhost:{port} 上有一个镜像代理,它从 kuik 的缓存 registry (当镜像已被缓存时)或直接从原始 registry (当镜像尚未被缓存时)提供镜像。
控制器负责监控 pod,当发现新的镜像时,就会为这些镜像创建 CachedImage 自定义资源。另一个控制器会监测这些 CachedImage 自定义资源,并相应地将镜像从源 registry 复制到 kuik 的缓存 registry 中。
架构和组件
在 kuik 的命名空间中,您可以找到:
- 运行 kuik 控制器的
Deployment - 运行 kuik 镜像代理的
DaemonSet - 当该组件在 HA 模式下运行时,会使用
StatefulSet来运行 kuik 的镜像缓存,而不是Deployment。
运行镜像缓存显然需要一定的磁盘空间(请参考 Garbage collection and limitations:https://github.com/enix/kube-image-keeper#garbage-collection-and-limitations)。除此之外,就计算资源而言,kuik 组件是相当轻量级的。这显示了默认设置下的 CPU 和 RAM 使用情况,其中两个控制器处于 HA 模式:
$ kubectl top pods
NAME CPU(cores) MEMORY(bytes)
kube-image-keeper-0 1m 86Mi
kube-image-keeper-controllers-5b5cc9fcc6-bv6cp 1m 16Mi
kube-image-keeper-controllers-5b5cc9fcc6-tjl7t 3m 24Mi
kube-image-keeper-proxy-54lzk 1m 19Mi

Warm-image
WarmImage CRD 获取镜像参考,并将其预取到集群中的每个节点上。
要在集群中安装这一自定义资源,只需运行:
# Install the CRD and Controller.
curl https://raw.githubusercontent.com/mattmoor/warm-image/master/release.yaml \
| kubectl create -f -
或者,您也可以 git clone 该仓库并运行:
# Install the CRD and Controller.
kubectl create -f release.yaml
结论
在这篇文章中,我们向您展示了如何通过在节点上缓存镜像来加快 Pod 的启动速度。通过在 kubernetes 集群的工作节点上预取容器镜像,您可以显著缩短 Pod 的启动时间,即使是大型镜像,也可以缩短到几秒钟。这项技术能让运行机器学习、仿真、数据分析和代码构建等工作负载的客户受益匪浅,提高容器启动性能和整体工作负载效率。
由于无需额外管理基础设施或 Kubernetes 资源,这种方法为解决基于 Kubernetes 的环境中容器启动缓慢的问题提供了一种经济高效的解决方案。
容器镜像加速指南:探索 Kubernetes 缓存最佳实践的更多相关文章
- 在 Kubernetes 容器集群,微服务项目最佳实践
转载自:https://mp.weixin.qq.com/s/WYu3gDwKKf06f_FYbO9YRg 本文主要介绍我个人在使用 Kubernetes 的过程中,总结出的一套「Kubernetes ...
- Kubernetes Deployment 最佳实践
零.示例 首先给出一个 Deployment+HPA+ PodDisruptionBudget 的完整 demo,后面再详细介绍其中的每一个部分: apiVersion: apps/v1 kind: ...
- Kubernetes YAML最佳实践和策略
Kubernetes工作负载最常用YAML格式的文件来定义. YAML的问题之一就是很难描述清单文件之间的约束或关系. 如果你希望检查是否已从受信任的注册表中提取部署到群集中的所有映像,该怎么办? 如 ...
- 探索云数据库最佳实践 阿里云开发者大会数据库专场邀你一起Code up!
盛夏.魔都.科技 三者在一起有什么惊喜? 7月24日,阿里云峰会·上海——开发者大会将在上海世博中心盛大启程,与未来世界的开发者们分享数据库.云原生.开源大数据等领域的技术干货,共同探讨前沿科技趋势, ...
- vue项目缓存最佳实践
需求 在开发vue的项目中有遇到了这样一个需求:一个视频列表页面,展示视频名称和是否收藏,点击进去某一项观看,可以收藏或者取消收藏,返回的时候需要记住列表页面的页码等状态,同时这条视频的收藏状态也需要 ...
- [转载]三小时学会Kubernetes:容器编排详细指南
原翻译by梁晓勇 原英文:Learn Kubernetes in Under 3 Hours: A Detailed Guide to Orchestrating Containers 我很奇怪,为什 ...
- 生产环境容器落地最佳实践 --JFrog 内部K8s落地旅程
引言 Kubernetes已经成为市场上事实上领先的编配工具,不仅对技术公司如此,对所有公司都是如此,因为它允许您快速且可预测地部署应用程序.动态地伸缩应用程序.无缝地推出新特性,同时有效地利用硬件资 ...
- ImageApparate(幻影)镜像加速服务让镜像分发效率提升 5-10 倍
作者介绍 李昂,腾讯高级开发工程师,主要关注容器存储和镜像存储相关领域,目前主要负责腾讯容器镜像服务和镜像存储加速系统的研发和设计工作. 李志宇,腾讯云后台开发工程师.负责腾讯云 TKE 集群节点和运 ...
- Kubernetes生产环境最佳实践
点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 众所周知,Kubernetes很难! 以下是在生产中使用 ...
- 制作 Python Docker 镜像的最佳实践
概述 ️Reference: 制作容器镜像的最佳实践 这篇文章是关于制作 Python Docker 容器镜像的最佳实践.(2022 年 12 月更新) 最佳实践的目的一方面是为了减小镜像体积,提升 ...
随机推荐
- MYSQL服务无法启动:InnoDB: .\ibdata1 can't be opened in read-write mode
今天在那做实验倒腾mysql数据库,后来发现服务无法启动,查看日志报错如下: 2015-01-07 17:48:54 9136 [ERROR] InnoDB: .\ibdata1 can't be o ...
- 【libGDX】加载G3DJ模型
1 前言 libGDX 提供了自己的 3D 格式模型文件,称为 G3D,包含 g3dj(Json 格式)和 g3db(Binary 格式)文件,官方介绍见 → importing-blender- ...
- Navicat 12连接mysql8.x报错2059 - authentication plugin 'caching_sha2_password' 解决办法
// %表示远程连接允许所有ip,如果只是连接本地,将%改为localhost即可 ALTER USER 'root'@'%' IDENTIFIED BY '你自己的mysql的密码' PASSWOR ...
- 鸿蒙开发学习(二)之ArkUI
目录 UI开发 布局 布局选择 布局位置 组件 容器组件 row.column RelativeContainer 列表 Tabs 子组件 页面路由 GitHub地址,欢迎star HmDemo: 鸿 ...
- 有了这份Java面试中的葵花宝典,让你面试起飞!!!
HashMap面试题 HashMap与HashTable的区别 1.HashMap线程不安全 HashTable 线程是安全的采用synchronized 2.HashMap允许存放key 为null ...
- mac环境下安装python3的requests包
大家知道,mac环境默认安装的都是python2,自己装好python3之后,怎么使用pip来安装到python3下的包呢? 解决方法:pip3 install requests
- springboot多线程TaskExecutor的使用,以及使用@Async实现异步调用
目录 @Async实现异步调用 pom.xml 启动类 定义controller 定义接口 实现类 将isDone换程CountDownLatch来判断线程是否执行完实例化CountDownLatch ...
- 【Azure 环境】 介绍两种常规的方法来监视Window系统的CPU高时的进程信息: Performance Monitor 和 Powershell Get-Counter
问题描述 部署在Azure上的VM资源,偶尔CPU飙高,但是发现的时候已经恢复,无法判断当时High CPU原因. 在Windows系统中,有什么方式能记录CPU被进程占用情况,查找出当时是排名前列的 ...
- 结构化思维助力Prompt创作:专业化技术讲解和实践案例
结构化思维助力Prompt创作:专业化技术讲解和实践案例 最早接触 Prompt engineering 时, 学到的 Prompt 技巧都是: 你是一个 XX 角色- 你是一个有着 X 年经验的 X ...
- Redis之哈希分片原理一致性哈希算法与crc16算法
集群分片模式 如果Redis只用复制功能做主从,那么当数据量巨大的情况下,单机情况下可能已经承受不下一份数据,更不用说是主从都要各自保存一份完整的数据.在这种情况下,数据分片是一个非常好的解决办法. ...