当使用远程执行预配程序时instance_count超过 2 时,Terraform 会卡住


  • 我正在尝试使用null_resource使用Terraform的远程执行配置器配置多个Windows EC2实例。

$ terraform -v Terraform v0.12.6 provider.aws v2.23.0 provider.null v2.1.2

  • 最初,我使用三个远程执行配置器(其中两个涉及重启实例(没有null_resource,对于单个实例,一切都运行良好。
  • 然后我需要增加计数,并根据几个链接,最终使用了null_resource。因此,我已经将问题减少到我甚至无法使用null_resource为 2 个以上的 Windows EC2 实例运行一个远程执行配置程序的程度。

用于重现错误消息的地形模板:

//VARIABLES
variable "aws_access_key" {
default = "AK"
}
variable "aws_secret_key" {
default = "SAK"
}
variable "instance_count" {
default = "3"
}
variable "username" {
default = "Administrator"
}
variable "admin_password" {
default = "Password"
}
variable "instance_name" {
default = "Testing"
}
variable "vpc_id" {
default = "vpc-id"
}
//PROVIDERS
provider "aws" {
access_key = "${var.aws_access_key}"
secret_key = "${var.aws_secret_key}"
region     = "ap-southeast-2"
}
//RESOURCES
resource "aws_instance" "ec2instance" {
count         = "${var.instance_count}"
ami           = "Windows AMI"
instance_type = "t2.xlarge"
key_name      = "ec2_key"
subnet_id     = "subnet-id"
vpc_security_group_ids = ["${aws_security_group.ec2instance-sg.id}"]
tags = {
Name = "${var.instance_name}-${count.index}"
}
}
resource "null_resource" "nullresource" {
count = "${var.instance_count}"
connection {
type     = "winrm"
host     = "${element(aws_instance.ec2instance.*.private_ip, count.index)}"
user     = "${var.username}"
password = "${var.admin_password}"
timeout  = "10m"
}
provisioner "remote-exec" {
inline = [
"powershell.exe Write-Host Instance_No=${count.index}"
]
}
//   provisioner "local-exec" {
//     command = "powershell.exe Write-Host Instance_No=${count.index}"
//   }
//   provisioner "file" {
//       source      = "testscript"
//       destination = "D:/testscript"
//   }
}
resource "aws_security_group" "ec2instance-sg" {
name        = "${var.instance_name}-sg"
vpc_id      = "${var.vpc_id}"

//   RDP
ingress {
from_port   = 3389
to_port     = 3389
protocol    = "tcp"
cidr_blocks = ["CIDR"]
}
//   WinRM access from the machine running TF to the instance
ingress {
from_port   = 5985
to_port     = 5985
protocol    = "tcp"
cidr_blocks = ["CIDR"]
}
tags = {
Name        = "${var.instance_name}-sg"
}
}
//OUTPUTS
output "private_ip" {
value = "${aws_instance.ec2instance.*.private_ip}"
}

观察:

  • 使用一个远程执行预配程序,如果计数设置为 1 或 2,则工作正常。对于计数 3,无法预测所有预配程序每次都会在所有实例上运行。但是,有一件事是肯定的,Terraform永远不会完成并且不显示输出变量。它一直显示"null_resource.nullresource[count.index]:仍在创建...">
  • 对于本地执行配置程序- 一切正常。测试时计数值为 1、2 和 7。
  • 对于文件配置器,它在 1、2 和 3 上工作正常,但在 7 上没有完成,但文件在所有 7 个实例上都已复制。它一直显示"null_resource.nullresource[count.index]:仍在创建...">
  • 此外,在每次尝试中,remote-exec 配置器都能够连接到实例,而不管计数的值如何,只是,它不会触发内联命令并随机选择跳过它并开始显示"仍在创建..."消息。
  • 我已经在这个问题上呆了很长时间了。在调试日志中也找不到任何重要内容。我知道不建议将 Terraform 用作配置管理工具,但是,如果实例计数仅为 1(即使没有 null_resource(,即使使用复杂的配置脚本,一切也可以正常工作,这表明 Terraform 应该很容易处理这样的基本配置要求。
  • TF_DEBUG日志:
  • count=2,TF 成功完成并显示"应用完成!"。
  • count=3,TF 在所有三个实例上运行远程可执行文件,但不会完成,也不会不显示输出变量。卡在"仍在创建...">
  • count=3,TF 仅在两个实例上运行远程可执行文件,并在 nullresource[1] 上跳过,不会完成并且不会不显示输出变量。卡在"仍在创建...">
  • 任何指示将不胜感激!

更新:最终的诀窍是根据此问题评论将 Terraform 降级为v11.14

您可以尝试以下几种方法:

  1. 内联remote-exec
resource "aws_instance" "ec2instance" {
count         = "${var.instance_count}"
# ...
provisioner "remote-exec" {
connection {
# ...
}
inline = [
# ...
]
}
}

现在,您可以参考connection块内的self来获取实例的私有 IP。

  1. triggers添加到null_resource
resource "null_resource" "nullresource" {
triggers {
host    = "${element(aws_instance.ec2instance.*.private_ip, count.index)}" # Rerun when IP changes
version = "${timestamp()}" # ...or rerun every time
}
# ...
}

可以使用triggers属性重新创建null_resource,从而重新执行remote-exec

我在null_resource中使用了这个triger,它非常适合我。当实例数量增加并在所有实例上进行配置时,它也可以工作。我正在使用terraform和openstack。

触发器= { instance_ids = join(",",openstack_compute_instance_v2.swarm-cluster-hosts[*].id( }

Terraform 0.12.26 为我解决了类似的问题(在部署多个虚拟机时使用多个文件配置器时(

希望这对您有所帮助: https://github.com/hashicorp/terraform/issues/22006

最新更新