Setting Up VPC and Subnets with Terraform: A Quick Start

Have you ever tried assembling IKEA furniture? The instructions can be pretty confusing at first, but it’s super satisfying once it’s all done (and fingers crossed, no extra parts lying around!). Similarly, setting up a Virtual Private Cloud (VPC) and subnets is one of the fundamental steps in cloud computing. In this article, I’ve outlined the steps to create a VPC and Public/Private Subnets using Terraform in a clear and straightforward manner. Go ahead and give it a try—it’s simpler than you think!


So, let’s start by creating a couple of files to structure our Terraform project:

  • providers.tf: This is where we define the provider information, such as AWS.
  • main.tf: This is the heart of our configuration where we define the resources we want to create.
  • outputs.tf: Here, we specify the outputs we’d like to fetch, such as IDs or endpoints of the resources we create.

The files somewhat look like this.

Terraform Files

Let’s start with providers.tf. In this file, we specify the provider we’ll use to create the resources—in our case, AWS. You can get this info from here. AWS. Make sure to also define the region to indicate where the resources should be created."

providers.tf

Now, we have the main.tf file, where we add the resource. Here, we have defined three resources: VPC, Subnet for Public, and Subnet for Private.

main.tf

To deploy a VPC, some parameters are mandatory while others are optional. For example, the cidr_block is a required parameter. You can find more information about these parameters in the following link.

Next, we define two subnets (Private and Public). In this block of code, the vpc_id is a required field, and it refers to the ID of the VPC. The reference for this ID will be defined in outputs.tf, which we'll explore shortly. As you know tags in AWS are very useful for managing/referring the resources so make sure the add any many as you prefer. To explore other optional parameters, refer to the doc.

So far, we've created the provider.tf and main.tf files. Now, let's proceed to fetch a couple of outputs, such as vpc.id and subnet.id, to ensure that the referencing works correctly.

So create another file as outputs.tf and add the following blocks.

output.tf

The vpc_id block will fetch the VPC ID once the resource is created. This ID will then be used for creating the subnets. After the subnets—my-pub-subnet-id (public) and my-pri-subnet-id (private)—are created, their respective IDs will also be displayed in the outputs.


Alright, now that we've defined the resources, let's go ahead and run the following Terraform commands to initialize the configuration, plan the changes, and apply them to create the resources:

  1. terraform init – Initializes the Terraform working directory and downloads the necessary provider plugins.

$ 

Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "5.79.0"...
- Installing hashicorp/aws v5.79.0...
- Installed hashicorp/aws v5.79.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should 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, other
commands will detect it and remind you to do so if necessary.        

2. terraform plan – Shows what changes Terraform will make to your infrastructure based on your configuration.

$ terraform plan -out=tfplan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_subnet.my-pri-subnet will be created
  + resource "aws_subnet" "my-pri-subnet" {
      + arn                                            = (known after apply)
      + assign_ipv6_address_on_creation                = false
      + availability_zone                              = (known after apply)
      + availability_zone_id                           = (known after apply)
      + cidr_block                                     = "10.0.2.0/24"
      + enable_dns64                                   = false
      + enable_resource_name_dns_a_record_on_launch    = false
      + enable_resource_name_dns_aaaa_record_on_launch = false
      + id                                             = (known after apply)
      + ipv6_cidr_block_association_id                 = (known after apply)
      + ipv6_native                                    = false
      + map_public_ip_on_launch                        = false
      + owner_id                                       = (known after apply)
      + private_dns_hostname_type_on_launch            = (known after apply)
      + tags                                           = {
          + "Name" = "my-pri-subnet"
        }
      + tags_all                                       = {
          + "Name" = "my-pri-subnet"
        }
      + vpc_id                                         = (known after apply)
    }

  # aws_subnet.my-pub-subnet will be created
  + resource "aws_subnet" "my-pub-subnet" {
      + arn                                            = (known after apply)
      + assign_ipv6_address_on_creation                = false
      + availability_zone                              = (known after apply)
      + availability_zone_id                           = (known after apply)
      + cidr_block                                     = "10.0.1.0/24"
      + enable_dns64                                   = false
      + enable_resource_name_dns_a_record_on_launch    = false
      + enable_resource_name_dns_aaaa_record_on_launch = false
      + id                                             = (known after apply)
      + ipv6_cidr_block_association_id                 = (known after apply)
      + ipv6_native                                    = false
      + map_public_ip_on_launch                        = false
      + owner_id                                       = (known after apply)
      + private_dns_hostname_type_on_launch            = (known after apply)
      + tags                                           = {
          + "Name" = "my-pub-subnet"
        }
      + tags_all                                       = {
          + "Name" = "my-pub-subnet"
        }
      + vpc_id                                         = (known after apply)
    }

  # aws_vpc.my-aws_vpc will be created
  + resource "aws_vpc" "my-aws_vpc" {
      + arn                                  = (known after apply)
      + cidr_block                           = "10.0.0.0/16"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_dns_hostnames                 = true
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags                                 = {
          + "Name" = "my-aws-vpc"
        }
      + tags_all                             = {
          + "Name" = "my-aws-vpc"
        }
    }

Plan: 3 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + my-pri-subnet-id = (known after apply)
  + my-pub-subnet-id = (known after apply)
  + vpc_id           = (known after apply)

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "tfplan"        

3. terraform apply – Applies the planned changes and creates the resources.

$ terraform apply "tfplan"
aws_vpc.my-aws_vpc: Creating...
aws_vpc.my-aws_vpc: Still creating... [10s elapsed]
aws_vpc.my-aws_vpc: Creation complete after 12s [id=vpc-0a33ad00ce1021a4c]
aws_subnet.my-pub-subnet: Creating...
aws_subnet.my-pri-subnet: Creating...
aws_subnet.my-pri-subnet: Creation complete after 1s [id=subnet-083300cefcf48ca7a]
aws_subnet.my-pub-subnet: Creation complete after 1s [id=subnet-050720249cf73c564]

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

Outputs:

my-pri-subnet-id = "subnet-083300cefcf48ca7a"
my-pub-subnet-id = "subnet-050720249cf73c564"
vpc_id = "vpc-0a33ad00ce1021a4c"        

As you can see, the final output displays the IDs of the VPC and the subnets that were created.


Let's check the resources we just created from AWS UI.

VPC details:

VPC from AWS UI

Subnet details:

Subnets from AWS UI.


Note: Once you're done, don't forget to clean up your resources. You can use the terraform destroy command to remove all the resources you’ve created and avoid any unnecessary costs.


And that's it! I hope you enjoyed this short guide on creating VPCs and subnets using Terraform. You can refer to the files in the GitHub repository linked below.

Github: https://github.com/joishvadiraj/TF-AWS-VPC


Vinay K Mishra

Enterprise Observability & Automation Shared Service Expert

3 个月

The example in the beginning of the post was quite helpful in understanding how the complete deployment may make one feel during the whole process. Nice post, thank you for sharing :)

要查看或添加评论,请登录

Vadiraj J.的更多文章

社区洞察

其他会员也浏览了