OCI
OCI(Open Container Initiative)为Linux基金会下的子项目,成立于2015年,由docker、coreos等公司发起,用来制定开放的容器和容器镜像标准,同时docker将其镜像格式和容器运行时runc捐献给了OCI,因此OCI中包含了容器镜像标准和容器运行时标准两部分。
容器镜像的发展历史
2013年,docker横空出世,docker的核心能力之一为将应用封装为镜像,便于打包、发布。
2014年,docker将镜像格式定位为docker镜像规范v1版本。
2016年,docker制定了新的镜像格式规范v2,解决v1版本的部分设计缺陷。
2017年,OCI发布了OCI镜像规范1.0版本,整个规范以docker镜像规范v2为基础,两者的规范比较类似。
容器镜像标准
官方定义:OCI Image Format Specification
容器镜像标准包含了镜像索引(可选)、manifest、层文件和配置文件四部分内容。包含了容器的构建、分发和准备可以运行的镜像。
skopeo为一个容器镜像和镜像仓库的命令行操作工具,可以使用该工具来学习OCI容器镜像规范,可以直接使用 yum install skopeo -y
进行安装。
使用如下命令可以将docker的镜像转换为oci格式,并将其保存到/tmp/local_nginx目录下。
1 | skopeo copy docker://nginx oci:/tmp/local_nginx |
/tmp/local_nginx的目录包含如下结构,参考链接:OCI Image Layout Specification
- blobs 目录:包含了镜像Manifest、镜像层和镜像配置信息,均已sha256值命名的文件形式存储,文件可以为文本文件,也可以为gzip压缩的二进制文件。
- oci-layout 文件:定义了当前目录结构的版本信息
- index.json 文件:定义了镜像索引信息
1 | . |
镜像索引
非必须部分。如果包含镜像索引,用来解决多架构问题。不同的平台上,可以使用同一个镜像tag,即可以获取到对应平台的镜像。
镜像索引为 json 格式的文件,查看 index.json 文件,内容如下:
1 | { |
镜像索引文件可以包含多种架构。其中digest对应的sha256值指向 blobs/sha256 下的文件,其文件为Manifest文件。
需要注意的是:docker 可以使用 docker manifest
命令来查看镜像的manifest信息,但格式并非为OCI Manifest格式,而更类似于OCI index的信息,下面的命令中,可以看到rancher镜像为多镜像。
1 | $ docker manifest inspect rancher/rancher |
Manifest
参考:OCI Image Manifest Specification
Manifest为json格式的描述文件,包含了如下三个用途:
- 每一个镜像都有一个唯一的 id 标识
- 对于同一个镜像tag,可以支持多架构镜像
- 可以直接转换为OCI的运行时规范
查看 blobs/sha256/15beb598b14fca498f13a46923de0614a17012abf675ba06e364904d642d8a61 内容如下:
1 | { |
包含了config 和 layers 两部分信息,其中 config 信息为运行镜像的配置,layers 为镜像中的层信息,其中gzip说明镜像的层为gzip压缩格式,每个层一个压缩文件。
镜像配置
通过 manifest 中的config信息,可以找到镜像的配置信息 blobs/sha256/67e9751bc5aab75bba375f0a24702d70848e5b2bea70de55e50f21ed11feed14:
1 | { |
其中包含了如下几个关键信息:
- config:运行镜像的参数,比如entrypoint、labels等,跟通过 docker inspect 命令看到的信息比较类似。
- rootfs:镜像的层信息
- history:镜像的历史构建信息,如果empty_layer的值为true,说明未产生新的层
镜像层
镜像层同样存在于 blobs/sha256 目录下,且以压缩格式存储,一个层一个压缩文件。manifests文件中的 application/vnd.oci.image.layer.v1.tar+gzip
说明镜像层的压缩格式为gzip。
容器运行时标准
用来定义容器的配置、运行环境和声明周期。runc为容器运行时的官方实现,其主要代码来源为docker的容器运行时,kara-containers也有对应的OCI实现。
参考文档:opencontainers/runtime-spec
容器配置
定义在config.json文件中,定义了创建容器的字段。由于runc更具体的操作系统环境有关,其中部分的规范是跟具体操作系统有关的。执行runc spec
可以获取到默认的config.json文件,文件内容如下:
1 | { |
运行时和生命周期
在config.json文件中可以声明跟容器生命周期相关的部分,比如prestart、poststop等。
定义了很多子命令,比如状态查询的state <container-id>
,删除容器的delete <container-id>
等,这些子命令runc部分均有实现。通过 runc state mycontainerid
来查看的输出结果如下:
1 | { |
镜像分发规范
pull
pull manifest
接口定义:GET /v2/<name>/manifests/<reference>
<name>
: 镜像的 namespace。<reference>
:镜像的 tag 或者摘要信息。
pull bolb
接口定义:GET /v2/<name>/blobs/<digest>
push
POST /v2/<name>/blobs/uploads/?digest=<digest>
PUT /v2/<name>/manifests/<reference>
list tag
接口定义:GET /v2/<name>/tags/list
返回格式如下:
1 | { |
list references
接口定义: GET /v2/<name>/referrers/<digest>
delete tag
接口定义: DELETE /v2/<name>/manifests/<tag>
delete manifest
接口定义: DELETE /v2/<name>/manifests/<digest>
delete blobs
接口定义: DELETE /v2/<name>/blobs/<digest>
k8s支持情况
K8s可以通过 pod 的 spec.runtimeClassName 来指定 oci runtime 的实现方式。