向 ServiceAccount 添加 ImagePullSecrets

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

创建 ImagePullSecret

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

向 ServiceAccount 添加 ImagePullSecret

如果你的原生应用的 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 proxy 进行认证。Connector 会避免将原始仓库的长期凭证分发到工作负载命名空间,但这并不意味着工作负载不需要 Kubernetes image pull Secret。Connector proxy Secret 使用一个有权访问 Connector 的 ServiceAccount 令牌,而不是原始仓库密码。

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

前提条件

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

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

创建 Connector proxy Secret

获取 Connector proxy 地址,并为工作负载的 ServiceAccount 创建一个令牌:

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>

创建 image pull 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 proxy,而不是原始仓库。如果 .status.proxy.httpAddress.url 包含 Connector 路径,请使用 proxy 主机和端口作为 registry server。该命令会创建一个类型为 kubernetes.io/dockerconfigjson 的 Secret。

令牌必须来自具有访问 Connector 权限的 ServiceAccount。默认情况下,在未指定获批时长的情况下创建的令牌有效期约为一小时。请根据组织的安全策略选择 --duration,并在令牌过期前轮换或重新创建 Secret。不要将手动复制的令牌视为永久凭证或轮换机制。

引用 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 的容器和 init container 的映射。
  2. 检查 Pod 选择的 image pull Secret,或其从 ServiceAccount 继承的 Secret。
  3. 检查实际 Pod 镜像是否已重写为 Connector proxy 地址。
  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 镜像仍然指向原始仓库,请首先检查 Connector 注解、Secret 的命名空间和类型、ServiceAccount 关联以及令牌有效性。针对原始 HTTP registry 的 HTTPS 错误,可能表明工作负载没有进入 Connector proxy 路径;不要通过永久将原始 registry 允许为 insecure registry 来规避该问题。