K3S配置GCR镜像仓库执行crictl pull拉取镜像时报401未授权错误
问题原因
401 Unauthorized报错核心是两个配置疏漏:
- GCR的镜像实际存储在
storage.googleapis.com域名下,containerd拉取镜像过程中会向该域名发起鉴权请求,现有配置仅为gcr.io配置了认证信息,请求发到存储后端时没有携带有效凭证,直接被鉴权拦截。 - 不少用户写完配置后没有重启K3s服务,
registries.yaml的配置根本没有被containerd加载;另外如果YAML文件里多行密钥的缩进不对,会导致service account的私钥格式被破坏,签名校验失败也会返回401。
日志开头的WARN是crictl没有指定固定runtime endpoint的弃用提示,和本次拉取失败无关。
修复方案
- 修改
/etc/rancher/k3s/registries.yaml配置,为gcr.io和storage.googleapis.com两个域名都配置相同的认证信息,严格注意YAML缩进(password块下的JSON内容要比password行多缩进2个空格,不要随意改动私钥原文的换行),参考配置如下:
mirrors: gcr.io: endpoint: - "https://gcr.io" configs: "gcr.io": auth: username: _json_key password: | { "type": "service_account", "project_id": "my-project-id", "private_key_id": "4c97dc266e4b303fc45dc70561e383ae92ccccae", "private_key": "-----BEGIN PRIVATE KEY-----\nXXXIEvAIBADANB........\n-----END PRIVATE KEY-----\n", "client_email": "build@my-project-id.iam.gserviceaccount.com", "client_id": "108884742074047075648", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/build%40my-project-id.iam.gserviceaccount.com" } "storage.googleapis.com": auth: username: _json_key password: | { "type": "service_account", "project_id": "my-project-id", "private_key_id": "4c97dc266e4b303fc45dc70561e383ae92ccccae", "private_key": "-----BEGIN PRIVATE KEY-----\nXXXIEvAIBADANB........\n-----END PRIVATE KEY-----\n", "client_email": "build@my-project-id.iam.gserviceaccount.com", "client_id": "108884742074047075648", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/build%40my-project-id.iam.gserviceaccount.com" }
- 保存配置后,重启K3s服务加载新配置,server节点执行:
systemctl restart k3s
agent节点执行:systemctl restart k3s-agent - 服务启动完成后,可先配置crictl默认endpoint消除警告,再测试拉取镜像:
crictl config runtime-endpoint unix:///run/k3s/containerd/containerd.sock crictl pull gcr.io/my-project-id/my-image:latest
排查兜底
如果操作后仍报401,逐一核对以下项:
- 所用service account已被授予GCR对应项目的
Storage Object Viewer及以上权限,有权限读取目标镜像 - service account密钥未过期、未被禁用,JSON内容完整无多余空格、换行
- 节点到
gcr.io、storage.googleapis.com的网络连通正常,无防火墙、代理拦截鉴权请求
内容的提问来源于stack exchange,提问作者Maoz Zadok
相关产品推荐
相关产品推荐

