You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何成功将ProxyCommand传递给Terraform的provisioner local-exec执行

问题根因

你遇到的报错确实来自多层单引号嵌套的解析冲突:Shell解析命令时会将--ssh-common-args='-o ProxyCommand='里的第二个单引号识别为第一个单引号的闭合符,导致整个命令结构被破坏,无法正常执行。你对堡垒机公网IP的变量引用${aws_instance.bastion.public_ip}是正确的,没有问题。

修复方案

方案1:直接修正命令行引号嵌套

通过转义双引号包裹--ssh-common-args的参数值,避免单引号嵌套冲突,同时修正Ansible单主机inventory的格式(末尾加逗号,避免Ansible将IP识别为文件路径),修改后的local-exec代码如下:

provisioner "local-exec" {
  command = "sleep 30; ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -u ubuntu --private-key ~/.ssh/id_rsa --ssh-common-args=\"-o ProxyCommand='ssh -W %h:%p ubuntu@${aws_instance.bastion.public_ip}'\" -i '${self.private_ip},' main.yml"
}

这里将sleep时间从120秒缩短到30秒,只要服务器SSH服务启动完成即可执行,无需等待过长时间。

方案2:模板渲染Ansible Inventory(更易维护)

如果后续需要管理多台内网服务器,建议通过Terraform模板渲染Inventory文件,避免命令行堆砌参数,可读性和可维护性更高:

  1. 新建Inventory模板文件inventory.tpl:
[servers]
${server_private_ip} ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p ubuntu@${bastion_public_ip}"'
  1. 修改Terraform代码,先渲染模板再执行Ansible:
resource "aws_instance" "server1" {
  # 原有实例配置保持不变
  ami           = var.ubuntu2004
  instance_type = "t3.small"
  subnet_id = aws_subnet.some_other_subnet.id
  vpc_security_group_ids = [aws_security_group.other_temp.id]
  key_name = "key"
  tags = {
    Name = "server1"
  }

  provisioner "local-exec" {
    command = templatefile("${path.module}/inventory.tpl", {
      server_private_ip = self.private_ip
      bastion_public_ip = aws_instance.bastion.public_ip
    }) > inventory.ini && sleep 30 && ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i inventory.ini main.yml
  }
}

方案3:配置SSH全局代理规则(最简便)

如果你的本地环境固定,可直接在~/.ssh/config中配置内网网段的全局代理规则,后续所有SSH/Ansible请求都会自动走堡垒机转发,无需在命令中携带任何代理参数:

Host 10.0.0.0/16 # 替换为你AWS VPC的内网网段
  User ubuntu
  ProxyCommand ssh -W %h:%p ubuntu@<堡垒机公网IP> # 也可直接写固定的堡垒机公网IP
  IdentityFile ~/.ssh/id_rsa
  StrictHostKeyChecking no

配置完成后,local-exec的命令可以简化为:

provisioner "local-exec" {
  command = "sleep 30; ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -u ubuntu --private-key ~/.ssh/id_rsa -i '${self.private_ip},' main.yml"
}
额外注意事项
  • 确保堡垒机安全组放行本地公网IP的22端口入站规则
  • 确保内网服务器server1的安全组放行堡垒机私网IP的22端口入站规则
  • 确保本地~/.ssh/id_rsa文件权限为600,避免SSH拒绝读取密钥

内容的提问来源于stack exchange,提问作者Fresh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 12:36:04