如何无需手动SSH密钥,使用Ansible连接GCP Compute实例?
我正在为GCP Compute实例配置Ansible,希望直接通过GCP凭证登录实例。已知ansible gcp_compute模块仅能获取清单列表,不想为所有实例手动配置SSH密钥,还要定期轮换,操作繁琐。
尝试采用GCP IAP隧道方式配置,但未能成功,报错信息如下:
fatal: [host-1]: FAILED! => {"ansible_facts": {}, "changed": false, "failed_modules": {"ansible.legacy.setup": {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "failed": true, "module_stderr": "ERROR: (gcloud.compute.ssh) argument [USER@]INSTANCE: Must be specified.
Usage: gcloud compute ssh [USER@]INSTANCE [optional flags] [-- SSH_ARGS ...]
optional flags may be --command | --container | --dest-group | --dry-run |
--force-key-file-overwrite | --help | --internal-ip |
--network | --plain | --region | --ssh-flag |
--ssh-key-expiration | --ssh-key-expire-after |
--ssh-key-file | --strict-host-key-checking |
--troubleshoot | --tunnel-through-iap | --zoneFor detailed information on this command and its flags, run:
gcloud compute ssh --help
", "module_stdout": "", "msg": "MODULE FAILURE
See stdout/stderr for the exact error", "rc": 2, "warnings": ["Platform unknown on host host-1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change the meaning of that path. See https://docs.ansible.com/ansible-core/2.16/reference_appendices/interpreter_discovery.html for more information."]}}, "msg": "The following modules failed to execute: ansible.legacy.setup
"}
错误原因分析
报错核心是gcloud compute ssh命令未获取到正确的实例参数,说明Ansible连接配置中的变量传递存在问题,导致命令无法识别目标实例。
1. 前置准备:确保gcloud工具具备IAP访问权限
- 确认操作账号拥有
roles/iap.tunnelResourceAccessor权限,可通过GCP IAP访问目标实例 - 本地gcloud已完成登录,且能直接执行
gcloud compute ssh <实例名> --tunnel-through-iap成功连接实例
2. 配置Ansible连接参数
方式一:静态inventory单独定义
在静态inventory文件(如hosts.ini)中,为每个实例指定连接参数:
[gcp_instances] host-1 ansible_host=<实例内部/外部IP> ansible_user=<实例默认用户,如ubuntu> ansible_connection=ssh ansible_ssh_common_args='-o ProxyCommand="gcloud compute ssh %h --user %r --tunnel-through-iap --ssh-flag=\"-W %h:%p\" --zone <实例所在区>"'
方式二:全局配置(适用于同区域实例)
编辑ansible.cfg,统一设置SSH连接参数:
[defaults] inventory = ./hosts.ini [ssh_connection] ssh_args = -o ProxyCommand="gcloud compute ssh %h --user %r --tunnel-through-iap --ssh-flag='-W %h:%p' --zone <实例所在区>"
注意:若实例分布在不同区域,建议使用host_vars单独定义zone,避免全局配置冲突
3. 动态inventory自动拉取实例(高效方案)
通过gcp_compute动态inventory自动获取实例信息,同时注入连接参数:
创建gcp_inventory.yml:
plugin: gcp_compute projects: - <你的GCP项目ID> auth_kind: serviceaccount service_account_file: <服务账号密钥文件路径> zones: - <实例所在区> filters: [] keyed_groups: - key: labels prefix: label compose: ansible_host: networkInterfaces[0].networkIP # 使用内部IP结合IAP更安全 ansible_user: "'ubuntu'" # 替换为实例默认登录用户 ansible_ssh_common_args: "'-o ProxyCommand=\"gcloud compute ssh %h --user %r --tunnel-through-iap --ssh-flag=-W%h:%p --zone {{ zone }}\"'"
在ansible.cfg中指定该动态inventory:
[defaults] inventory = ./gcp_inventory.yml
4. 测试连接
执行以下命令验证配置有效性:
ansible host-1 -m ping
关键注意事项
- 确保
%h(目标主机)和%r(登录用户)在ProxyCommand中被Ansible正确解析替换 - 若实例无外部IP,必须使用内部IP,且gcloud需能访问实例所在VPC(可通过Cloud VPN/Cloud Connect实现)
- 服务账号需具备
compute.instances.get权限,才能通过动态inventory获取实例信息 - 使用服务账号时,需先激活:
gcloud auth activate-service-account --key-file=<密钥文件>
内容的提问来源于stack exchange,提问作者Joel Shajan

