Despliegue de Storage Account con Terraform y Terragrunt

Introducción

En este proyecto, se presenta una estructura organizada para el despliegue de una infraestructura en Azure utilizando Terraform y Terragrunt. La solución facilita la creación y gestión de recursos de Storage Account, optimizando la reutilización de configuraciones entre diferentes entornos, como desarrollo y producción, mediante archivos de configuración bien estructurados.

La estructura del proyecto permite una implementación modular y reutilizable, separando la configuración de los entornos específicos de los archivos de despliegue principales. Terraform y Terragrunt ofrecen un enfoque robusto para gestionar el estado y las variables comunes y específicas por entorno, facilitando así la administración y escalabilidad de la infraestructura en entornos empresariales.

Estructura del Proyecto

La organización del proyecto es la siguiente:

├── env
│   ├── code
│   │   └── storage
│   │       └── 00
│   │           ├── backend.tf
│   │           ├── data.tf
│   │           ├── endpoint.tf
│   │           ├── locals.tf
│   │           ├── main.tf
│   │           ├── outputs.tf
│   │           ├── provider.tf
│   │           └── variables.tf
│   └── dev
│       ├── storage
│       │   └── 00
│       │       ├── terragrunt.hcl
│       │       └── vars.tfvars
│       └── varEnvironment.hcl
├── varCommon.hcl
└── varDataState.hcl

La carpeta env contiene la configuración específica del entorno, mientras que code alberga los archivos de configuración de Terraform para el despliegue deStorage Account. La carpeta dev contiene archivos de configuración específicos del entorno de desarrollo. terragrunt.hclvarCommon.hcl y varDataState.hcl son archivos de configuración para Terragrunt y variables comunes.

Configuración de Terraform

Ahora, profundicemos en los archivos de configuración de Terraform necesarios para desplegar Storage Account.

 

backend.tf

terraform {
  backend "azurerm" {
  }
  required_version = "~>0.14"
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "3.47.0"
    }
  }
}

data.tf

El archivo data.tf contiene bloques de datos que permiten a Terraform acceder a la información de recursos existentes en Azure. Estos bloques son fundamentales para reutilizar la infraestructura existente y garantizar que los nuevos recursos se implementen de manera coherente.

 

data "terraform_remote_state" "rg" {
  backend = "azurerm"
  config = {
    subscription_id             = var.lz_subscription_id
    resource_group_name         = var.lz_resource_group_name
    storage_account_name        = var.lz_storage_account_name
    container_name              = var.lz_container_name
    key                         = "${var.ProjectName}/${var.ServiceName}/env/${var.Environment}/${var.mapProjectPathKey.rg}/terraform.tfstate"
  }
}

data "azurerm_resource_group" "rg_net" {
  name = var.rg_net_name
}

#State Vnet
data "azurerm_virtual_network" "vnet" {
  name = var.vnet_net_name
  resource_group_name = data.azurerm_resource_group.rg_net.name 
}

data "azurerm_subnet" "sbn_data" {
  name                 = var.sbn_data_net_name 
  virtual_network_name = data.azurerm_virtual_network.vnet.name
  resource_group_name  = data.azurerm_resource_group.rg_net.name
}

data "azurerm_resource_group" "hub_rg" {
  provider = azurerm.hub
  name     = var.hub_resource_group_name
}

data "azurerm_private_dns_zone" "zone_01" {
  provider            = azurerm.hub
  name                = var.private_dns_zone_name_01
  resource_group_name = data.azurerm_resource_group.hub_rg.name
}

data "azurerm_private_dns_zone" "zone_02" {
  provider            = azurerm.hub
  name                = var.private_dns_zone_name_02 
  resource_group_name = data.azurerm_resource_group.hub_rg.name
}

Explicación:

1. data «terraform_remote_state» «rg»

Este bloque accede al estado remoto de Terraform para reutilizar configuraciones ya existentes en otro lugar (por ejemplo, recursos definidos en un proyecto diferente). Se utiliza comúnmente en configuraciones multi-modulares.

  • backend: Define el tipo de backend (en este caso, Azure Resource Manager, azurerm) donde se almacena el estado de Terraform.
  • config: Contiene la configuración necesaria para conectarse al estado remoto:
    • subscription_id: ID de la suscripción de Azure donde se encuentra el estado.
    • resource_group_name: Nombre del grupo de recursos que contiene la cuenta de almacenamiento.
    • storage_account_name: Nombre de la cuenta de almacenamiento que aloja el estado.
    • container_name: Nombre del contenedor de blobs dentro de la cuenta de almacenamiento.
    • key: Ruta específica al archivo de estado remoto, organizada utilizando variables como el proyecto, el servicio, el entorno y un mapeo de ruta (mapProjectPathKey).

2. data «azurerm_resource_group» «rg_net»

Este bloque recupera información sobre un grupo de recursos existente en Azure.

  • name: Nombre del grupo de recursos que se desea consultar. Se define mediante la variable var.rg_net_name.

3. data «azurerm_virtual_network» «vnet»

Obtiene detalles sobre una red virtual específica.

  • name: Nombre de la red virtual objetivo, definido mediante var.vnet_net_name.
  • resource_group_name: Nombre del grupo de recursos donde se encuentra esta red virtual. Se obtiene dinámicamente de data.azurerm_resource_group.rg_net.name.

4. data «azurerm_subnet» «sbn_data»

Recupera información sobre una subred dentro de una red virtual específica.

  • name: Nombre de la subred, especificado mediante var.sbn_data_net_name.
  • virtual_network_name: Nombre de la red virtual asociada a la subred. Se extrae de data.azurerm_virtual_network.vnet.name.
  • resource_group_name: Grupo de recursos de la red virtual. Se obtiene de data.azurerm_resource_group.rg_net.name.

5. data «azurerm_resource_group» «hub_rg»

Obtiene información de un grupo de recursos que actúa como hub.

  • provider: Asocia un proveedor específico para operaciones relacionadas con este grupo de recursos (azurerm.hub).
  • name: Nombre del grupo de recursos del hub, definido por var.hub_resource_group_name.

6. data «azurerm_private_dns_zone» «zone_01»

Obtiene información sobre una zona DNS privada para resolver nombres de dominio internos.

  • provider: Usa el proveedor configurado como azurerm.hub para realizar operaciones en esta zona DNS.
  • name: Nombre de la zona DNS privada, definido por var.private_dns_zone_name_01.
  • resource_group_name: Grupo de recursos que aloja la zona DNS privada. Se obtiene del recurso data.azurerm_resource_group.hub_rg.name.

7. data «azurerm_private_dns_zone» «zone_02»

Otro bloque similar al anterior, pero para una segunda zona DNS privada.

  • provider: Igual que el anterior, usa azurerm.hub.
  • name: Define el nombre de la zona DNS privada (por ejemplo, privatelink.web.core.windows.net) a través de var.private_dns_zone_name_02.
  • resource_group_name: Se asocia con el grupo de recursos data.azurerm_resource_group.hub_rg.name.

endpoint.tf

Este archivo define el recurso de Private Endpoint, permitiendo la conexión privada al Storage Account. Este Private Endpoint se asocia a la subred y la zona DNS privada especificadas.

resource "azurerm_private_endpoint" "pren_01" {
  name                = upper(join("-", [ var.Environment, var.BussinessUnitExtended, var.Provider, var.ServiceName, var.storage_account_name, "pren-01"])) 
  resource_group_name = data.terraform_remote_state.rg.outputs.name
  location            = var.region
  subnet_id           = data.azurerm_subnet.sbn_data.id

  private_service_connection {
    name                           = upper(join("-", [ var.Environment, var.BussinessUnitExtended, var.Provider, var.ServiceName, var.storage_account_name, "pren-01"]))
    private_connection_resource_id = azurerm_storage_account.storage_01.id
    is_manual_connection           = false
    subresource_names              = ["blob"]
  }

  private_dns_zone_group {
    name                 = data.azurerm_private_dns_zone.zone_01.name
    private_dns_zone_ids = [data.azurerm_private_dns_zone.zone_01.id]
  }

  tags = local.tags

  lifecycle {
    ignore_changes = [
      tags["CreationDate"]
    ]
  }
}

Explicación:

resource «azurerm_private_endpoint» «pren_01»:


Este recurso define un Private Endpoint que permite una conexión segura y privada a una cuenta de almacenamiento en Azure.

  • name:
    Nombre del Private Endpoint, generado dinámicamente a partir de varias variables (Environment, BussinessUnitExtended, Provider, ServiceName, storage_account_name). Este formato asegura consistencia con la nomenclatura corporativa. Se convierte a mayúsculas usando upper().
  • resource_group_name:
    Especifica el grupo de recursos donde se crea el Private Endpoint.
    Se obtiene del estado remoto de Terraform (data.terraform_remote_state.rg.outputs.name), que centraliza la definición del grupo de recursos.
  • location:
    Región donde se despliega el Private Endpoint.
    Se define a través de la variable var.region.
  • subnet_id:
    ID de la subred donde se alojará el Private Endpoint.
    Se obtiene de data.azurerm_subnet.sbn_data.id, que recupera los detalles de la subred correspondiente.

Bloque private_service_connection

Configura la conexión privada al recurso de destino, en este caso, una cuenta de almacenamiento.

  • name:
    Nombre de la conexión privada, generado de forma similar al nombre del Private Endpoint.
  • private_connection_resource_id:
    ID del recurso de destino al que se conecta el Private Endpoint.
    En este caso, corresponde a la ID de la cuenta de almacenamiento (azurerm_storage_account.storage_01.id).
  • is_manual_connection:
    Establecido como false, lo que indica que la conexión privada se gestiona automáticamente por Azure.
  • subresource_names:
    Especifica el subrecurso dentro del servicio al que conectarse.
    En este caso, es el subrecurso blob de la cuenta de almacenamiento.

Bloque private_dns_zone_group

Define la relación entre el Private Endpoint y una zona DNS privada para resolver nombres de dominio internos.

  • name:
    Nombre de la zona DNS privada, obtenido de data.azurerm_private_dns_zone.zone_01.name.
  • private_dns_zone_ids:
    Lista de IDs de zonas DNS privadas asociadas al Private Endpoint.
    Aquí se utiliza el ID de data.azurerm_private_dns_zone.zone_01.id.

tags

Aplica etiquetas definidas en local.tags, lo que facilita la organización y el seguimiento del recurso dentro del entorno.

Bloque lifecycle

Configura el comportamiento de Terraform respecto a cambios en el recurso.

locals.tf

El archivo locals.tf define variables locales que pueden ser reutilizadas en múltiples partes del código Terraform. Las variables locales son útiles para centralizar valores que se utilizan en varios recursos, mejorando la claridad y mantenibilidad del código.

locals {
  storage_name = lower(join("", [var.Environment, var.BussinessUnitExtended, var.Provider, var.ServiceName, "st01"]))
  tags = var.tags
}

Explicación:

Define un nombre dinámico para un recurso, en este caso, probablemente una cuenta de almacenamiento.

Componentes:

  • lower(): Convierte el valor generado a minúsculas para cumplir con las restricciones de nombres de recursos en Azure (por ejemplo, los nombres de cuentas de almacenamiento deben estar en minúsculas).
  • join("", [...]): Combina los valores en una lista en una sola cadena, sin separadores.
  • Lista de valores usados:
    • var.Environment: Variable que representa el entorno, como «dev», «prod», etc.
    • var.BussinessUnitExtended: Identifica la unidad de negocio.
    • var.Provider: Especifica el proveedor o tecnología utilizada, como «azr» para Azure.
    • var.ServiceName: Nombre del servicio relacionado con el recurso.
    • "st01": Sufijo fijo para indicar que se trata de una cuenta de almacenamiento.

 

main.tf

En el archivo main.tf se definen los principales recursos de la infraestructura. En este caso, se está creando un recurso de Azure Storage Account que servirá para almacenar secretos y otros valores sensibles, asegurando así la seguridad de la información.

resource "azurerm_storage_account" "storage_01" {
  name                     = local.storage_name
  resource_group_name      = data.terraform_remote_state.rg.outputs.name
  location                 = var.region
  account_tier             = var.storage_account_tier 
  account_replication_type = var.storage_account_replication_type
  access_tier              = var.storage_account_access_tier 
  min_tls_version          = var.storage_account_min_tls_version 
  account_kind             = var.storage_account_kind
  is_hns_enabled           = var.storage_account_is_nhs_enabled 
  public_network_access_enabled = false
  tags                     = local.tags


  lifecycle {
    ignore_changes = [
      tags["CreationDate"]
    ]
  }

  blob_properties {
    container_delete_retention_policy {
      days = 7
    }
    delete_retention_policy {
      days = 7
    }
  }
}

Explicación

1. Definición del recurso

  • resource "azurerm_storage_account" "storage_01": Define un recurso de tipo azurerm_storage_account (Azure Storage Account) en Terraform.
    El identificador storage_01 se utiliza para referenciar este recurso en otras partes del código.

2. Atributos principales

  • name:
    Construye el nombre de la cuenta de almacenamiento utilizando la variable local local.storage_name, la cual combina dinámicamente valores como el entorno, unidad de negocio, proveedor y servicio. Esto garantiza un nombre único y estándar.
    (Ejemplo: devfinanceazrbackupst01)
  • resource_group_name:
    Especifica el grupo de recursos donde se creará la cuenta de almacenamiento.
    El nombre se obtiene del estado remoto de Terraform (terraform_remote_state.rg.outputs.name), asegurando consistencia con otros recursos que comparten el mismo grupo.
  • location:
    Define la región donde se ubicará la cuenta de almacenamiento, especificada por la variable var.region.
    (Ejemplo: eastus)
  • account_tier:
    Define el nivel de rendimiento de la cuenta de almacenamiento.
    Puede ser Standard o Premium, según el uso previsto.
    (Ejemplo: Standard)
  • account_replication_type:
    Especifica el tipo de replicación para garantizar la redundancia.
    Valores posibles: LRS, GRS, ZRS, etc.
    (Ejemplo: LRS)
  • access_tier:
    Determina si los datos se acceden frecuentemente (Hot) o de manera esporádica (Cool).
    (Ejemplo: Hot)
  • min_tls_version:
    Configura la versión mínima de TLS permitida para las conexiones. Mejora la seguridad al aceptar únicamente versiones modernas.
    (Ejemplo: TLS1_2)
  • account_kind:
    Tipo de cuenta de almacenamiento.
    (Ejemplo: StorageV2)
  • is_hns_enabled:
    Habilita la compatibilidad con Azure Data Lake Storage Gen2, permitiendo un modelo de acceso jerárquico para Big Data.
    (Ejemplo: true)
  • public_network_access_enabled:
    Establecido en false para restringir el acceso desde redes públicas, mejorando la seguridad al limitar el uso a redes privadas o endpoints privados.

3. Configuraciones avanzadas

  • tags:
    Aplica etiquetas definidas en local.tags para organizar el recurso. Estas etiquetas ayudan a la clasificación y búsqueda en Azure.
    (Ejemplo: { Environment = "dev", Owner = "John Doe" })
  • lifecycle:
    El bloque lifecycle indica que Terraform debe ignorar cualquier cambio en la etiqueta CreationDate. Esto evita que se realicen actualizaciones innecesarias en el recurso cuando solo cambia esta etiqueta.

4. Propiedades del blob

El bloque blob_properties define políticas para la gestión del ciclo de vida de los datos:

  • container_delete_retention_policy: Retiene contenedores eliminados durante 7 días, permitiendo su recuperación.
  • delete_retention_policy: Retiene blobs eliminados durante 7 días antes de su eliminación definitiva.

outputs.tf

El archivo outputs.tf expone información relevante del recurso azurerm_storage_account para facilitar su uso en otros módulos o para proporcionar datos clave a los usuarios de Terraform. Esto incluye endpoints, ubicaciones, claves de acceso, entre otros.

# IDs
output "id" {
    value = azurerm_storage_account.storage_01.id
    description = "The ID of the Storage Account."
}

output "primary_location" {
    value = azurerm_storage_account.storage_01.primary_location
    description = "The primary location of the storage account"
}

output "secondary_location" {
    value = azurerm_storage_account.storage_01.secondary_location
    description = "The secondary location of the storage account"
}

output "primary_blob_endpoint" {
    value = azurerm_storage_account.storage_01.primary_blob_endpoint
    description = "The primary blob endpoint of the storage account"
}

output "primary_blob_host" {
    value = azurerm_storage_account.storage_01.primary_blob_host
    description = "The primary blob host of the storage account"
}

output "secondary_blob_endpoint" {
    value = azurerm_storage_account.storage_01.secondary_blob_endpoint
    description = "The secondary blob endpoint of the storage account"
}

output "secondary_blob_host" {
    value = azurerm_storage_account.storage_01.secondary_blob_host
    description = "The secondary blob host of the storage account"
}

output "primary_access_key" {
    value = azurerm_storage_account.storage_01.primary_access_key
    description = "The primary access key of the storage account"
}

output "secondary_access_key" {
    value = azurerm_storage_account.storage_01.secondary_access_key
    description = "The secondary access key of the storage account"
}

output "primary_web_endpoint" {
    value = azurerm_storage_account.storage_01.primary_web_endpoint
    description = "The primary web endpoint of the storage account"
}

output "primary_web_host" {
    value = azurerm_storage_account.storage_01.primary_web_host
    description = "The primary web host of the storage account"
}

output "secondary_web_endpoint" {
    value = azurerm_storage_account.storage_01.secondary_web_endpoint
    description = "The secondary web endpoint of the storage account"
}

output "secondary_web_host" {
    value = azurerm_storage_account.storage_01.secondary_web_host
    description = "The secondary web host of the storage account"
}

output "primary_connection_string" {
    value = azurerm_storage_account.storage_01.primary_connection_string
    description = "The primary connection string of the storage account"
}

output "secondary_connection_string" {
    value = azurerm_storage_account.storage_01.secondary_connection_string
    description = "The secondary connection string of the storage account"
}

output "identity" {
    value = azurerm_storage_account.storage_01.identity
    description = "The identity of the storage account"
}

Explicación

  • output "id"

    • Proporciona el ID único del recurso de Azure Storage Account.
    • Útil para referencias cruzadas o integraciones con otros servicios de Azure.
      (Ejemplo: /subscriptions/{subscription-id}/resourceGroups/{rg-name}/providers/Microsoft.Storage/storageAccounts/{storage-name})
  • output "primary_location" y output "secondary_location"

    • Indican la ubicación primaria y secundaria de la cuenta de almacenamiento.
    • Relevante en configuraciones con replicación geográfica para identificar las regiones en uso.
      (Ejemplo: eastus, westus)
  • output "primary_blob_endpoint" y output "secondary_blob_endpoint"

    • Muestran los endpoints primarios y secundarios del servicio Blob.
    • Estos se utilizan para acceder y gestionar blobs almacenados en la cuenta.
      (Ejemplo: https://{storage-name}.blob.core.windows.net/)
  • output "primary_blob_host" y output "secondary_blob_host"

    • Exponen los nombres de host asociados a los endpoints Blob.
      (Ejemplo: {storage-name}.blob.core.windows.net)
  • output "primary_access_key" y output "secondary_access_key"

    • Devuelven las claves de acceso primarias y secundarias de la cuenta.
    • Estas claves son esenciales para autenticación cuando no se utiliza identidad administrada.
      (Nota: Debe manejarse con precaución y restringirse el acceso a este output en entornos sensibles).
  • output "primary_web_endpoint" y output "secondary_web_endpoint"

    • Proporcionan los endpoints primario y secundario del servicio web asociado.
      (Ejemplo: https://{storage-name}.web.core.windows.net/)
  • output "primary_connection_string" y output "secondary_connection_string"

    • Contienen las cadenas de conexión primarias y secundarias, utilizadas por aplicaciones para interactuar con la cuenta de almacenamiento.
      (Ejemplo: DefaultEndpointsProtocol=https;AccountName={storage-name};AccountKey={key};EndpointSuffix=core.windows.net)
  • output "identity"

    • Expone la identidad administrada asociada a la cuenta de almacenamiento, si está configurada.
      (Ejemplo: {"principal_id": "...", "tenant_id": "...", "type": "SystemAssigned"})

provider.tf

En el archivo provider.tf se configuran los proveedores de infraestructura, en este caso el proveedor de Azure (azurerm). Aquí se definen dos configuraciones para el proveedor de Azure, una por defecto y otra con un alias. Esto permite trabajar con múltiples suscripciones de Azure dentro del mismo proyecto Terraform

provider "azurerm" {
  subscription_id = var.Subscription
  tenant_id       = var.Tenant
  features {}
}

provider "azurerm" {
  alias           = "hub"
  subscription_id = var.subscription_hub_id
  tenant_id       = var.Tenant
  features {}
}

Explicación:

  • Primer bloque provider "azurerm":
    • subscription_id: Esta propiedad define la ID de la suscripción de Azure que se utilizará para aprovisionar y gestionar recursos. Se obtiene de la variable var.Subscription, que debe estar configurada previamente.
    • tenant_id: El ID de tenant de Azure Active Directory al que se debe asociar el proveedor de Azure. En este caso, se toma de var.Tenant.
    • features {}: Un bloque requerido por el proveedor de Azure (azurerm) que puede contener configuraciones adicionales. Aunque en este caso está vacío, es necesario para inicializar correctamente el proveedor.
  • Segundo bloque provider "azurerm" con alias hub:
    • alias: El alias "hub" permite crear un segundo proveedor de Azure dentro de la misma configuración de Terraform, lo cual es útil cuando se necesitan trabajar con múltiples suscripciones. Al asignar un alias, se puede referenciar este proveedor específico más adelante en los recursos o datos, de forma que se pueda diferenciar del proveedor predeterminado.
    • subscription_id: Similar al primer bloque, esta propiedad se define a través de var.subscription_hub_id, que representa la ID de la suscripción de Azure para la configuración del «hub».
    • tenant_id: El ID de tenant sigue siendo el mismo y se toma de var.Tenant para mantener la consistencia en el entorno.
    • features {}: Al igual que el primer bloque, este bloque es necesario aunque no contenga configuraciones adicionales.

variables.tf

En el archivo variables.tf se definen todas las variables utilizadas a lo largo de la infraestructura de Terraform. Este archivo centraliza los parámetros configurables que pueden cambiar dependiendo del entorno, la suscripción, el nombre de recursos, etc. Esto permite la reutilización del código y facilita su gestión.

 

######################
# VARIABLES COMUNES  #
######################

variable "lz_subscription_id" {
  type        = string
  description = "ID de la susbcriptcion de los tfstate"
  default     = ""
}

variable "lz_resource_group_name" {
  type        = string
  description = "Nombre del resoruce group de los tfstate"
  default     = ""
}

variable "lz_storage_account_name" {
  type        = string
  description = "Nombre del storage account de los tfstate"
  default     = ""
}

variable "lz_container_name" {
  type        = string
  description = "Nombre del container name de los tfstate"
  default     = ""
}

variable "Tenant" {
  type        = string
  description = "Nombre del tenant"
  default     = ""
}

variable "Subscription" {
  type        = string
  description = "Nombre de la subscripcion"
  default     = ""
}

variable "Provider" {
  type        = string
  description = "Nombre del Provider cloud"
  default     = ""
}

variable "Environment" {
  type        = string
  description = "(Required) Specifies the Environment where the Resources should exist."
  default     = ""
}

variable "BussinessUnit" {
  type        = string
  description = "(Required) Bussiness Unit."
  default     = ""
}

variable "BussinessUnitExtended" {
  type        = string
  description = "(Required) Bussiness Unit Extended."
  default     = ""
}


variable "ProjectName" {
  type        = string
  description = "(Required) ProjectName."
  default     = ""
}

variable "ServiceName" {
  type        = string
  description = "(Required) ServiceName."
  default     = ""
}

variable "mapProjectPathKey" {
  type        = map(string)
  default     = {}
  description = "Mapa de rutas de los elementos"
}

variable "region" {
  type        = string
  description = "(Required) Region Name"
  default     = ""
}

#############################
#   VARIABLES DATAS         #
#############################

variable "rg_net_name" {
  type        = string
  description = "Name rg of net"
  default = ""
}

variable "vnet_net_name" {
  type        = string
  description = "Name of vnet of net"
  default = ""
}

variable "sbn_data_net_name" {
  type        = string
  description = "Name of Subnet Data of net"
  default = ""
}

variable "rg_bkp_name" {
  type        = string
  description = "Name of resource group of bkp"
  default = ""
}

variable "st_bkp_name" {
  type        = string
  description = "Name of storage Account of bkp"
  default = ""
}

variable "EntityName" {
  type        = string
  description = "(Required) Entity Name."
  default     = ""
}

#############################
# VARIABLES Storage Account #
#############################

variable "storage_account_name" {
  type        = string
  description = "Nombre del storage account"
  default     = ""
}


variable "storage_account_tier" {
  type = string
  description = "Tier of storage account"
  default = ""
}

variable "storage_account_replication_type" {
  type = string
  description = "Replication type of storage account"
  default = ""
}

variable "storage_account_access_tier" {
  type = string
  description = "Access tier storage account"
  default = ""
}

variable "storage_account_min_tls_version" {
  type = string
  description = "Min tls version storage account"
  default = ""
}


variable "storage_account_kind" {
  type = string
  description = "Storage account kind"
  default = ""
}


variable "storage_account_is_nhs_enabled" {
  type = bool
  description = "is nhs storage account enabled"
  default = true
}

######################
#   VARIABLE TAGS    #
######################

variable "tags" {
  type        = map(string)
  default     = {}
  description = "(Optional) A mapping of tags which should be assigned to the Resource Group."
}

##########################
# Variables Provider HUB #
##########################

variable "hub_resource_group_name" {
  type    = string
  default = ""
  description = "Nombre del resource group de HUB"
}

variable "private_dns_zone_name_01" {
  type    = string
  default = ""
  description = "Nombre del private dns zone name de HUB"
}

variable "private_dns_zone_name_02" {
  type    = string
  default = ""
  description = "Nombre del private dns zone name de HUB"
}

variable "virtual_network_appgw_name" {
  type    = string
  default = ""
  description = "Nombre del network appgw de HUB"
}

variable "subnet_appgw_name" {
  type    = string
  default = ""
  description = "Nombre del subnet appgw de HUB"
}

variable "subscription_hub_id" {
  type    = string
  default = ""
  description = "Nombre de la subscripcion de HUB"
}

Explicación:

1. Variables comunes

Estas variables permiten establecer configuraciones básicas para el estado remoto, la suscripción y otros parámetros clave:

  • lz_subscription_id y lz_resource_group_name

    • ID de la suscripción y nombre del grupo de recursos donde se almacenará el estado remoto.
    • Facilitan la gestión del backend remoto en Terraform, generalmente almacenado en Azure Storage.
  • lz_storage_account_name y lz_container_name

    • Configuración del Storage Account y contenedor usados para almacenar el estado remoto (tfstate).
  • Tenant, Subscription, Provider

    • Información relacionada con el tenant de Azure, la suscripción y el proveedor en uso.
  • Environment, BussinessUnit, ProjectName y ServiceName

    • Detallan el entorno, la unidad de negocio, el nombre del proyecto y el servicio asociado al despliegue.
    • Estos valores suelen utilizarse en la definición de etiquetas (tags) o en nombres de recursos.
  • region

    • Define la región de Azure donde se desplegarán los recursos.
    • (Ejemplo: eastus, westeurope)

2. Variables específicas de red (DATAS)

Estas variables son necesarias para configurar la red del entorno:

  • rg_net_name: Nombre del grupo de recursos que contiene la red virtual.
  • vnet_net_name: Nombre de la red virtual asociada.
  • sbn_data_net_name: Nombre de la subred dentro de la red virtual.
  • rg_bkp_name y st_bkp_name: Recursos relacionados con backups, como grupo de recursos y Storage Account.
  • EntityName: Nombre identificador de la entidad asociada al despliegue.

3. Variables para el Storage Account

Estas variables permiten personalizar la configuración del almacenamiento:

  • storage_account_name

    • Nombre del Storage Account. (Ejemplo: stproject001)
    • Este valor suele tener que ser único globalmente.
  • storage_account_tier

    • Determina el nivel de rendimiento, como Standard o Premium.
  • storage_account_replication_type

    • Tipo de replicación: LRS, GRS, ZRS, etc.
    • (Ejemplo: LRS para replicación local, GRS para replicación geográfica).
  • storage_account_access_tier

    • Acceso a datos en el almacenamiento: Hot o Cool.
  • storage_account_min_tls_version

    • Versión mínima de TLS para conexiones seguras. (Ejemplo: TLS1_2)
  • storage_account_kind

    • Tipo de cuenta: Storage, StorageV2, etc.
  • storage_account_is_nhs_enabled

    • Indica si el almacenamiento está habilitado para NHS (Network Hierarchy Storage).

4. Variables de etiquetas

  • tags
    • Mapeo opcional para asignar etiquetas a los recursos.
    • Facilita la organización y el filtrado de recursos en Azure. (Ejemplo: {"Environment" = "Dev", "Owner" = "TeamA"})

5. Variables específicas del proveedor HUB

Estas variables son útiles cuando el despliegue implica integración o comunicación con una suscripción secundaria de tipo HUB (red compartida, App Gateway, etc.):

  • hub_resource_group_name

    • Grupo de recursos del HUB.
  • private_dns_zone_name_01 y private_dns_zone_name_02

    • Zonas de DNS privadas utilizadas en el entorno HUB. (Ejemplo: privatelink.blob.core.windows.net)
  • virtual_network_appgw_name y subnet_appgw_name

    • Configuración de la red y subred para un Application Gateway.
  • subscription_hub_id

    • ID de la suscripción asociada al HUB.

terragrunt.hcl

El archivo terragrunt.hcl que proporcionas configura un entorno para gestionar infraestructura utilizando Terragrunt, que es una herramienta para gestionar configuraciones de Terraform de manera modular. Aquí está un desglose detallado de lo que hace este archivo:

dependencies {
  paths = [
    "../../rg/00/"
  ]
}

include "varEnvironment" {
  path = find_in_parent_folders("varEnvironment.hcl")
  expose = true
}

include "varCommon" {
  path = find_in_parent_folders("varCommon.hcl")
  expose = true
}

include "varDataState" {
  path = find_in_parent_folders("varDataState.hcl")
  expose = true
}

locals {
  mapProjectPathKey = jsonencode(include.varEnvironment.inputs.mapProjectPathKey)
  tags = jsonencode(merge({
    Managed_By = "Terraform"
    Provider = "AZR"
  },
  include.varCommon.inputs.globalTags,
  include.varEnvironment.inputs.environmentTags
  ))
}

generate "backend"{
  path      = "backend.tfvars"
  if_exists = "overwrite" # "overwrite" "skip" "overwrite_terragrunt" 
  contents = <<EOF
subscription_id = "${include.varDataState.inputs.lz_subscription_id}"
key = "${include.varCommon.inputs.ProjectName}/${include.varCommon.inputs.ServiceName}/${get_path_from_repo_root()}/terraform.tfstate"
resource_group_name = "${include.varDataState.inputs.lz_resource_group_name}"
storage_account_name =  "${include.varDataState.inputs.lz_storage_account_name}"
container_name = "${include.varDataState.inputs.lz_container_name}"
EOF
}

generate "vars"{
  path      = "vars.tfvars"
  if_exists = "overwrite"
  contents = <<EOF
###############################
#    VALORES DATA DataState     #
###############################
lz_subscription_id             = "${include.varDataState.inputs.lz_subscription_id}"
lz_resource_group_name         = "${include.varDataState.inputs.lz_resource_group_name}" 
lz_storage_account_name        = "${include.varDataState.inputs.lz_storage_account_name}" 
lz_container_name              = "${include.varDataState.inputs.lz_container_name}" 

###############################
#     VALORES GENERALES       #
###############################
region  = "${include.varEnvironment.inputs.region}"
Environment = "${include.varEnvironment.inputs.Environment}"
BussinessUnit = "${include.varCommon.inputs.BussinessUnit}"
ProjectName = "${include.varCommon.inputs.ProjectName}"
ServiceName = "${include.varCommon.inputs.ServiceName}"
Subscription = "${include.varEnvironment.inputs.Subscription}"
Tenant = "${include.varCommon.inputs.Tenant}"
# ApplicationName = null
mapProjectPathKey = ${local.mapProjectPathKey}

##################################
# Valores Container Provider HUB #
##################################

hub_resource_group_name = "PRO-NWHUB-RGP-01"
private_dns_zone_name_01 = "privatelink.blob.core.windows.net"
private_dns_zone_name_02 = "privatelink.web.core.windows.net"
subscription_hub_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"

##############################
# Valores Storage Account    #
##############################

rg_net_name = "${include.varEnvironment.inputs.NetworkResourceGroup}"
vnet_net_name = "${include.varEnvironment.inputs.Network}"
sbn_data_net_name = "${include.varEnvironment.inputs.SubnetworkFront}"

storage_account_name = "st01"

storage_account_tier = "Standard"
storage_account_replication_type = "LRS"
storage_account_access_tier = "Hot"
storage_account_min_tls_version = "TLS1_2"
storage_account_is_nhs_enabled = "false"
storage_account_kind = "StorageV2"

###########################
#       VALORES TAGS      #
###########################

tags = ${local.tags}

EOF
}

terraform {
  source = "../../..//code/storage/00/"

  before_hook "print_tags" {
    commands = ["plan", "apply"] #["${get_terraform_commands_that_need_vars()}"]
    execute  = ["echo", "tags", "=", "${local.tags}", ">", "vars.tfvars"]
  }

  before_hook "copy_vars" {
    commands = ["plan", "apply"] #["${get_terraform_commands_that_need_vars()}"]
    execute  = ["cp", "-f", "vars.tfvars", "${get_original_terragrunt_dir()}/vars.tfvars"]
  }

  extra_arguments "backend_vars" {
    commands = ["init"]
    arguments = [
      "-backend-config=backend.tfvars"
    ]
  }
  extra_arguments "vars_vars" {
    commands = ["plan", "apply", "destroy", "import"]

    arguments = [
      "-var-file=vars.tfvars"
    ]
  }
}

Explicación:

  • dependencies: Este bloque define las dependencias del Terragrunt. En este caso, no se especifican rutas de dependencias, ya que el bloque paths está vacío.
  • include: Estos bloques incluyen archivos de variables externos (varEnvironment.hclvarCommon.hclvarDataState.hcl) en el Terragrunt. Los archivos incluidos pueden exponer sus variables para ser utilizadas en este archivo Terragrunt.
  • locals: Este bloque define variables locales que se utilizan dentro de este archivo Terragrunt.
  • mapProjectPathKey: Codifica como JSON el mapa mapProjectPathKey del archivo varEnvironment.hcl.
  • tagsCodifica como JSON un conjunto de etiquetas combinando un conjunto fijo de etiquetas (Managed_By y Provider), las etiquetas globales definidas en varCommon.hcl y las etiquetas específicas del entorno definidas en varEnvironment.hcl.
  • generate "backend": Este bloque genera un archivo llamado backend.tfvars. Este archivo se utiliza para configurar el backend de Terraform. Contiene variables como subscription_idkeyresource_group_namestorage_account_name, y container_name. Los valores de estas variables se obtienen de los archivos incluidos (varDataState.hcl y varCommon.hcl).
  • generate "vars": Este bloque genera un archivo llamado vars.tfvars. Este archivo se utiliza para proporcionar valores de variables a Terraform. Contiene valores para las variables específicas definidas en los archivos incluidos (varDataState.hclvarCommon.hclvarEnvironment.hcl). Los valores se interpolan a partir de las variables incluidas.
  • terraform: Este bloque proporciona configuraciones adicionales para Terraform.
  • source: Especifica la ruta de origen del módulo de Terraform. En este caso, el origen se establece en un directorio relativo ../../..//code/rg/00/.
  • before_hookEste bloque define ganchos de ejecución que se ejecutarán antes de ciertos comandos de Terraform, como plan y apply. En este caso, se ejecutan dos ganchos: print_tags y copy_vars.
  • extra_arguments: Este bloque especifica argumentos adicionales que se pasarán a los comandos de Terraform (initplanapplydestroyimport). En este caso, se especifican argumentos adicionales para la configuración del backend (backend_vars) y para las variables (vars_vars).

varEnvironment.hcl

locals {
  region               = "northeurope"
  Environment          = "dev"
  EnvironmentLetter    = "d"
  Subscription         = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  NetworkResourceGroup = "DEV-REDORBITA-RG-01"
  Network              = "DEV-REDORBITA-NET-01"
  SubnetworkFront      = "DEV-REDORBITA-SBN-01"
  SubnetworkVint       = "DEV-REDORBITA-VINT-SBN-01"
  mapProjectPathKey = {
    rg                          = "rg/00",
    sbnVint00                   = "networking/sbn/vint00",
	storage                     = "storage/00"
   }
}

inputs = {
  region               = local.region
  Environment          = local.Environment
  EnvironmentLetter    = local.EnvironmentLetter
  Subscription         = local.Subscription
  NetworkResourceGroup = local.NetworkResourceGroup
  Network              = local.Network
  SubnetworkFront      = local.SubnetworkFront
  SubnetworkVint      = local.SubnetworkVint
  environmentTags = {
    Enviroment       = "${upper(local.Environment)}"
  }
  mapProjectPathKey = local.mapProjectPathKey
 }
}

varCommon.hcl

Este archivo contiene una definición estructurada de valores locales y entradas comunes que se utilizan para organizar y parametrizar los recursos dentro de Terraform. La combinación de locals e inputs permite separar las configuraciones por entorno y facilita la reutilización del código en múltiples proyectos. A continuación, se detalla cada sección:

locals {
  EntityName              = "RO"
  ProjectName             = "RedOrbita"
  ServiceName             = "RedOrbita"
  BussinessUnit           = "XX"
  Subscription            = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  Tenant                  = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  Provider                = "azr"
  required_version = "~>0.14"
  globalTags = {
      Company             = "Red-Orbita"
      Owner               = "xxxx@redorbita.com"
      ProjectName         = "XXXX"
      "Service Description" = "XXXX"
      Status              = "Implementacion"
      Provider            = "Azure"
      Cluster             = "N/A"
      "Operating System"  = "N/A"
      Temporal            = "NO"
      "App ID"              = "N/A"
    }
  storage_account          = "protfdata"
  container_name           = "iasearch" 
  subscription_hub_id2     = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  location                 = "northeurope"
}



inputs = {
  ##############################
  #  VARIABLES COMMON          #
  ##############################

  EntityName              = local.EntityName
  ProjectName             = local.ProjectName
  ServiceName             = local.ServiceName
  BussinessUnit           = local.BussinessUnit
  Subscription            = local.Subscription
  Tenant                  = local.Tenant
  Provider                = local.Provider
  required_version        = local.required_version
  globalTags              = local.globalTags
}



inputs = {
  ##############################
  #  VARIABLES COMMON          #
  ##############################

  EntityName              = local.EntityName
  ProjectName             = local.ProjectName
  ServiceName             = local.ServiceName
  BussinessUnit           = local.BussinessUnit
  # Subscription            = local.Subscription
  # Subscription_pro        = local.Subscription_pro
  Tenant                  = local.Tenant
  Provider                = local.Provider
  required_version        = local.required_version
  id_project              = local.id_project
  globalTags              = local.globalTags
}
  • Bloque locals

    En este bloque, se definen variables locales dentro del archivo que pueden ser utilizadas dentro del propio archivo o por otros módulos de Terraform:

    • EntityName: Es el nombre de la entidad asociada al proyecto, en este caso, «RO». Generalmente se utiliza como identificador de un proyecto o unidad dentro de la organización.
    • ProjectName: El nombre del proyecto, en este caso, «RedOrbita», que identifica el nombre de la iniciativa bajo la cual se gestionan los recursos.
    • ServiceName: El nombre del servicio relacionado con el proyecto, aquí también se define como «RedOrbita». Hace referencia al servicio o solución principal que se implementará.
    • BussinessUnit: Especifica la unidad de negocio asociada al proyecto, aquí representada por «XX».
    • Subscription: El identificador de la suscripción de Azure asociada al proyecto. Es un valor único que se usa para gestionar los recursos dentro de la suscripción de Azure.
    • Tenant: El identificador del tenant de Azure, que representa un directorio único dentro de Azure Active Directory.
    • Provider: El proveedor de infraestructura que se utilizará. En este caso, «azr» hace referencia a Azure.
    • required_version: Especifica la versión de Terraform requerida para ejecutar este archivo. En este caso, se requiere cualquier versión compatible con «0.14.x».
    • globalTags: Define un conjunto de etiquetas globales que se aplicarán a todos los recursos. Las etiquetas incluyen detalles como el nombre de la empresa, el propietario del proyecto, el estado del proyecto, la descripción del servicio, el proveedor de infraestructura, etc.
    • storage_account: El nombre de la cuenta de almacenamiento de Azure, en este caso, «protfdata».
    • container_name: El nombre del contenedor dentro de la cuenta de almacenamiento de Azure, «iasearch».
    • subscription_hub_id2: Un segundo ID de suscripción, posiblemente relacionado con el hub de red o recursos específicos.
    • location: Especifica la región de Azure donde se desplegarán los recursos, en este caso, «northeurope».
  • Bloque inputs

    El bloque de inputs toma los valores definidos en el bloque locals y los pasa como entradas para ser utilizados en otros módulos o recursos dentro del proyecto. Las variables comunes definidas en locals se referencian aquí para garantizar la consistencia de los valores a través del proyecto. En este caso, se repiten las mismas entradas para las variables definidas, permitiendo su reutilización en otros módulos de Terraform.

    • EntityName, ProjectName, ServiceName, BussinessUnit, Subscription, Tenant, Provider, required_version, globalTags: Estas entradas se asignan directamente a las variables locales definidas anteriormente, garantizando que los valores sean consistentes en todo el proyecto.

    • id_project: Se hace referencia a una variable llamada id_project, aunque esta no está definida en los locales. Esto sugiere que esta variable se puede definir en otro lugar o se utiliza para proyectos específicos.

varDataState.hcl

Este archivo varDataState.hcl se utiliza para definir y organizar las variables relacionadas con el estado de los datos y la infraestructura de Terraform en el entorno de trabajo. Este archivo contiene configuraciones para el almacenamiento del estado de Terraform en Azure, lo cual es crucial para el manejo de los recursos de infraestructura y su persistencia. A continuación, se explica el propósito y uso de las configuraciones definidas en este archivo:

 


locals {
 lz_subscription_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
 lz_resource_group_name = "PRO-HUB-01"
 lz_storage_account_name = "storage"
 lz_container_name = "storage"
 path_resources_terraform_state = jsonencode({
 rg = "rg/00"

})
}

inputs = {
##############################
# VARIABLES FOR DATA STATES #
##############################
lz_subscription_id = local.lz_subscription_id
lz_resource_group_name = local.lz_resource_group_name
lz_storage_account_name = local.lz_storage_account_name
lz_container_name = local.lz_container_name
path_resources_terraform_state = local.path_resources_terraform_state
}

1. Bloque locals

El bloque locals define las variables locales dentro de este archivo, las cuales pueden ser reutilizadas dentro del archivo o en otros módulos de Terraform. Las variables locales que se definen aquí incluyen:

  • lz_subscription_id: El ID de la suscripción de Azure utilizada para gestionar los recursos en la infraestructura. Este valor es único para cada suscripción de Azure.
  • lz_resource_group_name: El nombre del grupo de recursos de Azure que se utilizará para almacenar los recursos de Terraform, en este caso PRO-HUB-01. Los grupos de recursos son unidades lógicas que agrupan recursos relacionados en Azure.
  • lz_storage_account_name: El nombre de la cuenta de almacenamiento de Azure, en este caso storage, que se utilizará para almacenar el estado de Terraform y otros recursos persistentes.
  • lz_container_name: El nombre del contenedor dentro de la cuenta de almacenamiento de Azure, aquí denominado storage, donde se almacenarán los archivos de estado de Terraform.
  • path_resources_terraform_state: Un valor en formato JSON que define la ruta dentro del contenedor de almacenamiento donde se guardarán los archivos de estado de Terraform. En este caso, la ruta está definida como rg/00.

2. Bloque inputs

El bloque inputs se utiliza para definir las entradas de las variables que serán pasadas a los módulos de Terraform. Estas entradas corresponden a las variables locales que se definieron previamente y que se usarán para configurar el almacenamiento del estado de Terraform en Azure. Las variables de entrada son:

  • lz_subscription_id: El ID de la suscripción de Azure que se pasa como entrada a los módulos.
  • lz_resource_group_name: El nombre del grupo de recursos que se pasará como entrada.
  • lz_storage_account_name: El nombre de la cuenta de almacenamiento que se utilizará para gestionar el estado.
  • lz_container_name: El nombre del contenedor donde se almacenará el estado.
  • path_resources_terraform_state: La ruta donde se almacenará el estado de Terraform dentro del contenedor.

:wq!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *