Linux基金会于2015年6月成立OCI(Open Container Initiative)组织,旨在围绕容器格式和运行时制定一个开放的工业化标准。
开放容器格式标准(OCF, Open Container Format)
容器格式标准
制定容器格式标准的宗旨概括来说就是不受上层结构的绑定,如特定的客户端、编排栈等,同时也不受特定的供应商或项目的绑定,即不限于某种特定操作系统、硬件、CPU架构、公有云等。
容器标准化宗旨
操作标准化:容器的标准化操作包括使用标准容器感觉创建、启动、停止容器,使用标准文件系统工具复制和创建容器快照,使用标准化网络工具进行下载和上传。
内容无关:内容无关指不管针对的具体容器内容是什么,容器标准操作执行后都能产生同样的效果。如容器可以用同样的方式上传、启动,不管是php应用还是mysql数据库服务。
基础设施无关:无论是个人的笔记本电脑还是AWS S3,亦或是Openstack,或者其他基础设施,都应该对支持容器的各项操作。
为自动化量身定制:制定容器统一标准,是的操作内容无关化、平台无关化的根本目的之一,就是为了可以使容器操作全平台自动化。
工业级交付:制定容器标准一大目标,就是使软件分发可以达到工业级交付成为现实。
容器标准包(bundle)和配置
一个标准的容器包, 具体包含下面三个部分:
config.json : 基本配置文件, 包括与宿主机独立和应用相关的特定信息, 如安全权限,环境变量和参数等. 具体如下
- 容器格式版本
- rootfs 路径及是否只读
- 各类文件挂载点及相应容器内挂载目录(此处信息必须与 runtime.json 配置中保持一致.
- 初始化进程配置信息, 包括是否绑定终端, 运行可执行文件的工作目录,环境变量配置,可执行文件及执行参数,uid,gid 以及 额外需要加入的 gid,hostname,底层操作系统及 CPU 架构信息.
runtime.json : 运行时配置文件, 包含运行时与主机相关的信息, 如内存限制,本地设备访问权限,挂载点等. 除了上述配置信息以外, 运行时配置文件还提供了 "钩子(hook)" 的特性, 这样可以在容器运行前和体制后各执行一些自定义脚本. hooks 的配置包含执行脚本路径,参数,环境变量等.
rootfs : 根文件系统目录, 包含了容器执行所需的必要环境依赖. 如 /bin,/var,/dev,/usr 等目录及相应文件. rootfs 目录必须与包含配置信息的 config.json 文件同时存在容器目录最顶层.
容器运行时和生命周期
容器标准格式也要求 容器把自身运行时的状态持久化到磁盘中, 这样便于其他工具对此信息的使用和演绎. 该运行时状态已 JSON 格式编码存储. 推荐吧运行时状态的 json 文件保存在临时文件系统中, 以便于系统重启后自动移除.
基于 Linux 内核的操作系统, 该信息应该统一存储于 /run/opencontainer/containers 目录下, 该目录结构下已容器 ID 命名的文件夹(/run/opencontainer/containers//state.json)中存放容器的状态信息并实时更新.
state.json 文件中包含的具体信息如下:
1. 版本信息 : 存放 OCI 标准的具体版本号.
2. 容器ID : 通常是一个哈希值, 也可以是一个易读的字符串. 在 state.json 文件中加入容器ID是为了便于之前提到的运行时 hooks 只需载入 state.json 就可以定位到容器, 然后检测 state.json ,发现文件不见了就认为容器关闭, 然后执行响应预定义的脚本操作.
3. PID : 容器中运行的首个进程在宿主机上的进程号.
4. 容器文件目录 : 存放容器 rootfs 及响应配置的目录. 外部程序只需读取 state.json 即可定位到宿主机上的容器文件目录.
标准的容器生命周期有以下三个基本过程:
1. 容器创建 : 创建包括文件系统、namespaces、cgroups、用户权限在内的各项内容。
2. 容器进程启动 : 运行容器进程,进程的可执行文件定义在的config.json中,args项。
3. 容器暂停 : 容器实际上作为进程可以被外部程序关停(kill),然后容器标准规范应该包含对容器暂停信号的捕获,并做相应资源回收的处理,避免孤儿进程的出现。
基于 OCF 标准的具体实现.
容器运行时opencontainers/runc : docker 贡献的 runc项目,是后来者的参照标准。
虚拟机运行时hyperhq/runv : 基于Hypervisor技术的开放容器规范实现。
测试huawei-openlab/oct : 基于开放容器规范的测试框架。