容器技术之容器镜像篇

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: # 前言 常言道,startup有startup的好,大厂有大厂的好,那么大厂究竟好在哪呢?拿硅谷老牌大厂们FLG来说,如果要问最令人怀念的是什么?Free food和基础设施(Infrastructure)一定是会上榜的,两者均极大提升了广大应用开发者的幸福指数。那么能不能“让天下没有难做的应用”呢?请大家把目光投向正在兴起的云原生生态。 在云原生生态中,容器服务包括了镜像和容器引擎

前言

常言道,startup有startup的好,大厂有大厂的好,那么大厂究竟好在哪呢?拿硅谷老牌大厂们FLG来说,如果要问最令人怀念的是什么?Free food和基础设施(Infrastructure)一定是会上榜的,两者均极大提升了广大应用开发者的幸福指数。那么能不能“让天下没有难做的应用”呢?请大家把目光投向正在兴起的云原生生态。

在云原生生态中,容器服务包括了镜像和容器引擎两个部分。其中容器镜像作为核心的云原生应用制品,打包了完整的操作系统和应用运行环境,应用的迭代也因为使用了这种不可变架构而变得更简单,更频繁。
本文将围绕着容器镜像这一核心,分享它的相关知识和业界的思考与实践。

1. 容器镜像的概念

  • 容器镜像

容器镜像有一个官方的类比,"生活中常见的集装箱",虽然拥有不同的规格,但箱子本身是不可变的(Immutable),只是其中装的内容不同。
对于镜像来说,不变的部分包含了运行一个应用软件(如mysql)所需要的所有元素。开发者可以使用一些工具(如Dockerfile)构建出自己的容器镜像,签名并上传到互联网上,然后需要运行这些软件的人可以通过指定名称(如_example.com/my-app_)下载、验证和运行这些容器。

  • OCI标准镜像规范

在OCI 标准镜像规范出台之前,其实有两套广泛使用的镜像规范,分别是appc和docker v2.2,但“合久必分,分久必合”,有意思的是两者的内容已经在各自的发展中逐步同化了,所以OCI组织顺水推舟地在docker v2.2 的基础上推出了oci image format spec,规定了对于符合规范的镜像,允许开发者只要对容器打包和签名一次,就可以在所有的容器引擎上运行该容器。

这份规范给出了OCI image的定义,

This specification defines an OCI Image, consisting of a manifest, 
an image index (optional), a set of filesystem layers, and a configuration.
  • 容器的工作流程

一个典型的容器工作流程是从由developers制作容器镜像开始的(build),然后上传到镜像存储中心(ship),最后部署在集群中(run)。
p7.png

容器镜像技术发展中遇到的问题

不得不说,容器镜像的设计是很出彩的,首先它蕴含了“完整的操作系统就是一个包”的优秀思想,带着大家跳出了安装包的思路,又提出了诸如dockerfile这样的提升开发者体验的killer features,还能利用分层结构来节约时间空间。
不过,"金无足赤,人无完人",优秀的设计并不等于优秀的实践,下面来聊一聊问题具体出在哪。

1. 容器镜像使用者

  • 问题一:启动容器慢

容器启动慢的情况普遍发生在当用户启动一个很大size的容器镜像时,由于在容器准备阶段需要三步(以overlayfs为例),

 - download镜像, 
 - unpack镜像,
 - 使用overlayfs将容器可写层和镜像中的只读层聚合起来提供容器运行环境

其中,download镜像时需要download整个镜像,不能实现文件数据按需加载。再加上download镜像本身受限于网络带宽的影响,当容器镜像size在到几个G时,下载时间会较长,破坏了容器原本优秀的用户体验。

  • 问题二:较高的本地存储成本

不同镜像之间可以共享的最小单位是镜像中的层,它的缺点之一是在deduplication上的效率是较低的,原因是,

  • 首先,层内部存在重复的数据,
  • 其次,层与层之间可能存在大量重复的数据,但即使有微小的差别,也会被作为不同的层,
  • 再次,根据OCI image spec对删除文件和hardlink的设计,一个镜像内部可能存在已经被上层删除的文件仍然存在于下层中,并包含在镜像中。

所以,当不同镜像的容器被调度到同一台机器上运行时,镜像本身在本地文件系统中所占的存储空间是一笔不可忽视的成本开销。

2. 镜像提供者侧

这里的提供者主要指容器服务的镜像中心。

  • 问题一:巨大的存储浪费

    • 存在大量相似镜像
      造成这种情况有两个原因,

      • 首先,上面提到的层的缺点,在容器镜像中心会产生许多相似镜像,
      • 其次,OCI image 使用了tar+gzip格式来表达镜像中的层,而tar格式并不区分tar archive entries ordering,这带来一个问题,即如果用户在不同机器上build去同一个镜像,最终可能会因为使用了不同的文件系统而得到不同的镜像,然后用户上传之后,镜像中心中会存在若干不同镜像的实质内容是完全相同的情况。
    • 镜像去重效率低

虽然镜像中心有垃圾回收来实现去重功能,但其仍然以层为单位,所以只能在有完全相同hash value的层之间去重。

  • 问题二:云原生软件供应链带来的新需求

随着时间推移,和软件供应链一起发展的还有对软件供应链环节的多样性攻击手段。安全防护是软件供应链中非常重要的组成,不光体现在对软件本身的安全增强,也体现在对供应链本身的安全增强。而因为应用运行环境被前置到了容器镜像中,所以对容器镜像的安全,包括对镜像的漏洞扫描和签名成为了容器服务提供者的必要能力。

对容器镜像的思考和讨论

1. 业界的尝试

针对前面所述的问题,业界大小厂也是集思广益,各显神通,下面提几个典型的项目,

  • CernVM-FS

使用了fuse按需从远程加载需要的数据

  • Slacker

通过设计一个镜像的benchmark贡献了几个有意思的理论基础,

  • 事实上,容器启动时间很长
  • 启动时数据读写放大系数很大(启动时中只使用6%的数据)
  • 分析了57个docker image的layer数量发现一半以上的image的layer数量大于9

Slacker最终使用了按需加载和减少镜像层数将启动速度提高了5-20倍。

  • SquashFs

Oracle使用Linux SquashFS来替代targz存储容器 image layer的内容,去掉了unpack tar的环节。

2. OCI社区中的讨论

自2019年开始,对于镜像本身的吐槽慢慢多了起来,发酵了一年多,OCI 社区觉得时机成熟了,从2020年6月开始,花了一个多月时间密集讨论了当前 OCI 镜像规范的缺陷,以及 OCIv2 镜像格式(*)需要满足哪些要求。

(*)OCIv2 在这里只是一个宣传命名,实际上 OCIv2 是当前 OCI 镜像规范的改进,而不会是一个全新的镜像规范。

2.1 OCI镜像规范的缺陷

经过讨论得出目前的缺陷主要有两点,

  • tar格式标准

    • tar格式并不区分tar archive entries ordering,这带来一个问题,即如果用户在不同机器上build去同一个镜像,最终可能会因为使用了不同的文件系统而得到不同的镜像,比如在文件系统A上的order是foo在 bar之前进入tar,在文件系统B上的order是bar在foo之前进入tar,那么这两个镜像是不同的。
    • 当tar 被gzip压缩过之后不支持seek,导致run container之前必须先下载并解压targz的image layers,而不能实现文件数据按需加载。
  • 以层为镜像的基本单位

    • 内容冗余:不同层之间相同信息在传输和存储时都是冗余内容,在不读取内容的时候无法判断到这些冗余的存在;
    • 无法并行:单一层是一个整体,对同一个层既无法并行传输,也不能并行提取;
    • 无法进行小块数据的校验,只有完整的层下载完成之后,才能对整个层的数据做完整性校验;
    • 其他一些问题:比如,跨层数据删除难以完美处理。

2.2 下一代镜像格式的要求

这次镜像格式大讨论从一个邮件和一份共享文档开始,并促成了多次在线的 OCI 社区讨论会议。最后的结论也很鼓舞人心,在这份共享文档中可以找到对OCIv2 镜像格式需要满足的要求的详细描述。我们可以将这些要求分类为,

效率 易用 安全
- 更少的重复数据
- 明确的更少的文件系统元数据(*)
- 镜像数据按需加载
- 更少的上传数据
- 可重建的镜像格式
- 可以 mount 的文件系统格式
- 可扩展性
- 镜像内容列表
- 可校验和/或可修复
- 可以工作在不可信存储上

(*): 诸如file timestamp等只在一个特定机器上有意义的metadata 是没有必要存在于镜像中的。

可以看出,上面这些要求明确了容器镜像的下一步重点在易用、效率、安全三个方面,达到在"build - ship - run" 这三个阶段协同优化的目的。

3. 阿里云在容器镜像上的思考

阿里云一直积极地推动和发展云原生生态,提供了基础设施“阿里云容器镜像服务(ACR)”作为用户云原生容器化的第一站,负责提供容器镜像、Helm Chart 等 OCI Artifacts 管理和分发服务。同时我们也在结合容器业务现状深化对容器镜像格式的理解,不断地总结什么是满足发展需求的容器镜像格式,这里可以概括为以下几点,新的镜像格式需要

  • 满足容器"build once, run anywhere"的理念
  • 实现在镜像中心和容器运行结点上存储资源上的高效使用
  • 在容器镜像的全链路上(build, ship, run)比现有的OCI镜像格式速度更快
  • 能够扩展在安全上的能力
  • 最大程度兼容已有基础设施,普惠大多数用户

阿里云沙箱容器的镜像加速

相比于社区的讨论重点放在了新的镜像格式的设计上,阿里云更关心如何设计出一套优化全链路的镜像方案,为客户带来能够应用在生产中的价值。

在明确以上在技术发展过程中产生的需求之后,我们为阿里云沙箱容器设计了新的镜像格式Rafs,并为CNCF下的Dragonfly项目引入了容器镜像服务,它能够极大缩短镜像下载时间,并提供端到端的镜像数据一致性校验,从而让用户能够更安全快捷地管理容器应用。

1. Rafs: 镜像格式

Rafs 把一个容器镜像只分成元数据和数据两层。其中,

  • 元数据层:元数据层是一颗自校验的哈希树。每个文件和目录都是哈希树中的一个附带哈希值的节点。一个文件节点的哈希值是由文件的数据确定,一个目录节点的哈希值则是由该目录下所有文件和目录的哈希值确定。
  • 数据层:每个文件的数据被按照固定大小切片并保存到数据层中。数据切片可以在不同文件以及不同镜像中的不同文件共享。

p8.png

2. Nydus: Dragonfly的容器镜像服务

除了使用上面的镜像格式Rafs,Nydus还包含一个负责解析容器镜像的 FUSE 用户态文件系统进程。

p9.png
nydus 能够解析 FUSE 或者 virtiofs 协议来支持传统的 runc 容器或者 阿里云沙箱容器。容器仓库,OSS 对象存储,NAS,以及 Dragonfly 的超级节点和 peer 节点都可以作为 nydus 的镜像数据源。同时, nydus 还可以配置一个本地缓存,从而避免每次启动都从远端数据源拉取数据。

基于这个设计架构,nydus 分别在build, ship, run 和兼容性方面提供下面这些优化:

build container 环节 ship container 环节 run container 环节 兼容性
- 块级别的镜像数据去重,最大限度为用户节省存储资源 - 支持不同的镜像存储后端,镜像数据不只可以存放在镜像仓库,还可以放到 NAS 或者类似 S3 的对象存储上
- 与 Dragonfly 的p2p能力良好集成
- 容器镜像按需下载,用户不再需要下载完整镜像就能启动容器
- 镜像只有最终可用的数据,不需要保存和下载过期数据
- 端到端的数据一致性校验,为用户提供更好的数据保护
- 兼容 OCI 分发标准和 artifacts 标准,开箱即可用

3. 为什么选择基于文件的设计

在设计之初,Nydus选择了基于文件的设计而不是基于块的设计,为什么这样做呢?
主要的原因是,我们想在镜像加速的基础上做基于容器特点的附加能力,这一切都建立在能够获取到镜像中的文件元数据;而基于块的设计只使用disk LBA,天然地无法获取其上层(即文件系统)中的信息。

有了文件元数据之后,我们轻松地实现了以下几个增值功能,

  • 镜像优化建议:在build container环节,提示用户有哪些文件是根本没有访问过的,可以考虑借此来优化镜像;
  • 预读:在run container环节预加载,猜到用户要读文件,那就预先在读操作发生之前送过去,从而优化访问速度;
  • 安全审计:在run container环节,如果一个容器访问镜像内容的模式和其他容器产生了明显差异,那么,这有可能是一个安全性风险;
  • 变更风险发现:在run container环节,如果一个镜像升级之后,发现它访问内容的模式和之前发生了明显差异,那么,要么是程序自己有意变了,要么就可能是引入 bug了,这时可以考虑提醒开发者这个变化。

总结

OCI image 分层镜像机制虽然极大地方便了开发,但在大规模集群运行时,也有颇多不足,对此,OCI镜像社区也在寻求着如何利用镜像内容可感知性,让它更加快速、节省资源,也更加安全。阿里云在这个基础上本着为客户带来价值的原则,提出了公有云上对镜像的稳定性、预读等需求,并为阿里云沙箱容器研发出了相应的的镜像加速方案,实现"build-ship-run"整个镜像链路上的统一优化,让用户不光听着热闹,也能用着开心,切实得到云原生基础设施发展的红利。

References

镜像格式二十年:从Knoppix到OCI-Image-v2

迈向云原生,云原生软件供应链安全实践

docker 101

Celebrating the Open Container Initiative Image Specification

相关实践学习
通过workbench远程登录ECS,快速搭建Docker环境
本教程指导用户体验通过workbench远程登录ECS,完成搭建Docker环境的快速搭建,并使用Docker部署一个Nginx服务。
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
1月前
|
Java Go 开发者
Docker容器技术简介及其与Go语言的结合点
【2月更文挑战第23天】本文首先概述了Docker容器技术的核心概念和优势,接着探讨了Go语言与Docker容器技术的结合点。通过阐述Docker的轻量级、可移植性和版本控制等特性,以及Go语言在容器化应用中的优势,本文旨在说明两者结合能够实现更高效、灵活的应用开发和部署。
|
1月前
|
Kubernetes 开发者 Docker
基于容器技术的微服务架构
基于容器技术的微服务架构
33 0
|
1天前
|
运维 Kubernetes Docker
这是一项颠覆性技术 - 容器
这是一项颠覆性技术 - 容器
|
10天前
|
运维 Kubernetes Devops
构建高效自动化运维体系:DevOps与容器技术融合实践
【4月更文挑战第15天】 在当今快速发展的信息技术时代,传统的IT运维模式已难以满足业务敏捷性的需求。本文旨在探讨如何通过整合DevOps理念和容器技术来构建一个高效的自动化运维体系。文章将详细阐述DevOps的核心原则、容器技术的基础知识,以及两者结合的优势。此外,文中还将分享一系列实践经验,包括持续集成/持续部署(CI/CD)流程的搭建、微服务架构的应用,以及监控和日志管理策略的优化,以期帮助企业实现快速、可靠且安全的软件交付过程。
|
16天前
|
Linux Shell 虚拟化
linux 部署docker容器虚拟化平台(二)--------docker 镜像制作方法
linux 部署docker容器虚拟化平台(二)--------docker 镜像制作方法
28 0
|
27天前
|
Kubernetes API 调度
总结归纳Kubernetes | 一站式速查知识,助您轻松驾驭容器编排技术(水平扩展控制)
总结归纳Kubernetes | 一站式速查知识,助您轻松驾驭容器编排技术(水平扩展控制)
60 0
|
29天前
|
NoSQL 关系型数据库 MySQL
安装Docker&镜像容器操作&使用Docker安装部署MySQL,Redis,RabbitMQ,Nacos,Seata,Minio
安装Docker&镜像容器操作&使用Docker安装部署MySQL,Redis,RabbitMQ,Nacos,Seata,Minio
372 1
|
1月前
|
运维 监控 Devops
构建高效自动化运维体系:基于容器技术的持续集成与持续部署实践
在数字化转型的浪潮中,企业的IT基础设施和软件交付模式正经历着深刻的变革。传统的运维方式已难以满足快速迭代、灵活扩展的现代业务需求。本文将探讨如何通过容器技术实现高效的自动化运维体系,重点分析持续集成(CI)与持续部署(CD)的实践方法及其对企业运维效率的影响。通过引入微服务架构、容器编排、DevOps文化等概念,我们旨在为读者提供一套全面的自动化运维解决方案,以支持业务的敏捷性和可扩展性。
|
1月前
|
边缘计算 Kubernetes 负载均衡
容器编排技术在云计算中的应用
随着云计算技术的飞速发展,容器编排技术作为一种重要的部署和管理工具,正在逐渐成为云计算领域的热门话题。本文将介绍容器编排技术在云计算中的应用,探讨其在提高应用程序部署效率、资源利用率以及系统可靠性方面的优势,并分析其未来发展趋势。
|
1月前
|
Kubernetes 云计算 开发者
云计算中的容器化技术:Docker与Kubernetes的实践
云计算中的容器化技术:Docker与Kubernetes的实践
107 0

相关产品

  • 容器镜像服务