Efficient terraform modules

Do you wanna write your own efficient terraform modules? I hope so! Read the article and check out sources on my GitHub, cheers!

I hope you enjoyed my previous article in the Network Series, you can find it here! You will get information about created architecture, used Azure services, and what is necessary to set up for terraform execution.

In this post, I briefly describe the terraform module’s structure, and overall solution organization.

Before you start reading further, please download the most recent terraform source, from my GitHub.

If you want to check all content from Network Series go to #what-next section.

Terraform solution organization

In the 2_terraform directory are two main catalogs:

  • environment – in my case I have only dev. But if you want to use more than one, create a directory with your environment name, and provide the required variables.
  • modules – contains definitions of all modules used in the solution, feel free to modify it and adjust to your needs.

Modules in Terraform

In my terraform approach to modules, you will find all the needed components for resource creation. For example:

  • api_management – needs public IP, network security group, KV access policy, and azure function header policy. All these components are created in a single module.
  • application_insights – create log analytics workspace and application insights.
  • azure_function_linux – creates all components needed for Azure Function, so storage account, service plan, KeyVault access policy, storage account private endpoint and last but not least azure function.
  • container_registry – in this particular case, this module is tricky. It creates: Azure Container Registry, Private Endpoint, pay attention that in DNS A record are two items, and finally container registry agent pool. Why do I need this pool? check in the #what-next section!
  • key_vault – contains Azure Key Vault and private endpoint.
  • virtual_network – contains VNET and all Subnets creation. I don’t like splitting this into separate modules, as it becomes harder to maintain. There you have all vnet/subnets CIDRs in one place so you can very fast add new subnets with fitting address space.

Create a private endpoint in terraform

So in general you always need components:

  • azurerm_private_endpoint – for private endpoint resource
  • azurerm_private_dns_zone – enable your services for DNS resolving
  • azurerm_private_dns_a_record – to attach the proper private IP address for your resource
  • azurerm_private_dns_zone_virtual_network_link – to enable your service within the virtual network to resolve DNS you just created. Without this link, your service will try to use a public IP of your resource.


You must be extremely careful when you set record A in your private DNS Zone. Some resources have more than one private IP, so you cannot assume always one IP. For example, Azure Container Registry has two private IPs. One for API second for Data. So for the Azure Container Registry private endpoint, you must set:

1st A Record:

2nd A Record

The whole definition of Azure Container Registry private endpoint for terraform you can find here.

What next?

In this article, I explained how resources are isolated on the network level and how easily you can set up Managed Identity authentication.

However, this is only part of the solution, the whole solution contains the:

If you have any suggestions please leave a comment or use the contact form

Leave a Reply

Your email address will not be published. Required fields are marked *