تحديد ترتيب توزيع الموارد في قوالب ARM

عند توزيع الموارد، قد تحتاج إلى التأكد من وجود بعض الموارد قبل الموارد الأخرى. على سبيل المثال، أنت بحاجة إلى خادم SQL منطقي قبل توزيع قاعدة بيانات. يمكنك إنشاء هذه العلاقة عن طريق وضع علامة على أحد الموارد باعتباره معتمداً على المورد الآخر. استخدم عنصر dependsOn لتعريف تبعية صريحة. استخدم الدالتين reference أو list لتعريف التبعية الضمنية.

يقوم Azure Resource Manager بتقييم التبعيات بين الموارد وتوزيعها بترتيبها التابع. عندما لا تكون الموارد تابعة لأحدها الآخر، يقوم Resource Manager بتوزيعها بالتوازي. ما عليك سوى تحديد التبعيات للموارد التي يتم توزيعها في نفس القالب.

تلميح

نوصي باستخدام Bicep لأنها تقدم نفس الإمكانات التي توفرها قوالب ARM ولأن بناء الجملة أسهل في الاستخدام. لمعرفة المزيد، راجع تبعيات الموارد.

dependsOn

ضمن قالب Azure Resource Manager (قالب ARM)، يمكّنك العنصر dependsOn من تحديد مورد واحد كمورد معتمد على مورد واحد أو أكثر. قيمته هي مصفوفة JavaScript Object Notation (JSON) من السلاسل، كل منها عبارة عن اسم مورد أو معرّف. يمكن أن تتضمن المصفوفة الموارد التي تم توزيعها بشروط. عندما لا يتم توزيع مورد شرطي، يقوم Azure Resource Manager بإزالته تلقائياً من التبعيات المطلوبة.

يوضح المثال التالي واجهة شبكة تعتمد على شبكة ظاهرية ومجموعة أمان شبكة وعنوان IP عام. للحصول على النموذج الكامل، راجع نموذج البدء السريع لنظام التشغيل Linux VM.

{
  "type": "Microsoft.Network/networkInterfaces",
  "apiVersion": "2022-07-01",
  "name": "[variables('networkInterfaceName')]",
  "location": "[parameters('location')]",
  "dependsOn": [
    "[resourceId('Microsoft.Network/networkSecurityGroups/', parameters('networkSecurityGroupName'))]",
    "[resourceId('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]",
    "[resourceId('Microsoft.Network/publicIpAddresses/', variables('publicIpAddressName'))]"
  ],
  ...
}

باستخدام languageVersion 2.0، استخدم اسما رمزيا للموارد في dependsOn الصفائف. على سبيل المثال:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "languageVersion": "2.0",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "resources": {
    "myStorage": {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2023-01-01",
      "name": "[format('storage{0}', uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "StorageV2"
    },
    "myVm": {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2023-03-01",
      "name": "[format('vm{0}', uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "myStorage"
      ],
      ...
    }
  }
}

بينما قد تميل إلى استخدام dependsOn لتخطيط العلاقات بين مواردك، فمن المهم أن تفهم سبب قيامك بذلك. على سبيل المثال، لتوثيق كيفية ترابط الموارد، فإن dependsOn ليس هو النهج الصحيح. بعد التوزيع، لا يحتفظ المورد بتبعيات التوزيع في خصائصه، لذلك لا توجد أوامر أو عمليات تتيح لك رؤية التبعيات. يؤدي تعيين التبعيات غير الضرورية إلى إبطاء وقت التوزيع لأن إدارة الموارد لا يمكنها توزيع هذه الموارد بالتوازي.

الموارد التابعة

لا يتم إنشاء تبعية التوزيع الضمني تلقائياً بين مورد فرعي والمورد الأصلي. إذا كنت بحاجة إلى توزيع المورد الفرعي بعد المورد الأصلي، فقم بتعيين الخاصية dependsOn .

يوضح المثال التالي قاعدة بيانات وخادم SQL منطقيين. لاحظ أنه يتم تحديد تبعية صريحة بين قاعدة البيانات والخادم، على الرغم من أن قاعدة البيانات تابعة للخادم.

"resources": [
  {
    "type": "Microsoft.Sql/servers",
    "apiVersion": "2022-05-01-preview",
    "name": "[parameters('serverName')]",
    "location": "[parameters('location')]",
    "properties": {
      "administratorLogin": "[parameters('administratorLogin')]",
      "administratorLoginPassword": "[parameters('administratorLoginPassword')]"
    },
    "resources": [
      {
        "type": "databases",
        "apiVersion": "2022-05-01-preview",
        "name": "[parameters('sqlDBName')]",
        "location": "[parameters('location')]",
        "sku": {
          "name": "Standard",
          "tier": "Standard"
          },
        "dependsOn": [
          "[resourceId('Microsoft.Sql/servers', parameters('serverName'))]"
        ]
      }
    ]
  }
]

للحصول على النموذج الكامل، راجع نموذج البدء السريع لAzure SQL Database.

دوال مرجعية وقائمة

تمكّن الدالة المرجعية التعبير من اشتقاق قيمته من اسم JSON وأزواج القيمة أو موارد وقت التشغيل. تعرض قائمة * دوال قيماً لمورد من عملية قائمة.

تعلن تعابير المرجع والقائمة ضمنياً أن أحد الموارد يعتمد على مورد آخر. كلما كان ذلك ممكناً، استخدم مرجعاً ضمنياً لتجنب إضافة تبعية غير ضرورية.

لفرض تبعية ضمنية، ارجع إلى المورد بالاسم وليس معرّف المورد. إذا قمت بتمرير معرف المورد إلى دوال المرجع أو القائمة، فلن يتم إنشاء مرجع ضمني.

التنسيق العام لدالة reference هو:

reference('resourceName').propertyPath

التنسيق العام لدالة listKeys هو:

listKeys('resourceName', 'yyyy-mm-dd')

في المثال التالي، تعتمد نقطة نهاية CDN بشكل صريح على ملف تعريف CDN، وتعتمد ضمنياً على تطبيق ويب.

{
    "type": "endpoints",
    "apiVersion": "2021-06-01",
    "name": "[variables('endpointName')]",
    "location": "[resourceGroup().location]",
    "dependsOn": [
      "[variables('profileName')]"
    ],
    "properties": {
      "originHostHeader": "[reference(variables('webAppName')).hostNames[0]]",
      ...
    }
    ...
}

لمعرفة المزيد، راجع الدالة المرجعية.

الاعتماد على الموارد في حلقة

لتوزيع الموارد التي تعتمد على الموارد في تكرار النسخ، لديك خياران. يمكنك إما تعيين تبعية على الموارد الفردية في الحلقة أو على الحلقة بأكملها.

ملاحظة

بالنسبة لمعظم السيناريوهات، يجب عليك تعيين التبعية على الموارد الفردية داخل حلقة النسخ. تعتمد فقط على الحلقة بأكملها عندما تحتاج إلى وجود جميع الموارد الموجودة في الحلقة قبل إنشاء المورد التالي. يؤدي ضبط التبعية على الحلقة بأكملها إلى توسيع الرسم البياني للتبعيات بشكل كبير، خاصةً إذا كانت تلك الموارد الحلقية تعتمد على موارد أخرى. تجعل التبعيات الموسعة من الصعب إكمال التوزيع بكفاءة.

يوضح المثال التالي كيفية توزيع أجهزة افتراضية متعددة. يقوم القالب بإنشاء نفس عدد واجهات الشبكة. يعتمد كل جهاز ظاهري على واجهة شبكة واحدة، بدلاً من الحلقة بأكملها.

{
  "type": "Microsoft.Network/networkInterfaces",
  "apiVersion": "2022-07-01",
  "name": "[format('{0}-{1}', variables('nicPrefix'), copyIndex())]",
  "location": "[parameters('location')]",
  "copy": {
    "name": "nicCopy",
    "count": "[parameters('vmCount')]"
  },
  ...
},
{
  "type": "Microsoft.Compute/virtualMachines",
  "apiVersion": "2022-11-01",
  "name": "[format('{0}{1}', variables('vmPrefix'), copyIndex())]",
  "location": "[parameters('location')]",
  "dependsOn": [
    "[resourceId('Microsoft.Network/networkInterfaces',format('{0}-{1}', variables('nicPrefix'),copyIndex()))]"
  ],
  "copy": {
    "name": "vmCopy",
    "count": "[parameters('vmCount')]"
  },
  "properties": {
    "networkProfile": {
      "networkInterfaces": [
        {
          "id": "[resourceId('Microsoft.Network/networkInterfaces',format('(0)-(1)', variables('nicPrefix'), copyIndex()))]",
          "properties": {
            "primary": "true"
          }
        }
      ]
    },
    ...
  }
}

يوضح المثال التالي كيفية توزيع ثلاثة حسابات تخزين قبل توزيع الجهاز الظاهري. لاحظ أن العنصر copy تم تعيينه name على storagecopy والعنصر dependsOn للجهاز الظاهري تم أيضاً تعيينه على storagecopy.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[format('{0}storage{1}, copyIndex(), uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "copy": {
        "name": "storagecopy",
        "count": 3
      },
      "properties": {}
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2022-11-01",
      "name": "[format('VM{0}', uniqueString(resourceGroup().id))]",
      "dependsOn": ["storagecopy"],
      ...
    }
  ]
}

يمكن استخدام الأسماء الرمزية في dependsOn الصفائف. إذا كان الاسم الرمزي لحلقة نسخ، تتم إضافة جميع الموارد في التكرار الحلقي كتبعيات. يمكن كتابة العينة السابقة على أنها JSON التالية. في العينة، يعتمد myVM على جميع حسابات التخزين في حلقة myStorages .

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "languageVersion": "2.0",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "resources": {
    "myStorages": {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[format('{0}storage{1}, copyIndex(), uniqueString(resourceGroup().id))]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "Storage",
      "copy": {
        "name": "storagecopy",
        "count": 3
      },
      "properties": {}
    },
    "myVM": {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2022-11-01",
      "name": "[format('VM{0}', uniqueString(resourceGroup().id))]",
      "dependsOn": ["myStorages"],
      ...
    }
  }
}

التبعيات الدائرية

يحدد Resource Manager التبعيات الدائرية أثناء التحقق من صحة القالب. إذا تلقيت خطأ يتعلق بتبعية دائرية، فقم بتقييم القالب الخاص بك لمعرفة ما إذا كان يمكن إزالة أي تبعيات. إذا لم تنجح إزالة التبعيات، فيمكنك تجنب التبعيات الدائرية عن طريق نقل بعض عمليات التوزيع إلى الموارد التابعة. توزيع الموارد التابعة بعد الموارد التي لها تبعية دائرية. على سبيل المثال، لنفترض أنك تنشر جهازين افتراضيين ولكن يجب عليك تعيين خصائص لكل منهما تشير إلى الآخر. يمكنك توزيعها بالترتيب التالي:

  1. vm1
  2. VM2
  3. يعتمد التمديد على vm1 على vm1 وvm2. يعيّن الملحق القيم على vm1 التي يحصل عليها من vm2.
  4. يعتمد التمديد على vm2 على vm1 وvm2. يعيّن الملحق القيم على vm2 التي يحصل عليها من vm1.

للحصول على معلومات حول تقييم أمر التوزيع وحل أخطاء التبعية، راجع استكشاف أخطاء توزيع Azure الشائعة وإصلاحها باستخدام Azure Resource Manager.

الخطوات التالية