如何解码拉取 Secret
- 把以下任意一种内容粘贴到输入框:
kubectl get secret regcred -o yaml的输出- 只有
.dockerconfigjson的 Base64 值 - JSON 本身,例如你的
~/.docker/config.json
- 最先列出的是镜像仓库凭据:镜像仓库、用户名、密码,以及拆分为用户名和密码的
auth值。 - 如果要创建 Secret,打开 生成拉取 Secret,填写 镜像仓库、用户名、密码,以及可选的 电子邮件。结果与
kubectl create secret docker-registry写出的 Secret 相同。
拉取 Secret 中的双层 Base64
拉取 Secret 是在 Base64 里又套了一层 Base64,所以手动解码需要两步。
apiVersion: v1
kind: Secret
metadata:
name: regcred
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: eyJhdXRocyI6eyJyZWdpc3RyeS5leGFtcGxlLmNvbSI6eyJ1c2VybmFtZSI6ImNpLWJvdCIsInBhc3N3b3JkIjoicHVsbC1vbmx5LXRva2VuIiwiYXV0aCI6Ilkya3RZbTkwT25CMWJHd3RiMjVzZVMxMGIydGxiZz09In19fQ==
第一层是 Secret 的值,解码后得到 Docker 配置 JSON:
{"auths":{"registry.example.com":{"username":"ci-bot","password":"pull-only-token","auth":"Y2ktYm90OnB1bGwtb25seS10b2tlbg=="}}}
第二层是 auth,解码后得到 ci-bot:pull-only-token。由 kubectl create secret docker-registry 创建的 .dockerconfigjson 值以 eyJhdXRocyI6 开头,即 {"auths": 的 Base64,所以在日志和清单文件中很容易认出这类字符串。
你可能遇到的格式
| 结构 | 来源 |
|---|---|
{"auths": {"host": {...}}} | .dockerconfigjson、当前版本的 ~/.docker/config.json |
{"host": {"auth": "...", "email": "..."}} | 旧版 .dockercfg Secret(kubernetes.io/dockercfg) |
主机为 "https://index.docker.io/v1/" | Docker Hub |
用 identitytoken 代替密码 | 在 docker login 后发放 OAuth 刷新令牌的镜像仓库 |
这里两种 Secret 类型都能解码。旧版 .dockercfg 没有外层的 auths,所以为一种格式编写的脚本在另一种格式中会悄无声息地什么也找不到。
在 shell 中解码
kubectl get secret regcred -o jsonpath='{.data.\.dockerconfigjson}' | base64 --decode | jq .
kubectl get secret regcred -o jsonpath='{.data.\.dockerconfigjson}' | base64 --decode \
| jq -r '.auths | to_entries[] | "\(.key) \(.value.auth | @base64d)"'
第二条命令为每个镜像仓库输出一行 registry user:password。auth 值的格式与 Basic Auth 请求头相同,所以 Basic Auth 解码器 也能读取它。
拉取 Secret 为什么会失败
- 镜像仓库键名不对。
auths中的主机必须与镜像引用相匹配:ghcr.io/org/app需要ghcr.io,Docker Hub 镜像需要https://index.docker.io/v1/。 - Secret 在另一个命名空间中。
imagePullSecrets只会在 Pod 自己的命名空间中查找 Secret。 - 令牌已过期。 有些镜像仓库发放的是短期密码,例如 Amazon ECR 的令牌有效期为 12 小时。昨天还能用的 Secret,今天就可能导致
ImagePullBackOff。 - 手工编写的 JSON。 复制密码时带上了末尾的换行符或空格,或者
auth值是由错误的字符串编码而来,都会悄无声息地失败。请把解码后的auth与用户名和密码字段进行比较,或者用kubectl create secret docker-registry重新创建 Secret。
任何能读取该 Secret 的人都能使用这个账号,因为 Base64 什么也隐藏不了。请为拉取 Secret 使用只读的镜像仓库令牌。
常见问题
怎么解码 imagePullSecret?
把 kubectl get secret regcred -o yaml 的输出粘贴到上方。在 shell 中,kubectl get secret regcred -o jsonpath='{.data.\.dockerconfigjson}' | base64 --decode 会输出 JSON,而其中的 auth 字段又是一层 Base64。
config.json 中的 auth 字段是什么?
它是 username:password 的 Base64,格式与 HTTP Basic Authorization 请求头相同。Y2ktYm90OnB1bGwtb25seS10b2tlbg== 解码后是 ci-bot:pull-only-token。
为什么我的 ~/.docker/config.json 中 auths 条目是空的?
设置了 credsStore 或 credHelpers 时,Docker 会把密码存放在凭据助手中,例如系统钥匙串。这时文件中每个镜像仓库只有 {},没有可解码的内容。