【问题标题】:How to execute PowerShell command through Terraform如何通过 Terraform 执行 PowerShell 命令
【发布时间】:2018-11-09 06:37:36
【问题描述】:

我正在尝试从 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
  • CategoryInfo : ObjectNotFound: (C:\ProgramData...izeInstance.ps1:String) [], CommandNotFoundException
  • FullyQualifiedErrorId : CommandNotFoundException

【问题讨论】:

  • 文件 'C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1' 存在吗?
  • 是的......它会在那里......但是在创建EC2实例之后......并且命令在创建后执行
  • 您是否有理由不简单地将 powershell 脚本中的代码放入带有 <powershell></powershell> 标签的 terraform 文档中?
  • 我也遵循了同样的方法,但我如何测试它是否执行?

标签: amazon-web-services powershell amazon-ec2 terraform


【解决方案1】:

您正在使用 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 连接。

不过,还有其他选项可以完成此任务。比如使用userdatawhich Terraform also supports。这可能类似于以下示例:

在 Terraform 中使用用户数据文件的示例

文件名为userdata.txt:

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

使用用户数据文件启动实例:

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)}"
}

file interpolation 将读取用户数据文件的内容作为字符串传递给用户数据以启动实例。一旦实例启动,它应该会按照您的预期运行脚本。

【讨论】:

  • 脚本执行得非常好,但我不确定如何测试命令是否成功执行?
  • 它正在从 AWS API 获取损坏的元数据
  • 这个脚本做了很多事情它会出现docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2launch.html你怎么判断它正常成功?
  • 如何配置安全组以接受 WinARM 连接。我在 aws_security_group 级别,在入口部分添加了 tcp 端口 3389、5985 和 22。但它仍然不起作用。你有什么想法吗?
【解决方案2】:

Brian 声称的内容是正确的,您将收到“无效或未知的密钥:解释器”错误。

根据 Brandon 的回答,要正确运行 powershell,您需要按以下方式运行它:

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不推荐provisioners,完整的说明和解释(很长)可以在以下位置找到:terraform.io/docs/provisioners/index.html

【讨论】:

  • 这完全没用。我们不需要运行 AMI 上已经存在的 powershell 脚本。我们需要它来运行运行 terraform 的机器上存在的 powershell 脚本。换句话说,如何将powershell脚本发送到远程机器并执行。
  • @C johnson - 我的回答很完整。没有提到如何复制文件,而是如何运行 powershell 命令。添加到如何使用“文件”配置器的答案中,尽管答案是第一个搜索结果。
【解决方案3】:

FTR:Brandon 的回答是正确的,除了为 remote-exec 提供的示例代码包含配置程序不支持的键。

commandinterpreter 都不支持密钥。

https://www.terraform.io/docs/provisioners/remote-exec.html

【讨论】:

    猜你喜欢
    • 2011-09-19
    • 2015-04-08
    • 1970-01-01
    • 1970-01-01
    • 2022-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    相关资源
    最近更新 更多