cloud-init - 我试图通过云初始化将文件复制到 Windows EC2 实例,方法是将其传递给用户数据

mel*_*ous 3 amazon-web-services cloud-init terraform terraform-provider-aws

我试图通过云初始化将文件复制到 Windows EC2 实例,方法是传递用户数据,云初始化模板运行,它创建一个文件夹但不复制文件,您能帮助我理解我在代码中做错了什么吗?

此代码通过自动缩放组的启动配置传递

data template_cloudinit_config ebs_snapshot_scripts {
  gzip          = false
  base64_encode = false

  part {
    content_type = "text/cloud-config"
    content      = <<EOF
<powershell>
$path = "C:\aws"
If(!(test-path $path))
{
      New-Item -ItemType Directory -Force -Path $path
}
</powershell>

write_files:
   -  content: |
     ${file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/1-start-ebs-snapshot.ps1")}
       path: C:\aws\1-start-ebs-snapshot.ps1
       permissions: '0744'
   -   content: |
     ${file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/2-run-backup.cmd")}
       path: C:\aws\2-run-backup.cmd
       permissions: '0744'
   -   content: |
     ${file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/3-ebs-snapshot.ps1")}
       path: C:\aws\3-ebs-snapshot.ps1
       permissions: '0744'
EOF
  }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ins 7

您当前的方法涉及使用 Terraform 模板语言通过将字符串连接在一起来生成 YAML,其中一些字符串是来自外部文件的多行字符串,并且由于 YAML 是一种空白敏感语言,因此要正确执行该操作始终非常复杂。

我有两个想法可以让这件事变得更容易。您可能会同时执行这两项操作,尽管执行其中一项也可能有效。


第一个想法是遵循Terraform 函数文档中有关生成 JSON 和 YAML 的建议templatefile。尽管您的模板是内联的而不是在单独的文件中,但您可以在此处应用类似的原则,让 Terraform 本身负责生成有效的 YAML,然后您只需担心使输入数据结构成为正确的形状:

  part {
    content_type = "text/cloud-config"

    # JSON is a subset of YAML, so cloud-init should
    # still accept this even though it's jsonencode.
    content = jsonencode({
      write_files = [
        {
          content     = file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/1-start-ebs-snapshot.ps1")
          path        = "C:\\aws\\1-start-ebs-snapshot.ps1"
          permissions = "0744"
        },
        {
          content     = file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/2-run-backup.cmd")
          path        = "C:\\aws\\2-run-backup.cmd"
          permissions = "0744"
        },
        {
          content     = file("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/3-ebs-snapshot.ps1")
          path        = "C:\\aws\\3-ebs-snapshot.ps1"
          permissions = "0744"
        },
      ]
    })
  }
Run Code Online (Sandbox Code Playgroud)

和Terraform 函数知道如何自动转义换行符和其他特殊字符,因此您只需将文件内容作为jsonencode属性yamlencode包含在对象中,Terraform 就会自动将其编码为有效的字符串文字。


第二个想法是使用base64编码而不是直接编码。如果您将附加属性设置为 .Cloud-init 允许将文件内容作为 base64encoding传递b64。然后,您可以使用Terraform 的filebase64函数将文件内容直接读取到 Base64 字符串中,然后将其包含到 YAML 中,而无需任何特殊的引用或转义。

使用 base64 还意味着放置在远程系统上的文件应该与 Terraform 模块中磁盘上的文件逐字节相同,而通过使用fileYAML 字符串,可能会更改行结尾和其他空格一路上。

另一方面,使用 base64 的一个缺点是文件内容在输出中无法直接读取terraform plan,因此计划不会像使用普通 YAML 字符串编码那样清晰。


filebase64您可以通过使用函数作为jsonencode第一个示例中参数的一部分来将这两种想法结合在一起:

        # ...
        {
          encoding    = "b64"
          content     = filebase64("${path.module}/../../../../scripts/aws-ebs-snapshot-ps/1-start-ebs-snapshot.ps1")
          path        = "C:\\aws\\1-start-ebs-snapshot.ps1"
          permissions = "0744"
        },
        # ...
Run Code Online (Sandbox Code Playgroud)