将 ImagePullSecrets 添加到 ServiceAccount

如果镜像仓库需要身份验证,你需要将相应的 ImagePullSecrets 添加到应用所使用的 ServiceAccount 中。这样可以确保应用能够成功从私有仓库拉取镜像。

创建 ImagePullSecret

要创建 ImagePullSecret,请参阅 创建 Secret 了解创建 ImagePullSecret 的详细步骤。

将 ImagePullSecret 添加到 ServiceAccount

如果你的应用的 Pod 使用 ServiceAccount example,你可以将 ImagePullSecret 添加到应用所在命名空间中的 example ServiceAccount。

使用 patch 命令编辑 ServiceAccount example:

kubectl patch serviceaccount example -p '{"imagePullSecrets": [{"name": "my-registry-creds"}]}' -n <namespace>

将 <namespace> 替换为你的应用所在的命名空间,并将 my-registry-creds 替换为你创建的 ImagePullSecret 名称。

你可以通过描述该 ServiceAccount 来验证 ImagePullSecret 是否已添加:

kubectl describe serviceaccount example -n <namespace>
Name:                example
Namespace:           <namespace>
Labels:              <none>
Annotations:         <none>
Image pull secrets:  my-registry-creds
Mountable secrets:   <none>
Tokens:              <none>
Events:              <none>

你应该会看到 Image pull secrets 部分显示已添加的 secret。

NOTE

注意:如果你的 Pod 未指定 ServiceAccount,则默认会使用该命名空间中的 default ServiceAccount。你也可以用同样的方式将 ImagePullSecret 添加到 default ServiceAccount。

验证新 Pod 已设置 imagePullSecrets

当你创建一个使用 ServiceAccount example 的新 Pod 时,Pod 会自动使用 ServiceAccount 中指定的 ImagePullSecrets。

你可以通过运行以下命令进行验证:

kubectl get pod <pod-name> -n <namespace> -o=jsonpath='{.spec.imagePullSecrets}'

在 OCI Connector 中使用 ImagePullSecret

当通过 OCI Connector 选择工作负载镜像时,工作负载仍然需要一个镜像拉取 Secret 来对 Connector 代理进行身份验证。Connector 避免将原始 registry 的长期凭证分发到工作负载命名空间,但这并不意味着工作负载不需要 Kubernetes 镜像拉取 Secret。Connector 代理 Secret 使用的是一个被授权访问 Connector 的 ServiceAccount token,而不是原始 registry 密码。

你可以直接在 Pod 模板中引用该 Secret,或者将其附加到工作负载所使用的 ServiceAccount 上。任一方式都可以。

前提条件

在创建 Secret 之前,请确认以下事项:

  • 已安装 Alauda DevOps Connectors,Connector 处于 Ready 状态,并且已启用 enable-pod-image-pull-via-connector。
  • OCI 代理已通过主机端口或 Ingress 暴露,并且每个目标节点的 container runtime 都可以访问该代理地址。如果代理使用 HTTP,则 runtime 必须允许该代理地址。
  • 用于创建 token 的 ServiceAccount 已获授权访问 Connector。
  • Secret 已创建在与工作负载相同的 namespace 中。

创建 Connector 代理 Secret

获取 Connector 代理地址,并为工作负载的 ServiceAccount 创建 token:

kubectl get connector <connector-name> -n <connector-namespace> \
  -o jsonpath='{.status.proxy.httpAddress.url}'

kubectl create token <service-account> \
  -n <workload-namespace> \
  --duration=<approved-duration>

创建镜像拉取 Secret:

kubectl create secret docker-registry <connector-pull-secret> \
  --docker-server='<connector-proxy-host-and-port>' \
  --docker-username='u' \
  --docker-password='<service-account-token>' \
  --docker-email='<email>' \
  -n <workload-namespace>

--docker-server 的值必须指向 Connector 代理,而不是原始 registry。如果 .status.proxy.httpAddress.url 包含 Connector 路径,请使用代理的 host 和 port 作为 registry server。该命令会创建一个类型为 kubernetes.io/dockerconfigjson 的 Secret。

token 必须来自一个有权限访问 Connector 的 ServiceAccount。未指定经批准持续时间创建的 token,默认有效期约为一小时。请根据你所在组织的安全策略选择 --duration,并在 token 过期前轮换或重新创建 Secret。不要将手动复制的 token 视为永久凭证或轮换机制。

引用该 Secret

要直接在 Pod 模板中引用该 Secret,请配置:

spec:
  imagePullSecrets:
    - name: <connector-pull-secret>

或者,将该 Secret 附加到工作负载所使用的 ServiceAccount:

kubectl patch serviceaccount <service-account> \
  -n <workload-namespace> \
  -p '{"imagePullSecrets":[{"name":"<connector-pull-secret>"}]}'

Pod 模板引用和 ServiceAccount 继承是两种可选的有效来源。你无需同时配置两者。

验证与排障

创建或更新工作负载后,请按以下顺序验证 Connector 路径:

  1. 检查工作负载 Pod 模板是否具有期望的 connectors.<baseDomain>/connectors 注解,并且包含每个使用 OCI Connector 的 container 和 init container 的映射。
  2. 检查 Pod 选择的,或从其 ServiceAccount 继承的镜像拉取 Secret。
  3. 检查实际 Pod 镜像是否已重写为 Connector 代理地址。
  4. 检查 Pod 是否到达 Running 状态(对于已完成的 Job,则为 Completed),然后查看其 Events。

运行以下命令:

kubectl get serviceaccount <service-account> -n <workload-namespace> -o yaml
kubectl get pod <pod-name> -n <workload-namespace> -o jsonpath='{.spec.imagePullSecrets}'
kubectl get pod <pod-name> -n <workload-namespace> -o jsonpath='{.spec.containers[*].image}'
kubectl get pod <pod-name> -n <workload-namespace>
kubectl describe pod <pod-name> -n <workload-namespace>

如果实际 Pod 镜像仍然指向原始 registry,请先检查 Connector 注解、Secret 的 namespace 和类型、ServiceAccount 关联以及 token 有效性。原始 HTTP registry 的 HTTPS 错误可能表明工作负载没有进入 Connector 代理路径;不要通过永久允许原始 registry 作为不安全 registry 来规避此问题。