terraform/website/source/intro/getting-started/provision.html.md

3.8 KiB

layout page_title sidebar_current
intro Provision gettingstarted-provision

Provision

You're now able to create and modify infrastructure. This page introduces how to use provisioners to run basic shell scripts on instances when they're created.

If you're using an image-based infrastructure (perhaps with images created with Packer), then what you've learned so far is good enough. But if you need to do some initial setup on your instances, provisioners let you upload files, run shell scripts, etc.

Defining a Provisioner

To define a provisioner, modify the resource block defining the "example" EC2 instance to look like the following:

resource "aws_instance" "example" {
	ami = "ami-aa7ab6c2"
	instance_type = "t1.micro"

	provisioner "local-exec" {
		command = "echo ${aws_instance.example.public_ip} > file.txt"
	}
}

This adds a provision block within the resource block. Multiple provision blocks can be added to define multiple provisoining steps. Terraform supports multiple provisioners, but for this example we use the "local-exec" provisioner.

The "local-exec" provisioner executes a command locally on the machine running Terraform. We're using this provisioner versus the others so we don't have to worry about specifying any connection info right now.

Running Provisioners

Provisioners are run only when a resource is created. They are not a replacement for configuration management and changing the software of an already-running server, and are instead just meant as a way to bootstrap a server. For configuration management, you should use Terraform provisioning to bootstrap a real configuration management solution.

Make sure that your infrastructure is destroyed if it isn't already, then run apply:

$ terraform apply
aws_instance.example: Creating...
  ami:           "" => "ami-aa7ab6c2"
  instance_type: "" => "t1.micro"
aws_eip.ip: Creating...
  instance: "" => "i-213f350a"

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Terraform currently doesn't output anything to indicate the provisioners have run. This is going to be fixed soon. However, we can verify everything worked by looking at the "file.txt" file:

$ cat file.txt
54.192.26.128

It contains the IP, just ask we asked!

Failed Provisioners and Tainted Resources

If a resource successfully creates but fails during provision, Terraform will error and mark the resource as "tainted." A resource that is tainted has been physically created, but can't be considered safe to use since provisioning failed.

When you generate your next execution plan, Terraform will remove any tainted resources and create new resources, attempting to provision again. It does not attempt to restart provisioning on the same resource because it isn't guaranteed to be safe.

Terraform does not automatically roll back and destroy the resource during the apply when the failure happens, because that would go against the execution plan: the execution plan would've said a resource will be created, but does not say it will ever be deleted. But if you create an execution plan with a tainted resource, the plan will clearly state that the resource will be destroyed because it is tainted.

Next

Provisioning is important for being able to bootstrap instances. As another reminder, it is not a replacement for configuration management. It is meant to simply bootstrap machines. If you use configuration management, you should use the provisioning as a way to bootstrap the configuration management utility.

In the next section, we start looking at variables as a way to better parameterize our configurations.