调度读写BigQuery的Cloud Function时Cloud Scheduler执行失败
解决GCP Cloud Scheduler调用Cloud Function权限拒绝问题
问题背景
在GCP中尝试调度一个用于读写BigQuery的Cloud Function,但Cloud Scheduler执行始终失败。函数已通过Cloud Functions验证并处于激活状态,当前仅实现从BigQuery表读取数据并写入新表的逻辑,后续计划添加数据转换操作。
函数代码
def geopos_test(request): from flatten_json import flatten import requests import flatten_json import pandas as pd import os, json, sys,glob,pathlib import seaborn as sns from scipy import stats import collections try: collectionsAbc = collections.abc except AttributeError: collectionsAbc = collections import numpy as np import pandas as pd import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.colors as colors import matplotlib.ticker as ticker import datetime import seaborn as sns from mpl_toolkits.axes_grid1 import make_axes_locatable from matplotlib.colors import ListedColormap, LinearSegmentedColormap from matplotlib.lines import Line2D import numpy as np import math from pandas.io.json import json_normalize from operator import attrgetter from datetime import date, timedelta import pandas_gbq import collections from google.cloud import bigquery client = bigquery.Client() project = "<ProjectId>" dataset_id = "<DataSet>" dataset_ref = bigquery.DatasetReference(project, dataset_id) table_ref = dataset_ref.table('sectional_accuracy') table = client.get_table(table_ref) Sectional_accuracy = client.list_rows(table).to_dataframe() sectional_accuracy = sectional_accuracy.drop_duplicates() sectional_accuracy.sort_values(['Store']) job_config = bigquery.LoadJobConfig( schema=[ bigquery.SchemaField("Store", bigquery.enums.SqlTypeNames.STRING), bigquery.SchemaField("storeid", bigquery.enums.SqlTypeNames.STRING), bigquery.SchemaField("storeIdstr", bigquery.enums.SqlTypeNames.STRING), bigquery.SchemaField("Date", bigquery.enums.SqlTypeNames.TIMESTAMP), bigquery.SchemaField("Sections", bigquery.enums.SqlTypeNames.STRING), bigquery.SchemaField("Percentage", bigquery.enums.SqlTypeNames.FLOAT), bigquery.SchemaField("devicePercentage", bigquery.enums.SqlTypeNames.FLOAT), bigquery.SchemaField("distance", bigquery.enums.SqlTypeNames.STRING), ],) NtableId = '<ProjectId>.<DataSet>.test' job = client.load_table_from_dataframe(sectional_accuracy, NtableId, job_config=job_config)
当前配置与权限
- 函数关联App Engine默认服务账号(提问者为账号所有者),已添加Cloud Run Invoker、Cloud Functions Invoker及Cloud Scheduler Job Runner权限
- Cloud Scheduler配置:HTTP类型、POST方法,使用函数对应URL,采用OIDC令牌认证(与函数使用相同服务账号),HTTP头设置
User-Agent: Google-Cloud-Scheduler
已尝试操作
- 将函数入口从
geopos_test(request)改为geopos_test(event, context) - 修改HTTP头为
Content-Type: application/octet-stream或Content-Type: application/json - 更换服务账号
错误日志
{ "httpRequest": {}, "insertId": "********", "jsonPayload": { "@type": "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished", "jobName": "******************", "status": "PERMISSION_DENIED", "targetType": "HTTP", "url": "*************" }, "logName": "*************/logs/cloudscheduler.googleapis.com%2Fexecutions", "receiveTimestamp": "2022-10-24T10:10:52.337822391Z", "resource": {}, "severity": "ERROR", "timestamp": "2022-10-24T10:10:52.337822391Z" }
解决方案
1. 修正服务账号权限绑定
- 确保Cloud Scheduler使用的服务账号直接绑定
roles/cloudfunctions.invoker权限,避免通过组继承导致的权限失效 - 进入Cloud Function的权限设置页面,将该服务账号添加为成员,角色选择
Cloud Functions Invoker
2. 完善Cloud Scheduler OIDC配置
- 在Cloud Scheduler的OIDC设置中,必须指定受众(Audience),值为Cloud Function的完整URL(例如
https://us-central1-your-project.cloudfunctions.net/geopos_test),这是OIDC令牌认证通过的核心要求 - 保留
Content-Type: application/json请求头,请求体填写{}(空JSON对象),确保HTTP请求格式符合函数预期
3. 恢复函数入口格式
- 由于函数是HTTP触发,入口必须保持
def geopos_test(request):的形式,之前改成event, context是Pub/Sub触发的格式,会导致HTTP请求无法正确解析,改回原入口格式
4. 验证BigQuery权限(提前规避后续问题)
- 确保函数关联的服务账号拥有
roles/bigquery.dataEditor权限,或针对目标数据集/表的读写权限,避免函数执行到BigQuery操作时出现新的权限错误
5. 重新部署并测试
- 重新部署Cloud Function,更新Cloud Scheduler的配置(尤其是受众设置),然后手动触发调度任务验证执行结果
内容的提问来源于stack exchange,提问作者Serge de Gosson de Varennes
相关产品推荐
相关产品推荐

