为业务集群选择镜像 Registry

Alauda Container Platform 会在每个业务集群上安装并管理一组平台组件,包括 Kube-OVN 以及集群启动后交付的平台模块。这些组件的镜像来自镜像 Registry,默认情况下使用 global 集群所使用的同一 Registry。

你也可以将业务集群绑定到专用的 Registry。常见原因是距离:当 global 集群与业务集群位于不同地域时,通过该链路拉取每个平台镜像既缓慢又不稳定。使用靠近业务集群的 Registry 可以消除这种依赖。

请在创建集群之前做出决定。绑定关系仅在创建集群时读取,现有集群无法迁移到其他 Registry。

选项

选项配置内容使用时机
global 集群的 Registry无需配置。所有业务集群都会继承该 Registry。业务集群可以以可接受的吞吐量和可用性访问 global 集群使用的 Registry。
专用 Registrycpaas-system 中创建 RegistryCredential Secret,并通过 cpaas.io/registry-reference 标签从 Cluster 引用该 Secret。业务集群位于不同地域或网络分段,需要从靠近它的 Registry 拉取镜像。

这两个选项适用于每个基础设施提供商。默认选项无需任何配置,因此通过 Web UI 创建的集群也适用。专用 Registry 只能通过 YAML 进行配置:集群创建向导不提供可供选择的 Registry 凭证,因此当集群需要使用专用 Registry 时,请使用对应提供商集群创建指南中的 YAML 工作流。

绑定范围

该绑定适用于 Alauda Container Platform 在业务集群上安装和管理的平台组件,例如 Kube-OVN 以及交付到该集群的平台模块。

以下内容适用。每项内容都在其他位置配置,将集群指向专用 Registry 不会对其产生任何影响。

不包括的内容来源
kubeadm 管理的镜像:kube-apiserver、kube-controller-manager、kube-scheduler、etcd、CoreDNS 和 kube-proxyKubeadmControlPlane.spec.kubeadmConfigSpec.clusterConfiguration.imageRepository,每个提供商指南都会单独设置该字段。在 Huawei DCS 和裸金属环境中,该字段为 cloud.alauda.io/alauda,与预加载到操作系统镜像中的镜像保持一致。如果这些镜像必须来自其他 Registry,请更改该字段,并确保引用仍与节点本地的镜像相匹配。
pause(沙箱)镜像节点上的容器运行时配置。受支持的操作系统镜像会在 containerd 中设置该镜像;它不会通过任何 Kubernetes 对象解析。
裸金属操作系统镜像主机会在 elemental install 期间以及每次重新置备时,从平台 Registry 拉取 base-imagebase-image-iso,此时还不存在任何集群级绑定。
原生应用工作负载镜像每个工作负载声明的镜像引用和拉取 Secret。绑定仅配置平台镜像源。

继承 global 集群的 Registry

这是默认行为,无需进行配置。创建集群时不添加 cpaas.io/registry-reference 标签,该集群就会使用与 global 集群相同的 Registry。

地址和凭证如何传递到业务集群,取决于平台 Registry 是否需要身份验证:

  • 需要身份验证的 Registry — 平台会将地址和凭证存储在 global 集群上 cpaas-system 中的 public-registry-credential Secret 内。每个未显式引用 Registry 的业务集群都会从该 Secret 解析其 Registry。尽管名称如此,该 Secret 保存的是平台自身使用的 Registry,并不局限于面向互联网的 Registry。
  • 匿名 Registry — 不会填充凭证 Secret,平台组件会回退到安装时记录的平台级 Registry 地址。

在这两种情况下,operator 都无需针对每个集群进行配置。

将业务集群绑定到其专用 Registry

开始之前

  • 你可以在 global 集群的 cpaas-system 命名空间中创建 Secret。引用该凭证 Secret 的集群创建之前,该 Secret 必须已经存在。
  • 每个业务集群节点都可以访问专用 Registry;如果你希望从 global 集群进行验证,该集群也必须能够访问专用 Registry。
  • 专用 Registry 中已包含目标版本的 Alauda Container Platform Core,以及计划在该集群上安装的每个插件所需的软件包。请参阅准备 Registry

步骤 1 — 准备 Registry

平台不会将镜像复制到专用 Registry。请在创建集群之前自行填充该 Registry。

其中必须包含的内容取决于以下两点:

  • 始终需要目标版本的 Alauda Container Platform Core。其中的镜像和软件包必须与即将创建的集群的版本和 CPU 架构匹配。
  • 除 Core 之外的所有内容取决于你计划在该集群上安装哪些平台插件。只有你知道这组插件;平台不会推导该列表,也不会在之后补齐缺失内容。请将这些插件的软件包与 Core 一起上传。

使用准备外部平台镜像 Registry 时所用的相同 Core Package 上传操作步骤,并将专用 Registry 作为目标地址。

然后,从目标网络中的某个节点确认 Registry 可以响应:

export DEDICATED_REGISTRY="<registry-host>:<port>"
curl -sk "https://${DEDICATED_REGISTRY}/v2/" -o /dev/null -w '%{http_code}\n'

这只能证明网络可达性和 TLS 状态。请在 Registry 自有的管理界面或 API 中确认已上传的仓库和标签。

/v2/ 片段仅用于 Registry HTTP API 请求。请勿将其或协议添加到 Secret 或任何集群字段中。

WARNING

请在创建集群之前验证内容。绑定到不完整 Registry 的集群仍然可以启动——kubeadm 会从其他 Registry 解析控制平面,因此节点可以到达 Ready,集群看起来也很健康。缺失内容只会在之后暴露为卡在 ImagePullBackOff 中的平台 Pod。这比预先失败的 Registry 检查更难诊断。

步骤 2 — 创建 RegistryCredential Secret

global 集群的 cpaas-system 命名空间中创建 Secret。集群上的引用只携带名称,因此只会查询此命名空间;其他命名空间中同名的 Secret 会被忽略。

请使用编辑器编写凭证文件,而不要在 shell 提示符中输入这些值。Shell 会将包含密码在内的完整命令记录到历史记录中;使用编辑器写入的文件不会留下此类副本。

registry-credential.env
registry=<registry-host>:<port>
username=<username>
password=<password>

对于匿名 Registry,仅保留 registry 行,并省略另外两行。

限制文件权限,从文件创建 Secret,然后将其删除:

chmod 600 registry-credential.env

REGISTRY_CREDENTIAL_NAME="<registry-credential-name>"

kubectl create secret generic "${REGISTRY_CREDENTIAL_NAME}" \
  --namespace cpaas-system \
  --from-env-file=registry-credential.env

rm -f registry-credential.env
WARNING

请勿使用 kubectl apply 创建凭证 Secret。客户端 apply 会将其应用的清单(包括其中的每个值)存储在 Secret 自身的 kubectl.kubernetes.io/last-applied-configuration 注解中。kubectl create 不会写入此类注解。无论这些值是以 stringData 还是 base64 data 的形式写入,这一规则都适用;base64 是编码方式,并非保护措施。

文件中的每一行都是 key=value。请勿为值添加引号——kubectl 会将引号字符按字面值处理,因此 password="s3cret" 会将带引号的 "s3cret" 存储为值。值可以包含 = 和其他特殊字符;每行中只有第一个 = 用于分隔键和值。

Secret 创建时使用的类型为 Opaque,此处这样设置是正确的。平台通过标签而不是类型识别 Registry 凭证,因此请在创建任何引用该 Secret 的集群之前应用以下两个标签:

kubectl label secret "${REGISTRY_CREDENTIAL_NAME}" --namespace cpaas-system --overwrite \
  capi.cpaas.io/provider=registry-credential \
  cpaas.io/registry-credential-format=direct
必需说明
命名空间必须为 cpaas-system
capi.cpaas.io/provider 标签必须为 registry-credential
cpaas.io/registry-credential-format 标签是,本操作步骤需要对于你创建的凭证,将其设置为 direct。该标签本身对平台是可选的,但省略后会选择旧版加密格式;该格式要求上传身份验证文件,而不是使用下面的键。
registry仅使用 <host>[:<port>]。不得包含协议或路径。
usernamepassword一起设置同时设置两者,或都不设置。对于匿名 Registry,请省略两者。只设置其中一个会被拒绝。
WARNING

请勿跳过 capi.cpaas.io/provider 标签。即使 Secret 缺少该标签,仍然可以针对该 Secret 创建集群,因为创建路径会直接读取这三个键。但平台的其余部分不会再将该 Secret 识别为凭证:其值的后续更改永远不会传播到引用它的集群,并且在仍被使用时也不会受到删除保护。

步骤 3 — 创建集群时引用凭证

cpaas.io/registry-reference 标签添加到 Cluster 资源,并将 Secret 名称作为其值:

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: <cluster-name>
  namespace: cpaas-system
  labels:
    cpaas.io/registry-reference: <registry-credential-name>

按照提供商集群创建指南中的说明应用其余集群清单。

执行此操作时,Secret 必须已经存在。平台注册新集群时会解析该引用,并在此时从 cpaas-system 按名称读取 Secret。如果 Secret 不存在,注册将无法完成,集群也不会取得进展。这不是永久性失败——平台会持续重试,因此之后创建 Secret 即可解除集群阻塞——但在此期间不会发生任何变化,并且原因不会报告在 Cluster 资源本身上。请先创建 Secret。

WARNING

该标签仅在首次创建集群时读取。在现有 Cluster 上添加、更改或移除该标签,都不会对该集群产生任何影响。要将现有集群迁移到其他 Registry,必须重新创建集群。

步骤 4 — 验证绑定

global 集群上运行以下检查。确认引用已传递到平台集群记录:

export CLUSTER_NAME="<cluster-name>"
kubectl get cluster.platform.tkestack.io "${CLUSTER_NAME}" \
  -o jsonpath='{.metadata.labels.cpaas\.io/registry-reference}{"\n"}'

确认平台已从凭证中解析 Registry 地址。该注解由平台写入,请勿自行设置:

kubectl get cluster.platform.tkestack.io "${CLUSTER_NAME}" \
  -o jsonpath='{.metadata.annotations.cpaas\.io/registry-address}{"\n"}'

该值必须是 Secret 中的地址。如果为空或仍显示其他 Registry,请参阅故障排除

最后,在业务集群上确认平台 Pod 是否从预期的 Registry 拉取镜像:

kubectl --kubeconfig <workload-cluster-kubeconfig> get pods -A \
  -o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{end}' \
  | sort -u

平台组件镜像使用专用 Registry。kubeadm 管理的镜像以及 pause 镜像不会使用该 Registry——请参阅绑定范围。部分镜像仍解析到其他 Registry 属于预期情况;但所有平台组件镜像都解析到旧 Registry 则不符合预期。

操作现有绑定

任务是否支持方法
轮换 Registry 密码或切换到其他账户修改 Secret,然后移除补丁文件。平台会将更改传播到引用该 Secret 的每个集群,而无需重启集群。
更正凭证中的 Registry 地址是,但需谨慎以相同方式修改。它会将引用此 Secret 的每个集群重新指向新地址,因此请确认所有这些集群都能访问新地址,并且该地址包含其各自版本所需的负载。
将现有集群迁移到其他 Registry该引用在创建时即固定。请使用预期的引用重新创建集群。
在多个集群之间共享一个凭证任意数量的集群都可以引用同一个 Secret。一次更新即可应用到所有这些集群。不同的 Secret 互不影响。
删除凭证仅当未被引用时当仍有任何集群引用该 Secret 时,平台会拒绝删除操作,并在错误信息中列出这些集群。请先移除该引用:删除这些集群,或使用其他凭证重新创建它们。

请使用 kubectl patch 更新凭证,而不是使用 kubectl apply,原因与创建凭证时使用 kubectl create 相同:

registry-credential-patch.yaml
stringData:
  username: <new-username>
  password: <new-password>
chmod 600 registry-credential-patch.yaml

kubectl patch secret "${REGISTRY_CREDENTIAL_NAME}" --namespace cpaas-system \
  --type=merge --patch-file=registry-credential-patch.yaml

rm -f registry-credential-patch.yaml

补丁中的 stringData 会替换 data 中相应的键。如果此处的值包含 YAML 元字符,请将其引起来——不同于创建时使用的 key=value 文件,此文件是 YAML。

故障排除

症状可能原因操作
平台集群记录中的 cpaas.io/registry-address 仍为空Secret 不存在、位于 cpaas-system 之外,或缺少 capi.cpaas.io/provider: registry-credential 标签。确认名称、命名空间以及这两个标签。
创建或更新时 Secret 被拒绝registry 为空,或者 usernamepassword 中只有一个被设置。设置 registry,并同时设置凭证对,或将两者都留空。
Secret 因不支持的格式消息而被拒绝cpaas.io/registry-credential-format 携带的值不是 directencrypted,包括空值。对于自行创建的凭证,使用 direct;或者移除该标签以使用旧版加密格式。
集群报告其控制平面已就绪,但平台 Pod 仍停留在 ImagePullBackOff专用 Registry 不包含此版本的负载,或者节点无法向其进行身份验证。从业务集群节点重复执行 步骤 1,并确认 Secret 中的凭证。
删除凭证被拒绝仍有一个或多个集群引用该凭证。从错误信息中读取集群名称。在删除此凭证之前,删除这些集群,或使用其他凭证重新创建它们。
现有 Cluster 的新标签值未产生任何变化该引用仅在创建集群时读取。使用预期的引用重新创建集群。
已应用 Cluster,但始终没有出现平台集群记录,且集群没有任何进展cpaas-system 中不存在被引用的 Secret,因此平台无法完成集群注册。Cluster 资源本身不会对此报告错误。创建 Secret。平台会重试,因此 Secret 存在后集群即可继续。
kubectl apply --dry-run=server 接受了清单,但实际应用停滞服务器端试运行会在平台解析 Registry 引用之前返回,因此无法检测缺少的 Secret。不要依赖试运行来完成此检查。先确认 Secret 存在:kubectl -n cpaas-system get secret <registry-credential-name>
Secret 的值更改始终无法传播到集群,或者在集群仍使用该 Secret 时可以将其删除Secret 缺少 capi.cpaas.io/provider: registry-credential 标签。应用该标签。请参阅步骤 2