Deploy local files to instances without using Terraform file provisioners

前端 未结 1 1402
再見小時候
再見小時候 2021-01-16 07:01

As several other users who have posted to StackOverflow, I ran into problems with file provisioners, and the Terraform documentation says we should not rely on them.

<
相关标签:
1条回答
  • 2021-01-16 07:30

    One solution, which works very well and does not require a direct connection to the instance, is to use the userdata as a hook to "install" the files from the base64 version of the file(s).

    We can actually embed the files as base64 strings in the userdata initialization scripts. This works for both Windows and Linux instances in AWS, and is compatible also with having a userdata script run on startup.

    Solution Description:

    1. During terraform plan, encode whatever local files you need as base64 strings using terraform functions base64encode(file("path/to/file")).
    2. (Optional) Save a marker file (_INIT_STARTED_) at the start of userdata execution; this file will have the creation timestamp of when the userdata execution started.
    3. Before running the actual userdata script, write the base64 strings to text files. (The actual command varies between windows and linux, see examples below.)
    4. Run the userdata script itself (userdata_win.bat or userdata_lin.sh)
    5. (Optional) Finally, save a second marker file (_INIT_COMPLETE_) which will have the creation timestamp of when the userdata script completed. (The absence of this file is also helpful to detect script failures and/or still-running scripts after logging into the instance.)

    For AWS Linux instances:

    data "template_file" "userdata_lin" {
      template = <<EOF
    #!/bin/bash
    mkdir -p /home/ubuntu/setup-scripts
    cd /home/ubuntu/setup-scripts
    touch _INIT_STARTED_
    echo ${base64encode(file("${path.module}/userdata_lin.sh"))} | base64 --decode > userdata.sh
    echo ${base64encode(file("${path.module}/config.json"))} | base64 --decode > config.json
    ${file("${path.module}/userdata_lin.sh")}
    sudo chmod 777 *
    touch _INIT_COMPLETE_
    EOF
    }
    
    # ...
    
    resource "aws_instance" "my_linux_instance" {
      # ...
      user_data = data.template_file.userdata_lin.rendered
    }
    

    For AWS Windows instances:

    data "template_file" "userdata_win" {
      template = <<EOF
    <script>
    mkdir C:\Users\Administrator\setup-scripts
    cd C:\Users\Administrator\setup-scripts
    echo "" > _INIT_STARTED_
    echo ${base64encode(file("${path.module}/userdata_win.bat"))} > tmp1.b64 && certutil -decode tmp1.b64 userdata.bat
    echo ${base64encode(file("${path.module}/config.json"))} > tmp2.b64 && certutil -decode tmp2.b64 config.json
    ${file("${path.module}/userdata_win.bat")}
    echo "" > _INIT_COMPLETE_
    </script>
    <persist>false</persist>
    EOF
    }
    
    # ...
    
    resource "aws_instance" "my_windows_instance" {
      # ...
      user_data = data.template_file.userdata_win.rendered
    }
    
    0 讨论(0)
提交回复
热议问题