Img[1]是一个开源项目,由该领域最著名的软件工程师之一Jessie Frazelle发起,旨在满足对无守护程序和无root权限构建容器镜像的需求,尤其是在Kubernetes中。她的博客文章《在Kubernetes上安全地构建容器镜像[2]》对该项目做了描述。
Img实际上是对另一个叫做BuildKit的开源的构建技术的封装,该技术以库的形式嵌入在Img中。BuildKit是一个功能强大的多功能构建引擎,它源自于Docker制定的Moby项目。在研究BuildKit提供的构建功能之前,让我们看一下Img的功能。
Img
Img CLI
对于镜像构建,Img build命令照搬了docker build命令所提供的最重要的子集,从而为熟悉Docker镜像制作者带来无缝的体验。使用Img构建镜像就像将“docker”替换为“img”一样简单。
$ img build --build-arg VERSION=1.0 -t mycorp/myapp .
在这方面,Img与Podman(我们在上一篇文章中讨论过)相似,但仅限于镜像构建任务,而Podman可用于构建镜像,运行容器等。
构建状态
无根构建
Img使用用户命名空间来实现无根构建,但是在使用overlayfs时(Ubuntu发行版除外)受限,即目前缺乏对非特权用户命名空间中挂载的支持。Overlayfs通常是用于组装容器文件系统的最佳联合挂载方法,由于Img不支持非特权用户命名空间,因此Img必须依靠复制文件来进行复制,效率非常低。
尽管有此限制,Img仍实现了提供无根构建的目标,同时又利用了BuildKit提供的一些高级构建功能。
BuildKit
BuildKit将构建步骤的内部表示形式组装为有向非循环图(DAG),这使它能够确定哪些构建步骤可以并行。对于包含多个构建阶段的Dockerfile,这可以显着减少构建完成的时间。对于Img使用者来说,这有明显的优势,因为镜像制作者无需具备相关知识。
跨平台/系统构建
Img和Kubernetes
对于镜像制作的主要贡献是:
构建镜像无需特权账户
下级uid / gid文件用于为非特权用户定义用户命名空间映射
二进制文件newuidmap和newgidmap,用于对每次在构建步骤中运行容器时创建的用户命名空间进行映射
使用Img在Kubernetes上运行无根构建时,不同的层(layer)在参与工作。构建步骤在Img容器内嵌套的BuildKit worker容器中执行。Img容器很可能在Docker容器运行时下运行,所有这些都由Kubernetes容器运行时接口(CRI)管理。安全地消除各层特权执行的约束这一任务并非易事,那么存在一些限制也就不足为奇了。
目前,尽管仍可以使用AppArmor和Seccomp来保护容器,但AppArmor和Seccomp配置文件无法应用于执行无根构建的Img pod。Pod中的Img容器还需要对其/ proc文件系统具有“unmasked”的访问权限,对于从1.12开始的Kubernetes版本,可以使用Pod安全特性securityContext.procMount来实现。这需要设置为Unmasked。
让Img pod能追踪不断变化的构建状态是在Kubernetes中使用Img进行构建的现实需求。这样,对Img的分开调用就可以利用本地存储区中构建的镜像和缓存层。例如,构建的镜像可能需要作为CI / CD工作流程的一部分被推送到镜像仓库,并且构建迭代肯定会受益于重用存储在缓存中的先前构建的层。使用Kubernetes(持久)卷抽象,可以使构建状态对Img pod可用。
结论
为Img所使用的构建引擎BuildKit具有许多Img当前未公开的功能。如果这些附加功能及时进入Img的用户界面,它将成为构建容器镜像的利器——特别是在Kubernetes环境中进行无根构建。
相关链接:
https://github.com/genuinetools/img
https://blog.jessfraz.com/post/building-container-images-securely-on-kubernetes/
原文链接:https://www.giantswarm.io/blog/building-container-images-with-img