skip to Main Content

If I was to use this example to create an Azure Container Environment and Apps via Terraform, I would find some additional resources created in a new resource group with a random name:
New Resources

My question is, can we use Terraform to create those so that I can apply naming conventions, tags etc.

2

Answers


  1. When you deploy resources in Azure using Terraform, Azure sometimes creates additional, ancillary resources to support the primary resource. These automatically generated resources usually come with auto-generated names.

    Some Azure resources inherently depend on other resources. For example, when you create a Virtual Machine, Azure might create additional resources like a Network Interface Card (NIC) if you don’t specify an existing one.

    To avoid surprises, I always, Before applying any changes, run terraform plan. This will show you all the resources Terraform intends to create, modify, or destroy. This is a good chance to catch unexpected resources.

    If there are resources you find being created automatically and you want to define and control them via Terraform, you can:

    1.  Look for the corresponding Terraform resource in the Terraform Azure Provider documentation.
    2.  Define the resource explicitly in your Terraform code.
    3.  Link the resource to its parent/dependent resource as necessary.
    
    Login or Signup to reply.
  2. My question is, can we use Terraform to create those so that I can apply naming conventions, tags etc.

    To create resources with your own naming conventions, below is the Terraform code

    name ="${var.resource_prefix}-${var.blob_private_endpoint}"
    

    ${var.resource_prefix}" is a constant value used for all resources.
    "${var.blob_private_endpoint}" allows you to define a custom resource name at the time of input.

    For example, if "resource_prefix" is set to "Prod" and "blob_private_endpoint" is set to "demoendpoint," the resource name is created as follows: [resource_prefix]-demoendpoint

     prod-demoendpoint 
     
    

    Kindly follow the same format in all resources.

    Terraform Plan:

    enter image description here

    Here is terraform code to create Azure Container Environment and Apps with network resources using own naming convention.

     terraform {
      required_version = ">= 1.3"
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~> 3.43.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
    data "azurerm_client_config" "current" {
    }
    
    resource "random_string" "resource_prefix" {
      length  = 6
      special = false
      upper   = false
      numeric  = false
    }
    
    data "azurerm_resource_group" "rg" {
      name = "venkattests-resources"
    }
    
    module "log_analytics_workspace" {
      source                           = "./modules/log_analytics"
      name                             = "log-${var.resource_prefix}-${var.log_analytics_workspace_name}"
      location                         = var.location
      resource_group_name              = data.azurerm_resource_group.rg.name
      tags = {
        environment = "Production"
      }
    }
    
    module "application_insights" {
      source                           = "./modules/application_insights"
      name                             = "${var.resource_prefix}-${var.application_insights_name}"
      location                         = var.location
      resource_group_name              = data.azurerm_resource_group.rg.name
      application_type                 = var.application_insights_application_type
      workspace_id                     = module.log_analytics_workspace.id
      tags = {
        environment = "Production"
      }
    }
    
    module "virtual_network" {
      source                           = "./modules/virtual_network"
      resource_group_name              = data.azurerm_resource_group.rg.name
      vnet_name                        = "${var.resource_prefix}-${var.virtual_network}"
      location                         = var.location
      address_space                    = var.vnet_address_space
      log_analytics_workspace_id       = module.log_analytics_workspace.id
      log_analytics_retention_days     = var.log_analytics_retention_days
      tags = {
        environment = "Production"
      }
    
      subnets = [
        {
          name : var.aca_subnet_name
          address_prefixes : var.aca_subnet_address_prefix
          private_endpoint_network_policies_enabled : true
          private_link_service_network_policies_enabled : false
        },
        {
          name : var.private_endpoint_subnet_name
          address_prefixes : var.private_endpoint_subnet_address_prefix
          private_endpoint_network_policies_enabled : true
          private_link_service_network_policies_enabled : false
        }
      ]
    }
    
    module "blob_private_dns_zone" {
      source                       = "./modules/private_dns_zone"
      name                         = "${var.resource_prefix}-${var.blob_private_dns_zone}"
      resource_group_name          = data.azurerm_resource_group.rg.name
      virtual_networks_to_link     = {
        (module.virtual_network.name) = {
          subscription_id = data.azurerm_client_config.current.subscription_id
          resource_group_name = data.azurerm_resource_group.rg.name
        }
      }
    }
    
    module "network-security-group" {
      source                = "Azure/network-security-group/azurerm"
      resource_group_name   = data.azurerm_resource_group.rg.name
      location              = "EastUS" # Optional; if not provided, will use Resource Group location
      security_group_name   = "${var.resource_prefix}-${var.network-security-group}"
      source_address_prefix = ["10.0.3.0/24"]
      predefined_rules = [
        {
          name     = "SSH"
          priority = "500"
        },
        {
          name              = "LDAP"
          source_port_range = "1024-1026"
        }
      ]
    
      custom_rules = [
        {
          name                   = "myssh"
          priority               = 201
          direction              = "Inbound"
          access                 = "Allow"
          protocol               = "Tcp"
          source_port_range      = "*"
          destination_port_range = "22"
          source_address_prefix  = "10.151.0.0/24"
          description            = "description-myssh"
        },
        {
          name                    = "myhttp"
          priority                = 200
          direction               = "Inbound"
          access                  = "Allow"
          protocol                = "Tcp"
          source_port_range       = "*"
          destination_port_range  = "8080"
          source_address_prefixes = ["10.151.0.0/24", "10.151.1.0/24"]
          description             = "description-http"
        },
      ]
    
      tags = {
        environment = "dev"
        costcenter  = "it"
      }
    }
    resource "azurerm_public_ip" "example" {
      name                = "${var.resource_prefix}-${var.azurerm_public_ip}"
      location            = data.azurerm_resource_group.rg.location
      resource_group_name = data.azurerm_resource_group.rg.name
      allocation_method   = "Dynamic"
      idle_timeout_in_minutes = 30
    
      tags = {
        environment = "test"
      }
    }
    
    module "mylb" {
      source              = "Azure/loadbalancer/azurerm"
      resource_group_name = data.azurerm_resource_group.rg.name
      prefix              = "terraform-test"
    
      remote_port = {
        ssh = ["Tcp", "22"]
      }
    
      lb_port = {
        http = ["80", "Tcp", "80"]
      }
    
      lb_probe = {
        http = ["Tcp", "80", ""]
      }
    
    }
    module "blob_private_endpoint" {
      source                         = "./modules/private_endpoint"
      name                           = "${var.resource_prefix}-${var.blob_private_endpoint}"
      location                       = var.location
      resource_group_name            = data.azurerm_resource_group.rg.name
      subnet_id                      = module.virtual_network.subnet_ids[var.private_endpoint_subnet_name]
      private_connection_resource_id = module.storage_account.id
      is_manual_connection           = false
      subresource_name               = "blob"
      private_dns_zone_group_name    = "BlobPrivateDnsZoneGroup"
      private_dns_zone_group_ids     = [module.blob_private_dns_zone.id]
      tags = {
        environment = "Production"
      }
    }
    
    module "storage_account" {
      source                           = "./modules/storage_account"
      name                             = "${var.storage_account}"
      location                         = var.location
      resource_group_name              = data.azurerm_resource_group.rg.name
      account_kind                     = var.storage_account_kind
      account_tier                     = var.storage_account_tier
      replication_type                 = var.storage_account_replication_type
      tags = {
        environment = "Production"
      }
    }
    
    module "container_apps" {
      source                           = "./modules/container_apps"
      managed_environment_name         = "container-${var.resource_prefix}"
      location                         = var.location
      resource_group_name              = data.azurerm_resource_group.rg.name
      infrastructure_subnet_id         = module.virtual_network.subnet_ids[var.aca_subnet_name] 
      instrumentation_key              = module.application_insights.instrumentation_key
      workspace_id                     = module.log_analytics_workspace.id
      dapr_components                  = [{
                                          name            = var.dapr_name
                                          component_type  = var.dapr_component_type
                                          version         = var.dapr_version
                                          ignore_errors   = var.dapr_ignore_errors
                                          init_timeout    = var.dapr_init_timeout
                                          secret          = [
                                            {
                                              name        = "storageaccountkey"
                                              value       = module.storage_account.primary_access_key
                                            }
                                          ]
                                          metadata: [
                                            {
                                              name        = "accountName"
                                              value       = module.storage_account.name
                                            },
                                            {
                                              name        = "containerName"
                                              value       = var.container_name
                                            },
                                            {
                                              name        = "accountKey"
                                              secret_name = "storageaccountkey"
                                            }
                                          ]
                                          scopes          = var.dapr_scopes
                                         }]
     container_apps                   = var.container_apps
    }
    
    
    

    Varaible.tf

    variable "resource_prefix" {
      description = "Specifies a prefix for all the resource names."
      type        = string
    }
    
    variable "location" {
      description = "(Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created."
      type        = string
      default     = "WestEurope"
    }
    
    variable "blob_private_dns_zone" {
      description = "Specifies the name of the log analytics workspace"
      type        = string
    }
    variable "azurerm_public_ip" {
      description = "Specifies the name of the log analytics workspace"
      type        = string
    }
    
    variable "blob_private_endpoint" {
      description = "Specifies the name of the log analytics workspace"
      type        = string
    }
    
    variable "storage_account" {
      description = "Specifies the name of the log analytics workspace"
      type        = string
    }
    
    
    variable "network-security-group" {
      description = "Specifies the name of the log analytics workspace"
      type        = string
    }
    variable "log_analytics_workspace_name" {
      description = "Specifies the name of the log analytics workspace"
      type        = string
    }
    
    variable "log_analytics_retention_days" {
      description = "Specifies the number of days of the retention policy for the log analytics workspace."
      type        = number
      default     = 30
    }
    
    variable "application_insights_name" {
      description = "Specifies the name of the application insights resource."
      type        = string
    }
    
    variable "application_insights_application_type" {
      description = "(Required) Specifies the type of Application Insights to create. Valid values are ios for iOS, java for Java web, MobileCenter for App Center, Node.JS for Node.js, other for General, phone for Windows Phone, store for Windows Store and web for ASP.NET. Please note these values are case sensitive; unmatched values are treated as ASP.NET by Azure. Changing this forces a new resource to be created."
      type        = string
      default     = "web"
    }
    
    variable "virtual_network" {
      description = "Specifies the name of the virtual network"
      type        = string
    }
    
    variable "vnet_address_space" {
      description = "Specifies the address prefix of the virtual network"
      default     =  ["10.0.0.0/16"]
      type        = list(string)
    }
    
    variable "aca_subnet_name" {
      description = "Specifies the name of the subnet"
      type        = string
    }
    
    variable "aca_subnet_address_prefix" {
      description = "Specifies the address prefix of the Azure Container Apps environment subnet"
      default     = ["10.0.0.0/20"]
      type        = list(string)
    }
    
    variable "private_endpoint_subnet_name" {
      description = "Specifies the name of the subnet"
      type        = string
    }
    
    variable "private_endpoint_subnet_address_prefix" {
      description = "Specifies the address prefix of the private endpoints subnet"
      default     = ["10.0.16.0/24"]
      type        = list(string)
    }
    
    variable "storage_account_name" {
      description = "(Optional) Specifies the name of the storage account"
      type        = string
    }
    
    variable "storage_account_replication_type" {
      description = "(Optional) Specifies the replication type of the storage account"
      default     = "LRS"
      type        = string
    
      validation {
        condition = contains(["LRS", "ZRS", "GRS", "GZRS", "RA-GRS", "RA-GZRS"], var.storage_account_replication_type)
        error_message = "The replication type of the storage account is invalid."
      }
    }
    
    variable "storage_account_kind" {
      description = "(Optional) Specifies the account kind of the storage account"
      default     = "StorageV2"
      type        = string
    
       validation {
        condition = contains(["Storage", "StorageV2"], var.storage_account_kind)
        error_message = "The account kind of the storage account is invalid."
      }
    }
    
    variable "storage_account_tier" {
      description = "(Optional) Specifies the account tier of the storage account"
      default     = "Standard"
      type        = string
    
       validation {
        condition = contains(["Standard", "Premium"], var.storage_account_tier)
        error_message = "The account tier of the storage account is invalid."
      }
    }
    
    variable "managed_environment_name" {
      description = "(Required) Specifies the name of the managed environment."
      type        = string
    }
    
    variable "internal_load_balancer_enabled" {
      description = "(Optional) Should the Container Environment operate in Internal Load Balancing Mode? Defaults to false. Changing this forces a new resource to be created."
      type        = bool
      default     = false
    }
    
    variable "dapr_name" {
      description = "(Required) Specifies the name of the dapr component."
      type        = string
      default     = "statestore"
    }
    
    variable "dapr_component_type" {
      description = "(Required) Specifies the type of the dapr component."
      type        = string
      default     = "state.azure.blobstorage"
    }
    
    variable "dapr_ignore_errors" {
      description = "(Required) Specifies  if the component errors are ignored."
      type        = bool
      default     = false
    }
    
    variable "dapr_version" {
      description = "(Required) Specifies the version of the dapr component."
      type        = string
      default     = "v1"
    }
    
    variable "dapr_init_timeout" {
      description = "(Required) Specifies the init timeout of the dapr component."
      type        = string
      default     = "5s"
    }
    
    variable "dapr_scopes" {
      description = "(Required) Specifies the init timeout of the dapr component."
      type        = list
      default     = ["nodeapp"]
    }
    
    variable "container_name" {
      description = "Specifies the name of the container in the storage account."
      type        = string
      default     = "state"
    }
    
    variable "container_access_type" {
      description = "Specifies the access type of the container in the storage account."
      type        = string
      default     = "private"
    }
    
    variable "container_apps" {
      description = "Specifies the container apps in the managed environment."
      type = list(object({
        name                           = string
        revision_mode                  = optional(string)
        ingress                        = optional(object({
          allow_insecure_connections   = optional(bool)
          external_enabled             = optional(bool)
          target_port                  = optional(number)
          transport                    = optional(string)
          traffic_weight               = optional(list(object({
            label                      = optional(string)
            latest_revision            = optional(bool)
            revision_suffix            = optional(string)
            percentage                 = optional(number)
          })))
        }))
        dapr                           = optional(object({
          app_id                       = optional(string)
          app_port                     = optional(number)
          app_protocol                 = optional(string)
        }))
        secrets                        = optional(list(object({
          name                         = string
          value                        = string
        })))
        template                       = object({
          containers                   = list(object({
            name                       = string
            image                      = string
            args                       = optional(list(string))
            command                    = optional(list(string))
            cpu                        = optional(number)
            memory                     = optional(string)
            env                        = optional(list(object({
              name                     = string
              secret_name              = optional(string)
              value                    = optional(string)
            })))
          }))
          min_replicas                 = optional(number)
          max_replicas                 = optional(number)
          revision_suffix              = optional(string)
          volume                       = optional(list(object({
            name                       = string
            storage_name               = optional(string)
            storage_type               = optional(string)
          })))
        })
      }))
      default                          = [{
        name                           = "nodeapp"
        revision_mode                  = "Single"
        ingress                        = {
          external_enabled             = false
          target_port                  = 3000
          transport                    = "http"
          traffic_weight               = [{
            label                      = "blue"
            latest_revision            = true
            revision_suffix            = "blue"
            percentage                 = 100
          }]
        }
        dapr                           = {
          app_id                       = "nodeapp"
          app_port                     = 3000
          app_protocol                 = "http"
        }
        template                       = {
          containers                   = [{
            name                       = "hello-k8s-node"
            image                      = "dapriosamples/hello-k8s-node:latest"
            cpu                        = 0.5
            memory                     = "1Gi"
            env                        = [{
              name                     = "APP_PORT"
              value                    = 3000
            }]
          }]
          min_replicas                 = 1
          max_replicas                 = 1
        }
      },
      {
        name                           = "pythonapp"
        revision_mode                  = "Single"
        dapr                           = {
          app_id                       = "pythonapp"
          app_port                     = 80
        }
        template                       = {
          containers                   = [{
            name                       = "hello-k8s-python"
            image                      = "dapriosamples/hello-k8s-python:latest"
            cpu                        = 0.5
            memory                     = "1Gi"
          }]
          min_replicas                 = 1
          max_replicas                 = 1
        }
      }]
    }
    

    Resources are created in portal with my own naming convention, as below.

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search