乐趣区

关于kubernetes:OCI-与容器镜像构建

大家好,我是张晋涛。

这篇文章中我将介绍 OCI 及 Docker 镜像相干的内容,欢送留言探讨。

OCI 的前世今生

2013 年 3 月 dotCloud 公司在 PyCon 上进行了 Docker 的首次展现,随后发表开源。自此 Docker 开始被众人通晓,随后掀起了一股容器化的热潮。

在 2014 年 6 月 Docker 1.0 正式公布,有近 460 位贡献者和超过 8700 次提交,这也标记着 Docker 达到了生产可用的状态。

在过后,提到容器化第一想法就是用 Docker。而过后 Docker 的实现或者说倒退方向次要是由 Docker Inc. 公司管制的,并没有一个对立的工业规范。这对于一些头部公司而言,显然是不能承受的,没有对立的工业规范意味着如果抉择了应用 Docker 的容器化技术,便会被 Docker Inc. 公司所绑定;加上随着 Docker 软件的降级,某些性能或者个性必然会进行变动,没人能保障不产生破坏性变更。

所以,为了推动容器化技术的工业标准化,2015 年 6 月在 DockerCon 上 Linux 基金会与 Google,华为,惠普,IBM,Docker,Red Hat,VMware 等公司独特发表成立凋谢容器我的项目 (OCP),后更名为 OCI。它的次要指标便是 建设容器格局和运行时的工业凋谢通用规范

倒退至今,OCI 制订的次要规范有三个别离是 runtime-specimage-specdistribution-spec 这三个规范别离定义了容器运行时,容器镜像还有散发的标准,前面会开展介绍。

为了反对 OCI 容器运行时规范的推动,Docker 公司起草了镜像格局和运行时标准的草案,并将 Docker 我的项目的相干实现募捐给了 OCI 作为容器运行时的根底实现,当初我的项目名为 runc

起初 Docker 将其容器运行时独立成了一个我的项目,名为 containerd 并将此我的项目募捐给了 CNCF,当初曾经是 CNCF 毕业我的项目了。

OCI image vs Docker image

OCI 的建设推动了容器技术的工业标准化,但是否此规范就是惟一呢?其实不然。在成立 OCI 并制订 image-spec 规范的时候 Docker 曾经空前凋敝,并失去了宽泛的利用。

因为规范只定义了最根本的内容,想要将 Docker 的实现全副依照规范进行革新的话,会对 Docker 造成破坏性变更,也不利于 Docker 性能的迭代。

所以,Docker 为了反对 OCI 规范的遍及,曾经推动了 registry 对 OCI 镜像的反对,当初也正在给 Docker 本身减少适配中,指标是让 Docker 反对两种镜像格局,别离是合乎 Docker 规范的镜像和合乎 OCI 规范的镜像。

那这两者有什么异同呢?咱们来逐渐看下。

Docker Image 和 OCI Image 的区别和分割

在我以前的文章中咱们曾经具体的从根本上介绍了 Docker image 是什么,这里咱们就疾速的介绍下。

每个 Docker 镜像都是由一系列的配置清单和相应的层进行组织的。每个层个别都是 tar 格局的归档,配置清单中形容了对应的层应该按何种程序进行组织,以及镜像的一些元属性。比方镜像所反对的架构,例如 amd64 之类的,还有 ENV 等提前配置好的一些参数等。

当然,在 Docker Image 中也蕴含着构建镜像时候所用的 Docker 版本 docker_version 以及构建镜像的历史记录 history 等信息。所以你在 DockerHub 或者其余的镜像仓库上能够看到构建镜像所用的 Docker 版本,或者可通过 docker history <IMAGE> 的形式来查看构建历史。

那么 OCI Image 是什么呢?首先咱们须要有一个 OCI Image 才好探索它到底是什么。

这里介绍一个工具 skopeo 能够很不便的从镜像仓库或者本地 Docker daemon 甚至是通过 docker save 保留的 Docker Image tar 文件转换为 OCI Image。

对于 skopeo 的装置过程就不再赘述了,参考我的项目主页的文档阐明即可。这里间接开始应用。

咱们应用 debian 的镜像为例。

(MoeLove) ➜  skopeo copy docker://debian:stretch oci:debian:stretch    
Getting image source signatures
Copying blob a4d8138d0f6b done
Copying config 45f82268e3 done
Writing manifest to image destination
Storing signatures

通过下面的命令便会失去一个 OCI Image 了,咱们看下它的目录构造。

(MoeLove) ➜  tree debian 
debian
├── blobs
│   └── sha256
│       ├── 0043cd2a654fe86258f43f5b1dbbb4e6c582cc4bb6e505e9c5171c124150d155
│       ├── 45f82268e32180cb1839f90467d9b8a8258953d68b7221199976653308d92ef5
│       └── a4d8138d0f6b5a441aaa533faf5fe0c3996a6ca42643c46f4402c7e8bda53742
├── index.json
└── oci-layout

2 directories, 5 files

是不是有种似曾相识的感觉?没错 OCI Image 的标准是在 Docker Image 的根底上建设的,所以大抵看起来差别不是特地大。咱们看看其中具体的内容。

oci-layout

这个文件是 OCI Image 的布局文件,也是用于阐明它所应用或者遵循的镜像标准。

(MoeLove) ➜  debian cat oci-layout| jq
{"imageLayoutVersion": "1.0.0"}

能够看到此处的内容写的是 1.0.0 这便阐明该镜像遵循 OCI 1.0.0 版本的布局标准。

index.json

index.json 文件中的 manifest 字段相似于 Docker Image 中的 manifest.json 作为 OCI Image 的顶级配置, 也是镜像的一个入口配置。

(MoeLove) ➜  debian cat index.json | jq
{
  "schemaVersion": 2,
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:0043cd2a654fe86258f43f5b1dbbb4e6c582cc4bb6e505e9c5171c124150d155",
      "size": 349,
      "annotations": {"org.opencontainers.image.ref.name": "stretch"},
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    }
  ]
}

从它的内容能够看到它其中的 mediaType 字段与 Docker Image 中的类型模式雷同,然而将 docker 都换成了 oci。从这个配置文件,咱们能够找到第一个 blob 是 sha256:0043cd2a654fe86258f43f5b1dbbb4e6c582cc4bb6e505e9c5171c124150d155 咱们看看它的内容。

(MoeLove) ➜  debian cat blobs/sha256/0043cd2a654fe86258f43f5b1dbbb4e6c582cc4bb6e505e9c5171c124150d155 | jq
{
  "schemaVersion": 2,
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "digest": "sha256:45f82268e32180cb1839f90467d9b8a8258953d68b7221199976653308d92ef5",
    "size": 579
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:a4d8138d0f6b5a441aaa533faf5fe0c3996a6ca42643c46f4402c7e8bda53742",
      "size": 45337510
    }
  ]
}

这个入口文件形容了 OCI 镜像的理论配置和其中的 Layer 配置。如果有多层那 layers 也会相应减少。

留神:layers 中 mediaType 应用了 application/vnd.oci.image.layer.v1.tar+gzip 阐明数据内容是通过 gzip 压缩的 如果有趣味你能够将它用 tar 解压一下,你会发现很乏味的内容。

这里先将后果说进去,解压后你会失去一个 rootfs 这与 Docker Image 是相似的。

小结

咱们通过 skopeo 工具,从本地的 Docker daemon 中由 debian 的 Docker Image 失去了 OCI Image,并剖析了它其中的内容。

最次要的区别在于它们的目录构造不完全相同,配置信息尤其是 mediaType 的标准是不雷同的。

而它们的分割也在于此,OCI Image 的标准是由 Docker Image 的标准批改而来的,所以相似它们的 blob 的组织模式大抵是雷同的,配置文件中很多的参数也类似。

另外,咱们也能够很容易的失去另一个论断,那便是咱们能够很不便的将 Docker Image 转换为 OCI Image。

OCI image 和 Docker image 的转换

下面咱们曾经看到,应用 skopeo 工具,能够将 Docker Image 转换为 OCI Image,当然它也能够将 OCI Image 转换为 Docker Image。上面给出了办法:

# 从 DockerHub 将 debian 的 Docker Image 拉取并转换为 OCI Image
(MoeLove) ➜  skopeo copy docker://debian:stretch oci:debian:stretch    
Getting image source signatures
Copying blob a4d8138d0f6b done
Copying config 45f82268e3 done
Writing manifest to image destination
Storing signatures


# 将当前目录下的 debian 的 OCI Image 转换为 Docker Image 并存储到本地 docker daemon 中
(MoeLove) ➜  skopeo copy  oci:debian:stretch docker-daemon:local/debian:oci
Getting image source signatures
Copying blob 0e350e141713 done
Copying config aae58a37cf done
Writing manifest to image destination
Storing signatures
# 验证
(MoeLove) ➜  oci docker images local/debian
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
local/debian        oci                 ac6bcf605d82        6 months ago        101MB

镜像构建工具

在 CI/CD 环境中,尽管咱们能够应用 DinD (Docker in Docker) 的形式启动一个 docker daemon 或者应用挂载的形式,将内部的 /var/run/docker.sock 挂载进容器外部,亦或者将 Docker API 应用 HTTP 的形式裸露进去,间接应用该地址进行构建。

但这些形式你是否会感觉比拟重?是否有思考平安问题,或者压力及负载的问题?

这里的压力及负载次要是指当所有的工作都共用同一个 docker daemon 提供服务的话,对该 docker daemon 造成的压力。

这里咱们来介绍一些其余的镜像构建工具,应用这些工具能够让你在无 Docker 的环境下构建出镜像并上传至 Docker 镜像仓库中。

到目前为止,咱们能够有很多种抉择:

  • BuildKit
  • img
  • orca-build
  • umoci
  • buildah
  • kaniko
  • FTL
  • Bazel rules_docker

这些工具侧重点各有不同,当然也不仅有下面列到的这些工具,只是这些工具比拟典型罢了。

通常状况下,在网络上比拟容易见到宣传为下一代镜像构建工具的是 buildah,最次要起因是因为它能够间接构建 OCI 规范的镜像或 Docker 镜像,也能够间接应用 Dockerfile。并且它还能够 pull/push 镜像,能够说在镜像构建方面与 Docker 是齐全兼容,甚至能够说它在构建镜像方面能够作为 Docker 的替代品了。

并且 buildah 构建镜像的时候不须要任何 root 权限,也不依赖 Docker,它应用了简略的 fork-exec 模型,同时它也能够作为一个库蕴含在其余的工具中。它的最终目标便是提供一个更低层次的外围工具集,来实现构建镜像相干的事件。

说完这个典型的替代品,咱们再来说下 BuildKitimg , img 这个工具是构建在 BuildKit 之上的,所以有很多相似性。它们应用非 root 用户来构建镜像。当然 BuildKit 我在之前的文章中具体介绍过了,它是 Docker 内置的下一代构建工具,独立应用也是能够的。称它为“下一代镜像构建工具”也并不为过。

kaniko 是 Google 推出的,它次要的宣传语为“在 Kubernetes 中构建容器镜像”实际上无论是在 K8S 集群中或者在容器中它都是能够工作的。它也能够应用 Dockerfile 构建镜像。当然还有很重要的一点,它所有的构建命令都是运行在用户态的,并且也能够很好的与 Kubernetes 联合,在云原生时代下,它也占据了肯定的劣势。

以上工具都只是大抵介绍了下,如果对它们感兴趣,可间接进入我的项目主页查看 README.md 根底应用都有比拟具体的阐明,这里不再进行赘述了。

总结

本篇为大家介绍了 OCI 的前世今生,以及 OCI Image 的标准和特点,另外也介绍了一个可用于在 OCI Image 和 Docker Image 之间镜像转换的工具 skopeo。另外介绍了一些可用于在 CI 环境或其余有特定场景环境下代替 Docker build 的工具,请大家按理论需要进行抉择。


欢送订阅我的文章公众号【MoeLove】

退出移动版