记一次镜像仓库凭证相关问题分析
本文永久链接: https://www.xtplayer.cn/kubernetes/docker-credentials-secret/
问题现象
用户反馈说在 Rancher UI 部署应用时, 在以下几种凭证均未使用的情况下,也依然可以下载私有仓库中的镜像。
即使未配置集群镜像仓库
也没有配置项目中的镜像仓库凭证
主机上也执行了 docker logout xxxx 退出了所有已登录的镜像仓库。
问题分析
Dcoker 本身是 server/client 架构,根据 Docker 私有镜像仓库拉取镜像时的认证机制,client 需要先登录仓库,然后在拉取镜像时传递认证 token 去鉴权。
通过 Rancher UI 部署应用时,容器创建大概有以下几个步骤:
- Rancher server 发送指令给 Rancher agent;
- Rancher agent 再通过 K8S API 接口发送给 API SERVER;
- API SERVER 经过处理后再把请求发送给 kubelet;
- kubelet 再通过 Docker API 发送指令给 Docker;
- 最后 Docker 去执行创建容器的动作。
所以这个时候 kubelet 可以看做是 Docker server 的一个客户端,对于下载私有仓库的镜像,kubelet 则需要携带对应的认证 token 去做鉴权。
因为每个 docker client 都需要登录,并在下载镜像时候传递认证 token 镜像鉴权。所以主机上 docker cli 有没有登录镜像仓库,并不会影响 kubelet 下载镜像。
在 K8S 创建 workload 时,会通过 imagePullSecrets 字段传递认证 token,kubelet 拿着这个 token 访问私有镜像仓库即可正常下载镜像。
根据以上原理,查看 workload YAML 并没有发现 imagePullSecrets 相关字段,说明创建 workload 时并没有传递 token 给 kubelet。
查看 kubelet 日志
根据以上分析,可以排除 Rancher UI 传递 token 的因素,那么问题基本可以确定出自 kubelet 本身。
在 Rancher 创建的 K8S 环境中,执行 docker logs kubelet –tail 100 -f 查看 kubelet 的运行日志。在日志中发现了这样的日志
复制
Refreshing cache for provider: *credentialprovider.defaultDockerConfigProvider |
出现以上日志说明了 kubelet 中缓存了镜像仓库凭证,所以即使 Rancher UI 未配置镜像仓库凭据,也依然可以正常拉取镜像。
kubelet 查找凭据顺序
- kubelet 拉取 Pod 镜像时,首先使用 Pod 中指定的 ImagePullSecrets。
- 如果 Pod 没有指定 ImagePullSecrets,则依次在
–root-dir(默认是/var/lib/kubelet)
、$HOME/.docker/
、/.docker/
中查找config.json
文件。注意:因为 Rancher K8S 中 kubelet 是以容器方式运行,那么这里的路径指的是容器中的路径。不过/var/lib/kubelet
默认是映射到主机的/var/lib/kubelet
- 如果没有找到 config.json,再按照同样的顺序查找
.dockercfg
文件。
解决方法
根据 kubelet 查找凭据的顺序,在 /var/lib/kubelet
中查询到 config.json
文件。这个是一个 json 格式的文件,里面可能包含了多个镜像仓库的认证信息,根据需求删除不需要的认证信息即可。