现象
拉取镜像报 toomanyrequests: You have reached your pull rate limit;集群中多个节点同时出现 ImagePullBackOff;CI 任务失败但本机 docker pull 仍可成功;扩容或夜间重建后集中出现。
诊断
先复现并确认完整错误:
docker pull nginx:1.27
docker info | grep -iE 'username|registry|credential'
用户名为空表示匿名拉取;在共享 CI 中使用个人账号同样会消耗该账号配额。要直接测量配额,可向 registry 申请拉取令牌并读取响应头:
TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/nginx:pull" | jq -r .token)
curl -sI -H "Authorization: Bearer $TOKEN" \
https://registry-1.docker.io/v2/library/nginx/manifests/1.27 | grep -i ratelimit
ratelimit-remaining: 0 即可确认配额耗尽,与本地 Docker 守护进程无关。集群侧用 kubectl describe pod 查看事件,若多个节点同时报 429,通常是共享 NAT 出口或缺少 imagePullSecret。
修复
使用只读权限的机器账号令牌,配置为 Kubernetes imagePullSecret 与 CI Secret;在内网部署 pull-through cache 或 registry mirror;生产清单按 digest 固定镜像并复用缓存层;删除无意义的定时重新拉取。不要在 CI 中明文保存个人密码:
docker login registry-1.docker.io -u ci-puller --password-stdin < token.txt
docker pull nginx@sha256:0f0f0f...
验证
从节点与 CI 各拉取一次确认不再出现 429,registry 响应头中剩余配额明显大于 0;滚动发布后新 Pod 均应进入 Running 而不是 ImagePullBackOff。若仅单个节点失败,需单独检查其出口 IP,因为匿名配额按 IP 计算,一个 NAT 网关就可能拖累整个节点组。