Series – Get your database running with Terraform part 5: Route Tables

Now when we have created IGW and NAT GW on previous post it’s time to create route tables which will send traffic outside from your VCN to the destination you require. It can be for example to your on-premise network (via DRG) or to object storage (via Service GW). Or it can be towards public internet like in this example.

You can always create multiple rules per route table.

Since we have the existing IGW and NAT GW what we will now do is create two new route tables. One which will be assigned to our public subnet and another one which will be assigned to our private subnet. During creation we will link them with our IGW and NAT GW.

One important concept to remember with OCI is that the traffic inside your VCN CIDR block gets routed without adding VCN CIDR to a route table.

When we create route table we need to define a name then assign compartment and a VCN where it gets created.

In addition we define destination which is IP range of routed traffic or CIDR block value for a service when routed through service gateway. Finally you need to have network entity id which is OCID of the target we are using for the route.

You can read more about route tables from here.

Terraform

Once again we continue adding these to our existing main.tf and variables.tf.

Following lines get added to main.tf

//Create two route tables - one public which has route to internet gateway and another one for private with a route to NAT GW

resource "oci_core_route_table" "CreatePublicRouteTable" {
  compartment_id = "${oci_identity_compartment.CreateCompartment.id}"

  route_rules = [{
    destination       = "${var.igw_route_cidr_block}"
    network_entity_id = "${oci_core_internet_gateway.CreateIGW.id}"
  }]

  vcn_id       = "${oci_core_virtual_network.CreateVCN.id}"
  display_name = "${var.public_route_table_display_name}"
}

resource "oci_core_route_table" "CreatePrivateRouteTable" {
  compartment_id = "${oci_identity_compartment.CreateCompartment.id}"

  route_rules = [{
    destination       = "${var.natgw_route_cidr_block}"
    network_entity_id = "${oci_core_nat_gateway.CreateNatGateway.id}"
  }]

  vcn_id       = "${oci_core_virtual_network.CreateVCN.id}"
  display_name = "${var.private_route_table_display_name}"
}

Highlighted the previously created IGW and NAT GW usage on creating route table.

And in the variables.tf just name and cidr_block for destination.

// PUBLIC AND PRIVATE ROUTETABLE VARIABLES

variable "public_route_table_display_name" {
  default = "PublicRoute"
} // Name for the public routetable

variable "private_route_table_display_name" {
  default = "PrivateRoute"
} // Name for the private routetable

variable "igw_route_cidr_block" {
  default = "0.0.0.0/0"
} 

variable "natgw_route_cidr_block" {
  default = "0.0.0.0/0"
} 

After running terraform plan I see two new resources are getting created and I’m ready to run terraform apply.

PS C:\builddemo> terraform.exe apply
oci_identity_compartment.CreateCompartment: Refreshing state... (ID: ocid1.compartment.oc1..aaaaaaaav43jwd5o...xxxxx)
data.oci_identity_availability_domains.ADs: Refreshing state...
oci_core_virtual_network.CreateVCN: Refreshing state... (ID: ocid1.vcn.oc1.eu-frankfurt-1.aaaaaaaar2...xxxxx)
oci_core_internet_gateway.CreateIGW: Refreshing state... (ID: ocid1.internetgateway.oc1.eu-frankfurt-...xxxxx)
oci_core_nat_gateway.CreateNatGateway: Refreshing state... (ID: ocid1.natgateway.oc1.eu-frankfurt-1.aaa...xxxxx)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + oci_core_route_table.CreatePrivateRouteTable
      id:                                       <computed>
      compartment_id:                           "ocid1.compartment.oc1..xxxxx"
      display_name:                             "PrivateRoute"
      freeform_tags.%:                          <computed>
      route_rules.#:                            "1"
      route_rules.2309354893.cidr_block:        <computed>
      route_rules.2309354893.destination:       "0.0.0.0/0"
      route_rules.2309354893.destination_type:  <computed>
      route_rules.2309354893.network_entity_id: "ocid1.natgateway.oc1.eu-frankfurt-1.xxxxx"
      state:                                    <computed>
      time_created:                             <computed>
      time_modified:                            <computed>
      vcn_id:                                   "ocid1.vcn.oc1.eu-frankfurt-1.xxxxx"

  + oci_core_route_table.CreatePublicRouteTable
      id:                                       <computed>
      compartment_id:                           "ocid1.compartment.oc1..xxxxx"
      display_name:                             "PublicRoute"
      freeform_tags.%:                          <computed>
      route_rules.#:                            "1"
      route_rules.2660137267.cidr_block:        <computed>
      route_rules.2660137267.destination:       "0.0.0.0/0"
      route_rules.2660137267.destination_type:  <computed>
      route_rules.2660137267.network_entity_id: "ocid1.internetgateway.oc1.eu-frankfurt-1.xxxxx"
      state:                                    <computed>
      time_created:                             <computed>
      time_modified:                            <computed>
      vcn_id:                                   "ocid1.vcn.oc1.eu-frankfurt-1.xxxxx"


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

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

oci_core_route_table.CreatePrivateRouteTable: Creating...
  compartment_id:                           "" => "ocid1.compartment.oc1..xxxxx"
  display_name:                             "" => "PrivateRoute"
  freeform_tags.%:                          "" => "<computed>"
  route_rules.#:                            "" => "1"
  route_rules.2309354893.cidr_block:        "" => "<computed>"
  route_rules.2309354893.destination:       "" => "0.0.0.0/0"
  route_rules.2309354893.destination_type:  "" => "<computed>"
  route_rules.2309354893.network_entity_id: "" => "ocid1.natgateway.oc1.eu-frankfurt-1.xxxxx"
  state:                                    "" => "<computed>"
  time_created:                             "" => "<computed>"
  time_modified:                            "" => "<computed>"
  vcn_id:                                   "" => "ocid1.vcn.oc1.eu-frankfurt-1.xxxxx"
oci_core_route_table.CreatePublicRouteTable: Creating...
  compartment_id:                           "" => "ocid1.compartment.oc1..xxxxx"
  display_name:                             "" => "PublicRoute"
  freeform_tags.%:                          "" => "<computed>"
  route_rules.#:                            "" => "1"
  route_rules.2660137267.cidr_block:        "" => "<computed>"
  route_rules.2660137267.destination:       "" => "0.0.0.0/0"
  route_rules.2660137267.destination_type:  "" => "<computed>"
  route_rules.2660137267.network_entity_id: "" => "ocid1.internetgateway.oc1.eu-frankfurt-1.xxxxx"
  state:                                    "" => "<computed>"
  time_created:                             "" => "<computed>"
  time_modified:                            "" => "<computed>"
  vcn_id:                                   "" => "ocid1.vcn.oc1.eu-frankfurt-1.xxxxx"
oci_core_route_table.CreatePublicRouteTable: Creation complete after 1s (ID: ocid1.routetable.oc1.eu-frankfurt-1.aaa...xxxxx)
oci_core_route_table.CreatePrivateRouteTable: Creation complete after 1s (ID: ocid1.routetable.oc1.eu-frankfurt-1.aaa...xxxxx)

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

Just as an example in case you would need to add DRG to route traffic to on-premise and still keep the NAT GW then the route rules must be passed as a list.

        route_rules = [{
                destination = "${var.drg_route_table_route_rules_cidr_block}"
                network_entity_id = "${var.drg_network_id}"
        }, {
           destination = "${var.natgw_route_table_route_rules_cidr_block}"
                network_entity_id = "${var.natgw_network_id}"
        }]

See the highlighted parts so list is defined with [] and values separated with a comma.

Next part will jump into security lists which are created to allow certain ingress and egress traffic to our subnets.

Simo

View Comments

  • Hi- Thanks so much for putting these examples together. This has become my starting point of exploring Terraform on OCI.

    Quick input on this, while testing this, released we don't need "=" sine in main.tf for route_rules

    route_rules = [{

    It should be just
    route_rules {

    • Thanks Deepak! Did you test this with Terraform 0.12? I think it changed with between 0.11 and 0.12 so you don't need = sign anymore. Also the reason I have it with [] is so I can send it as list for multiple rules. Obviously if you need only one then this wouldn't be needed.

  • Hi Simo - while reading through this series, I noted an error in the code.

    The route rules blocks for the Public and Private subnets should not be enclosed in [ ]. And, according to the documentation, the equals sign is not required. The code sample should look like this for the public and private route rules blocks:

    route_rules {
    destination = "${var.igw_route_cidr_block}"
    network_entity_id = "${oci_core_internet_gateway.CreateIGW.id}"
    }
    vcn_id = "${oci_core_virtual_network.CreateVCN.id}"
    display_name = "${var.public_route_table_display_name}"
    }

    • Hi George,

      I think the functionality actually changed. So beginning with I think Terraform 0.12 (not sure if specific OCI provider is required too) you don't need [] anymore and same with equal sign. I've had to edit some newer versions of our route rules when I've done some modifications and noticed the same. I went back to check what I had in some older versions of the code and have that committed as working version. It's good observation and something I think comes up when you have to modify some parts of older code.. there is always bit more to modify than expected. :)

      Here is how I've done it with Terraform 0.12 module:

      https://github.com/svilmune/tf-012-create-three-instances-demo/blob/master/module-routetable/main.tf

Recent Posts

Connecting to Autonomous Database Running on Google Cloud

Last time I showed how to provision Autonomous Database Serverless (ADB-S) on Google Cloud. This…

1 month ago

Can you believe it? Provisioning Autonomous Database in GCP!

I bet few years back folks didn't expect that by 2024 we would be able…

2 months ago

IP Address Insights with CLI

My previous post on IP Address Insights I mentioned it wasn't yet available with CLI…

6 months ago

Thoughts on Oracle Database@Azure

This will NOT be a technical walkthrough on Oracle Database@Azure but rather my opinions and…

6 months ago

OCI Vulnerability Scanning Setup

Many times when you work for someone, they already have their own vulnerability scanning throughout…

6 months ago

OCI IP Address Insights

Recently OCI announced small but VERY useful service, IP Address Insights. Why this matters? I've…

6 months ago