从CoreOS发布Rocket应用容器项目到现在,已经过去半年时间了。为了增加辨识度,项目更名为了Rkt。在沉寂了许久后,最近又开始在社区里出现了一些新鲜的声音。 首先是4月7日的一条新闻,Google领头投资CoreOS公司1200万美元以共同合作发展旗下的Kubernetes组件。此次合作除了促成新的商业发行版Tectonic的诞生,也使得Rkt容器与Kubernetes的关系拉近了一步:Kubernetes将提供对Rkt的友好支持,而Rkt则将沿用Kubernetes的Pods等概念来规划容器。 随后的4月20日,VMWare发布了旗下的通过容器部署应用的开源操作系统发行版:Photon。这个项目比较闪亮的地方在于,除了最知名的Docker容器,Photon还支持另外两种容器标准:CloudFoundry旗下的Garden,以及我们即将介绍的AppC/Rkt。CoreOS也在多篇博客中暗示VMWare其实以已经是AppC规范社区的一员。 就在5月4日的CoreOS Fest大会上,Linux大鳄红帽公司(Red Hat)联合谷歌(Google)、VMware和Apcera共同宣布,将大力支持AppC社区的发展。红帽和谷歌甚至确认将派出工程师协助维护AppC项目。 一个还在Alpha阶段的项目获得如此高的关注,对于CoreOS公司确实是个好兆头。这个系列接下来的两篇里,将带大家走进Rkt容器和它所代表的AppC容器规范,且做抛砖引玉之用。 Rkt的前世今生作为一个年轻的应用容器新秀,开源的Rkt并不是一个人在战斗,在它的背后支撑的是一支俨然有序的庞大社区力量。 诞生背景Rkt项目最初的发起者是CoreOS公司。 CoreOS公司与其核心产品 2014年12月,CoreOS公布了自己的容器计划,并在几个月后结合社区中的容器实践,着手制定新的开放应用容器规范,Rkt则作为此规范中的一个具体实现而继续发展。 AppC标准应用容器规范AppC的全称是“Application Container Specification(标准应用容器规范)”,这个规范的制定不是为了服务于特定的Linux系统环境,其初衷在于制定一组不依赖于具体平台、技术、操作系统和编程语言的容器虚拟化规范,解除已经初露端倪的企业容器产品互不兼容、各自封闭发展的危机,防止更多技术壁垒的产生。 正在制定中的AppC容器规范设计目标包括:
为了确保规范的开放并兼顾多方利益,CoreOS作为规范的倡导者、参与者和实施者,但并不会成为其唯一的制定者。 目前已经在遵循AppC的开源应用容器除了Rkt,还有FreeDBSD平台的容器Jet Pack和Linux平台通过C++实现的容器Nose Cone。更好的通用性,更小的入侵性,以及更高的开放性,正是由于这些AppC规范的独具匠心,使得它在Docker如日中天之时,恰逢其时的给业界带来一阵清风,引发许多技术玩家和企业的驻足和思考。 Rkt容器使用尝鲜且不论AppC的未来发展究竟会如何,远水不解近渴,既然Rkt容器本身是开源免费的,何不自己动手尝试一番。 作为开放式容器标准的样板项目,Rkt自然不会只能用在CoreOS的自家系统里。与Docker相似,Rkt虽然也被预装在了CoreOS系统中,但其他的任何Linux发行版都可以安装并使用它。在接下来的部分里,我们将以比较常见的64位Ubuntu系统为例,演示Rkt的安装和使用方法。 在64位Ubuntu中安装Rkt事实上,在任何Intel架构的64位Linux中,安装Rkt都简单到极致。这得益于Golang语言原生的静态编译方式,几乎所有编译过的Golang程序都可以下载即运行,而不需要安装额外依赖。 从GitHub网站可以直接下载到打包好的Rkt的二进制文件,目前最新的版本是v0.5.4。Rkt只提供了64位的编译版本,虽然通过自行编译源代码的方式也能够得到32位的可执行文件,但在32位系统上运行Rkt是不被官方推荐和支持的。 wget https://github.com/coreos/rkt/releases/download/v0.5.4/rkt-v0.5.4.tar.gz 下载后得到一个压缩文件。然后,恩,解压它。 tar xzvf rkt-v0.5.4.tar.gz 将解压后得到的文件统统放到系统的可执行目录里面,安装就算完成了。 sudo cp rkt-v0.5.4/* /usr/local/bin/ 接下来,试在命令行下执行不带任何参数的 $ rkt version rkt version 0.5.4 appc version 0.5.1+git Rkt工具的组成工欲善其事,必先利其器。在前面安装Rkt时,我们还没来得及多看一眼,就直接将解压后的文件一股脑儿丢进了系统目录里。这种部署方式虽然方便,但也实在简单粗暴。现在安装完了,至少还是得回头瞅瞅这个目录里到底提供了哪些东西。 不过,这一瞅简直让人失望,偌大一个压缩包,里面就这么俩文件。 $ ls rkt-v0.5.4 rkt stage1.aci 第一个文件刚刚已经试过了,它是Rkt容器的主程序,所有操作容器的命令都会通过这个命令作为入口。而第二个文件是个非常巧妙的设计。首先它的 Rkt容器默认是采用基于 此外,AppC规范还提供了一套用于制作和转换“符合AppC容器标准的”镜像的工具,这部分内容将会在系列的下篇中进行详述。 权限与镜像签名在目前阶段的Rkt还必须通过root用户来执行大多数的命令,不过未来也计划支持如Docker那样使用普通用户运行。在运行Rkt命令时如果出现“permission denied”的错误,请检查是否忘记了sudo。 使用Docker的用户,大多比较习惯在网上随便找到一个镜像地址,就直接pull下来使用。因此,即便Docker官方发现了一些恶意镜像的发布者,也无法有效的阻止这些镜像在网络的传播。 AppC规范中,特别强调了镜像的 $ sudo rkt trust --prefix coreos.com/etcd Prefix: "coreos.com/etcd" Key: "https://coreos.com/dist/pubkeys/aci-pubkeys.gpg" GPG key fingerprint is: 8B86 DE38 890D DB72 9186 7B02 5210 BD88 8818 2190 CoreOS ACI Builder Are you sure you want to trust this key (yes/no)? yes <--输入"yes"回车 Trusting "https://coreos.com/dist/pubkeys/aci-pubkeys.gpg" for prefix "coreos.com/etcd". Added key for prefix "coreos.com/etcd" at "/etc/rkt/trustedkeys/prefix.d/coreos.com/etcd/8b86de38890ddb7291867b025210bd8888182190" 在命令输出的最后一行,Rkt显示了签名在本地保存的位置。查看文件的内容就会发现,这个签名实际上是一个标准的GunPG签名公钥。GunPG是著名RSA非对称加密算法PGP的开源实现,关于PGP算法的介绍可以参考这篇百度百科。 $ cat /etc/rkt/trustedkeys/prefix.d/coreos.com/etcd/8b86de38890ddb7291867b025210bd8888182190 -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mQINBFTCnMQBEAC/49bGbStCpa3peej+/42mobfuGbTcdmcGGwYZmigP0Kl0TPZK ... 省略部分输出 ... fMkBtaM3knaFonHZc19BD1FOishRThCCq2Ty8HUoN2Fk7w0l =bYl7 -----END PGP PUBLIC KEY BLOCK----- 获取远程镜像通过 $ sudo rkt fetch coreos.com/etcd:v2.0.9 rkt: searching for app image coreos.com/etcd:v2.0.9 rkt: fetching image from https://github.com/coreos/etcd/releases/download/v2.0.9/etcd-v2.0.9-linux-amd64.aci Downloading signature from https://github.com/coreos/etcd/releases/download/v2.0.9/etcd-v2.0.9-linux-amd64.aci.asc Downloading ACI: [=============================================] 3.79 MB/3.79 MB rkt: signature verified: CoreOS ACI Builder sha512-91e98d7f1679a097c878203c9659f2a2 值得一提的是,如果用户在上一步中没有添加签名信任,则镜像在下载完成后会由于无法正确的验证来源,而被直接丢弃(不会进入Rkt的本地仓库)。并提示镜像没有签名,或镜像的签名没有被信任。 $ sudo rkt fetch coreos.com/etcd:v2.0.9 ... Downloading ACI: [=============================================] 3.79 MB/3.79 MB openpgp: signature made by unknown entity 有的时候,用户确实希望下载或导入一个没有签名认证的镜像。可以明确的使用 $ sudo rkt --insecure-skip-verify fetch coreos.com/etcd:v2.0.9 rkt: searching for app image coreos.com/etcd:v2.0.9 rkt: fetching image from https://github.com/coreos/etcd/releases/download/v2.0.9/etcd-v2.0.9-linux-amd64.aci Downloading ACI: [=============================================] 3.79 MB/3.79 MB sha512-91e98d7f1679a097c878203c9659f2a2 下载完成的镜像会被存储在本地的 $ tree /var/lib/rkt/cas/blob/sha512/ /var/lib/rkt/cas/blob/sha512/ └── 91 └── sha512-91e98d7f1679a097c878203c9659f2a26ae394656b3147963324c61fa3832f15 目前Rkt还没有提供一个命令能够快速列出本地仓库里所有镜像名字的方法。这看起来是一个比较匪夷所思的缺失功能。 运行容器运行Rkt容器的命令是 最常用,也是最方便的方法是使用标准的镜像的命名。比如例子中的 $ sudo rkt run coreos.com/etcd:v2.0.9 rkt: searching for app image coreos.com/etcd:v2.0.9 rkt: fetching image from https://github.com/coreos/etcd/releases/download/v2.0.9/etcd-v2.0.9-linux-amd64.aci ... Press ^] three times to kill container 也可以直接使用镜像的哈希值指定: $ sudo rkt run sha512-91e98d7f1679a097c878203c9659f2a26ae394656b3147963324c61fa3832f15 ... Press ^] three times to kill container 或者直接指定镜像文件的完整地址,这个地址可以是本地文件,也可以是网络文件,比如这样: $ sudo rkt run https://github.com/coreos/etcd/releases/download/v2.0.9/etcd-v2.0.9-linux-amd64.aci rkt: fetching image from https://github.com/coreos/etcd/releases/download/v2.0.9/etcd-v2.0.9-linux-amd64.aci ... Press ^] three times to kill container 使用时可以根据具体情况,哪种方便就用哪种。容器启动后就会自动运行镜像制作时指定的入口程序,连续按 通过 $ sudo rkt run --help Usage: -inherit-env=false: inherit all environment variables not set by apps -interactive=false: run pod interactively -local=false: use only local images (do not discover or download from remote URLs) -no-overlay=false: disable overlay filesystem -pod-manifest="": the path to the pod manifest. If it's non-empty, then only '--private-net', '--no-overlay' and '--interactive' will have effects -port=: ports to expose on the host (requires --private-net) -private-net=false: give pod a private network -set-env=: an environment variable to set for apps in the form name=value -signature=: local signature file to use in validating the preceding image -stage1-image="/usr/local/bin/stage1.aci": image to use as stage1. Local paths and http/https URLs are supported. If empty, rkt will look for a file called "stage1.aci" in the same directory as rkt itself -volume=: volumes to mount into the pod 比较常用的选项有:
对于经常在使用Docker的用户,有两点值得注意的Rkt与Docker运行镜像时不同的地方:
导入本地镜像文件Rkt导入本地镜像的命令和下载远程镜像是一样的,同样使用 $ wget https://github.com/coreos/etcd/releases/download/v2.0.9/etcd-v2.0.9-linux-amd64.aci ... aving to: ‘etcd-v2.0.9-linux-amd64.aci’ 100%[=================================>] 3,788,138 1.00MB/s in 5.1s ‘etcd-v2.0.9-linux-amd64.aci’ saved [3788138/3788138] $ sudo rkt run etcd-v2.0.9-linux-amd64.aci error opening signature file: open /home/ubuntu/etcd-v2.0.9-linux-amd64.aci.asc: no such file or directory 默认的签名文件应该和镜像在同一目录下,并且文件名应为镜像名加后缀 sudo rkt run image.aci --signature sign.asc 下载Docker仓库的镜像Rkt支持直接下载Docker镜像,并自动转换为AppC镜像。这一设计在Docker基础资源如此丰富的当下,真的是很贴心。操作起来也非常简单,只需要在Docker的标准镜像路径前面加上 不过,颇具讽刺意味的是,由于Docker镜像本来是没有签名验证机制的,因此下载任何Docker镜像时,都必须使用 例如,下载Docker官方仓库的CentOS镜像: $ sudo rkt --insecure-skip-verify fetch docker://centos rkt: fetching image from docker://centos Downloading layer: 6941bfcbbfca7f4f48becd38f2639157042b5cf9ab8c080f1d8b6d047380ecfc Downloading layer: 41459f052977938b824dd011e1f2bec2cb4d133dfc7e1aa0e90f7c5d337ca9c4 Downloading layer: fd44297e2ddb050ec4fa9752b7a4e3a8439061991886e2091e7c1f007c906d75 sha512-94b712e21c2f88aebcbe67b7e97911c9 直接通过哈希值试运行容器,注意加上 $ sudo rkt run --interactive sha512-94b712e21c2f88aebcbe67b7e97911c9ed3be062f976cefcebed8baab826ed32 [root@rkt-0ff47941-3934-4dcd-9b9d-3db558f62cd9 /]# 同样的,按三下 对于需要登录的Docker仓库,Rkt也提供了下载镜像的解决办法。首先需要在 $ sudo cat /etc/rkt/auth.d/myuser.json { "rktKind": "dockerAuth", "rktVersion": "v1", "registries": ["quay.io"], "credentials": { "user": "myuser", "password": "sekr3tstuff" } } 然后就可以执行fetch了。很方便有木有。 $ sudo rkt --insecure-skip-verify fetch docker://quay.io/myuser/privateapp rkt: fetching image from docker://quay.io/myuser/privateapp Downloading layer: cf2616975b4a3cba083ca99bc3f0bf25f5f528c3c52be1596b30f60b0b1c37ff Downloading layer: 6ce2e90b0bc7224de3db1f0d646fe8e2c4dd37f1793928287f6074bc451a57ea .... 更多功能通过 $ rkt help ... COMMANDS: enter Enter the namespaces of an app within a rkt pod fetch Fetch image(s) and store them in the local cache gc Garbage-collect rkt pods no longer in use help Show a list of commands or help for one command install Set up rkt data directories with correct permissions list List pods metadata-service Run metadata service prepare Prepare to run image(s) in a pod in rkt run Run image(s) in a pod in rkt run-prepared Run a prepared application pod in rkt status Check the status of a rkt pod trust Trust a key for image verification version Print the version and exit GLOBAL OPTIONS: --debug=false Print out more debug information to stderr --dir=/var/lib/rkt rkt data directory --help=false Print usage information and exit --insecure-skip-verify=false skip image or key verification --local-config=/etc/rkt local configuration directory --system-config=/usr/lib/rkt system configuration directory 2015年是各种容器技术与名词扎堆的一年,Docker的出现使得“应用容器”的实施变得易如反掌的同时,也带动了它的许多竞争者。其中一个比较有趣的看点就在于“容器规范”的较量,最近红帽和英特尔也按捺不住,拿出自家的产品趁势搅局。 5月14日,红帽宣布了新的多容器应用规范Nulecule(DockOne翻译了这篇新闻),同时推出符合这个规范的一个实现:AtomicApp。(这个路子怎么看都有点像AppC和Rkt采用的模式) 因特尔则是发挥自家的特长,在5月18日,发布了介于虚拟机与容器之间的跨界产品ClearLinux(DockOne同样翻译了这篇新闻)。之所以特别要提这个项目,是因为它首先会实现基于Rkt/AppC规范的容器模型,而将Docker放在了其次的位置。 “容器规范”的概念,看起来让人有些摸不着头脑,但在容器业界中,它确实是颇具诱惑力的一块蛋糕。在这一篇里,我们就来聊一聊支撑Rkt背后的那个“容器规范”:AppC Spec。 AppC规范究竟约定了什么使用了开源软件的人,未必都会有心情仔细阅读各种开源协议的内容。大多数的使用容器产品用户,也不见得要对容器规范的内容有很高的兴致。 不过,为了更好的理解后面将要介绍到的相关工具,还是不妨稍微深入的了解一些AppC规范约定的内容。其内容归纳起来主要有四个方面,下面依次罗列出来,并与当下的主流容器Docker做一个简要的对比。 PS:严格来说,AppC与AppC Spec两个词是有区别的。前者指的是CoreOS的 1.容器的镜像格式本质上说,容器 镜像就是符合特定目录结构的文件压缩包。镜像中的内容在容器启动后被展开,然后复制到一个独立的namespace空间内,并通过cgroup限制容器能 够使用的系统资源。稍后在制作镜像时,会详细介绍AppC Spec规定的镜像目录结构。这里只先指出一点,AppC的镜像没有支持像Docker那样的分层结构,这种设计简化了容器运行时的一些操作,但带来的弊 端也是很明显的:无法复用镜像相同的部分。因此在磁盘空间的利用上造成了浪费,也增加了容器镜像在网络传输成本。 除了目录的结 构,镜像还需要一个描述镜像内容的文件,称为“镜像属性清单文件(Image Manifest)”,其中定义的内容包括:镜像的作者信息、容器暴露的端口、暴露的挂载点、所需的系统资源(CPU/内存)等。此外,AppC Spec的约定的属性清单中,还会包含许多编排调度所需的信息,例如容器运行所依赖的其他容器、容器的标签。 在这方面来说,AppC镜像的信息量远远多于Docker镜像。相当于囊括了Docker镜像本身、Compose编排配置以及一部分Docker运行参数的内容。 此外,AppC规范也约定的镜像ID和签名的生成方法,关于镜像ID和签名的作用和在Rkt文章上篇中已经介绍过,稍后还会详细介绍镜像签名的生成方法。 2.镜像的分发协议分发协议主要是约定镜像下载使用的协议类型和URL的样式。AppC的镜像URL采用类似Docker的 Rkt/AppC目前支持以下几种URL格式:
第一种方式是AppC推荐的镜像分发URL,这种方式有点像Docker Repository,但实际上只是HTTPS协议的简写方式。AppC会根据指导的域名和路径依照约定的方式转换为完整URL地址,然后下载指定的镜像。 第二种方式相当于导入本地镜像。值得一提的是,即便使用本地镜像,AppC同样要求镜像有签名认证,关于签名文件的细节在后面的内容里会详细讨论。 第三种和第四种方式都是直接通过完整URL获取镜像,规范中并不推荐直接这样使用裸的HTTPS的URL,因为这种命名过于随意的镜像地址不利于镜像的管理和统一,特别是HTTP协议的URL更只应该在内网的环境中出现。 第五种方式不是AppC规范支持的协议类型,目前只是Rkt支持这种协议(本质上还是HTTP或HTTPS)。兼容Docker镜像的URL,只需要在前面加上 3.容器的编排结构AppC规范中的容器编排和集群描述方式与Kubernetes十分相似,采用“容器组属性清单文件(Pod Manifest)”描述。其中沿用了Kubernetes中诸如
考虑到CoreOS公司与谷歌共同合作的背景(已经推出了Tectonic CaaS平台),这样的设计为Kubernetes未来与符合AppC规范的容器进行深度集成提供了良好的技术基础。 4.容器的执行器执行器,也就像是Rkt这样的容器工具。这个部分规范了设计符合AppC Spec的容器执行器所需要遵循的原则和应该具备的功能。 例如,必须为每个容器提供唯一的UUID;在容器的运行上下文中必须至少提供一个本地Loopback网卡,以及0个至多个其他TCP/IP网卡;应该将容器中程序打印到Stdout和Stderr的日志进行收集和展示等细节。 其中还详细约定了,对于镜像属性清单中的诸多属性,执行器应当如何进行处理。这些内容对大部分的使用者而言都只能作为参考,还是需要以具体实现的容器产品文档为准。 镜像工具在AppC的项目中,除了一纸洋洋洒洒的规范文书以外,还提供了不少AppC镜像相关的示范工具。不像Docker这种一个命令集成所有功能的玩法,这些工具中的每个只是关注于容器的某个方面功能。例如通用类型镜像的制作、打包、格式转换以及特定类型镜像的制作等。 目前已有的工具主要包括:
其中,
下面将重点介绍 镜像的制作与镜像制作相关的工具是 wget https://github.com/AppC/spec/releases/download/v0.5.2/AppC-v0.5.2.tar.gz
tar zxf AppC-v0.5.2.tar.gz
sudo mv AppC-v0.5.2/actool /usr/local/bin/
说到构建镜像,前面已经提到,新的命令式构建镜像的工具 下面来制作一个十分朴素的AppC容器镜像,这个镜像中只包含一个可执行文件。 首先新建一个用于制作镜像的工作目录,例如 >mkdir AppC-image
接下来,为了让这个例子足够简单,我们需要一个能够不依赖任何外部动态库或运行时环境,能够单独运行的程序。我们写一个C语言的“Hello World”吧。新建一个叫 #include <stdio.h>
int main(int argc, char* argv[])
{
printf("Hello AppC\n"); //随便输出点什么东西
return 0;
}
然后,需要一个C语言编译器,有些Linux系统已经自带了这个东西,用 sudo apt-get install gcc
CoreOS系统会稍微麻烦一点,需要借助一个额外的容器来完成。提示一下,Docker有一个官方的C/C++语言运行环境镜像,就叫 编译的命令如下,其中的 gcc --static -o hello hello.c
在刚刚工作目录里面新建一个叫 mkdir -p AppC-image/rootfs/bin
cp hello AppC-image/rootfs/bin/
现在镜像的目录结构已经成型了。下面就可以开始创建镜像的属性清单文件了,在工作目录中新建一个名为 {
"acKind": "ImageManifest",
"acVersion": "0.5.2",
"name": "my-app",
"labels": [
{"name": "os", "value": "linux"},
{"name": "arch", "value": "amd64"}
],
"app": {
"exec": [
"/bin/hello"
],
"user": "0",
"group": "0"
}
}
此时,工作目录里的文件结构应该是这样的: AppC-image
├── manifest
└── rootfs
└── bin
└── hello
最后就可以用 actool build AppC-image hello.aci
镜像的验证容器镜像的来源无非有两种:本地的或者远程的。 因此对镜像的验证也就包含两部分内容。
对于前一种情况,前面说过,容器镜像其实就是符合一定标准结构的打包文件。 $ file hello.aci
hello.aci: gzip compressed data
在AppC规范中,镜像文件的后缀名应该是 直接执行这个命令时,actool只会通过命令的返回值表示验证的结果,返回0表示验证通过: $ actool validate hello.aci
$ echo $?
0
可以加上 $ actool -debug validate hello.aci
hello.aci: valid app container image
对于后一种情况,URL的验证,同样可以通过actool工具完成,相应的命令是 这个命令会返回镜像的实际下载地址: $ actool discover coreos.com/etcd
ACI: https://github.com/coreos/etcd/releases/download/latest/etcd
-latest-linux-amd64.aci, ASC: https://github.com/coreos/etcd
/releases/download/latest/etcd-latest-linux-amd64.aci.asc
Keys: https://coreos.com/dist/pubkeys/aci-pubkeys.gpg
试一下在Rkt里面用过的Docker镜像地址,会发现这个地址是无效的。 $ actool discover docker://ubuntu
error fetching docker://ubuntu: Get https://docker?ac-discovery=1:
dial tcp: lookup docker: no such host
这也证实了在前面说的, 镜像的转换AppC的规范制定者们显然很清楚,哪些轮子该重造,哪些轮子是可以直接复用的。在Docker的各种镜像已然是铺天盖地的当下,一个新的容器工具想要最快积累镜像数量,最好的办法就是兼容Docker镜像或者将Docker的镜像进行转换。 其实对于镜像兼容这个问题,新标准们有各自不同的做法,红帽的Nulecule选择了支持Dockerfile格式,只需要把已有的镜像代码加上一些额外的配置文件,重新构建一次就可以。而AppC做过同样的尝试,(之前有个 下面就来说说从Docker到AppC镜像的转换,相应的工具是 这个工具不论是
在Ubuntu或者CoreOS上都没有预装,因此需要单独安装。这个工具还没有正式发布,因此官方也没有提供编译好的二进制包,要获得它只能从源代码编
译。值得庆幸的是,Golang语言的编译方式还是比较友好的,如果本地已经安装了Golang语言的开发环境,可以直接通过 考虑到大多数用户都是没有Golang开发环境的,另一个比较简单的办法是:通过容器。因为,Docker官方已经提供了一个用于Golang开发的容器镜像,名字就叫 sudo docker run -v $(pwd):/pkg -i -t golang:1.4 /bin/bash -c "go
get github.com/AppC/docker2aci; cp \$GOPATH/bin/docker2aci /pkg/"
编译好的 sudo mv docker2aci /usr/local/bin/
执行 $ docker2aci
Usage of docker2aci:
docker2aci [--debug] [--nosquash] IMAGE
Where IMAGE is
[--image=IMAGE_NAME[:TAG]] FILEPATH
or
docker://[REGISTRYURL/]IMAGE_NAME[:TAG]
Flags:
-debug=false: Enables debug messages
-image="": When converting a local file, it selects a particular image to convert. Format: IMAGE_NAME[:TAG]
-nosquash=false: Don't squash layers and output every layer as ACI
将一个Docker镜像导出,然后可以通过 $ docker pull ubuntu
$ docker save -o ubuntu.docker ubuntu
$ ./docker2aci ubuntu.docker
... ...
Generated ACI(s):
ubuntu-latest.aci
转换后的镜像会保存在当前目录,并自动用“<镜像>-<标签>”的格式命名。 此外,比较实用的是, $ docker2aci docker://busybox
... ...
Generated ACI(s):
busybox-latest.aci
镜像的签名这个时候,如果直接用Rkt运行刚刚创建的 $ sudo rkt run hello.aci
error opening signature file: open /home/core/hello.aci.asc: no such file or directory
镜像的签名,是 AppC引入的一种镜像来源验证机制,本质上是利用非对称加密的标准数字签名。通过将镜像提供者的私钥和镜像文件本身加密生产一组签名字符串,通过发布者 提供的公钥就能够解开这串字符并得到与镜像匹配的信息,这样就能验证镜像是否是真的来自特定的作者或来源。 AppC的签名算法是标准是RSA,采用的是开源的GPG实现,关于GPG的详细介绍参考这篇文章。 首先准备一个密钥配置文件,命名为 %echo Generating a default key
Key-Type: RSA
Key-Length: 2048
Subkey-Type: RSA
Subkey-Length: 2048
Name-Real: 你的英文名字
Name-Email: 你的邮箱地址
Name-Comment: ACI signing key
Expire-Date: 0
Passphrase: 签名时的密码
%pubring rkt.pub
%secring rkt.sec
%commit
%echo done
然后用下面的命令生成一个密钥对: gpg --batch --gen-key gpg-batch
执行完成后,在目录中会多出 然后就可以使用这对密钥给镜像签名了: gpg --no-default-keyring --armor --secret-keyring ./rkt.sec
--keyring ./rkt.pub --output hello.aci.asc --detach-sig hello.aci
在提示输入密码时,输入在 再次尝试运行容器: $ sudo rkt run hello.aci
openpgp: signature made by unknown entity
这次提示的错误是,签名文件虽然找到了,但是这个签名的来源并没有在信任列表中。为了将签名添加到信任里面里面,首先要用 gpg --no-default-keyring --armor --secret-keyring ./rkt.sec
--keyring ./rkt.pub --export 在gpg-batch中的邮箱 > pubkeys.gpg
然后将这个文本文件中的公钥添加到Rkt的信任列表中。 $ sudo rkt trust --root pubkeys.gpg Prefix: "" Key: "pubkeys.gpg" GPG key fingerprint is: 37E2 6071 5382 5868 5A0D 1356 98A9 5E24 6E19 7AED Subkey fingerprint: 46AF 81E4 77D4 BFCA DFCE 73C6 3D94 79C2 2611 F243 Kelsey Hightower (ACI signing key) Are you sure you want to trust this key (yes/no)? yes Trusting "pubkeys.gpg" for prefix "". Added root key at "/etc/rkt/trustedkeys/root.d/37e26071538258685a0d135698a95e246e197aed" 这次运行容器,就可以看到容器中的Hello程序已经正确的执行了。 $ sudo rkt run hello.aci
rkt: signature verified:
Kelsey Hightower (ACI signing key) <kelsey.hightower@coreos.com>
Hello AppC
镜像的仓库最后简单的介绍一下AppC的镜像仓库(Image Repository)。 AppC规范定义了获取镜像的URL,其形式大致是 这里只说两个比较有意思的地方。 首先,AppC是没有所谓“官方镜像仓库”的,所以URL中的 其次,AppC会对用户的URL尝试通过两种方式解析。换句话说,镜像仓库的实现方式可以有两种。第一种几乎不需要额外的配置工作,将镜像依照一定的命名规则放在域名的相应路径下即可,例如 此外,前面介绍过,对于内网环境,还可以直接使用HTTP路径获取镜像。举个栗子,把之前制作好的镜像文件 $ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...
在任意另一个主机上就可以直接使用HTTP全路径下载镜像了。 $ sudo rkt fetch http://<服务器IP>:8000/hello.aci
... ...
Downloading ACI: [ ] 1.26 KB/358 KB
sha512-f7a2feff02a07ed7c604c14133b7aede
这种简单粗暴到 无以复加的方式,对于懒人们也许算得上是一种福利,然而不论是从安全性还是镜像版本的可管理性上看来,其能力都相当弱。这从一个侧面说明,一些为开发者们 提供的便利通道,如果没有规范的约束,可能带来很大的隐患。在实际运用时,建议遵循AppC的URL解析规范设计仓库为上策。 小结与处于 Alpha开发期的Rkt一样,AppC项目距离最终的成熟还有很长的路要走。然而随着谷歌、VMWare和因特尔等互联网公司的加入,他们旗下的产品, 如Kubernetes、Photon、ClearLinux等都已经将集成AppC容器作为其运营策略的一部分,其运用场景也日渐明朗。 “轻量”、“开 放”、“安全”,很难说这样一种由“一个公司牵头,多个公司入伙,希望依赖社区力量发展”的容器标准会走向何方。至少我们已经看到,不论是CoreOS的 AppC还是红帽的Nulecule,这些后来的容器标准的出现,或多或少是为了改善Docker的某些短板,也为容器业界提供了的一些可供选择的新思 路。从技术的大环境来说,它们的未来是值得期待的。 |