使用注册表镜像创建集群

本页面介绍如何使用从注册表镜像(而非从 gcr.io 等公共注册表)中拉取的映像创建集群。

注册表镜像是公共注册表的本地副本,它会复制或镜像公共注册表的文件结构。例如,假设本地注册表镜像的路径为 172.18.0.20:5000。当 containerd 遇到拉取 gcr.io/kubernetes-e2e-test-images/nautilus:1.0 等映像的请求时,containerd 会尝试从位于以下路径的本地注册表(而非从 gcr.io)中拉取该映像:172.18.0.20:5000/kubernetes-e2e-test-images/nautilus:1.0。如果该映像不在此本地注册表路径中,则系统会自动从公共注册表 gcr.io 中拉取该映像。

使用注册表镜像具有以下优势:

  • 保护您免受公共注册表服务中断的影响。
  • 加速 Pod 创建。
  • 允许您执行自己的漏洞扫描。
  • 避免公共注册表对发出命令的频率施加限制。

准备工作

  • 您必须在网络中设置容器注册表服务器。
  • 如果您的注册表服务器运行专用 TLS 证书,则您必须拥有证书授权机构 (CA) 文件。
  • 如果您的注册表服务器需要身份验证,则您必须具有适当的登录凭据或 Docker 配置文件。
  • 如需使用注册表镜像,您必须将容器运行时设置为 containerd

下载 Google Distributed Cloud 所需的所有映像

下载页面下载最新版本的 bmctl 工具和映像软件包。

将容器映像上传到您的注册表服务器

通过运行以下命令将映像软件包中的映像上传到您的注册表服务器:

[HTTPS_PROXY=http://PROXY_IP:PORT] ./bmctl push images \
    --source=./bmpackages_VERSION.tar.xz \
    --private-registry=REGISTRY_IP:PORT \
    [--cacert=CERT_PATH] \
    [--need-credential=false]

请替换以下内容:

  • PROXY_IP:PORT 替换为代理的 IP 地址和端口(如果您需要使用代理来将映像从工作站上传到注册表服务器)。
  • VERSION 替换为从下载页面下载的映像软件包的版本。
  • REGISTRY_IP:PORT 替换为专用注册表服务器的 IP 地址和端口。
  • CERT_PATH 替换为 CA 证书文件的路径(如果您的注册表服务器使用专用 TLS 证书)。

出现提示时,输入您的用户名和密码,或选择 Docker 配置文件。如果您的注册表服务器不需要凭据,请指定 --need-credential=false

如需详细了解 bmctl push images 命令,请运行以下命令:

bmctl push images --help

使用您自己的命名空间

如果您想要在注册表服务器中使用您自己的命名空间(而非根命名空间),则可在 registryMirrors.endpoint 中提供您的私有注册表的 API 端点,以便 containerd 可以从此命名空间执行拉取。端点通常采用 <REGISTRY_IP:PORT>/v2/<NAMESPACE> 格式。请参阅私有注册表的用户指南,以了解特定详细信息。

例如,如果您只拥有 172.18.0.20:5000/test-namespace/ 的访问权限,则可以使用以下命令上传命名空间 test-namespace 下的所有映像:

./bmctl push images \
    --source=./bmpackages_VERSION.tar.xz \
    --private-registry=172.18.0.20:5000/test-namespace
    --username=<USERNAME>
    --password=<PASSWORD>
    --cacert <path/to/cert.crt>

然后,在集群配置文件中,添加以下内容,以便 containerd 从该命名空间执行拉取:

registryMirrors:
  - endpoint: https://172.18.0.20:5000/v2/test-namespace

从注册表镜像创建集群

以下示例集群配置文件会指定从端点为 https://172.18.0.20:5000 的本地注册表镜像中拉取映像。以下部分会介绍在此配置文件开头出现的一些字段。

# Sample cluster config with registry mirror:
---
gcrKeyPath: /bmctl/bmctl-workspace/.sa-keys/my-gcp-project-anthos-baremetal-gcr.json
sshPrivateKeyPath: /root/ssh-key/id_rsa
registryMirrors:
  - endpoint: https://172.18.0.20:5000
    caCertPath: /root/ca.crt
    pullCredentialConfigPath: /root/.docker/config.json
    hosts:
      - somehost.io
      - otherhost.io
---
apiVersion: v1
kind: Namespace
metadata:
  name: cluster-admin1
---
apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
  name: admin1
  namespace: cluster-admin1
spec:
  nodeConfig:
    containerRuntime: containerd
...

hosts 字段

containerd 会检查集群配置文件的 hosts 部分,以发现具有本地镜像的主机。在示例配置文件中,hosts 部分中列出的公共注册表是 somehost.iootherhost.io。由于这些公共注册表显示在 hosts 部分中,因此 containerd 在遇到来自 somehost.iootherhost.io 的映像拉取请求时,会先检查私有注册表镜像。

例如,假设 containerd 收到对 somehost.io/kubernetes-e2e-test-images/nautilus:1.0 的拉取命令。由于 somehost.io 在集群配置文件的 hosts 部分中被列作主机之一,因此 containerd 会在本地注册表镜像中查找 kubernetes-e2e-test-images/nautilus:1.0 映像。如果 somehost.io 未列在 hosts 部分,则 containerd 将不知道存在 somehost.io 的本地镜像。在这种情况下,containerd 不会检查映像的镜像,而只是从 somehost.io 公共注册表中拉取映像。

请注意,默认情况下,Google Distributed Cloud 会自动镜像 gcr.io 中的映像,因此您无需在 hosts 部分中将 gcr.io 列为主机。

gcrKeyPath 字段

如果您希望 Google Distributed Cloud 自动使用 Container Registry (gcr.io) 拉取未出现在本地注册表中的映像,则必须指定 Container Registry 服务帐号密钥的路径。Google Distributed Cloud 没有为其他公共注册表提供密钥的机制。

如果您不打算使用在本地注册表中未显示映像时从 gcr.io 中拉取映像的功能,则无需将 gcrKeyPath 添加到集群配置文件。

caCertPath 字段

如果您的仓库需要私有传输层安全协议 (TLS) 证书,则此字段会使用服务器根 CA 证书文件的路径。此证书文件应位于管理员工作站上,即运行 bmctl 命令的机器。如果您的仓库不需要私有 TLS 证书,则可以将 caCertPath 字段留空。

pullCredentialConfigPath 字段

如果您的注册表服务器不需要身份验证 Docker 配置文件,则可以将 pullCredentialConfigPath 字段留空。 请注意,这是运行 bmctl 命令的机器上配置文件的路径。

从注册表镜像中创建用户集群

如果用户的管理员集群已配置为自动从注册表镜像中拉取映像,则用户集群不会自动从注册表镜像中拉取映像。如需让用户集群从注册表镜像中拉取映像,您需要按照从注册表镜像中创建集群中的说明单独配置用户集群。

更新注册表镜像端点、证书和拉取凭据

如需更新注册表镜像端点、证书或拉取凭据,请执行以下操作:

  1. 在集群配置文件中,更新端点、CA 证书文件和拉取凭据配置文件路径。

  2. 通过运行以下命令来应用更改:

    bmctl update cluster -c CLUSTER_NAME --kubeconfig=ADMIN_KUBECONFIG
    

    请替换以下内容:

    • CLUSTER_NAME 替换为要更新的集群的名称。
    • ADMIN_KUBECONFIG 替换为其管理员集群的配置文件的路径。

验证映像是否是从注册表镜像中拉取的

本部分介绍可用于验证 containerd 是否从本地注册表镜像而非公共注册表中拉取映像的两种方法。

方法 1:比较代码库摘要

此方法涉及比较代码库摘要以确定是否从注册表镜像中拉取了映像。

请注意,注册表具有称为代码库摘要的唯一标识符,而映像具有名为容器映像摘要的唯一标识符。两个相同的映像具有相同的容器映像摘要,即使这些映像来自不同的注册表亦如此。但是,如果映像来自不同的注册表,则它们具有不同的代码库摘要。

  1. 使用 SSH 登录集群节点。

  2. 选择要验证其来源的映像。

  3. 通过运行以下命令从您使用的公共注册表中拉取映像:

    crictl pull PUBLIC_ENDPOINT
    

    PUBLIC_ENDPOINT 替换为公共注册表中的映像路径。例如:gcr.io/anthos-baremetal-release/kube-rbac-proxy:v0.6.0-gke.0

  4. 通过运行以下命令从注册表镜像中拉取同一映像:

    crictl pull MIRROR_ENDPOINT
    

    MIRROR_ENDPOINT 替换为注册表镜像中的映像路径。例如:10.168.15.224:5007/test-namespace/anthos-baremetal-release/kube-rbac-proxy:v0.6.0-gke.0

  5. 运行以下命令,以显示您在上述步骤中拉取的两个映像的代码库摘要:

    crictl inspecti PUBLIC_OR_MIRROR_ENDPOINT | grep -A 3 repoDigests
    

    PUBLIC_OR_MIRROR_ENDPOINT 替换为映像的公共端点或映像的注册表镜像端点。两者都可以,因为 crictl inspecti 命令会查看传递给它的参数的容器映像摘要。由于公共注册表中的映像与注册表镜像中的映像相同,因此它们具有相同的容器映像摘要。

    此命令的输出可能如下所示:

     "repoDigests": [
       "gcr.io/anthos-baremetal-release/kube-rbac-proxy@sha256:27be66fb9140d83c4af8794a234b998c90e844e3414108ce72db603f4f6ea0b3",
       "10.168.15.224:5007/test-namespace/anthos-baremetal-release/kube-rbac-proxy@sha256:27be66fb9140d83c4af8794a234b998c90e844e3414108ce72db603f4f6ea0b3"
     ],
    
  6. 比较上一步输出中以粗体显示的代码库摘要。如果摘要相同,则集群中的节点将从注册表镜像中拉取。否则,您的集群节点会从公共注册表中拉取映像。

方法 2:检查 config.toml 文件

可以通过检查 config.toml 文件的内容来确定 containerd 是否从本地注册表拉取映像,如以下步骤所示:

  1. 登录节点并检查以下文件的内容:/etc/containerd/config.toml

  2. 检查 config.toml 文件的 plugins."io.containerd.grpc.v1.cri".registry.mirrors 部分,查看您的注册表服务器是否列在 endpoint 字段中。以下摘录自示例 config.toml 文件,其中 endpoint 字段以粗体显示:

version = 2
root = "/var/lib/containerd"
state = "/run/containerd"
...
[plugins."io.containerd.grpc.v1.cri".registry]
  [plugins."io.containerd.grpc.v1.cri".registry.configs]
    [plugins."io.containerd.grpc.v1.cri".registry.configs."gcr.io"]
      [plugins."io.containerd.grpc.v1.cri".registry.configs."privateregistry2.io".tls]
        ca_file = '/etc/containerd/certs.d/privateregistry2.io/ca.crt'
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]
      endpoint = ["http://privateregistry.io", "http://privateregistry2.io"]
...

如果您的注册表镜像显示在 endpoint 字段中,则该节点会从注册表镜像中拉取映像,而不是从公共注册表中拉取映像。