写点什么

《containerd 系列》一文了解 containerd 中的镜像加解密

  • 2024-04-26
    浙江
  • 本文字数:2435 字

    阅读完需:约 8 分钟

内容节选自《containerd 原理剖析与实战》,新书内购中,点击阅读原文,限时 69.9 元购买

1. containerd 中的镜像解密

OCI 镜像规范中,一个镜像是由多层镜像层构成的,镜像层可以通过加密机制来加密机密数据或代码,以防止未经授权的访问。如下图所示。



<p align=center>图 镜像加密原理  </p>


OCI 镜像加密原理主要是在原来的 OCI 镜像规范基础上,添加了一种新的 mediaType,表示数据文件被加密;同时在 annotation 中添加具体加密相关信息。镜像层没加密前的原始数据如下。


"layers":[  {    "mediaType":"application/vnd.oci.image.layer.v1.tar+gzip",    "digest":"sha256:7c9d20b9b6cda1c58bc4f9d6c401386786f584437abbe87e58910f8a9a15386b",    "size":760770  }]
复制代码


加密之后的数据如下。


"layers":[  {    "mediaType":"application/vnd.oci.image.layer.v1.tar+gzip+encrypted",    "digest":"sha256:c72c69b36a886c268e0d7382a7c6d885271b6f0030ff022fda2b6346b2b274ba",    "size":760770,    "annotations": {      "org.opencontainers.image.enc.keys.jwe":"eyJwcm90ZWN0Z...",      "org.opencontainers.image.enc.pubopts":"eyJjaXBoZXIiOi..."    }  }]
复制代码


在启动容器时, containerd 通过解密信息来解密这些加密镜像。这些解密信息包括密钥、选项和加密元数据。这些信息配置在 CRI Plugin 的 image_decryption 配置项中。此外,还需要设置正确的密钥模型并确保已正确配置 stream processors 和 containerd imgcrypt 解码器。


下面介绍如何在 containerd 的 CRI Plugin 中配置镜像解密。在介绍 CRI Plugin 中的镜像解密前,先介绍 k8s 中的镜像加解密和 containerd 中的 stream_processor

1.k8s 生态的镜像加解密

首先介绍镜像加密模式,Kubernetes 社区共支持两种镜像加密模式:


  1. Node Key Model,将密钥放在 Kubernetes 工作节点上,以节点为粒度实现解密,参考图 4.21 所示。

  2. Multi-tenancy Key Model,多租户模型,以集群粒度实现解密(当前社区还未实现)。



<p align=center>图 镜像解密模式 Node Key Model</p>


containerd 中当前支持的 是 Node Key Model,如上图所示,这种模式下 containerd 会在可信的 Node 上进行拉取镜像并利用私钥进行解密镜像。具体配置如下。首先是 containerd 中配置 CRI Pluging 的 image_decryption 选项,


version = 2[plugins."io.containerd.grpc.v1.cri".image_decryption]  key_model = "node"
复制代码


在 containerd 及以后的版本中, key_model = "node"是默认的配置,如果是 1.4 以及以前的配置,则需要手动配置上述信息并重启 containerd。除此之外,还需要配置 stream_processors 配置项。

2. containerd 中的 stream_processors

stream_processors 是 containerd 中的一种基于内容流的二进制 API。


传入的内容流通过 STDIN 传递给对应的二进制文件,二进制处理后输出 STDOUT 到 stream_processors,如下图所示。



<p align=center>图 stream_processors 处理流程</p>


streaming_processor 是对二进制的调用,如上图所示,相当于针对每层镜像都进行了 unpiz 操作,等价于:


<tar image layer>=`unpiz -d -c <tar.gzip image layer>`
复制代码


其中:


  • <tar.gzip image layer> 为输入的 targzip 格式的镜像层。

  • <tar image layer> 则为执行 unpiz -d -c 之后的 stdout 输出,即解压的结果。  该示例的 stream_processor 配置如下。


version = 2[stream_processors]  [stream_processors."io.containerd.processor.v1.pigz"] accepts = ["application/vnd.docker.image.rootfs.diff.tar.gzip"] returns = "application/vnd.oci.image.layer.v1.tar" path = "unpigz" args = ["-d", "-c"]
复制代码


stream_processor 中支持的配置有:


  • ID: 即 示例中的 "io.containerd.processor.v1.pigz",通过 stream_processors.<Process ID> 来指定某个 processor 的配置。

  • accepts: 该 processor 能处理的格式。

  • returns: 该 processor 处理之后的格式。

  • path: 该 processor 对应的可执行二进制文件的路径。

  • args:该 processor 处理时所需的参数。path + args 组成该 processor 的处理步骤,例如上述示例则是 unpigz -d -c


此外,processor 还支持 env 配置,格式为 ["key1=value1","key2=value2"]

3. 配置镜像解密

containerd 中的镜像解密则是利用了 stream_processor 机制,containerd/imgcrypt (https://github.com/containerd/imgcrypt)中的二进制 ctd-decoder 对每层镜像进行解密。具体配置如下。


version = 2[plugins."io.containerd.grpc.v1.cri".image_decryption]  key_model = "node"[stream_processors]  [stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]    accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]    returns = "application/vnd.oci.image.layer.v1.tar+gzip"    path = "ctd-decoder"    args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]    env= ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]  [stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]    accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]    returns = "application/vnd.oci.image.layer.v1.tar"    path = "ctd-decoder"    args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]    env= ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
复制代码


上述配置中,利用二进制 ctd-decoder 通过参数 --decryption-keys-path 指定镜像解密私钥,分别对 tar 格式和 tar.gzip 格式进行解密。


以上内容节选自新书 《containerd 原理剖析与实战》


最后,附上本书的购买链接,新书刚刚上架原价 109,限时优惠内购 69.9 元,感兴趣的朋友可以尽快入手。内购链接点击左下角**“阅读原文**”



本文使用 文章同步助手 同步

发布于: 刚刚阅读数: 6
用户头像

just do it 2018-09-25 加入

赵吉壮,《containerd 原理剖析与实战》作者,曾就职于华为 Cloud BU,字节跳动 Data 团队,专注于 k8s, Serverless, Go 云原生

评论

发布
暂无评论
《containerd 系列》一文了解 containerd 中的镜像加解密_Docker_公众号:云原生Serverless_InfoQ写作社区