Chapter 3. Resource Dependencies and Modules

Previously, we have managed only one resource with Terraform-a single EC2 instance. Obviously, the real infrastructure is much more complicated than a single server. The more resources you have, the more dependencies between them you have to handle. Also, when the number of resources grows, you will have hard time managing them via single huge template file.

In this chapter, we will learn about one of the most important features of Terraform: dependency graph. We will figure out how dependencies work and see it in practice by creating a complete virtual network via AWS VPC. Then, we will learn how to work around some limitations in dependency handling using some of the advanced Terraform features. Finally, when we will find out that our template is too big, we will use Terraform modules to DRY (Don't Repeat Yourself) our code.

Note

DRY is a software development principle. Its goal is to reduce the amount of duplication in your code, thus reducing the chance of mistake and increasing the maintainability of the code.

Creating AWS Virtual Private Cloud

Perhaps, one of the best features of AWS is VPC (Virtual Private Cloud).

In the essence, VPC is a virtual network that you can divide into subnets. Some subnets can be public (with access to the Internet), and some are private. You can define routing between subnets, and by default, they can freely access each other. You can also create VPN to your VPC, add NAT gateways, manage DHCP options, and define ACLs for your networks. VPC is a complex service with many subtools and options. For our purpose, we will use only a subset of them, though.

Note

Typical use case for VPC:

Keeping publicly accessible web servers in public subnet and database servers in private one and enable secure connection between cloud resources and on-premise machines.

Security groups are also a part of AWS VPC. With security groups, you can define inbound and outbound firewall rules and then you can attach these groups to EC2 instances. As a source of traffic for these rules, you can either use IP ranges, IDs of other security groups, or even IDs of other instances.

If you've created a new AWS account in the previous chapter, you should have a default VPC. If you have a very old AWS account, then you might not have it. In any case, we won't use any of precreated VPCs. Instead, let's start with creating VPC by making our template.tf look as follows:

provider "aws" { 
  region = "eu-central-1" 
} 
resource "aws_vpc" "my_vpc" { 
  cidr_block = "10.0.0.0/16" 
} 

For each VPC, you need to specify CIDR block range of IP addresses used for EC2 instances in this VPC. Go ahead and apply the following template:

$> terraform apply 
 
aws_vpc.my_vpc: Creating... 
  cidr_block:                "" => "10.0.0.0/16" 
  default_network_acl_id:    "" => "<computed>" 
  default_security_group_id: "" => "<computed>" 
  dhcp_options_id:           "" => "<computed>" 
  enable_classiclink:        "" => "<computed>" 
  enable_dns_hostnames:      "" => "<computed>" 
  enable_dns_support:        "" => "<computed>" 
  instance_tenancy:          "" => "<computed>" 
  main_route_table_id:       "" => "<computed>" 
aws_vpc.my_vpc: Creation complete 
Apply complete! Resources: 1 added, 0 changed, 0 destroyed. 

Note

In case you are asking yourself what <computed> means, it means that the value won't be known until the resource is created.

Creating a VPC is not enough: to be able to place instances in this network, we also need a subnet. This subnet belongs to a previously created VPC. It means that we have to pass a VPC ID when we create it. We don't have to hardcode it, though. Terraform, via interpolation syntax, allows us to reference any other resource it manages using the following syntax: ${RESOURCE_TYPE.RESOURCE_NAME.ATTRIBUTE_NAME}.

Interpolation allows you to reference other resources and variables and call various functions. In case of resource reference, it saves you from hard-coding their IDs. Terraform will put required value (in this case, VPC ID) as soon as it has it.

Add the following to the template:

resource "aws_subnet" "public" { 
    vpc_id = "${aws_vpc.my_vpc.id}" 
    cidr_block = "10.0.1.0/24" 
} 

Note the interpolated string: ${aws_vpc.my_vpc.id}. We referenced the previously created VPC inside a subnet configuration. That's how an interpolation syntax in Terraform looks: you wrap the code with ${}.

We will take a deeper look at variables and functions a bit later. For now, let's focus on how Terraform handles referencing resources inside other resources. After all, it's backed by one of the most powerful core Terraform features: dependency graph.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.196.59