Procedimientos recomendados para plantilla de Resource Manager

En este artículo se explica cómo usar procedimientos recomendados al crear la plantilla de Azure Resource Manager (plantilla de ARM). Estas recomendaciones ayudan a evitar problemas comunes al usar una plantilla de Resource Manager para implementar una solución.

Límites de plantilla

Limite el tamaño de la plantilla a 4 MB y cada definición de recurso a 1 MB. Los límites se aplican al estado final de la plantilla una vez se ha ampliado con definiciones de recursos iterativas y los valores de variables y parámetros. El archivo de parámetros también está limitado a 4 MB. Es posible que reciba un error con una plantilla o un archivo de parámetros de menos de 4 MB si el tamaño total de la solicitud es demasiado grande. Para más información sobre cómo simplificar la plantilla para evitar una solicitud de gran tamaño, consulte Resolución de errores de tamaño de trabajo superado.

También está limitado a:

  • 256 parámetros
  • 256 variables
  • 800 recursos (incluido el recuento de copia)
  • 64 valores de salida
  • 10 ubicaciones únicas por ámbito de suscripción, inquilino o grupo de administración
  • 24 576 caracteres en una expresión de plantilla

Puede superar algunos límites de plantilla utilizando una plantilla anidada. Para más información, consulte Uso de plantillas vinculadas y anidadas al implementar recursos de Azure. Para reducir el número de parámetros, variables o salidas, puede combinar varios valores en un objeto. Para más información, consulte Objetos como parámetros.

Resource group

Al implementar recursos en un grupo de recursos, este almacena metadatos sobre los recursos. Estos metadatos se almacenan en la ubicación del grupo de recursos.

Si la región del grupo de recursos no está disponible temporalmente, no puede actualizar los recursos del grupo de recursos porque los metadatos no están disponibles. Los recursos de otras regiones seguirán funcionando según lo previsto, pero no podrá actualizarlos. Para minimizar el riesgo, busque el grupo de recursos y los recursos en la misma región.

Parámetros

La información en esta sección puede ser útil cuando se trabaja con parámetros.

Recomendaciones generales para parámetros

  • Minimice el uso de los parámetros. En su lugar, use las variables o valores literales de propiedades que no deben especificarse durante la implementación.

  • Use una mezcla de mayúsculas y minúsculas para los nombres de parámetro.

  • Use parámetros para configuraciones que varían según el entorno, como la SKU, el tamaño o la capacidad.

  • Use parámetros para nombres de recurso que quiera especificar para facilitar la identificación.

  • Proporcione una descripción de cada parámetro en los metadatos.

    "parameters": {
      "storageAccountType": {
        "type": "string",
        "metadata": {
          "description": "The type of the new storage account created to store the VM disks."
        }
      }
    }
    
  • Defina valores predeterminados para los parámetros que no son confidenciales. Al especificar un valor predeterminado, resulta más fácil implementar la plantilla y los usuarios de esta ven un ejemplo de un valor adecuado. Cualquier valor predeterminado para un parámetro debe ser válido para todos los usuarios en la configuración de implementación predeterminada.

    "parameters": {
      "storageAccountType": {
        "type": "string",
        "defaultValue": "Standard_GRS",
        "metadata": {
          "description": "The type of the new storage account created to store the VM disks."
        }
      }
    }
    
  • Para especificar un parámetro opcional, no use una cadena vacía como valor predeterminado. En su lugar, use un valor literal o una expresión de lenguaje para construir un valor.

    "storageAccountName": {
       "type": "string",
       "defaultValue": "[concat('storage', uniqueString(resourceGroup().id))]",
       "metadata": {
         "description": "Name of the storage account"
       }
    }
    
  • Use allowedValues con moderación. Úselo solo cuando deba asegurarse de que algunos valores no están incluidos en las opciones permitidas. Si usa allowedValues de forma demasiado amplia, podría bloquear implementaciones válidas al no mantener actualizada la lista.

  • Cuando un nombre de parámetro en la plantilla coincide con un parámetro en el comando de PowerShell de implementación, Resource Manager resuelve este conflicto de nomenclatura agregando el postfijo FromTemplate al parámetro de plantilla. Por ejemplo, si incluye un parámetro llamado ResourceGroupName en la plantilla, entra en conflicto con el parámetro ResourceGroupName del cmdlet New-AzResourceGroupDeployment. Durante la implementación, se le pide que proporcione un valor para ResourceGroupNameFromTemplate.

Recomendaciones de seguridad para parámetros

  • Use siempre los parámetros para los nombres de usuario y contraseñas (o secretos).

  • Use securestring para todas las contraseñas y secretos. Si pasa datos confidenciales en un objeto JSON, use el tipo secureObject. No se pueden leer los parámetros con los tipos secureString o secureObject después de la implementación de recursos.

    "parameters": {
      "secretValue": {
        "type": "securestring",
        "metadata": {
          "description": "The value of the secret to store in the vault."
        }
      }
    }
    
  • No proporcione valores predeterminados para los nombres de usuario, contraseñas o cualquier valor que requiera un tipo secureString.

  • No proporcione valores predeterminados para las propiedades que aumenten la superficie de ataque de la aplicación.

Recomendaciones de ubicación para parámetros

  • Use un parámetro para especificar la ubicación de recursos y establecer el valor predeterminado en resourceGroup().location. Proporcionar un parámetro de ubicación permite a los usuarios de la plantilla especificar una ubicación en la que tienen permiso para implementar recursos.

    "parameters": {
       "location": {
         "type": "string",
         "defaultValue": "[resourceGroup().location]",
         "metadata": {
           "description": "The location in which the resources should be deployed."
         }
       }
    }
    
  • No especifique allowedValues para el parámetro de ubicación. Las ubicaciones que especifique pueden no estar disponibles en todas las nubes.

  • Utilice el valor del parámetro de ubicación para los recursos que pueden estar en la misma ubicación. Con este enfoque se minimiza la cantidad de veces que se les pide a los usuarios que proporcionen información de ubicación.

  • Para los recursos que no están disponibles en todas las ubicaciones, utilice un parámetro independiente o especifique un valor de ubicación literal.

variables

La siguiente información puede ser útil cuando se trabaja con variables:

  • Use mayúsculas y minúsculas combinadas para los nombres de variables.

  • Use las variables para los valores que deba utilizar más de una vez en una plantilla. Si un valor se usa solo una vez, codificarlo de forma rígida hace que la plantilla resulte más fácil de leer.

  • Use variables para los valores que construya a partir de una organización compleja de funciones de plantilla. La plantilla es más fácil de leer cuando la expresión compleja aparece solo en las variables.

  • No se puede usar la función reference en la sección variables de la plantilla. La función reference deriva su valor desde el estado de tiempo de ejecución del recurso. Sin embargo, las variables se resuelven durante el análisis inicial de la plantilla. Construya valores que requieran la función reference directamente en las secciones resources u outputs de la plantilla.

  • Incluya variables para los nombres de recursos que deben ser únicos.

  • Use un bucle de copia en variables para crear un patrón repetido de objetos JSON.

  • Quite las variables no utilizadas.

Versión de API

Establezca la propiedad apiVersion en una versión de API codificada de forma rígida para el tipo de recurso. Al crear una plantilla, se recomienda usar la última versión de la API para un tipo de recurso. Para determinar los valores disponibles, consulte la referencia de plantilla.

Cuando la plantilla funciona según lo previsto, se recomienda seguir usando la misma versión de la API. Al usar la misma versión de la API, no tiene que preocuparse de los cambios importantes que se pueden introducir en versiones posteriores.

Evite usar un parámetro en la versión de API. Las propiedades y los valores de los recursos pueden variar en función de la versión de API. La función IntelliSense en un editor de código no puede determinar el esquema correcto si la versión de API se establece como un parámetro. Si pasa una versión de API que no coincide con las propiedades de la plantilla, se producirá un error en la implementación.

No use variables para la versión de API.

Dependencias de recursos

A la hora de decidir qué dependencias establecer, use las siguientes directrices:

  • Use la función reference y pase el nombre del recurso para establecer dependencias implícitas entre los recursos que deben compartir una propiedad. No agregue un elemento dependsOn explícito cuando ya haya definido una dependencia implícita. Este enfoque reduce el riesgo de que se tengan dependencias innecesarias. Para un ejemplo de cómo establecer una dependencia implícita, vea Funciones de referencia y lista.

  • Establezca un recurso secundario como dependiente de su recurso principal.

  • Los recursos con el elemento condition establecido en false se quitan automáticamente de la orden de dependencia. Establezca las dependencias como si siempre se implementase el recurso.

  • Permita dependencias en cascada sin establecerlas explícitamente. Por ejemplo, la máquina virtual depende de una interfaz de red virtual y la interfaz de red virtual depende de una red virtual y las direcciones IP públicas. Por lo tanto, la máquina virtual se implementa después de los tres recursos, pero no se establece explícitamente la máquina virtual como dependiente de los tres recursos. Este enfoque aclara el orden de dependencia y facilita el cambio de la plantilla más adelante.

  • Si no se puede determinar un valor antes de la implementación, intente implementar el recurso sin una dependencia. Por ejemplo, si un valor de configuración necesita el nombre de otro recurso, quizás no necesite una dependencia. Esta guía no siempre funciona porque algunos recursos comprueban la existencia de los otros. Si recibe un error, agregue una dependencia.

Recursos

La información siguiente puede ser útil cuando se trabaja con recursos:

  • Para ayudar a otros colaboradores a comprender el propósito del recurso, especifique comments para cada recurso de la plantilla.

    "resources": [
      {
        "name": "[variables('storageAccountName')]",
        "type": "Microsoft.Storage/storageAccounts",
        "apiVersion": "2019-06-01",
        "location": "[resourceGroup().location]",
        "comments": "This storage account is used to store the VM disks.",
          ...
      }
    ]
    

    Si la plantilla de ARM se almacena en un archivo de .jsonc, se admiten comentarios mediante la sintaxis //, como se muestra aquí.

    "resources": [
      {
        // This storage account is used to store the VM disks.
        "name": "[variables('storageAccountName')]",
        "type": "Microsoft.Storage/storageAccounts",
        "apiVersion": "2019-06-01",
        "location": "[resourceGroup().location]",
          ...
      }
    ]
    

    Para obtener más información sobre comentarios y metadatos, consulte Nociones sobre la estructura y la sintaxis de las plantillas de Azure Resource Manager.

  • Si usa un punto de conexión público en la plantilla (como un punto de conexión público de Azure Blob Storage), no codifique de forma rígida el espacio de nombres. Use la función reference para recuperar dinámicamente el espacio de nombres. Puede usar este enfoque para implementar la plantilla en diversos entornos de espacios de nombres públicos sin cambiar manualmente el punto de conexión de la plantilla. Establezca la versión de API en la misma versión que usa para la cuenta de almacenamiento de la plantilla.

    "diagnosticsProfile": {
      "bootDiagnostics": {
        "enabled": "true",
        "storageUri": "[reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').primaryEndpoints.blob]"
      }
    }
    

    Si la cuenta de almacenamiento se implementa en la misma plantilla que está creando y el nombre de la cuenta de almacenamiento no se comparte con otro recurso de la plantilla, no es necesario especificar el espacio de nombres del proveedor ni apiVersion al hacer referencia al recurso. En el siguiente ejemplo se muestra la sintaxis simplificada.

    "diagnosticsProfile": {
      "bootDiagnostics": {
        "enabled": "true",
        "storageUri": "[reference(variables('storageAccountName')).primaryEndpoints.blob]"
      }
    }
    

    También puede hacer referencia a una cuenta de almacenamiento existente que se encuentra en un grupo de recursos distinto.

    "diagnosticsProfile": {
      "bootDiagnostics": {
        "enabled": "true",
        "storageUri": "[reference(resourceId(parameters('existingResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('existingStorageAccountName')), '2019-06-01').primaryEndpoints.blob]"
      }
    }
    
  • Asigne direcciones IP públicas a una máquina virtual solo cuando lo requiera una aplicación. Para conectarse a una máquina virtual con fines administrativos, use reglas NAT de entrada, una puerta de enlace de red virtual o Jumpbox.

    Para obtener más información sobre cómo conectarse a máquinas virtuales, consulte:

  • La propiedad domainNameLabel para las direcciones IP públicas debe ser única. El valor domainNameLabel debe contener entre 3 y 63 caracteres y seguir las reglas especificadas por esta expresión regular: ^[a-z][a-z0-9-]{1,61}[a-z0-9]$. Como la función uniqueString genera una cadena de trece caracteres, el parámetro dnsPrefixString se limita a no más de cincuenta caracteres.

    "parameters": {
      "dnsPrefixString": {
        "type": "string",
        "maxLength": 50,
        "metadata": {
          "description": "The DNS label for the public IP address. It must be lowercase. It should match the following regular expression, or it will raise an error: ^[a-z][a-z0-9-]{1,61}[a-z0-9]$"
        }
      }
    },
    "variables": {
      "dnsPrefix": "[concat(parameters('dnsPrefixString'),uniquestring(resourceGroup().id))]"
    }
    
  • Cuando agregue una contraseña a una extensión de script personalizada, use la propiedad commandToExecute en la propiedad protectedSettings.

    "properties": {
      "publisher": "Microsoft.Azure.Extensions",
      "type": "CustomScript",
      "typeHandlerVersion": "2.0",
      "autoUpgradeMinorVersion": true,
      "settings": {
        "fileUris": [
          "[concat(variables('template').assets, '/lamp-app/install_lamp.sh')]"
        ]
      },
      "protectedSettings": {
        "commandToExecute": "[concat('sh install_lamp.sh ', parameters('mySqlPassword'))]"
      }
    }
    

    Nota:

    Para garantizar que los secretos se cifran cuando se transmiten como parámetros a máquinas virtuales y extensiones, use la propiedad protectedSettings de las extensiones pertinentes.

  • Especifique valores explícitos para las propiedades que tienen valores predeterminados que podrían cambiar con el tiempo. Por ejemplo, si va a implementar un clúster de AKS, puede especificar u omitir la propiedad kubernetesVersion. Si no la especifica, el clúster toma como valor predeterminado la versión secundaria N-1 y la revisión más reciente. Al implementar el clúster mediante una plantilla de ARM, este comportamiento predeterminado podría no ser el esperado. Volver a implementar la plantilla puede dar lugar a que el clúster se actualice a una nueva versión de Kubernetes de forma inesperada. En su lugar, considere la posibilidad de especificar un número de versión explícito y cambiarlo manualmente cuando esté listo para actualizar el clúster.

Comentarios

Además de la propiedad comments, se admiten comentarios mediante la sintaxis //. Para obtener más información sobre comentarios y metadatos, consulte Nociones sobre la estructura y la sintaxis de las plantillas de Azure Resource Manager. Puede optar por guardar archivos JSON que contengan comentarios de // mediante la extensión de archivo .jsonc para indicar que el archivo JSON contiene comentarios. El servicio ARM también aceptará comentarios en cualquier archivo JSON, incluidos los archivos de parámetros.

Herramientas de ARM de Visual Studio Code

Trabajar con plantillas de ARM es mucho más fácil con las herramientas de Azure Resource Manager (ARM) para Visual Studio Code. Esta extensión proporciona compatibilidad con el lenguaje, fragmentos de código de recursos y finalización automática de recursos para ayudarle a crear y validar plantillas de Azure Resource Manager. Para obtener más información e instalar la extensión, consulte Herramientas de Azure Resource Manager (ARM).

Uso del kit de herramientas para pruebas

El kit de herramientas para pruebas de plantillas de ARM comprueba si la plantilla usa los procedimientos recomendados. Cuando la plantilla no es compatible con los procedimientos recomendados, devuelve una lista de advertencias con los cambios sugeridos. El kit de herramientas para pruebas le puede servir para aprender a implementar procedimientos recomendados en la plantilla.

Una vez completada la plantilla, ejecute el kit de herramientas para pruebas para ver si hay alguna forma de mejorar su implementación. Para más información, vea Uso del kit de herramientas para pruebas de plantillas de ARM.

Pasos siguientes