如何通过Terraform执行PowerShell命令

3

我正在尝试从AMI创建一个Windows Ec2实例,并在该实例上执行powershell命令,命令如下:

data "aws_ami" "ec2-worker-initial-encrypted-ami" {
    filter {
        name   = "tag:Name"
        values = ["ec2-worker-initial-encrypted-ami"]
    }  
}

resource "aws_instance" "my-test-instance" {
  ami             = "${data.aws_ami.ec2-worker-initial-encrypted-ami.id}"
  instance_type   = "t2.micro"

  tags {
    Name = "my-test-instance"
  }

  provisioner "local-exec" {
    command = "C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule",
    interpreter = ["PowerShell"]
  }

}

我遇到了以下错误:

  • aws_instance.my-test-instance: 运行命令时出错 'C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule': 结束状态为1。 输出:未识别项 'C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1' 是 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,或者如果包含路径,请验证该路径是否正确,然后重试。 在行:1 字符:72
  • C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 <<<< -Schedule
    • CategoryInfo : ObjectNotFound: (C:\ProgramData...izeInstance.ps1:String) [], CommandNotFoundException
    • FullyQualifiedErrorId : CommandNotFoundException

文件'C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1'存在吗? - Victor Silva
是的...它会在EC2实例创建后出现..并且该命令在创建后执行。 - Akshay Tilekar
1
你为什么不直接将 PowerShell 脚本中的代码放入 Terraform 文档中,并用 <powershell></powershell> 标签包围它呢? - webmite
我已经按照相同的步骤进行了,但如何测试它是否已执行? - Akshay Tilekar
更详细的解释和示例源代码请参见此处 - Raygun
3个回答

12
您正在使用local-exec提供程序,在运行Terraform的工作站上运行请求的powershell代码:

local-exec提供程序在资源创建后调用本地可执行文件。这会在运行Terraform的计算机上启动进程,而不是在资源上。

听起来您想要在生成的实例上执行powershell脚本,那么您需要使用remote-exec提供程序,在目标资源上运行您的powershell:

remote-exec提供程序在创建远程资源后在其中调用脚本。这可用于运行配置管理工具、引导到集群等。

您还需要包含connection详细信息,例如:
  provisioner "remote-exec" {
    command = "C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule",
    interpreter = ["PowerShell"]
    connection {
      type     = "winrm"
      user     = "Administrator"
      password = "${var.admin_password}"
    }
  }

这意味着该实例必须准备好接受WinRM连接。

还有其他完成此任务的选项。例如,使用userdataTerraform也支持此功能。示例如下:

Terraform中使用userdata文件的示例

名为userdata.txt的文件:

<powershell>
C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule
</powershell>

使用userdata文件启动实例:

resource "aws_instance" "my-test-instance" {
  ami             = "${data.aws_ami.ec2-worker-initial-encrypted-ami.id}"
  instance_type   = "t2.micro"

  tags {
    Name = "my-test-instance"
  }

  user_data = "${file(userdata.txt)}"
}
文件插值将以字符串形式读取userdata文件的内容,以便将其传递给实例启动的userdata。一旦实例启动,它应该按照您的预期运行脚本。

脚本执行得非常好,但我不确定如何测试命令是否成功执行? - Akshay Tilekar
它正在从AWS API中获取与损坏的元数据相关的信息。 - Akshay Tilekar
这个脚本似乎做了很多事情,你如何通常确定它是否成功?https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2launch.html - Brandon Miller
如何配置安全组以接受WinARM连接。我在aws_security_group级别上添加了入口部分的tcp端口3389、5985和22。但它仍然无法工作。你有什么想法吗? - cherah30

6

Brian所说的是正确的,你会遇到"无效或未知的键:interpreter"错误。

为了正确运行PowerShell,你需要按照Brandon的答案运行它:

provisioner "remote-exec" {
    connection {
      type     = "winrm"
      user     = "Administrator"
      password = "${var.admin_password}"
    }

inline = [
         "powershell -ExecutionPolicy Unrestricted -File C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule"
        ]
      }

编辑 将文件复制到计算机上,请使用以下方法:

  provisioner "file" {
    source      = "${path.module}/some_path"
    destination = "C:/some_path"

    connection {
      host = "${azurerm_network_interface.vm_nic.private_ip_address}"
      timeout  = "3m"
      type     = "winrm"
      https    = true
      port     = 5986
      use_ntlm = true
      insecure = true

      #cacert = "${azurerm_key_vault_certificate.vm_cert.certificate_data}"
      user     = var.admin_username
      password = var.admin_password
    }
  }

更新: 目前,Hashicorp不建议使用配置程序。完整的说明和解释(很长)可以在 terraform.io/docs/provisioners/index.html 找到。

2
这完全没有用。我们不需要在 AMI 上运行已经存在的 PowerShell 脚本。我们需要运行一个存在于运行 Terraform 的机器上的 PowerShell 脚本。换句话说,我们需要将 PowerShell 脚本发送到远程机器并执行它。 - C.J.
1
@C johnson - 我的答案是完整的。没有提到如何复制文件,而是如何运行PowerShell命令。在答案中添加了如何使用“file”配置管理器,尽管该问题的答案是第一个搜索结果。 - Pixel

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接