Terraform user_data, remote-exec & triggers

(example using aws ec2 instance)

user_data attribute is used to define custom initialization scripts or cloud-init scripts that are executed when launching an instance or a resource. This attribute is commonly used in cloud platform like AWS, Azure & Google Cloud.

remote-exec is a terraform provisioner that allows you to execute commands on a remote resource after it's created. This is commonly used with null_resource.

triggers are used to force recreation of a resource under certain conditions. One scenario can be to set trigger for stop/start an application or resource based on certain conditions.

We are going to demonstrate all three attributes by building an EC2 instance.

1.Below step creates a standard ec2 instance with user_data attribute for installing and starting an apache webserver. (Note: custom VPC, subnet is used in this case, we will go through this topic in another article )

# Step 1 - implement user_data
resource "aws_instance" "my_webserver" {
  ami = var.my-ami
  availability_zone = var.myaz
  instance_type = var.my-instance-type
  associate_public_ip_address = true
  subnet_id = aws_subnet.my_subnet.id
  vpc_security_group_ids = [aws_security_group.allow_ssh_http.id]
  tags = {
    Name = "${var.my-ec2-instance}"
  }
   user_data = <<-EOF
   #!/bin/bash
   sudo apt update
   sudo apt install apache2 -y
   echo "Hello from Srini" > /var/www/html/index.html
   echo "Hi there !!"> /var/www/html/hi.html
   echo "test webserver" > /var/www/html/test.html
   sudo systemctl restart apache2
   sudo systemctl enable apache2
  EOF  
}        

Standard installation commands are written under user_data attribute which is represented within a <<-EOF ... EOF block.

2. null_resource is used for sending remote execution commands. In the below snippet, we establish a ssh connection using pem key with ec2 instance. using this provisioner commands can be passed to the instance like stopping apache instance or writing a log entry etc.

resource "null_resource" "test1" {
  connection {
    type = "ssh"
    user = "ubuntu"
    host = aws_instance.my_webserver.public_ip
    private_key = file("C:\\terraform\\srini_ec2.pem")
  }
  provisioner "remote-exec" {
    inline = ["echo 'Hello from Terraform ${timestamp()}' | sudo tee /var/www/html/test.html"]
  }
}        

In above snippet, two blocks are written, one for setting up ssh connection where a pem file is assigned to private_key. secondly, remote-exec provisioner used to pass comands in a list. Note, above command will execute once while setting up aws_instance.

3. trigger attribute is included in null_resource provisioner , based on the trigger condition, remote-exec command can be executed whenever terraform apply is issued.

resource "null_resource" "test1" {
   triggers = {
   always_run = "${timestamp()}"
   }
...        

In summary, user_data is primarily used for providing initialization scripts or cloud-init directives at instance launch.

remote-exec is used for running commands on a running instance after it has been created.

While user_data is more cloud-agnostic, remote-exec is often used in combination with cloud-specific provisioners.

Pavan Wankhade

Chief Information Officer | RHCI | SCI | Devops Consultant and Instructor | Ansible, Terraform, Kubernetes, CICD

1y

Keep exploring more in DevOps

Like
Reply

To view or add a comment, sign in

More articles by Srinivasan (Srini) Viswanathan

Insights from the community

Others also viewed

Explore topics