CircleCI通过Cloud Run部署至GKE时gcloud认证失败求助
解决CircleCI GCP GCR Orb 解析服务账号JSON失败的问题
问题背景
我尝试通过CircleCI结合Google Cloud Run将应用部署到GKE,使用官方GCP Orbs来简化配置,但在initialize gcloud步骤中始终报错:
ERROR: (gcloud.auth.activate-service-account) Could not read json file /root/gcloud-service-key.json: No JSON object could be decoded
错误原因分析
从配置和报错信息来看,主要有两个关键问题:
- 环境变量写入语法错误:在
Prepare env vars步骤中,echo 'export GOOGLE_COMPUTE_ZONE=us-east1-b' >> BASH_ENV缺少了$符号,应该是$BASH_ENV,这会导致这条环境变量无法正确加载,后续步骤可能读取到无效内容。 - 服务账号密钥传递流程冗余且易出错:你把
GCP_PROJECT_KEY写入文件后,再将文件内容导出为GOOGLE_CLOUD_KEYS,这个过程容易出现格式损坏(比如换行符丢失、转义字符处理异常),导致生成的gcloud-service-key.json不是有效的JSON结构。另外,你已经在CircleCI项目设置中配置了GCLOUD_SERVICE_KEY,完全可以直接使用这个变量,不需要额外的文件读写操作。
修正后的配置方案
以下是调整后的config.yaml,重点修正了环境变量处理和服务账号密钥的传递方式:
version: 2.1 orbs: gcp-gcr: circleci/gcp-gcr@0.6.1 cloudrun: circleci/gcp-cloud-run@1.0.2 executors: node-executor: docker: - image: node:12.8.1-stretch gcloud-executor: docker: - image: google/cloud-sdk machine-executor: machine: true jobs: build: description: initial build executor: machine-executor steps: - checkout build_push_image_cloud_run_mangaged: executor: node-executor steps: - checkout - setup_remote_docker: docker_layer_caching: false - run: name: Prepare env vars command: | echo 'export PATH=$PATH:$HOME/.local/bin' >> $BASH_ENV echo 'export GOOGLE_PROJECT_ID=$GCLOUD_PROJECT' >> $BASH_ENV echo 'export GOOGLE_COMPUTE_ZONE=us-east1-b' >> $BASH_ENV echo 'export TAG=${CIRCLE_SHA1}' >> $BASH_ENV echo 'export IMAGE_NAME=$CIRCLE_PROJECT_REPONAME' >> $BASH_ENV source $BASH_ENV # 直接使用CircleCI项目配置的GCLOUD_SERVICE_KEY环境变量 - gcp-gcr/gcr-auth: gcloud-service-key: GCLOUD_SERVICE_KEY google-project-id: GOOGLE_PROJECT_ID google-compute-zone: GOOGLE_COMPUTE_ZONE - gcp-gcr/build-image: dockerfile: Dockerfile google-project-id: GOOGLE_PROJECT_ID image: $IMAGE_NAME registry-url: "gcr.io" tag: $CIRCLE_SHA1 - gcp-gcr/push-image: google-project-id: GOOGLE_PROJECT_ID image: $IMAGE_NAME registry-url: "gcr.io" tag: $CIRCLE_SHA1 - cloudrun/init: gcloud-service-key: GCLOUD_SERVICE_KEY google-project-id: GOOGLE_PROJECT_ID google-compute-zone: GOOGLE_COMPUTE_ZONE - cloudrun/deploy: cluster: "new-cluster" cluster-location: "us-east1-b" platform: "gke" image: "gcr.io/$GOOGLE_PROJECT_ID/$IMAGE_NAME:$TAG" service-name: "orb-gcp-cloud-run" workflows: build_gcloud_deploy: jobs: - build - build_push_image_cloud_run_mangaged: requires: - build
关键修正点说明
- 修复环境变量写入错误:把
BASH_ENV改为$BASH_ENV,确保环境变量正确写入到当前shell的配置文件中。 - 简化服务账号密钥传递:直接使用CircleCI项目设置中已配置的
GCLOUD_SERVICE_KEY环境变量,跳过手动写入文件再读取的步骤,避免格式损坏。 - 完善镜像标签:在
cloudrun/deploy步骤的image参数中加上:$TAG,确保部署的是刚构建的特定版本镜像,避免使用旧镜像。
额外建议
如果后续需要手动处理服务账号JSON,建议先对JSON内容进行base64编码后再存储到CircleCI环境变量中,解码时可以用如下命令:
echo $GCLOUD_SERVICE_KEY | base64 --decode > $HOME/gcloud-service-key.json
不过使用官方GCP Orbs的话,直接传递编码后的环境变量即可,Orb会自动处理解码逻辑。
内容的提问来源于stack exchange,提问作者vijayakumarpsg587




