为业务集群选择镜像仓库

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

您也可以将业务集群绑定到专属仓库。常见原因是距离:当 global 集群与业务集群位于不同地域时,通过该连接拉取每个镜像会很慢且不稳定。将仓库部署在靠近业务集群的位置,可以消除这种依赖。

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

选项

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

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

绑定涵盖的内容

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

以下内容不适用。每项内容都在其他位置进行配置,将集群指向专用仓库不会改变其中任何一项。

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

继承 global 集群的仓库

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

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

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

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

如果业务集群节点无法访问 global 集群上 Platform Built-in 仓库的地址,请参阅为内置仓库添加外部地址。

将业务集群绑定到其专用仓库

开始之前

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

第 1 步 — 准备仓库

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

以下两点决定了仓库必须包含的内容:

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

使用准备外部平台镜像仓库时采用的相同 Core Package 上传操作步骤,并将专用仓库作为目标地址。请参阅准备目标版本负载。

然后,从目标网络中的某个节点确认仓库能够响应:

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

这只能证明可达性和 TLS。请在你自己的仓库管理界面或 API 中确认已上传的仓库和标签。

/v2/ 部分仅属于 Registry HTTP API 请求。请勿将其 — 或 scheme — 包含在 Secret 或任何集群字段中。

WARNING

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

第 2 步 — 创建 RegistryCredential Secret

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

请使用编辑器编写凭证文件,而不是在 shell 提示符中输入值。Shell 会将整个命令(包括密码)记录到历史记录中;使用编辑器写入的文件不会留下这样的副本。

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

对于匿名仓库,只保留 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,此处这样设置是正确的。平台通过标签而不是类型识别仓库凭证,因此请在创建任何引用该 Secret 的集群之前应用以下两个标签:

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

请勿跳过 capi.cpaas.io/provider 标签。由于创建路径会直接读取这三个键,因此即使 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 上添加、更改或删除该标签都不会影响该集群。要将现有集群迁移到另一个仓库,必须重新创建集群。

第 4 步 — 验证绑定

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

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

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

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

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

最后,在业务集群上确认平台 Pod 从预期仓库拉取镜像:

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

平台组件镜像使用专用仓库。kubeadm 管理的镜像和 pause 镜像不会使用该仓库 — 请参阅绑定涵盖的内容。某些镜像仍解析到其他仓库是预期行为;但每个仍解析到旧仓库的平台组件镜像则不是。

操作现有绑定

任务是否支持操作
轮换仓库密码或切换到其他账户是修改 Secret,然后删除补丁文件。平台会将更改传播到引用该 Secret 的每个集群,无需重启集群。
更正凭证中的仓库地址是,但需谨慎以相同方式修改。它会重新指向引用此 Secret 的每个集群,因此请确认所有这些集群都能访问新地址,并且该地址包含每个集群版本所需的内容。
将现有集群迁移到其他仓库否引用在创建时即固定。请使用预期的引用重新创建集群。
在多个集群之间共享一个凭证是任意数量的集群都可以引用同一个 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 为空,或者 username 和 password 中只有一个被设置。设置 registry,并同时设置凭证对,或同时省略两者。
Secret 因不支持的格式消息而被拒绝cpaas.io/registry-credential-format 包含 direct 或 encrypted 之外的值,包括空值。对于自行编写的凭证,请使用 direct;或者移除该标签以使用旧版加密格式。
集群报告其控制平面已就绪,但平台 Pod 仍停留在 ImagePullBackOff专用仓库不包含此版本所需的有效载荷,或节点无法向其进行身份验证。从业务集群节点重复执行步骤 1,并确认 Secret 中的凭证。
删除凭证被拒绝仍有一个或多个集群引用该凭证。从错误信息中读取集群名称。在删除此凭证前,先删除这些集群,或使用其他凭证重新创建它们。
现有 Cluster 的新标签值未产生任何变化引用只在创建集群时读取。使用预期的引用重新创建集群。
已应用 Cluster,但平台集群记录始终未出现,且集群没有任何进展引用的 Secret 不存在于 cpaas-system 中,因此平台无法完成集群注册。Cluster 资源本身不会报告此错误。创建 Secret。平台会重试,因此 Secret 创建后集群即可继续运行。
kubectl apply --dry-run=server 接受了清单,但实际应用过程停滞服务器端 dry run 会在平台解析仓库引用之前返回,因此无法检测缺失的 Secret。不要依赖 dry run。先确认 Secret 存在:kubectl -n cpaas-system get secret <registry-credential-name>。
Secret 的值变更始终未传播到集群,或者即使集群仍在使用 Secret 也可以将其删除Secret 缺少 capi.cpaas.io/provider: registry-credential 标签。应用该标签。请参阅步骤 2。