ARM 範本最佳做法

本文說明在建構 Azure Resource Manager 範本 (ARM 範本) 時,如何使用建議的做法。 這些建議可協助您在使用 ARM 範本來部署解決方案時,避免常見問題。

範本限制

將您的範本大小限制為 4 MB,並將每個資源定義限制為 1 MB。 該限制適用於已增加反覆資源定義和變數與參數值之範本的最終狀態。 參數檔也會限制為 4 MB。 如果要求的總大小過大,您可能會收到一個錯誤,指出範本或參數檔案的大小小於 4 MB。 如需如何簡化範本以避免大型要求的詳細資訊,請參閱解決超過作業大小的錯誤

您也受限於:

  • 256 個參數
  • 256 個變數
  • 800 個資源 (包含複本計數)
  • 64 個輸出值
  • 每個訂用帳戶/租用戶/管理群組範圍 10 個唯一位置
  • 範本運算式中的 24,576 個字元

使用巢狀範本,即可超出一些範本限制。 如需詳細資訊,請參閱部署 Azure 資源時使用連結和巢狀的範本。 若要減少參數、變數或輸出數目,您可以將數個值合併成一個物件。 如需詳細資訊,請參閱物件作為參數

資源群組

當您將資源部署至資源群組時,資源群組會儲存資源的相關中繼資料。 中繼資料會儲存在資源群組的所在位置。

如果資源群組的區域暫時無法使用,您就無法更新資源群組中的資源,因為中繼資料無法使用。 其他區域中的資源仍可如預期般運作,但您無法更新這些資源。 若要將風險降至最低,請將資源群組和資源放在相同區域。

參數

本節資訊對您在使用參數時會有幫助。

參數的一般建議

  • 將參數的使用最小化。 相反地,請對不需要在部署期間指定的屬性使用變數或常值。

  • 參數名稱使用駝峰式大小寫。

  • 針對根據環境 (例如 SKU、大小或容量) 而有所不同的設定,請使用參數。

  • 針對希望能方便識別而指定的資源名稱使用參數。

  • 提供中繼資料中對每個參數的描述。

    "parameters": {
      "storageAccountType": {
        "type": "string",
        "metadata": {
          "description": "The type of the new storage account created to store the VM disks."
        }
      }
    }
    
  • 為不敏感的參數定義預設值。 藉由指定預設值,您可以更輕鬆地部署範本,且範本的使用者可以看到適當值的範例。 參數的預設值皆必須對預設部署組態中的所有使用者有效。

    "parameters": {
      "storageAccountType": {
        "type": "string",
        "defaultValue": "Standard_GRS",
        "metadata": {
          "description": "The type of the new storage account created to store the VM disks."
        }
      }
    }
    
  • 若要指定選擇性參數,請不要使用空字串作為預設值。 相反地,請使用常值或語言運算式來建構值。

    "storageAccountName": {
       "type": "string",
       "defaultValue": "[concat('storage', uniqueString(resourceGroup().id))]",
       "metadata": {
         "description": "Name of the storage account"
       }
    }
    
  • 謹慎地使用 allowedValues。 只有當您必須確保允許的選項中不會包含某些值時才可使用。 如果您過於廣泛地使用 allowedValues,可能會因為未能讓清單保持最新狀態而導致有效的部署遭到封鎖。

  • 當範本中的參數名稱與 PowerShell 部署命令中的參數相符時,Resource Manager 會在範本參數加上後置詞 FromTemplate 以避免命名衝突。 例如,如果您在範本中包含名為 ResourceGroupName 的參數,它會與 New-AzResourceGroupDeployment Cmdlet 中的 ResourceGroupName 參數發生衝突。 部署期間,系統會提示您為 ResourceGroupNameFromTemplate 提供值。

參數的安全性建議

  • 使用者名稱和密碼 (或祕密) 請一律使用參數。

  • 針對所有密碼和祕密使用 securestring。 如果您在 JSON 物件中傳遞敏感資料,請使用 secureObject 類型。 部署資源後,便無法讀取具有安全字串或安全物件類型的範本參數。

    "parameters": {
      "secretValue": {
        "type": "securestring",
        "metadata": {
          "description": "The value of the secret to store in the vault."
        }
      }
    }
    
  • 針對需要 secureString 類型的使用者名稱、密碼或任何值,請勿提供預設值。

  • 針對會增加應用程式受攻擊面的屬性,請勿提供預設值。

參數的位置建議

  • 請使用參數來指定資源的位置,並將預設值設定為 resourceGroup().location。 提供位置參數可讓範本的使用者指定其有權限部署資源的位置。

    "parameters": {
       "location": {
         "type": "string",
         "defaultValue": "[resourceGroup().location]",
         "metadata": {
           "description": "The location in which the resources should be deployed."
         }
       }
    }
    
  • 請勿針對位置參數指定 allowedValues。 您指定的位置可能無法在所有雲端中使用。

  • 針對可能位於相同位置的資源,請使用位置參數值。 此方法可以降低系統要求使用者提供位置資訊的次數。

  • 針對無法在所有位置中使用的資源,請使用不同參數或指定常值的位置值。

變數

當您使用變數時,下列資訊可能會很有幫助︰

  • 針對變數名稱使用駝峰式命名法。

  • 您需要在範本中使用一次以上的值,才使用變數。 如果值只會使用一次,硬式編碼值會讓您的範本較容易看懂。

  • 針對用複雜方式排列範本函式所建構的值,請使用變數。 當複雜的運算式只以變數形式顯示時,範本會較淺顯易懂。

  • 您不能在範本的 variables 區段使用參考函式。 reference 函式的值是衍生自資源的執行階段狀態。 不過,將範本初始剖析時,會將變數加以解析。 在範本的 resourcesoutputs 區段中,直接建立需要 reference 函式的值。

  • 包含必須是唯一的資源名稱的變數。

  • 在變數中使用複製迴圈來建立重複的 JSON 物件模式。

  • 請移除未使用的變數。

API 版本

請將 apiVersion 屬性設定為資源類型的硬式編碼 API 版本。 建立新的範本時,建議您針對資源類型使用最新的 API 版本。 若要決定可用的值,請參閱範本參考

當您的範本順利運作時,建議您繼續使用相同的 API 版本。 採用相同的 API 版本,您便不必擔心因為使用較新版本而可能帶來重大變更。

請勿使用 API 版本的參數。 資源屬性和值可能會隨 API 版本而有所不同。 將 API 版本設定為參數時,程式碼編輯器中的 Intellisense 會無法判斷正確的結構描述。 如果您傳入的 API 版本不符合範本中的屬性,部署將會失敗。

請勿使用 API 版本的變數。

資源相依性

在決定要設定哪些相依性時,請使用下列指導方針︰

  • 使用reference函式並傳入資源名稱,以設定需要共用屬性的資源間的隱含相依性。 當您已經定義隱含的相依性時,請勿新增明確的 dependsOn 元素。 這種方法可減少產生不必要相依性的風險。 如需設定隱含相依性的範例,請參閱參考和清單函式

  • 將子資源設定為依存於其父資源。

  • 狀態元素設定為 false 的資源會自動從相依性順序中移除。 請在假定一律會部署該資源的情況下設定相依性。

  • 讓相依性串聯,而不需明確地設定。 例如,您的虛擬機器相依於虛擬網路介面,而虛擬網路介面相依於虛擬網路和公用 IP 位址。 因此,會在所有三個資源之後部署虛擬機器,但不會明確地將虛擬機器設定為相依於所有三個資源。 這種方法可釐清相依性順序,而且稍後可以比較容易變更範本。

  • 如果部署之前可以決定值,請嘗試部署沒有相依性的資源。 例如,如果設定值需要另一個資源的名稱,您可能就不需要相依性。 本指引並非一律有效,因為某些資源會確認其他資源是否存在。 如果您收到錯誤,請加入相依性。

資源

當您使用資源時,下列資訊可能會很有幫助︰

  • 為了協助其他參與者了解資源的用途,請在範本中為每項資源指定 comments

    "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.",
          ...
      }
    ]
    

    如果您的 ARM 範本儲存在 .jsonc 檔案中,則支援使用 // 語法的註解,如下所示。

    "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]",
          ...
      }
    ]
    

    如需關於註解和中繼資料的詳細資訊,請參閱了解 ARM 範本的結構和語法

  • 如果您使用範本中的公用端點 (例如 Azure Blob 儲存體公用端點),請勿將命名空間硬式編碼。 使用 reference 函式以動態擷取命名空間。 您可以使用此方法可將範本部署到不同的公用命名空間環境中,而不需要將範本中的端點手動變更。 將 API 版本設定成與您在範本中用於儲存體帳戶相同的版本。

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

    如果儲存體帳戶部署在您要建立的相同範本中,而儲存體帳戶的名稱未與範本中的另一個資源分享,則您不需要在參考資源時指定提供者命名空間或 apiVersion。 下列範例顯示簡化的語法。

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

    您也可以參考不同資源群組中現有的儲存體帳戶。

    "diagnosticsProfile": {
      "bootDiagnostics": {
        "enabled": "true",
        "storageUri": "[reference(resourceId(parameters('existingResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('existingStorageAccountName')), '2019-06-01').primaryEndpoints.blob]"
      }
    }
    
  • 只在應用程式需要時,將公用 IP 位址指派給虛擬機器。 若要連線至虛擬機器 (VM) 進行系統管理,請使用輸入 NAT 規則、虛擬網路閘道或 Jumpbox。

    如需有關如何連線至虛擬機器的詳細資訊,請參閱︰

  • 公用 IP 位址的 domainNameLabel 屬性必須是唯一的。 domainNameLabel 值的長度必須介於 3 到 63 個字元之間,並須遵循此規則運算式指定的規則:^[a-z][a-z0-9-]{1,61}[a-z0-9]$uniqueString 函式會產生長度為 13 個字元的字串,因此 dnsPrefixString 參數會限制為 50 個字元。

    "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))]"
    }
    
  • 當您將密碼新增至自訂指令碼延伸模組時,請使用 commandToExecute 屬性中的 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'))]"
      }
    }
    

    注意

    為了確保做為參數傳遞至 VM 和延伸模組的密碼會經過加密,請使用相關延伸模組的 protectedSettings 屬性。

  • 若屬性具有可隨時間變更的預設值,請指定明確的值。 例如,如果您要部署 AKS 叢集,您可以指定或省略 kubernetesVersion 屬性。 如果您未指定,則叢集會預設為 N-1 次要版本和最新修補檔。 當您使用 ARM 範本部署叢集時,此預設行為可能不是您預期中的行為。 重新部署範本可能會導致叢集意外升級為新的 Kubernetes 版本。 若要避免這種情形,請考慮指定明確的版本號碼,然後在準備好升級叢集時手動變更。

註解

除了 comments 屬性之外,也支援使用 // 語法的註解。 如需關於註解和中繼資料的詳細資訊,請參閱了解 ARM 範本的結構和語法。 您可以選擇使用 .jsonc 副檔名來儲存包含 // 註解的 JSON 檔案,以指出 JSON 檔案包含註解。 ARM 服務也會接受任何 JSON 檔案中的註解,包括參數檔案。

Visual Studio Code ARM 工具

透過適用於 Visual Studio Code 的 Azure Resource Manager (ARM) 工具,使用 ARM 範本會更容易。 此延伸模組提供語言支援、資原始程式碼段和資源自動完成,可協助您建立及驗證 Azure Resource Manager 範本。 若要深入瞭解並安裝延伸模組,請參閱 Azure Resource Manager (ARM) 工具

使用測試工具組

ARM 範本測試工具組是一種指令碼,可檢查您的範本是否使用建議的做法。 當您的範本不符合建議的做法時,系統會傳回警告清單,內含變更建議。 測試工具組可協助您了解如何在範本中實作最佳做法。

當您完成範本之後,請執行測試工具組,以查看是否有可改善其實作的方法。 如需詳細資訊,請參閱使用 ARM 範本測試工具組

下一步