Amazon web services Terraform:等待实例为";可达的;

Amazon web services Terraform:等待实例为";可达的;,amazon-web-services,amazon-ec2,ansible,terraform,Amazon Web Services,Amazon Ec2,Ansible,Terraform,我有一些带有aws\u实例和null\u资源的地形代码: resource "aws_instance" "example" { ami = data.aws_ami.server.id instance_type = "t2.medium" key_name = aws_key_pair.deployer.key_name tags = { name = "example" } vpc_security_group_ids =

我有一些带有
aws\u实例
null\u资源的地形代码

resource "aws_instance" "example" {
  ami           = data.aws_ami.server.id
  instance_type = "t2.medium"
  key_name      = aws_key_pair.deployer.key_name

  tags = {
    name = "example"
  }

  vpc_security_group_ids = [aws_security_group.main.id]
}

resource "null_resource" "example" {
  provisioner "local-exec" {
    command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -T 300 -i ${aws_instance.example.public_dns}, --user centos --private-key files/id_rsa playbook.yml"
  }
}
它可以正常工作,但有时会出现bug(可能是在实例处于挂起状态时)。当我重新运行Terraform时,它按预期工作


问题:仅当实例正在运行并接受SSH连接时,我如何才能运行local exec?

请查看
取决于


它不应该被使用,但如果你这样做了,总是写评论!!这应该能解决你的问题。如果您真的希望它在ssh运行之后运行,ansible就是这样,然后,您可以为实例创建一个运行状况检查,并依赖于此。

当前,
null\u资源
只会等待
aws\u实例
资源完成,而该资源只会等待aws API返回其处于
运行
状态。从这里到实例启动操作系统,然后在您的
localexec
provisioner能够连接之前能够接受SSH连接,还有很长的距离

处理此问题的一种方法是首先在实例上使用
remoteexec
provisioner,因为它能够等待实例准备就绪。更改现有代码以处理此问题将如下所示:

resource "aws_instance" "example" {
  ami           = data.aws_ami.server.id
  instance_type = "t2.medium"
  key_name      = aws_key_pair.deployer.key_name

  tags = {
    name = "example"
  }

  vpc_security_group_ids = [aws_security_group.main.id]


}

resource "null_resource" "example" {
  provisioner "remote-exec" {
    connection {
      host = aws_instance.example.public_dns
      user = "centos"
      file = file("files/id_rsa")
    }

    inline = ["echo 'connected!'"]
  }

  provisioner "local-exec" {
    command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -T 300 -i ${aws_instance.example.public_dns},  --user centos --private-key files/id_rsa playbook.yml"
  }
}
这将首先尝试使用
files/id\u rsa
私钥作为
centos
用户连接到实例的公共DNS地址。一旦连接,它将运行
echo'connected!'
作为一个简单的命令,然后再转到针对实例运行Ansible的现有
local exec
provisioner

请注意,仅仅能够通过SSH进行连接实际上可能不足以提供实例。如果您的Ansible脚本试图与包管理器交互,则您可能会发现它已从实例的用户数据脚本运行中锁定。如果是这种情况,您需要远程执行一个脚本,等待
cloud init
首先完成。示例脚本如下所示:

resource "aws_instance" "example" {
  ami           = data.aws_ami.server.id
  instance_type = "t2.medium"
  key_name      = aws_key_pair.deployer.key_name

  tags = {
    name = "example"
  }

  vpc_security_group_ids = [aws_security_group.main.id]


}

resource "null_resource" "example" {
  provisioner "remote-exec" {
    connection {
      host = aws_instance.example.public_dns
      user = "centos"
      file = file("files/id_rsa")
    }

    inline = ["echo 'connected!'"]
  }

  provisioner "local-exec" {
    command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -T 300 -i ${aws_instance.example.public_dns},  --user centos --private-key files/id_rsa playbook.yml"
  }
}
#/bin/bash
而[!-f/var/lib/cloud/instance/boot finished];做
echo-e“\033[1;36M等待云初始化…”
睡眠1
完成

对于这个问题有一个可行的具体解决方案。将此代码添加到您的剧本中(如果您使用角色,则有all so pre_task子句)


这不会等待实例完全运行,它只会等待AWS API返回实例已启动。从那里到接受SSH连接的实例还有很长的距离。我觉得这是一个有点“黑客”的解决方案,但它解决了问题。Thx