部署GCP Node.js Cloud Function失败:GitLab CI报RESOURCE_ERROR 400、Serverless Framework报400构建错误
我来帮你梳理这两类GCP Cloud Function(Node.js)部署失败的排查和解决思路,都是我踩过的坑,亲测有用:
先盯紧服务账号权限
GitLab CI部署用的GCP服务账号权限不够是最常见的原因,至少得有cloudfunctions.developer、storage.admin(上传代码到GCS桶需要),如果涉及构建还要加cloudbuild.builds.editor。你可以用命令gcloud projects get-iam-policy <你的项目ID>查看当前权限配置,缺啥补啥就行。检查CI配置的参数细节
打开你的.gitlab-ci.yml,看看部署命令(比如gcloud functions deploy)的参数有没有错:--region是不是GCP支持的区域(比如us-central1,别瞎写不存在的);--runtime是不是对应你的Node.js版本(比如nodejs20,别用已经淘汰的nodejs16);--source路径有没有指向包含package.json的目录,比如代码在functions/下,就得设成--source functions/;- 触发器参数(比如
--trigger-http)有没有漏加或者写错。
排查自建Runner的网络问题
如果你的GitLab Runner是自己搭的,大概率是网络不通导致的。可以在CI步骤里加个测试命令,比如gcloud info或者curl https://cloudfunctions.googleapis.com/,看看能不能访问GCP的API。要是不通,就得调整Runner的网络策略,允许出站访问GCP的服务域名。去GCP控制台扒详细日志
GitLab CI的错误提示太笼统了,直接去GCP控制台的Cloud Functions页面,找对应失败的部署记录,然后点进去看Cloud Build日志,里面会有具体的失败原因——比如依赖安装失败、代码语法错误、Node版本不兼容这些,一查一个准。
这个错误提示“Build failed: Build error details not available”其实是SLS没拉到Cloud Build的详细日志,得自己去挖:
先去Cloud Build控制台看真相
直接打开GCP控制台的Cloud Build页面,找到对应部署任务的日志,这里面绝对有具体的失败原因,常见的比如:- Node.js版本不兼容:比如
package.json里engines指定了nodejs18,但serverless.yml里用了nodejs20; - 依赖安装失败:私有npm包无法访问,或者网络问题导致
npm install卡住; - 代码语法错误:比如用了未转译的ES6语法,或者handler路径写错了(比如serverless.yml里写
index.handler,但实际文件里导出的是app.main)。
- Node.js版本不兼容:比如
检查serverless.yml的配置细节
重点核对这几个配置项:provider.region:必须是GCP支持的区域,别瞎写;provider.runtime:要选GCP支持的Node.js版本(比如nodejs18、nodejs20);functions.xxx.handler:格式是文件名.导出的函数名,比如代码在src/main.js里导出hello,就得写成src/main.hello;package.patterns:确保包含了所有需要的文件,比如本地依赖、静态文件,不然Cloud Build的时候会找不到。
本地预测试提前排坑
先用serverless package命令把代码打包成zip,解压看看内容是不是完整的——虽然Cloud Build会重新装依赖,但得确保package.json和package-lock.json(或yarn.lock)没损坏。另外本地先跑npm install和npm run build(如果有构建脚本的话),提前发现语法错误或者依赖问题。确认SLS用的服务账号权限
和GitLab CI一样,SLS部署用的GCP服务账号也需要cloudfunctions.developer、storage.objectAdmin、cloudbuild.builds.editor这些权限,缺了就会报错。升级SLS的GCP插件
有时候是插件版本太旧导致的兼容性问题,比如serverless-google-cloudfunctions插件,你可以用npm update serverless-google-cloudfunctions升级到最新版本,再试部署,说不定能解决已知的bug。
内容的提问来源于stack exchange,提问作者Max

