本文永久链接: https://www.xtplayer.cn/kubernetes/docker-credentials-secret/

问题现象

用户反馈说在 Rancher UI 部署应用时, 在以下几种凭证均未使用的情况下,也依然可以下载私有仓库中的镜像。

即使未配置集群镜像仓库

也没有配置项目中的镜像仓库凭证

主机上也执行了 docker logout xxxx 退出了所有已登录的镜像仓库。

问题分析

Dcoker 本身是 server/client 架构,根据 Docker 私有镜像仓库拉取镜像时的认证机制,client 需要先登录仓库,然后在拉取镜像时传递认证 token 去鉴权。

通过 Rancher UI 部署应用时,容器创建大概有以下几个步骤:

  1. Rancher server 发送指令给 Rancher agent;
  2. Rancher agent 再通过 K8S API 接口发送给 API SERVER;
  3. API SERVER 经过处理后再把请求发送给 kubelet;
  4. kubelet 再通过 Docker API 发送指令给 Docker;
  5. 最后 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 格式的文件,里面可能包含了多个镜像仓库的认证信息,根据需求删除不需要的认证信息即可。