Containerd 1.5 于 2021 年 5 月 4 日发布。这是 Containerd 的第 6 个主要版本,包括许多稳定性改进, 以及代码组织结构变化,使后续开发更方便。该版本默认启用支持 OCI crypt 解密,并引入了对 zstd、NRI 和 FreeBSD 实验性支持还包括将 CRI 插件纳入主容器库和切换到 Go modules。Containerd 相对于 Docker 更轻量,也更先进。
🔗 详细设计稿参考:
https://static.sched.com/hosted_files/kccnceu2021/d3/containerd-KubeConEU2021.pdf
支持加密镜像
可以把镜像加密后上传到镜像仓库, Containerd 只需要配置解码的 key 就可以运行这加密的镜像, 对于一些对于安全性有需求的镜像可以使用这种方式。
自从 Containerd 1.3 加入该功能后,已支持容器使用加密镜像 「OCI crypt」但是一直并没有启用该功能。
该特性将在 1.5 中已经默认启用,使用方法请参见文档 「依赖的二进制文件包含在 cri-containerd-cni-1.5.0-linux-amd64.tar.gz」
注意:当前 Docker 是不支持 OCI crypt 的,因为 Docker 目前还没有使用 Containerd 管理镜像。
1.1 全局启用
在 /etc/containerd/config.toml 中增加如下配置并手动重启 Containerd 服务。
1version = 2
2
3[plugins."io.containerd.grpc.v1.cri".image_decryption]
4 key_model = "node"
5
6[stream_processors]
7 [stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
8 accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
9 returns = "application/vnd.oci.image.layer.v1.tar+gzip"
10 path = "ctd-decoder"
11 args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
12 env= ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
13 [stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
14 accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
15 returns = "application/vnd.oci.image.layer.v1.tar"
16 path = "ctd-decoder"
17 args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
18 env= ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
在本例中,容器镜像解码被设置为使用 Node 上的密钥,配置参数 –decryption-keys-path 以指定解密密钥在 Node 中的路径。
$OCICRYPT_KEYPROVIDER_CONFIG 环境变量用于 OCI crypt keyprovider protocol。
1.2 单独启用
可以使用如下所示的配置文件启动一个新的 Containerd。为了避免对当前安装的 Containerd 的干扰,我们使用 /tmp 作为目录。
创建 /tmp/etc/containerd/config.toml 配置, 并启动 Containerd。
1disable_plugins = ["cri"]
2root = "/tmp/var/lib/containerd"
3state = "/tmp/run/containerd"
4[grpc]
5 address = "/tmp/run/containerd/containerd.sock"
6 uid = 0
7 gid = 0
8[stream_processors]
9 [stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
10 accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
11 returns = "application/vnd.oci.image.layer.v1.tar+gzip"
12 path = "/usr/local/bin/ctd-decoder"
13 [stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
14 accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
15 returns = "application/vnd.oci.image.layer.v1.tar"
16 path = "/usr/local/bin/ctd-decoder"
17
18# sudo containerd -c config.toml
使用 openssl 命令行工具创建 RSA 密钥对,并对镜像进行加密:
1# openssl genrsa -out mykey.pem
2Generating RSA private key, 2048 bit long modulus (2 primes)
3...............................................+++++
4............................+++++
5e is 65537 (0x010001)
6# openssl rsa -in mykey.pem -pubout -out mypubkey.pem
7writing RSA key
8# sudo chmod 0666 /run/containerd/containerd.sock
9# CTR="/usr/local/bin/ctr-enc -a /run/containerd/containerd.sock"
10# $CTR images pull --all-platforms docker.io/library/bash:latest
11[...]
12# $CTR images layerinfo --platform linux/amd64 docker.io/library/bash:latest
13 # DIGEST PLATFORM SIZE ENCRYPTION RECIPIENTS
14 0 sha256:9d48c3bd43c520dc2784e868a780e976b207cbf493eaff8c6596eb871cbd9609 linux/amd64 2789669
15 1 sha256:7dd01fd971d4ec7058c5636a505327b24e5fc8bd7f62816a9d518472bd9b15c0 linux/amd64 3174665
16 2 sha256:691cfbca522787898c8b37f063dd20e5524e7d103e1a3b298bd2e2b8da54faf5 linux/amd64 340
17# $CTR images encrypt --recipient jwe:mypubkey.pem --platform linux/amd64 docker.io/library/bash:latest bash.enc:latest
18Encrypting docker.io/library/bash:latest to bash.enc:latest
19$ $CTR images layerinfo --platform linux/amd64 bash.enc:latest
20 # DIGEST PLATFORM SIZE ENCRYPTION RECIPIENTS
21 0 sha256:360be141b01f69b25427a9085b36ba8ad7d7a335449013fa6b32c1ecb894ab5b linux/amd64 2789669 jwe [jwe]
22 1 sha256:ac601e66cdd275ee0e10afead03a2722e153a60982122d2d369880ea54fe82f8 linux/amd64 3174665 jwe [jwe]
23 2 sha256:41e47064fd00424e328915ad2f7f716bd86ea2d0d8315edaf33ecaa6a2464530 linux/amd64 340 jwe [jwe]
启动一个支持加密镜像的最新版本的本地镜像仓库,这样我们就可以将加密的镜像推送进去。
1# docker pull registry:latest
2# docker run -d -p 5000:5000 --restart=always --name registry registry
将加密镜像推入本地镜像仓库,使用 ctr-enc 拉取镜像,然后运行镜像。
1# $CTR images tag bash.enc:latest localhost:5000/bash.enc:latest
2# $CTR images push localhost:5000/bash.enc:latest
3# $CTR images rm localhost:5000/bash.enc:latest bash.enc:latest
4# $CTR images pull localhost:5000/bash.enc:latest
5# sudo $CTR run --rm localhost:5000/bash.enc:latest test echo 'Hello World!'
6ctr: you are not authorized to use this image: missing private key needed for decryption
7# sudo $CTR run --rm --key mykey.pem localhost:5000/bash.enc:latest test echo 'Hello World!'
8Hello World!
节点资源接口
节点资源接口 「NRI」 用于 CPU 调度约束和内存配额的标准接口。
其类似容器网络接口 「CNI」 的基本接口、概念和插件设计是一种处理容器网络堆栈的多种实现的优雅方式。此概念可用于其他接口,以定制容器的运行时环境。节点资源接口(NRI)是一个新的接口,其实带有结构化API和容器插件设计,用对节点上的资源进行管理。与 CNI 相同 NRI 插件将在容器创建完毕, 但是还没有真正启动之前的初始化时被调用。
可以看示例代码 「https://github.com/containerd/nri#sample-plugin」 了解 NRI 的使用。
2.1 如何配置自己的 NRI 插件呢
配置分为两个部分。一个是特定于插件调用的可执行文件,而第二个是指定要运行哪些插件并为插件提供额外配置。
插件可执行文件路径可以通过用户配置,但默认为 /opt/nri/bin。二进制文件以其类型命名为二进制名称,与 CNI 插件命名方案相同。
配置的默认路径是 /etc/nri/resource.d/*.conf 。
1/etc/nri/resource.d/*.conf
2{
3 "version": "0.1",
4 "plugins": [
5 {
6 "type": "konfine",
7 "conf": {
8 "systemReserved": [0, 1]
9 }
10 },
11 {
12 "type": "clearcfs"
13 }
14 ]
15}
2.2 插件的工作原理
插件的输入输出是通过 STDIN/STDOUT 其格式是 JSON。
- 输入示例
1Input
2{
3 "version": "0.1",
4 "state": "create",
5 "id": "redis",
6 "pid": 1234,
7 "spec": {
8 "resources": {},
9 "cgroupsPath": "default/redis",
10 "namespaces": {
11 "pid": "/proc/44/ns/pid",
12 "mount": "/proc/44/ns/mnt",
13 "net": "/proc/44/ns/net"
14 },
15 "annotations": {
16 "qos.class": "ls"
17 }
18 }
19}
- 输出示例
1Output
2{
3 "version": "0.1",
4 "state": "create",
5 "id": "redis",
6 "pid": 1234,
7 "cgroupsPath": "qos-ls/default/redis"
8}
更好的压缩算法支持
现在除了 gzip 之外,还支持 zstd 作为镜像压缩算法。zstd 是 Facebook 在 2016 年开源的新无损压缩算法,优点是压缩率和压缩/解压缩性能都很突出。
zstd 的设计目的是达到与 deflate 算法 「开发于1991年,用于gzip」 相当的压缩比, 并且更快,尤其是解压的时候。
zstd 在其最大压缩级别的压缩比接近 lzma、lzham 和 ppmx,并且比 lza 或 bzip2 性能更好。它的解压速度比任何当前可用的算法都快,并且压缩比更好。
zstd 的基准测试结果在速度方面,在最快模式下,它的速度通常是 stdlib deflate/gzip 2倍。
🔗 图片来源:
支持 FreeBSD
现在支持在 FreeBSD 运行 Containerd,容器运行时 OCI 是使用 FreeBSD jails 「Samuel Karp 的 runj」。文件系统目前仅支持 ZFS, 后续计划支持 unionfs。
🔗 图片来源:
https://medium.com/nttlabs/containerd15-fe0a9845a572
未经允许不得转载:DaoCloud道客博客 » Containerd 1.5 震撼发布 | 支持镜像加密的容器引擎