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

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

1. containerd 中的镜像解密

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

图 镜像加密原理

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

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

加密之后的数据如下。

json 复制代码
"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 processorscontainerd 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,多租户模型,以集群粒度实现解密(当前社区还未实现)。

图 镜像解密模式 Node Key Model

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

ini 复制代码
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,如下图所示。

_图 stream\processors 处理流程

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

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

其中:

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

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

ini 复制代码
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 对每层镜像进行解密。具体配置如下。

ini 复制代码
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 元 ,感兴趣的朋友可以尽快入手。内购链接点击左下角**"阅读原文**"

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

相关推荐
Bright16685 小时前
centos9安装k8s集群
云原生·容器·kubernetes
!!!5257 小时前
华为云镜像加速器
docker·容器·华为云
xidianjiapei0018 小时前
Kubernetes的Ingress 资源是什么?
云原生·容器·kubernetes
sszdzq9 小时前
Docker
运维·docker·容器
dmy10 小时前
docker 快速构建开发环境
后端·docker·容器
土豆沒加11 小时前
K8S的Dashboard登录及验证
云原生·容器·kubernetes
终端行者12 小时前
kubernetes1.28部署mysql5.7主从同步,使用Nfs制作持久卷存储,适用于centos7/9操作系统,
数据库·容器·kubernetes
伪装成塔的小兵17 小时前
Windows使用docker部署fastgpt出现的一些问题
windows·docker·容器·oneapi·fastgpt
转身後 默落20 小时前
11.Docker 之分布式仓库 Harbor
分布式·docker·容器
菩提云21 小时前
Deepseek存算分离安全部署手册
人工智能·深度学习·安全·docker·容器