2

我创建了一个谷歌云任务,队列不断重试,该函数也没有被调用。

这是来自云控制台的日志。

  attemptResponseLog: {
   attemptDuration: "0.133874s"    
   dispatchCount: "19"    
   maxAttempts: 0    
   responseCount: "0"    
   retryTime: "2020-06-21T21:20:18.518655Z"    
   scheduleTime: "2020-06-21T21:20:15.718098Z"    
   status: "UNAVAILABLE"    
   targetAddress: "POST some url"    
   targetType: "HTTP"    
  }
4

2 回答 2

1

我遇到了同样的错误,我必须说文档不够清楚。

警告:我觉得要考虑角色有一点延迟,特别是对于 ServiceAccountUser 之一。

我进行了多次测试,并试图保持尽可能低的权限,所以我确实尝试删除一些......做一些测试,它有效......很好,没有必要拥有这个权利......稍后回来,并且东西坏了。

这是我的设置:

我使用 Cloud Scheduler 通过在队列上发布消息每 15 分钟触发一次 Cloud Function。CloudFunction 构建任务列表以计算 MySQL 上的统计信息并创建任务 另一个 Cloud Function 运行 SQL 查询以获取统计信息并将结果存储在 FireStore 中。

我使用云任务,这样 MySQL 的负载不会太重。

下面,我使用函数名称使其易于理解。

  • TaskCreatorCloudFunction 与TaskCreatorServiceAccount一起运行

    • TaskCreatorServiceAccount需要

      • Cloud Task Enqueuer ”角色 #1
      • 成为 CloudTaskComputeStatsServiceAccount 上的 ServiceAccountUser(见下文)#2
      • 完成这项工作所需的角色(读取 SQL 以获取要创建的任务列表、写入日志、访问机密管理器、监听由 Cloud Scheduler 通过 pubsub 触发的 pubsub)
  • 与 TaskImplementationServiceAccount 一起运行的TaskImplementationCloudFunction (http)

    • TaskImplementationServiceAccount对 CloudTasks 没有特定角色,只有完成工作所需的角色(读取 SQL、写入日志、访问密钥管理器、firestore 写入)

TaskQueue 被命名为“compute-stats-on-mysql”。

我创建了一个名为 CloudTaskComputeStatsServiceAccount #3 的专用 ServiceAccount

CloudTaskComputeStatsServiceAccount 拥有整个工作的具体权限。

  • 云函数调用程序 #4
  • 在 TaskImplementationServiceAccount #5 上添加 CloudTaskComputeStatsServiceAccount 作为 ServiceAccountUser

要在控制台中执行最后一项(下面的脚本版本),您需要

  • 转到 IAM-> 服务帐户
  • 检查 TaskImplementationServiceAccount
  • 在右上角,如果尚未显示,请单击“显示信息面板”
  • 点击添加成员
  • 粘贴 CloudTaskComputeStatsServiceAccount 的全名
  • 选择服务帐户用户作为角色
  • 节省

您可以在控制台中编辑它,但最好编写脚本。


gcloud tasks queues create compute-stats-on-mysql \
    --max-dispatches-per-second=10 \
    --max-concurrent-dispatches=15 \
    --max-attempts=2 \
    --min-backoff=1s
#3
gcloud iam service-accounts create CloudTaskComputeStatsServiceAccount --description="Service Account for the cloud task compute-stats-on-mysql" --display-name="Service Account for the cloud task compute-stats-on-mysql"
#4
gcloud projects add-iam-policy-binding ${PROJECT_ID} --member serviceAccount:CloudTaskComputeStatsServiceAccount@${PROJECT_ID}.iam.gserviceaccount.com --role "roles/cloudfunctions.invoker"

#1
gcloud projects add-iam-policy-binding ${PROJECT_ID} --member serviceAccount:TaskCreatorServiceAccount@${PROJECT_ID}.iam.gserviceaccount.com --role "roles/cloudtasks.enqueuer"

#5
gcloud iam service-accounts add-iam-policy-binding TaskImplementationServiceAccount@${PROJECT_ID}.iam.gserviceaccount.com --member="serviceAccount:CloudTaskComputeStatsServiceAccount@${PROJECT_ID}.iam.gserviceaccount.com"  --role "roles/iam.serviceAccountUser"

#2
gcloud iam service-accounts add-iam-policy-binding CloudTaskComputeStatsServiceAccount@${PROJECT_ID}.iam.gserviceaccount.com --member="serviceAccount:TaskCreatorServiceAccount@${PROJECT_ID}.iam.gserviceaccount.com"  --role=roles/iam.serviceAccountUser

创建任务时,使用 oidcToken 中的 CloudTaskComputeStatsServiceAccount

const body  = Buffer.from(JSON.stringify(data)).toString('base64');
  const task = {
    httpRequest: {
      httpMethod: 'POST',
      url,
      oidcToken: {
        serviceAccountEmail: "CloudTaskComputeStatsServiceAccount@${PROJECT_ID}.iam.gserviceaccount.com",
      },
      headers: {
        'Content-Type': 'application/json',
      },
      body,
    },
  };

我的理解是,当你运行

const [response] = await cloudTasksClient.createTask({parent, task});

云函数(任务创建者)需要创建任务,并充当“CloudTaskComputeStatsServiceAccount”和“CloudTaskComputeStatsServiceAccount”需要有云函数调用者并充当目标云函数。

于 2020-09-09T16:02:40.020 回答
0

实际上,这不是服务帐户问题。缺少 OIDC 令牌受众。似乎对于云功能,这是需要的。我找到了两个参考...您可以通过省略此参数来使用 cli 中的 OIDC 令牌重新创建此问题gcloud tasks create-http-task

--oidc-token-audience=OIDC_TOKEN_AUDIENCE
    The audience to be used when generating an OpenID Connect token to be 
    included in the request sent to the target when executing the task. 
    If not specified, the URI specified in the target will be used

ruby 中弹出的第二个参考显示audience https://googleapis.dev/ruby/google-cloud-tasks/latest/Google/Cloud/Tasks/V2/OidcToken.html

使用 google-cloud-tasks 1.5.0 的代码,tasks 对象看起来像这样,其中url_oidc只有云函数的 url(即触发 url...没有 url 参数)

# Construct the request body.
    task = {
            'http_request': {  # Specify the type of request.
                'http_method': 'GET',
                'url': url_final,  # The full url path that the task will be sent to.
                'oidc_token': {
                    'service_account_email': service_account_email,
                    'audience': url_oidc
                }
            }
    }
于 2021-02-02T21:17:05.897 回答