CoreOS 那些事之 Rkt 容器尝鲜(上)

阅读数:4485 2015 年 5 月 18 日

话题:语言 & 开发架构

Are you sure you want to trust this key (yes/no)? yes

在命令输出的最后一行,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-----

获取远程镜像

通过rkt fetch命令可以获取远程的镜像,和 Docker 的 pull 命令类似。下面这个命令会从 CoreOS 的 GitHub 仓库中下载预装了 Etcd 的示例容器。

$ 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

有的时候,用户确实希望下载或导入一个没有签名认证的镜像。可以明确的使用--insecure-skip-verify参数来告诉 Rkt 不要验证镜像的来源。

$ 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

下载完成的镜像会被存储在本地的/var/lib/rkt/cas/blob/sha512/仓库目录中,具体的命名规则是将镜像 SHA512 哈希值的前两位作为目录名,并以完成的 SHA512 哈希值作为镜像的文件名。例如刚刚下载的 Etcd 镜像哈希值为:sha512-91e98d7f1679a097c878203c9659f2a2,它存储的路径如下:

$ tree /var/lib/rkt/cas/blob/sha512/
/var/lib/rkt/cas/blob/sha512/
└── 91
    └── sha512-91e98d7f1679a097c878203c9659f2a26ae394656b3147963324c61fa3832f15

目前 Rkt 还没有提供一个命令能够快速列出本地仓库里所有镜像名字的方法。这看起来是一个比较匪夷所思的缺失功能。

运行容器

运行 Rkt 容器的命令是rkt run,可以通过几种方式指定容器使用的镜像。

最常用,也是最方便的方法是使用标准的镜像的命名。比如例子中的coreos.com/etcd:v2.0.9名称:

$ 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

使用时可以根据具体情况,哪种方便就用哪种。容器启动后就会自动运行镜像制作时指定的入口程序,连续按Ctrl+]组合键 3 次则会退出当前容器。

通过--help参数可以显示rkt run命令的可用选项。

$ 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

比较常用的选项有:

  • --volume外挂分区,类似于 Docker 的-v参数
  • --port暴露容器中的端口,类似于 Docker 的-p参数
  • --interactive启用交互模式,类似于 Docker 的-i加上-t参数的效果
  • --set-env向容器里添加环境变量,类似于 Docker 的-e参数

对于经常在使用 Docker 的用户,有两点值得注意的 Rkt 与 Docker 运行镜像时不同的地方:

  • 目前还没有与 Docker 的-d参数相当的运行选项,要后台运行镜像先将就用nohup&吧。
  • 在任意容器中连续按Ctrl+]组合键 3 次,都会结束当前容器,不论是否启用了交互模式。

导入本地镜像文件

Rkt 导入本地镜像的命令和下载远程镜像是一样的,同样使用rkt fetch。需要留意的是,即便是导入本地镜像,Rkt 仍然会强制验证签名(除非指定--insecure-skip-verify参数)。

$ 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

默认的签名文件应该和镜像在同一目录下,并且文件名应为镜像名加后缀.asc。如果签名文件的位置或名字与此规范不符,则可以用--signature指定。例如:

sudo rkt run image.aci --signature sign.asc

下载 Docker 仓库的镜像

Rkt 支持直接下载 Docker 镜像,并自动转换为 AppC 镜像。这一设计在 Docker 基础资源如此丰富的当下,真的是很贴心。操作起来也非常简单,只需要在 Docker 的标准镜像路径前面加上docker://前缀即可。

不过,颇具讽刺意味的是,由于 Docker 镜像本来是没有签名验证机制的,因此下载任何 Docker 镜像时,都必须使用--insecure-skip-verify参数。仿佛时刻在提醒用户:这个镜像可能是不安全的!

例如,下载 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

直接通过哈希值试运行容器,注意加上--interactive选项:

$ sudo rkt run --interactive sha512-94b712e21c2f88aebcbe67b7e97911c9ed3be062f976cefcebed8baab826ed32
[root@rkt-0ff47941-3934-4dcd-9b9d-3db558f62cd9 /]#

同样的,按三下Ctrl+]则会退出容器。

对于需要登录的 Docker 仓库,Rkt 也提供了下载镜像的解决办法。首先需要在/etc/rkt/auth.d/目录下添加一个用户名命名的配置文件。

$ 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命令可以查看到 Rkt 的更多操作和参数,其中的一些功能还在开发中,具体的进度可以查阅官方文档

$ 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

小结 & 下期预告

Rkt 是 CoreOS 公司继 Etcd 后,为 Linux 社区输出的又一利器。值得指出的是,Rkt 项目当前依然处于开发的 Alpha 时期,距离作为产品发布还有相当的差距。即便如此,其项目本身以及 AppC 规范在应用容器社区引发的讨论日渐强烈。

AppC 规范与 Docker 的差异到底有多大?在这个系列的下一期中,我们将重点介绍 AppC 提供的一些标准工具,以及制作 AppC 容器的方法。并揭秘更多 AppC 容器与 Docker 的异同之处。感谢您的阅读。


感谢郭蕾对本文的策划和审校。

给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ@丁晓昀),微信(微信号:InfoQChina)关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。