Embedded Registry Mirror

RKE2 embeds Spegel, a stateless distributed OCI registry mirror that allows peer-to-peer sharing of container images between nodes in a Kubernetes cluster. The distributed registry mirror is disabled by default. For RKE2 to leverage it, you must enable both the Distributed OCI Registry Mirror and the Registry mirroring as explained in the following subsections.

启用分布式 OCI 注册表镜像

要启用嵌入式注册表镜像,服务器节点必须使用`embedded-registry: true`进行配置。此选项使嵌入式镜像可在集群中的所有节点上使用。

当在集群级别启用时,所有节点将在 6443 端口上托管本地 OCI 注册表,并通过点对点网络在 5001 端口发布可用镜像的列表。在任何节点的 containerd 容器镜像存储中可用的任何镜像,都可以被其他集群成员拉取,而无需访问外部注册表。通过隔离 image tar 文件预导入导入的镜像会在 containerd 中被固定,以确保它们保持可用且不会被 Kubelet 垃圾回收清除。

要求

当启用嵌入式注册表镜像时,所有节点必须能够通过其内网 IP 地址在 TCP 端口 5001 和 9345 互相访问。如果节点无法相互访问,拉取镜像可能会花费更长时间,因为 containerd 会首先尝试分布式注册表,然后再回退到其他端点。

指标

Spegel 提供了一些有助于跟踪其活动的指标,并可以在监控器中查询。但是,监控器指标默认是禁用的。要启用它们,服务器节点必须在配置文件中使用`supervisor-metrics: true`启动。

启用后,查询:

kubectl get --server https://$SERVER_NAME:9345 --raw /metrics | grep spegel

启用注册表镜像

为注册表启用镜像允许节点从其他节点拉取该注册表的镜像,并与其他节点共享该注册表的镜像。如果某些节点启用了镜像的注册表,但其他节点没有启用,只有启用了注册表的节点才会从该注册表交换镜像。

为了启用从上游容器注册表的镜像,节点必须在 mirrorsregistries.yaml 部分中为该注册表添加条目。注册表不需要列出任何端点,只需存在即可。例如,要启用从 docker.ioregistry.k8s.io 的图像的分布式镜像,请在所有集群节点上将 registries.yaml 配置为以下内容:

mirrors:
  docker.io:
  registry.k8s.io:

注册表镜像的端点也可以像往常一样添加。在以下配置中,图像拉取尝试将首先尝试嵌入的镜像,然后是 mirror.example.com,最后是 docker.io

mirrors:
  docker.io:
    endpoint:
      - https://mirror.example.com

如果您直接使用私有注册表,而不是作为上游注册表的镜像,您可以像启用公共注册表那样启用分布式镜像——只需在镜像部分中列出它:

mirrors:
  mirror.example.com:

The "*" wildcard mirror entry can be used to enable distributed mirroring of all registries. Note that the asterisk MUST be quoted:

mirrors:
  "*":

如果在节点上没有启用任何注册表进行镜像,则该节点在分布式注册表中不以任何身份参与。

有关`registries.yaml`文件结构的更多信息,请参阅私有注册表配置

默认端点回退

默认情况下,containerd 在从配置了镜像端点的注册表拉取时将回退到默认端点。如果您想禁用此功能,仅从配置的镜像和/或嵌入式注册表中拉取镜像,请参阅私有注册表配置文档中的默认端点回退部分。

请注意,如果您使用`disable-default-endpoint`选项,并希望允许直接从某个特定注册表拉取,同时禁止其他注册表,您可以明确提供一个端点,以使图像拉取可以回退到该注册表本身:

mirrors:
  docker.io:           # no default endpoint, pulls will fail if not available on a node
  registry.k8s.io:     # no default endpoint, pulls will fail if not available on a node
  mirror.example.com:  # explicit default endpoint, can pull from upstream if not available on a node
    endpoint:
      - https://mirror.example.com

最新标签

当未为容器图像指定标签时,隐式默认标签为 latest。此标签会经常更新,以指向该镜像的最新版本。由于此标签会根据拉取时间指向镜像的不同修订版本,分布式注册表*将不会*从其他节点拉取`latest`该标签。这迫使 containerd 访问上游注册表或注册表镜像,以确保对 latest 标签所指内容的一致视图。

这与Kubernetes在使用`latest`标签为容器镜像时观察到的 特殊`imagePullPolicy`默认一致。

安全性

身份验证

访问嵌入式镜像的注册表API需要有效的客户端证书,该证书由集群的客户端证书颁发机构签署。

访问分布式哈希表的点对点网络需要一个由服务器节点控制的预共享密钥。节点使用预共享密钥和由集群证书颁发机构签署的证书相互认证。

潜在问题

分布式注册表建立在点对点原则之上,并假设所有集群成员之间具有相等的特权和信任级别。如果这与您集群的安全态势不符,则不应启用嵌入式分布式注册表。

嵌入式注册表可能会提供节点本来无法访问的镜像。例如,如果您的某些镜像是从需要通过Kubernetes镜像拉取密钥或`registries.yaml`中的凭据进行身份验证的注册表、项目或储存库中拉取的,分布式注册表将允许其他节点共享这些镜像,而无需向上游注册表提供任何凭据。

具有将镜像推送到一个节点的containerd镜像存储的用户,可能会利用这一点来“毒害”其他集群节点的镜像,因为其他节点将信任该节点所宣传的标签,并在未与上游注册表核对的情况下使用它。如果镜像完整性很重要,您应该使用镜像摘要而不是标签,因为摘要无法以这种方式被毒害。

共享隔离或手动加载的镜像

镜像共享是基于源注册表进行控制的。通过隔离tar包预导入或使用`ctr`命令行工具直接加载到containerd的镜像存储中的镜像,如果被标记为来自启用镜像的注册表,则在节点之间共享。

请注意,镜像看似来自的上游注册表实际上不必存在或可达。例如,您可以将镜像标记为来自虚构的上游注册表,并将这些镜像导入到containerd的镜像存储中。只要该注册表在`registries.yaml`中列出,您就可以从所有集群成员中拉取这些镜像。

推送镜像

嵌入式注册表是只读的,无法直接使用 docker push 或其他与 OCI 注册表交互的常用工具进行推送。

可以通过运行`ctr -n k8s.io image pull`拉取镜像,或通过`docker save`创建的镜像归档文件,使用`ctr -n k8s.io image import`命令或预导入功能手动使镜像在嵌入式注册表中可用。请注意,在通过 ctr 管理镜像时,必须指定 k8s.io 名称空间,以便它们对 kubelet 可见。