Define infrastructure with Terraform resources | Terraform | HashiCorp Developer (2024)

Terraform uses resource blocks to manage infrastructure, such as virtualnetworks, compute instances, or higher-level components such as DNS records.Resource blocks represent one or more infrastructure objects in your Terraformconfiguration.

Most Terraform providers have a number of different resources that map to the appropriateAPIs to manage that particular infrastructure type.

GenericAWS Provider ResourceAWS Infrastructure
Resource Aaws_instanceEC2 Instance
Resource Baws_security_groupSecurity Group

In this tutorial, you will create an EC2 instance that runs a PHP webapplication. You will then refer to documentation in the Terraform Registry tocreate a security group to make the application publicly accessible.

You can complete this tutorial using the same workflow with either TerraformCommunity Edition or Terraform Cloud. Terraform Cloud is a platform that you can use tomanage and execute your Terraform projects. It includes features like remotestate and execution, structured plan output, workspace resource summaries, andmore.

Select the Terraform Cloud tab to complete this tutorial using Terraform Cloud.

This tutorial assumes that you are familiar with the Terraform workflow. If you are new to Terraform, complete the Get Started collection first.

In order to complete this tutorial, you will need the following:

This tutorial assumes that you are familiar with the Terraform and TerraformCloud workflows. If you are new to Terraform, complete the Get Started collection first. If you are new to Terraform Cloud, complete the Terraform Cloud Get Startedtutorials first.

In order to complete this tutorial, you will need the following:

  • Terraform v1.2+ installed locally.
  • An AWS account.
  • A Terraform Cloud account with Terraform Cloud locally authenticated.
  • A Terraform Cloud variable set configured with your AWS credentials.

Clone the example repository

Clone the Learn TerraformResources repository,which contains example configuration to provision an AWS EC2 instance.

$ git clone https://github.com/hashicorp/learn-terraform-resources.git

Navigate to the repository directory in your terminal.

$ cd learn-terraform-resources

There are five files in this directory:

  1. init-script.sh contains the provisioning script to install dependencies and start a sample PHP application
  2. terraform.tf contains the terraform block that defines the providers required by your configuration
  3. main.tf contains the configuration for an EC2 instance
  4. outputs.tf contains the definitions for the output values of your resources
  5. README.md describes the repository and its contents

Open main.tf to review the two resource blocks: random_pet.name and aws_instance.web.

Review the random_pet resource

The first resource block defines a random_pet resource named name, whichgenerates a random pet name. You can use the name generated by this resource toensure that your other resources have unique names.

resource "random_pet" "name" {}

Resource blocks declare a resource type and name. Together, the type and nameform a resource identifier (ID) in the format resource_type.resource_name, inthis case random_pet.name. The resource's ID must be unique within aworkspace. When Terraform displays information about this resource in itsoutput it will use the resource ID.

Resource types always start with the provider name followed by an underscore.The random_pet resource type belongs to the random provider.

The Terraform Registry houses the documentation for Terraform providers and their associated resources. Open the random_pet documentation page and notice that it is nested under the documentation for the random provider. The page contains a description of the random_pet resource, an example usage, argument reference, and attribute reference.

Resources have arguments, attributes, and meta-arguments.

  • Arguments configure a particular resource; because of this, many arguments are resource-specific. Arguments can be required or optional, as specified by the provider. If you do not supply a required argument, Terraform will give an error and not apply the configuration.
  • Attributes are values exposed by an existing resource. References to resource attributes take the format resource_type.resource_name.attribute_name. Unlike arguments which specify an infrastructure object's configuration, a resource's attributes are often assigned to it by the underlying cloud provider or API.
  • Meta-arguments change a resource's behavior, such as using a count meta-argument to create multiple resources. Meta-arguments are a function of Terraform itself and are not resource or provider-specific.

The random_pet resource has four optional arguments and exposes one attribute. Because there are no required arguments, you can define the random_pet.name resource without arguments.

Review the EC2 instance resource

The aws_instance.web resource block defines an aws_instance resource named web to create an AWS EC2 instance.

resource "aws_instance" "web" { ami = "ami-a0cfeed8" instance_type = "t2.micro" user_data = file("init-script.sh") tags = { Name = random_pet.name.id }}

The arguments inside the aws_instance.web resource block specify what type of resource to create.

  • The instance_type and ami arguments tell the AWS provider to create a t2.micro EC2 instance using the ami-a0cfeed8 machine image.

    Note

    If you use a different AMI, you may need to update the init-script.sh. Connect to your EC2 instance and review /var/log/cloud-init-output.log to debug any errors.

  • The user_data argument uses the file() function to return the contents of init-script.sh.

  • The tags argument specifies this EC2 instance's name. Notice that the argument references the random_pet.name's ID attribute (random_pet.name.id) to give the EC2 instance a unique name. This defines an implicit dependency between the EC2 instance and the random_pet resource; Terraform cannot create the instance until it has a name for it.

These are only a subset of the available aws_instances arguments. Refer to the aws_instance documentation page for a complete list.

Initialize this configuration.

$ terraform initInitializing the backend...##...Terraform has been successfully initialized!You may now begin working with Terraform. Try running "terraform plan" to seeany changes that are required for your infrastructure. All Terraform commandsshould now work.If you ever set or change modules or backend configuration for Terraform,rerun this command to reinitialize your working directory. If you forget, othercommands will detect it and remind you to do so if necessary.

Open your terraform.tf file and uncomment the cloud block. Replace theorganization name with your own Terraform Cloud organization.

terraform { cloud { organization = "organization-name" workspaces { name = "learn-terraform-resource" } } required_providers { aws = { source = "hashicorp/aws" version = "~> 4.4.0" } } required_version = ">= 1.2"}

Initialize your configuration. Terraform will automatically create the learn-terraform-resource workspace in your Terraform Cloud organization.

$ terraform initInitializing Terraform Cloud...Initializing provider plugins...- Reusing previous version of hashicorp/aws from the dependency lock file- Installing hashicorp/aws v4.4.0...- Installed hashicorp/aws v4.4.0 (signed by HashiCorp)Terraform Cloud has been successfully initialized!You may now begin working with Terraform Cloud. Try running "terraform plan" tosee any changes that are required for your infrastructure.If you ever set or change modules or Terraform Settings, run "terraform init"again to reinitialize your working directory.

Note

This tutorial assumes that you are using a tutorial-specificTerraform Cloud organization with a global variable set of your AWScredentials. Review the Create a Credential VariableSet for detailed guidance. If you are using a scoped variable set, assign it to your new workspace now.

Apply your configuration to create the two resources. Confirm the operation with a yes.

$ terraform apply## ...Plan: 2 to add, 0 to change, 0 to destroy.## ...Apply complete! Resources: 2 added, 0 changed, 0 destroyed.Outputs:application-url = "ec2-18-236-123-132.us-west-2.compute.amazonaws.com/index.php"domain-name = "ec2-18-236-123-132.us-west-2.compute.amazonaws.com"

The domain-name output will display your EC2 instance's endpoint upon completion. However, if you try to visit the URL, it will not resolve. This is because you have not yet configured access to port 80 of the instance.

Tip

This tutorial shows the output for Terraform commands run with Terraform Community Edition. If you are following the Terraform Cloud workflow, the output may differ slightly but the results will be the same.

If you use Terraform Cloud to provision your resources, your workspace now displays the list of all of the resources it manages and the outputs for your configuration.

Define infrastructure with Terraform resources | Terraform | HashiCorp Developer (1)

Associate security group with instance

To enable access to the EC2 instance's web server, you must define a security group that allows ingress traffic on port 80 and all egress traffic, and associate the security group with your instance.

Open the AWS Provider documentation page. Search for security_group and select the aws_security_group resource.

Define infrastructure with Terraform resources | Terraform | HashiCorp Developer (2)

Review the configuration options available on the aws_security_groupdocumentationpage.Then, define a new aws_security_group resource named web-sg in main.tfthat allows ingress traffic on port 80 and all egress traffic for all CIDR blocks.

Your security group resource should be similar to the following:

resource "aws_security_group" "web-sg" { name = "${random_pet.name.id}-sg" ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] }}

Then, update your aws_instance.web resource to use this security group. Asspecified in the aws_instance Argument Referencesection,thevpc_security_group_ids argument requires a list of security group IDs.

Add the vpc_security_group_ids argument to the aws_instance.web resource as a list by placing the aws_security_group.web-sg.id attribute inside square brackets.

resource "aws_instance" "web" {  ami = "ami-a0cfeed8"  instance_type = "t2.micro"  user_data = file("init-script.sh")+ vpc_security_group_ids = [aws_security_group.web-sg.id]  tags = {  Name = random_pet.name.id  }}

Save your changes.

Next, apply your configuration. Remember to confirm your apply with a yes.

$ terraform apply## ...Apply complete! Resources: 1 added, 1 changed, 0 destroyed.Outputs:application-url = "ec2-18-236-123-132.us-west-2.compute.amazonaws.com/index.php"domain-name = "ec2-18-236-123-132.us-west-2.compute.amazonaws.com"

Verify that your EC2 instance is now publicly accessible.

In your browser, visit the application-url address from Terraform's output to view the PHP application. The address should start with http, not https.

To view your application-url output again, run the following command.

$ terraform output application-url"ec2-18-236-123-132.us-west-2.compute.amazonaws.com/index.php"

It may take about 10 minutes for the EC2 instance to completely deploy the PHP application. If you receive a ... took too long to respond. message, please wait a few minutes before trying again.

Define infrastructure with Terraform resources | Terraform | HashiCorp Developer (3)

Use curl to send an HTTP request to the domain-name output endpoint. It should return your EC2 instance ID.

$ curl $(terraform output -raw domain-name)i-035bf5dddf1361364

Now that you have verified that the EC2 instance is publicly available, runterraform destroy to destroy the resources. Remember to respond to theconfirmation prompt with yes.

$ terraform destroyAn execution plan has been generated and is shown below.Resource actions are indicated with the following symbols: - destroyTerraform will perform the following actions:##...Plan: 0 to add, 0 to change, 3 to destroy.Changes to Outputs: - application-url = "ec2-18-236-123-132.us-west-2.compute.amazonaws.com/index.php" - domain-name = "ec2-18-236-123-132.us-west-2.compute.amazonaws.com"Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yesaws_security_group.web-sg: Destroying... [id=sg-0cd7b5ebfafbe3d7f]aws_instance.web: Destroying... [id=i-0798dc10162db25f3]aws_security_group.web-sg: Destruction complete after 1saws_instance.web: Still destroying... [id=i-0798dc10162db25f3, 10s elapsed]aws_instance.web: Still destroying... [id=i-0798dc10162db25f3, 20s elapsed]aws_instance.web: Still destroying... [id=i-0798dc10162db25f3, 30s elapsed]aws_instance.web: Still destroying... [id=i-0798dc10162db25f3, 40s elapsed]aws_instance.web: Destruction complete after 42srandom_pet.name: Destroying... [id=pleasing-swine]random_pet.name: Destruction complete after 0sDestroy complete! Resources: 3 destroyed.

If you used Terraform Cloud for this tutorial, after destroying your resources, delete the learn-terraform-resource workspace from your Terraform Cloud organization.

Next steps

In this tutorial, you made an EC2 instance publicly available by referencingthe Terraform Registry to define a securitygroup. You also reviewed resource arguments and attributes and defined a dependency between resources.

To learn more about the Terraform configuration language, check out the following resources:

  • Learn more about resource dependencies in the Create Resource Dependencies tutorial.
  • Review the Perform Dynamic Operations with Functions and Create Dynamic Expressions tutorials.
  • Review the difference between resource arguments, attributes, and meta-arguments in the Terraform documentation.
Define infrastructure with Terraform resources | Terraform | HashiCorp Developer (2024)
Top Articles
Latest Posts
Article information

Author: Otha Schamberger

Last Updated:

Views: 6301

Rating: 4.4 / 5 (55 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Otha Schamberger

Birthday: 1999-08-15

Address: Suite 490 606 Hammes Ferry, Carterhaven, IL 62290

Phone: +8557035444877

Job: Forward IT Agent

Hobby: Fishing, Flying, Jewelry making, Digital arts, Sand art, Parkour, tabletop games

Introduction: My name is Otha Schamberger, I am a vast, good, healthy, cheerful, energetic, gorgeous, magnificent person who loves writing and wants to share my knowledge and understanding with you.