GitLab CI中Packer构建GCP镜像失败:{message:401 Unauthorized}命令未找到
问题分析
从报错信息可以看到,Packer尝试执行的脚本第一行被替换成了{message:401 Unauthorized},而非你编写的bash脚本头部。这说明原本的脚本没有被正确传输到GCP构建实例中,反而被返回了401未授权的错误响应。结合本地和GCP虚拟机能正常运行、仅GitLab CI环境失败的情况,问题核心出在CI环境的GCP认证配置或网络限制上。
排查与解决方案
1. 验证GitLab CI的GCP凭据有效性
- 确认CI中配置的GCP服务账号密钥完整且权限足够:
- 服务账号需至少拥有
Compute Instance Admin (v1)、Service Account User权限,若涉及镜像存储还需Storage Object Admin; - 检查CI变量
GOOGLE_APPLICATION_CREDENTIALS指向的密钥文件内容无截断、格式正确。
- 服务账号需至少拥有
- 在CI脚本中添加调试步骤验证凭据:
若此步骤报错401,需重新生成服务账号密钥或调整权限。gcloud auth activate-service-account --key-file="$GOOGLE_APPLICATION_CREDENTIALS" gcloud compute instances list --project=你的项目ID
2. 检查Packer模板的认证配置
- 避免在模板中硬编码凭据,依赖GitLab CI注入的
GOOGLE_APPLICATION_CREDENTIALS环境变量,Packer会自动读取该变量:source "googlecompute" "my_vm" { project_id = "你的项目ID" zone = "你的可用区" source_image_family = "debian-11" service_account_email = "你的服务账号邮箱" scopes = ["https://www.googleapis.com/auth/compute"] } - 不要使用模板中的
account_file字段,防止与CI环境的凭据冲突。
3. 排查GitLab Runner的网络限制
共享Runner可能存在网络访问限制,导致Packer无法正常调用GCP API或传输脚本:
- 添加网络连通性测试到CI脚本:
若返回401则聚焦凭据问题,若返回超时/无法访问,说明Runner网络无法连接GCP API,可临时使用代理或提前迁移自有Runner。curl -I https://www.googleapis.com/compute/v1/projects/你的项目ID/zones/你的可用区/instances
4. 换用内嵌脚本避免传输问题
将脚本内容直接嵌入Packer模板的shell配置中,绕开文件传输环节:
provisioner "shell" { inline = [ "#!/bin/bash", "set -e", "if [ \"$EUID\" -ne 0 ]; then echo \"Please run as root\"; exit; fi", "apt update", "apt install -y curl", "curl -fsSL https://deb.nodesource.com/setup_18.x | bash -", "apt upgrade -y iptables", "apt install -y nginx libzmq3-dev nodejs ipset iptables-persistent net-tools libre2-dev", "npm install -g yarn", "rm /etc/nginx/sites-enabled/default" ] }
5. 升级Packer Google插件
你当前使用的packer-plugin-googlecompute_v1.0.16版本较旧,可能存在已知的认证或脚本传输bug,在CI脚本中添加升级步骤:
packer plugins install github.com/hashicorp/googlecompute
内容的提问来源于stack exchange,提问作者Alon Ben Nun
相关产品推荐
相关产品推荐

