问题排查

本部分介绍如何排查常见的 Container Registry 和 Docker 问题。

网域级项目

如果您收到 invalid reference format 错误,一个可能问题是您的项目被限定在某一网域范围内。

如果您的项目被限定在您的网域范围内,那么项目 ID 应包含相应域名和一个英文冒号 (example.com:my-project:)。请参阅网域级项目,了解如何使用含有域名的项目 ID。

错误:状态 405:v1 Registry API is disabled.

如果您在拉取或推送映像时不断遇到诸如“v1 Registry API is disabled”之类的错误,请确保主机名、项目 ID、映像名称以及标记或摘要拼写正确。

要查看映像的标记和摘要,请运行以下命令:

gcloud container images list-tags [HOSTNAME]/[PROJECT-ID]/[IMAGE]

例如:

gcloud container images list-tags gcr.io/my-project/my-image

如需详细了解如何列出映像标记和摘要,请参阅管理映像

权限问题

以下部分介绍了针对特定权限问题的解决方案。 请始终确保您具有推送或拉取所需的权限。 请参阅权限和角色

如果您对 Container Registry 使用的存储桶启用了统一存储桶级访问权限,则在推送和拉取到 Container Registry 时您可能会遇到访问权限问题。

如需解决访问权限问题,请确保您拥有所需的推送或拉取权限。权限和角色中列出了这些权限。

如果您遇到 permission denied 错误(如以下示例所示):

FATA[0000] Post http://var/run/docker.sock/v1.17/images/gcr.io/container-engine-docs/example/push?tag=: dial unix /var/run/docker.sock: permission denied
ERROR: (gcloud.docker) A Docker command did not run successfully.
Tried to run: 'docker push gcr.io/container-engine-docs/example'
Exit code: 1

您可能需要将自己添加到 docker 用户群组中。

在 shell 或终端窗口中运行以下命令:

  sudo usermod -a -G docker ${USER}

在将您自己添加到 docker 用户群组后,请重启系统。

与 Container Registry 通信时的权限问题

如果您遇到如下所示的权限错误:

Permission denied: Unable to create the repository, please check that you have access to do so
  1. 验证是否已为您的项目启用结算功能

  2. 验证您的访问权限:

    1. 通过运行以下命令,确保您已通过 gcloud 身份验证:

      gcloud init
      
    2. 通过运行以下命令,确保将 Docker 配置为使用 gcloud 作为 Container Registry 凭据帮助程序:

      gcloud auth configure-docker
      
    3. 验证 docker-credential-gcloud 能否执行:

      docker-credential-gcloud list
      

      您应该会看到一个以您的目标注册表作为一个键的 JSON 对象。例如:

      {
        "https://asia.gcr.io": "oauth2accesstoken",
        "https://eu.gcr.io": "oauth2accesstoken",
        "https://gcr.io": "oauth2accesstoken",
        "https://us.gcr.io": "oauth2accesstoken"
      }
      
    4. 接下来,检查您是否有权对项目中要向其推送内容的 Cloud Storage 执行写入操作。如果您没有相关权限,请向管理员请求为您的用户授予访问权限,然后重试。

    5. 如果在获得正确权限后此问题依然存在,则说明在获取您的访问令牌时可能缺少以下范围:

      • https://www.googleapis.com/auth/devstorage.read_write
      • https://www.googleapis.com/auth/devstorage.full_control

      要验证这一点,请先自行获取访问令牌。具体获取方式因应用而异,例如,如果您使用 Compute Engine 默认服务账号中的访问令牌,则可以按照此处的说明获取该令牌。

      自行获取访问令牌后,您可以使用以下命令来查看获取访问令牌时使用的范围:

      curl -H "Authorization: Bearer <your access token>" https://www.googleapis.com/oauth2/v1/tokeninfo
      

      如果未包含上述范围,请修复问题以确保在代码中获取访问令牌时包含这些范围。例如,对于专门为 Compute Engine 虚拟机上的默认服务账号生成的令牌,您将需要修正该虚拟机的范围设置并重新创建该令牌。

推送和拉取映像的权限问题

如需访问 Container Registry 存储桶,您必须为推送或拉取映像的虚拟机实例正确配置所需的 IAM 权限和访问权限范围。如需了解所需设置,请参阅将 Container Registry 与 Google Cloud 搭配使用

Google Kubernetes Engine 中的 ImagePullBackoff 错误

如果 GKE 无法从注册表中拉取映像,则会返回 ImagePullBackoff 错误。如果找不到映像,或者您的节点没有从注册表拉取的权限,则可能会发生此错误。默认情况下,当注册表与您的节点属于同一 Google Cloud 项目时,GKE 节点有权从 Container Registry 拉取映像。

GKE 文档包含确定根本原因并解决问题的步骤。

组织政策强制执行

组织政策限制条件应用于 Container Registry 使用的服务时,可能会影响 Container Registry 的使用,包括要求使用客户管理的加密密钥 (CMEK) 的限制条件。

推送映像时出现“Bad Request”错误

当 Cloud Storage API 位于限制条件 constraints/gcp.restrictNonCmekServicesDeny 政策列表中时,如果未使用 CMEK 加密底层存储分区,则无法将映像推送到 Container Registry。系统会返回以下消息:

unknown: Bad Request

配置 constraints/gcp.restrictCmekCryptoKeyProjects 后,必须使用来自允许的项目、文件夹或组织的 CryptoKey 对存储分区进行加密。不符合政策规定的现有存储分区必须配置为默认使用所需的密钥。

如需加密存储分区,请参阅 Cloud Storage 说明。注册表主机的存储桶名称采用以下格式之一:

  • 对于存储在主机 gcr.io 上的映像,名称采用 artifacts.PROJECT-ID.appspot.com 格式
  • STORAGE-REGION.artifacts.PROJECT-ID.appspot.com(适用于存储在 asia.gcr.ioeu.gcr.ious.gcr.io 中的图片)。

系统没有自动创建 gcr Pub/Sub 主题

在 Google Cloud 项目中激活 Container Registry API 时,Container Registry 会尝试使用 Google 管理的加密密钥自动创建主题 ID 为 gcr 的 Pub/Sub 主题。

当 Pub/Sub API 位于限制条件 constraints/gcp.restrictNonCmekServicesDeny 政策列表中时,必须使用 CMEK 加密主题。创建未使用 CMEK 加密的主题的请求将失败。

如需创建使用 CMEK 加密的 gcr 主题,请参阅 Pub/Sub 主题加密说明

配额限制

如果超出了 Container Registry 的配额限制,您可能会看到如下错误消息:

Error: Status 429 trying to pull repository [...] "Quota Exceeded."

为避免超出固定配额限制,您可以采取以下措施:

  • 增加与 Container Registry 通信的 IP 地址数量。 配额以每个 IP 地址为单位。
  • 添加引入延迟的重试机制。例如,您可以使用指数退避算法

注册表端点对 boot2docker 无效

如果您在 boot2docker 环境中无法访问 Container Registry:

docker push gcr.io/example/sample

Error response from daemon: invalid registry endpoint https://gcr.io/v0/:
  unable to ping registry endpoint https://gcr.io/v0/
v2 ping attempt failed with error: Get https://gcr.io/v2/:
  x509: certificate has expired or is not yet valid
v1 ping attempt failed with error: Get https://gcr.io/v1/_ping:
  x509: certificate has expired or is not yet valid.
If this private registry supports only HTTP or HTTPS with an unknown CA
certificate, please add `--insecure-registry gcr.io` to the daemon's
arguments. In the case of HTTPS, if you have access to the registry's CA
certificate, no need for the flag; simply place the CA certificate at
/etc/docker/certs.d/gcr.io/ca.crt

您可能需要重新启动 boot2docker:

boot2docker stop
boot2docker start

推送根级映像时出错

尝试推送容器映像时,推送失败并显示包含以下消息的消息:

Pushing to root-level images is disabled

此消息表示您使用主机名和映像标记了映像,但未包含项目 ID。

使用正确的映像路径格式标记映像:

HOSTNAME/PROJECT-ID/IMAGE:TAG

例如:gcr.io/web-project/web-app:1.0

在 Mac 上使用 Docker

如果在 Mac 上使用 Docker 时遇到任何问题,您可能需要尝试解决这个问题。 错误可能包括 Docker 推送/拉取操作无响应或类似如下的网络错误:

Post https://us.gcr.io/v2/[repo name]/blobs/uploads/: dial tcp xx.xxx.xx.xx:xxx: i/o timeout

如果您遇到这些错误,请尝试以下步骤:

  • 在 Mac 终端中运行 docker-machine restart default 命令以重启 Docker 守护进程。

  • 确保 Docker 的“偏好设置”菜单中未启用“将 docker 登录安全存储到 macOS 钥匙串” (Securely store docker logins in macOS keychain)。

  • 确保您运行的是最新 Docker 版本。