排查 Cloud Run 函数(第 1 代)问题

本文档介绍了如何在使用 Cloud Run functions(第 1 代)时排查错误消息并解决问题。

部署

本部分列出了您可能遇到的部署问题,并提供了有关如何解决这些问题的建议。您在部署期间可能遇到的许多问题都与角色和权限或错误配置有关。

部署事件驱动的函数时,部署服务账号缺少 Pub/Sub 权限

执行管理操作时,Cloud Functions 服务会使用 Cloud Functions Service Agent 服务账号 (service-PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com)。 默认情况下,此账号拥有 Cloud Functions cloudfunctions.serviceAgent 角色。为了部署事件驱动的函数,Cloud Functions 服务必须访问 Pub/Sub 以配置主题和订阅。如果分配给服务账号的角色发生更改,并且没有更新适当的权限,则 Cloud Functions 服务将无法访问 Pub/Sub,并且部署将失败。

错误消息

控制台

Failed to configure trigger PubSub projects/PROJECT_ID/topics/FUNCTION_NAME

gcloud

ERROR: (gcloud.functions.deploy) OperationError: code=13, message=Failed to configure trigger PubSub projects/PROJECT_ID/topics/FUNCTION_NAME

解决方案

您可以重置服务账号为默认的 cloudfunctions.serviceAgent 角色。

默认运行时服务账号不存在

如果未指定用户管理的服务账号,Cloud Run 函数(第 1 代)默认使用 App Engine 服务账号。如果您删除默认账号但未指定用户管理的账号,部署将会失败。

错误消息

gcloud

ERROR: (gcloud.functions.deploy) ResponseError: status=[400], code=[Ok], message=[Default service account 'test-project-356312@appspot.gserviceaccount.com' doesn't exist. Please recreate this account or specify a different account. Please visit https://cloud.google.com/functions/docs/troubleshooting for in-depth troubleshooting documentation.]

解决方案

如需解决此问题,请按以下任一解决方案操作:

部署函数时,用户缺少运行时服务账号的权限

每个函数都与一个服务账号关联,该服务账号充当函数访问其他资源时的身份。此运行时服务账号可以是默认服务账号,也可以是用户管理的服务账号。如需使用运行时服务账号,部署者必须具有该服务账号的 iam.serviceAccounts.actAs 权限。创建非默认运行时服务账号的用户将自动获得此权限,但其他部署者必须由具有正确权限的用户授予此权限。

已分配 Project Viewer、Cloud Functions Developer 或 Cloud Functions Admin 角色的用户还必须获得运行时服务账号的 iam.serviceAccounts.actAs 权限。

错误消息

控制台

You must have the iam.serviceAccounts.actAs permission on the selected service account. To obtain this permission, you can grant a role that includes it like the Service Account User role, on the project.

gcloud

默认服务账号会出现以下错误:

ERROR: (gcloud.functions.deploy) ResponseError: status=[403], code=[Ok], message=[Caller USER is missing permission 'iam.serviceaccounts.actAs' on service account PROJECT_ID@appspot.gserviceaccount.com. Grant the role 'roles/iam.serviceAccountUser' to the caller on the service account PROJECT_ID@appspot.gserviceaccount.com. You can do that by running 'gcloud iam service-accounts add-iam-policy-binding
PROJECT_ID@appspot.gserviceaccount.com --member MEMBER --role roles/iam.serviceAccountUser' where MEMBER has a prefix like 'user:' or 'serviceAccount:'.

非默认服务账号会出现以下错误:

ERROR: (gcloud.functions.deploy) ResponseError: status=[403], code=[Ok], message=[Caller USER is missing permission 'iam.serviceaccounts.actAs' on service account SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com. Grant the role 'roles/iam.serviceAccountUser' to the caller on the service account SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com. You can do that by running 'gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com --member MEMBER --role roles/iam.serviceAccountUser' where MEMBER has a prefix like 'user:' or 'serviceAccount:'.

解决方案

在默认或用户管理的服务账号上为用户分配 roles/iam.serviceAccountUser 角色。此角色可提供 iam.serviceAccounts.actAs 权限。

部署函数时,Cloud Functions Service Agent 服务账号缺少项目存储桶权限

Cloud Run functions 只能由来自同一 Google Cloud Platform 项目中的 Cloud Storage 存储桶的事件触发。此外,Cloud Functions Service Agent 服务账号 (service-PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com) 需要项目的 cloudfunctions.serviceAgent 角色。

错误消息

控制台

Deployment failure: Insufficient permissions to (re)configure a trigger
(permission denied for bucket BUCKET_ID). Please, give owner permissions
to the editor role of the bucket and try again.

gcloud

ERROR: (gcloud.functions.deploy) OperationError: code=7, message=Insufficient
permissions to (re)configure a trigger (permission denied for bucket BUCKET_ID).
Please, give owner permissions to the editor role of the bucket and try again.

解决方案

如需解决此错误,请将服务代理服务账号重置为默认角色

拥有 Project Editor 角色的用户无法公开函数

Project Editor 角色具有管理项目内资源的广泛权限,但它本身并不授予公开 Cloud Functions 的权限。您必须向部署该函数的用户或服务授予 cloudfunctions.functions.setIamPolicy 权限。

错误消息

gcloud

 ERROR: (gcloud.functions.add-iam-policy-binding) ResponseError: status=[403], code=[Forbidden], message=[Permission 'cloudfunctions.functions.setIamPolicy' denied on resource 'projects/PROJECT_ID/locations/LOCATION/functions/FUNCTION_NAME (or resource may not exist).]

解决方案

如需解决此错误,请按以下任一解决方案操作:

使用资源位置限制条件组织政策时,函数部署失败

如果您的组织使用资源位置限制政策,则会限制将函数部署在受该政策限制的区域中。在 Google Cloud 控制台中,部署函数时,无法从区域下拉列表访问受限区域。

错误消息

gcloud

  ERROR: (gcloud.functions.deploy) ResponseError: status=[400], code=[Ok], message=[The request has violated one or more Org Policies. Please refer to the respective violations for more information. violations {
    type: "constraints/gcp.resourceLocations"
    subject: "orgpolicy:projects/PROJECT_ID"
    description: "Constraint constraints/gcp.resourceLocations violated for projects/PROJECT_ID attempting GenerateUploadUrlActionV1 with location set to RESTRICTED_LOCATION. See https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints for more information."
  }

解决方案

通过资源位置限制条件的 allowed_valuesdenied_values 列表添加或移除位置,以便成功部署。

执行函数的全局范围时函数部署失败

此错误表示您的代码存在问题。部署流水线已完成函数部署,但最后一步完成了,即向该函数发送健康检查。此健康检查用于执行函数的全局范围,这可能会导致异常、崩溃或超时。全局范围是您通常加载的库并初始化客户端的位置。

错误消息

控制台

Deployment failure: Function failed on loading user code. This is likely due to a bug in the user code.

gcloud

ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Function
failed on loading user code. This is likely due to a bug in the user code.

在 Cloud Logging 日志中:

  "Function failed on loading user code. This is likely due to a bug in the user code."

解决方案

如需解决此问题,请按以下任一解决方案操作:

  • 如需更详细的错误消息,请查看函数的构建日志以及函数的运行时日志

  • 如果不清楚函数为何无法执行其全局范围,请考虑使用全局变量延迟加载,暂时将代码移动到请求调用中。这样,您就可以围绕您的客户端库添加额外的日志语句,这些语句可能会在其实例化时超时(尤其是当调用其他服务时),也可能完全崩溃/抛出异常。

  • 增加函数超时。

  • 源代码必须包含通过 Cloud 控制台gcloud 在部署中正确指定的入口点函数。

具有 Viewer 角色的用户无法部署函数

拥有 Project Viewer 或 Cloud Functions Viewer 角色的用户对函数和函数详细信息具有只读权限,并且无法部署新函数。创建函数功能在 Google Cloud 控制台中呈灰显状态,并显示以下错误:

错误消息

gcloud

ERROR: (gcloud.functions.deploy) PERMISSION_DENIED: Permission
'cloudfunctions.functions.sourceCodeSet' denied on resource
'projects/PROJECT_ID/locations/LOCATION` (or resource may not exist)

解决方案

为用户分配 Cloud Functions Developer 角色。

Build 服务账号缺少权限

错误消息

在函数部署错误或构建日志中,您可能会看到以下错误之一:

The service account running this build does not have permission to write logs.
To fix this, grant the Logs Writer (roles/logging.logWriter) role to the service
account.
Step #0 - "fetch": failed to Fetch: failed to download archive gs://gcf-sources-PROJECT_NUMBER-LOCATION/FUNCTION_NAME/version-VERSION_NUMBER/function-source.zip: Access to bucket gcf-sources-PROJECT_NUMBER-LOCATION denied. You must grant Storage Object Viewer permission to PROJECT_NUMBER-compute@developer.gserviceaccount.com.
Step #2 - "build": ERROR: failed to create image cache: accessing cache image "LOCATION-docker.pkg.dev/PROJECT/gcf-artifacts/FUNCTION_NAME/cache:latest": connect to repo store "LOCATION-docker.pkg.dev/PROJECT/gcf-artifacts/FUNCTION_NAME/cache:latest": GET https://LOCATION-docker.pkg.dev/v2/token?scope=repository%3APROJECT%2Fgcf-artifacts%2FFUNCTION_NAME%2Fcache%3Apull&service=: DENIED: Permission "artifactregistry.repositories.downloadArtifacts" denied on resource "projects/PROJECT/locations/LOCATION/repositories/gcf-artifacts" (or it may not exist)
Could not build the function due to a missing permission on the build service account. If  you didn't revoke that permission explicitly, this could be caused by a change in the organization policies.

解决方案

Build 服务账号需要具备从源存储桶读取数据的权限以及对制品部署代码库的读写权限。如果 Cloud Build 使用服务账号的默认行为发生了变化,您可能会遇到此错误,详情请参阅 Cloud Build 服务账号更改

如需解决此问题,请使用以下任一解决方案:

Build 服务账号已停用

错误消息

Could not build the function due to disabled service account used by Cloud Build. Please make sure that the service account is active.

解决方案

您需要启用 Build 服务账号才能部署函数。如果 Cloud Build 使用服务账号的默认行为发生了变化,您可能会遇到此错误,详情请参阅 Cloud Build 服务账号更改

如需解决此问题,请使用以下任一解决方案:

提供服务

本部分列出了您可能遇到的服务问题,并提供了有关如何修复这些问题的建议。

由于函数需要身份验证,服务权限出错

未启用允许未经身份验证的调用的 HTTP 函数将会限制没有适当权限的最终用户和服务账号的访问。

在浏览器中访问 Cloud Run functions 网址不会自动添加身份验证标头。

错误消息

HTTP 错误响应代码:403 禁止

HTTP 错误响应正文:

Error: Forbidden Your client does not have permission
to get URL /FUNCTION_NAME from this server.

解决方案

如需解决此错误,请按以下任一解决方案操作:

由于 allow internal traffic only 配置问题导致服务权限出错

入站流量设置限制是否可以通过您的 Google Cloud 项目或 VPC Service Controls 服务边界之外的资源调用 HTTP 函数。为入站网络配置仅允许内部流量设置时,此错误消息表示仅允许来自同一项目或 VPC Service Controls 边界中的 VPC 网络的请求。

错误消息

HTTP 错误响应代码:404 未找到

HTTP 错误响应正文:

404 Page not found

解决方案

如需解决此错误,请按以下任一解决方案操作:

  • 确保请求来自您的 Google Cloud 项目或 VPC Service Controls 服务边界。

  • 将函数的入站流量设置更改为允许所有流量

  • Cloud Run 函数源代码可能会因函数网址、HTTP 方法或逻辑错误不正确而导致 404 错误。

函数调用缺少有效的身份验证凭据

使用访问受限配置的函数需要 ID 令牌。如果您使用访问令牌刷新令牌,函数调用将失败。

错误消息

HTTP 错误响应代码:401 未授权

HTTP 错误响应正文:

Your client does not have permission to the requested URL </FUNCTION_NAME>

解决方案

如需解决此错误,请按以下任一解决方案操作:

  • 确保您的请求包含 Authorization: Bearer ID_TOKEN 标头,并且该令牌是 ID 令牌,而不是访问令牌或刷新令牌。如果使用服务账号的私钥手动生成此令牌,则必须用自签名 JWT 令牌交换 Google 签名的身份令牌。如需了解详情,请参阅进行身份验证以便调用

  • 使用请求标头中的身份验证凭据调用 HTTP 函数。例如,您可以使用 获取身份令牌,如下所示:

    curl  -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
      https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME

    如需了解详情,请参阅进行身份验证以便调用

函数停止执行,或在您的代码完成后继续运行

某些 Cloud Run functions 运行时允许用户运行异步任务。如果您的函数创建了此类任务,还必须明确等待这些任务完成。否则,可能会导致您的函数在错误时间停止执行。

错误行为

您的函数具有以下行为之一:

  • 您的函数会在异步任务仍在运行期间,但在指定的超时期限之前终止。
  • 当这些任务完成后,您的函数不会停止运行,而是继续运行,直到超时期结束。

解决方案

如果您的函数提前终止,则应确保在函数执行以下任何操作之前,函数的所有异步任务都已完成:

  • 返回一个值
  • 解决或拒绝返回的 Promise 对象(仅限 Node.js 函数)
  • 抛出未捕获的异常和错误
  • 发送 HTTP 响应
  • 调用回调函数

如果您的函数在完成异步任务后未能终止,您应在函数运行完成后验证其是否正确发出了 Cloud Run functions 信号。特别是,确保在函数完成其异步任务之后,立即执行上面列出的操作之一。

访问受 VPC Service Controls 保护的资源时出现运行时错误

默认情况下,Cloud Run functions 使用公共 IP 地址向其他服务发出出站请求。如果您的函数不在 VPC Service Controls 边界内,则在尝试访问受 VPC Service Controls 保护的 Google Cloud 服务时,可能由于服务边界拒绝而导致收到 HTTP 403 响应。

错误消息

在“已审核的资源”日志中,如下所示的条目:

"protoPayload": {
  "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
  "status": {
    "code": 7,
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.PreconditionFailure",
        "violations": [
          {
            "type": "VPC_SERVICE_CONTROLS",
  ...
  "authenticationInfo": {
    "principalEmail": "CLOUD_FUNCTION_RUNTIME_SERVICE_ACCOUNT",
  ...
  "metadata": {
    "violationReason": "NO_MATCHING_ACCESS_LEVEL",
    "securityPolicyInfo": {
      "organizationId": "ORGANIZATION_ID",
      "servicePerimeterName": "accessPolicies/NUMBER/servicePerimeters/SERVICE_PERIMETER_NAME"
  ...

解决方案

如需解决此错误,请按以下任一解决方案操作:

可伸缩性

本部分列出了可伸缩性问题,并提供了有关如何修复每个问题的建议。

与待处理队列请求中止相关的 Cloud Logging 错误

以下情况可能与扩缩失败有关。

  • 流量突然激增。
  • 冷启动时间较长。
  • 请求处理时间较长。
  • 函数错误率高。
  • 达到实例数上限
  • 归因于 Cloud Run functions 服务的暂时性因素。

在每种情况下,Cloud Run functions 扩容速度可能不够快,无法管理流量。

错误消息

 The request was aborted because there was no available instance.

Cloud Run 函数具有以下严重级别:

* `severity=WARNING` ( Response code: 429 ) Cloud Run functions cannot scale due
  to the [`max-instances`](/functions/docs/configuring/max-instances) limit you set
  during configuration.
* `severity=ERROR` ( Response code: 500 ) Cloud Run functions intrinsically
  cannot manage the rate of traffic.

解决方案

  • 对于基于 HTTP 触发器的函数,请对不能丢弃的请求实现指数退避和重试。如果您要通过 Workflows 触发 Cloud Run functions,则可以使用 try/retry 语法来实现此目的。
  • 对于后台或事件驱动型函数,Cloud Run functions 支持至少传送一次。即使未明确启用重试功能,事件也将自动重新传送,并且函数执行将重试。如需了解详情,请参阅启用事件驱动型函数重试
  • 如果问题的根本原因是仅归因于 Cloud Run functions 的严重瞬时错误,或者您需要有关问题的帮助,请与支持团队联系。

日志记录

以下部分介绍了日志记录问题以及修复方法。

日志条目没有日志严重级别或具有不正确的日志严重级别

默认情况下,Cloud Run functions 包含运行时日志记录。写入 stdoutstderr 的日志会自动显示在 Google Cloud 控制台中。但在默认情况下,这些日志条目仅包含字符串消息。

解决方案

如需包含日志严重程度,您必须改为发送结构化日志条目

在崩溃时以不同方式处理或记录异常

您可能需要自定义如何管理和记录崩溃信息。

解决方案

try 块中封装您的函数,以自定义处理异常和记录堆栈轨迹。

tryretry on failure注意:添加 代码块可能会导致采用 配置的事件驱动型函数产生意外副作用。重试失败事件本身可能会失败。

示例

import logging
import traceback
def try_catch_log(wrapped_func):
  def wrapper(*args, **kwargs):
    try:
      response = wrapped_func(*args, **kwargs)
    except Exception:
      # Replace new lines with spaces so as to prevent several entries which
      # would trigger several errors.
      error_message = traceback.format_exc().replace('\n', '  ')
      logging.error(error_message)
      return 'Error';
    return response;
  return wrapper;

#Example hello world function

@try_catch_log
def python_hello_world(request):
  request_args = request.args

  if request_args and 'name' in request_args:
    1 + 's'
  return 'Hello World!'

Node.js 10+、Python 3.8、Go 1.13 和 Java 11 中的日志太大

这些运行时中常规日志条目的大小上限为 105 KiB。

解决方案

发送的日志条目未超出此限制。

尽管 Cloud Run functions 返回错误,但日志缺失

Cloud Run functions 将 Cloud Run functions 函数日志流式传输到默认存储桶。当您创建项目时,Cloud Run functions 会创建并启用默认存储桶。如果默认存储桶已停用,或者 Cloud Run functions 函数日志在排除项过滤器中,则日志不会显示在 Logs Explorer 中。

解决方案

启用默认日志,并确保未设置排除过滤器。

Cloud Run 函数日志未显示在日志浏览器中

某些 Cloud Logging 客户端库使用异步过程来写入日志条目。如果函数崩溃或终止,则某些日志条目可能尚未写入,稍后可能会显示。某些日志可能会丢失,也无法在日志浏览器中查看。

解决方案

使用客户端库界面在退出函数之前刷新缓冲的日志条目,或使用库同步写入日志条目。此外,您还可以将日志直接同步写入 stdoutstderr

使用日志路由器接收器时 Cloud Run 函数日志未显示

日志路由器接收器会将日志条目路由到不同的目的地。

控制台日志路由器的屏幕截图,其中突出显示了“查看接收器详情”

设置中包含排除项过滤条件,用于定义只需舍弃的条目。

显示排除项过滤条件的“控制台日志接收器详情”弹出窗口的屏幕截图

解决方案

移除为 resource.type="cloud_functions" 设置的排除项过滤条件。

数据库连接

许多数据库错误都与超出连接限制或超时有关。如果您在日志中看到 Cloud SQL 警告(例如 Context deadline exceeded),则可能需要调整连接配置。如需了解详情,请参阅 Cloud SQL 最佳做法

网络

本部分列出了网络问题,并提供了有关如何修复这些问题的建议。

网络连接

如果在您配置出站流量设置后,来自 Cloud Run functions 函数的所有出站请求都失败,您可以运行 Connectivity Tests 以识别任何潜在的网络连接问题。如需了解详情,请参阅创建和运行 Connectivity Tests

无服务器 VPC 访问通道连接器未就绪或不存在

如果无服务器 VPC 访问通道连接器失败,则它可能未按要求使用专用于连接器的 /28 子网掩码。

错误消息

VPC connector projects/xxxxx/locations/REGION/connectors/xxxx
is not ready yet or does not exist.

如果由于缺少 Google APIs Service Agent 服务账号 PROJECT_NUMBER@cloudservices.gserviceaccount.com 的权限而使用处于错误状态的连接器部署 Cloud Run functions,则会导致以下错误:

错误消息

Failed to prepare VPC connector. Please try again later.

解决方案

列出您的子网,以检查您的连接器是否使用 /28 子网掩码。如果您的连接器未使用 /28 子网掩码,请重新创建连接器或创建新连接器

如需解决此问题,请按以下任一解决方案操作:

  • 如果您重新创建连接器,则无需重新部署其他函数。在重新创建连接器时,您可能会遇到网络中断。

  • 如果您创建新的备用连接器,请重新部署您的函数以使用新连接器,然后删除原始连接器。此方法可避免网络中断。

  • 确保 Cloud Run functions 及其关联的连接器部署在同一区域中。

  • 对于共享 VPC 配置:

    • 确保 VPC Connector 用于在项目中预配资源的服务账号 SERVICE_PROJECT_NUMBER@cloudservices.gserviceaccount.comservice-SERVICE_PROJECT_NUMBER@gcp-sa-vpcaccess.iam.gserviceaccount.com 没有缺少权限。如果连接器位于服务项目中,这些服务账号应在共享 VPC 配置的宿主项目中具有 roles/compute.networkUser 角色。 否则,必须使用 roles/compute.networkAdmin

    • 如果连接器是在宿主项目中创建,请确保在宿主项目中的 Cloud Run functions Service Agent授予 Serverless VPC Access User 角色。

    • 如果连接器状态显示 Connector is in a bad state, manual deletion recommended 错误,并且 Google APIs Service Agent 缺少在连接器项目中预配计算资源所需的权限,请向 PROJECT_NUMBER@cloudservices.gserviceaccount.com 服务账号授予 roles/compute.admin。在某些情况下,您可能需要在更新权限后重新创建连接器。

使用 TCP 端口 25 发送到外部目标 IP 地址的 SMTP 流量被阻止

为了提高安全性,从 Cloud Run 函数发送电子邮件时,Google Cloud 会阻止与 TCP 目标端口 25 的连接。

解决方案

如需取消阻止这些连接,请选择以下选项之一:

其他

本部分概述了不属于其他类别的所有其他问题,并针对每种问题提供了解决方案。

Cloud 审核日志中方法 google.storage.buckets.testIamPermissions 上的 VPC Service Controls 错误

当您在 Google Cloud 控制台中打开函数详情页面时,Cloud Run 函数会检查您是否可以修改容器映像的存储库并公开访问该存储库。为了进行验证,Cloud Run functions 会使用以下格式的 google.storage.buckets.testIamPermissions 方法向 Container Registry 存储桶发送请求:[REGION].artifacts.[PROJECT_ID].appspot.com。这两项检查之间的唯一区别在于,一项检查会在进行身份验证的情况下运行,以验证用户修改存储桶的权限;而另一项检查则在未进行身份验证的情况下运行,以验证存储桶是否可公开访问。

如果 VPC Service Controls 边界限制了 storage.googleapis.com API,Google Cloud 控制台会在 Cloud Audit Logs 中显示 google.storage.buckets.testIamPermissions 方法的错误。

错误消息

对于没有身份验证信息的公共访问权限检查,VPC SC 拒绝政策审核日志会显示类似于以下内容的条目:

"protoPayload": {
  "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
  "status": {
    "code": 7,
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.PreconditionFailure",
        "violations": [
          {
            "type": "VPC_SERVICE_CONTROLS",
  ...
  "authenticationInfo": {},
  "requestMetadata": {
    "callerIp": "END_USER_IP"
  },
  "serviceName": "storage.googleapis.com",
  "methodName": "google.storage.buckets.testIamPermissions",
  "resourceName": "projects/PROJECT_NUMBER",
  "metadata": {
    "ingressViolations": [
      {
        "servicePerimeter": "accessPolicies/ACCESS_POLICY_ID/servicePerimeters/VPC_SC_PERIMETER_NAME",
        "targetResource": "projects/PROJECT_NUMBER"
      }
    ],
    "resourceNames": [
      "projects/_/buckets/REGION.artifacts.PROJECT_ID.appspot.com"
    ],
    "securityPolicyInfo": {
      "servicePerimeterName": "accessPolicies/ACCESS_POLICY_ID/servicePerimeters/VPC_SC_PERIMETER_NAME",
      "organizationId": "ORG_ID"
    },
    "violationReason": "NO_MATCHING_ACCESS_LEVEL",
  ...

对于包含身份验证信息的公共访问权限检查,VPC SC 拒绝政策审核日志会显示允许用户修改存储桶设置的条目,类似于以下示例:

"protoPayload": {
  "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
  "status": {
    "code": 7,
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.PreconditionFailure",
        "violations": [
          {
            "type": "VPC_SERVICE_CONTROLS",
  ...
  "authenticationInfo": {
    "principalEmail": "END_USER_EMAIL"
  },
  "requestMetadata": {
    "callerIp": "END_USER_IP",
    "requestAttributes": {},
    "destinationAttributes": {}
  },
  "serviceName": "storage.googleapis.com",
  "methodName": "google.storage.buckets.testIamPermissions",
  "resourceName": "projects/PROJECT_NUMBER",
  "metadata": {
    "ingressViolations": [
      {
        "servicePerimeter": "accessPolicies/ACCESS_POLICY_ID/servicePerimeters/VPC_SC_PERIMETER_NAME",
        "targetResource": "projects/PROJECT_NUMBER"
      }
    ],
    "resourceNames": [
      "projects/_/buckets/REGION.artifacts.PROJECT_ID.appspot.com"
    ],
    "securityPolicyInfo": {
      "servicePerimeterName": "accessPolicies/ACCESS_POLICY_ID/servicePerimeters/VPC_SC_PERIMETER_NAME",
      "organizationId": "ORG_ID"
    },
    "violationReason": "NO_MATCHING_ACCESS_LEVEL",
  ...

解决方案

如果 Container Registry 存储桶不可公开访问,您可以忽略 VPC Service Controls 错误。

或者,您也可以添加 VPC Service Controls 入站流量规则以允许使用 google.storage.buckets.testIamPermissions 方法,如以下示例所示:

ingress_from {
  sources {
    access_level: "*"
  }
  identity_type: ANY_IDENTITY
}
ingress_to {
  operations {
    service_name: "storage.googleapis.com"
    method_selectors {
      method: "google.storage.buckets.testIamPermissions"
    }
  }
  resources: "projects/PROJECT_NUMBER"
}

在可能的情况下,您可以通过使用用户 IP 地址定义访问权限级别,从而进一步细化入站规则。