Terraform:等到实例“可达”

kha*_*iuk 4 amazon-ec2 amazon-web-services ansible terraform

我有一些带有 aaws_instance和 a 的Terraform 代码null_resource

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"
  }
}
Run Code Online (Sandbox Code Playgroud)

它有点工作,但有时会出现错误(可能是当实例处于挂起状态时)。当我重新运行 Terraform 时 - 它按预期工作。

问题:如何仅在实例运行并接受 SSH 连接时运行 local-exec?

yda*_*coR 9

null_resource目前只打算等到aws_instance资源完成这又只有等到AWS API返回它的Running状态。从那里到实例启动操作系统然后能够在您的local-exec供应商可以连接之前接受 SSH 连接之间有很长的差距。

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

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"
  }
}
Run Code Online (Sandbox Code Playgroud)

这将首先尝试以centos具有files/id_rsa私钥的用户身份连接到实例的公共 DNS 地址。连接后,它将echo 'connected!'作为一个简单的命令运行,然后再local-exec转到针对实例运行 Ansible 的现有配置器。

请注意,仅仅能够通过 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"
  }
}
Run Code Online (Sandbox Code Playgroud)


kha*_*iuk 8

这是针对此问题的 Ansible 特定解决方案。将此代码添加到您的剧本中(如果您使用角色,还有一个 pre_task 子句)

- name: will wait till reachable
  hosts: all
  gather_facts: no # important
  tasks:
    - name: Wait for system to become reachable
      wait_for_connection:

    - name: Gather facts for the first time
      setup:
Run Code Online (Sandbox Code Playgroud)