m-t-w


Project maintained by m-t-w Hosted on GitHub Pages — Theme by mattgraham

Provisioning EC2s with cloudinit_config user-data and Terraform


For each file to be used for cloud_init, create a terraform templatefile

This is a terraform data source, called a template_file. This will allow us to pass in variables from terraform. Note: the data-source declaration here does not have access to variables already defined in variables.tf (or elsewhere) - you have to pass them in.

Update: the templatefile data source has been replaced with the templatefile function

data "template_file" "install_programs" {
  template = file("${path.module}/scripts/install-programs.yaml")
  vars     = {
               cluster_stack_name   = var.cluster_stack_name,
               region               = data.aws_region.current.name,
               instance_name        = var.instance_name,
             }
}

Each yaml file should conform to the cloud-config yaml syntax

User data can come is several formats - the format I’m using here is cloud-config syntax. Here is the module reference.

Gotchas:

You must include a merge-type header if you are using multi-part MIME

This is a way to specify how cloud-config YAML (user-data) are merged together when there are multiple YAML files. Previously the merging algorithm was very simple and would only overwrite and not append lists, or strings. There are a few different ways to do this, in the example below we’re including merge-type header for every cloud-config YAML file. (see: merge-types docs)

#cloud-config
merge_how:
 - name: list
   settings: [append]
 - name: dict
   settings: [no_replace, recurse_list]
runcmd:
  - echo
  - echo "*** Schedule Docker Cleanup"
  - echo "--- Set up 4 am docker system prune job"
  - touch /var/log/docker-prune.out
  - chown ec2-user:ec2-user /var/log/docker-prune.out
  - echo

Bring it all together in one cloudinit_config data source, for use with cloudinit

See: Terraform cloud_config data source

# Bringing it all together into a single, multi-part cloud-init configuration
data "cloudinit_config" "user_data" {

  part {
    content_type = "text/cloud-config"
    content      = data.template_file.install_programs.rendered
  }

  part {
    content_type = "text/cloud-config"
    content      = data.template_file.configure_docker.rendered
  }
}

Troubleshooting

Where is the user data file stored on an E2?

/var/lib/cloud/instances/[instance-id]/user-data.txt

Where are the logs from the cloud_config cloud init?

less /var/log/cloud-init.log

less /var/log/cloud-init-output.log

Boot stages

There are five stages to boot:

  1. Generator
    • determines whether cloud-init should run during boot
  2. Local
  3. Network
  4. Config
    • runcmd (NOTE: the runcmd module only writes the script to be run later. The module that actually runs the script is scripts-user in the Final boot stage)
  5. Final
    • Any scripts that a user is accustomed to running after logging into a system should run correctly here.
    • scripts-user
    • package installations
    • configuration management plugins (puppet, chef, salt-minion)
    • user-defined scripts (i.e. shell scripts passed as user-data)

Info from here and here

Helpful docs: