CRI-O镜像镜像配置下imagePullSecrets失效,拉取私有镜像需认证
环境信息
- Kubernetes版本:v1.26.4
- CRI-O版本:v1.25.2
- 私有镜像仓库:采用docker distribution代理模式搭建,带基础认证
配置情况
CRI-O的mirror.conf配置:
[[registry]] prefix = private.registry location = mirror.registry
Pod配置:
apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: pod name: pod namespace: my-ns spec: containers: - image: private.registry/image:tag name: pod imagePullSecrets: - name: registry-secret
Secret配置:
apiVersion: v1 data: .dockerconfigjson: base64-encoded-auths kind: Secret metadata: name: registry-secret namespace: my-ns type: kubernetes.io/dockerconfigjson
现象
- 执行
crictl pull --creds private.registry/image:tag可正常拉取镜像 - 创建Pod后出现认证失败报错:
Failed to pull image "private.registry/image:tag": rpc error: code = Unknown desc = reading manifest tag in mirror.registry/image: unauthorized: authentication required
- 若将
mirror.conf中prefix与location设为相同值则无问题,说明Secret认证信息正确:[[registry]] prefix = mirror.registry location = mirror.registry
疑问
为何prefix与location不同时,imagePullSecrets无法生效?
核心原因
Kubernetes的imagePullSecrets是基于镜像中声明的仓库地址(即private.registry)来匹配认证信息的,但CRI-O在使用镜像配置时,会将请求转发到location指定的mirror.registry,此时CRI-O不会自动把针对private.registry的认证信息传递给mirror.registry。
当你用crictl pull --creds时,是直接指定了要拉取的镜像地址,CRI-O会把认证信息同时应用到prefix和对应的mirror仓库;但通过Kubernetes调度Pod时,Kubernetes只把对应private.registry的认证信息传给CRI-O,CRI-O转发请求到mirror.registry时,没有对应的认证信息可用,导致认证失败。
解决方案
方案一:修改CRI-O的mirror.conf,添加mirror仓库的认证
在mirror.conf中为mirror.registry添加认证配置,示例如下:
[[registry]] prefix = private.registry location = mirror.registry [[registry]] prefix = mirror.registry location = mirror.registry auth = {username = "your-username", password = "your-password"}
也可以引用节点上的认证文件:
[[registry]] prefix = private.registry location = mirror.registry [[registry]] prefix = mirror.registry location = mirror.registry auth_file = "/etc/crio/auth/mirror-registry-auth.json"
方案二:更新Secret中的dockerconfigjson,包含两个仓库的认证
确保.dockerconfigjson中同时包含private.registry和mirror.registry的认证信息,示例JSON结构如下:
{ "auths": { "private.registry": { "auth": "base64-encoded-user-pass" }, "mirror.registry": { "auth": "base64-encoded-user-pass" } } }
重新生成Secret并替换原有的registry-secret即可。
内容的提问来源于stack exchange,提问作者Dmitry Paniklov

