تحديد ترتيب توزيع الموارد في قوالب 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 التبعيات الدائرية أثناء التحقق من صحة القالب. إذا تلقيت خطأ يتعلق بتبعية دائرية، فقم بتقييم القالب الخاص بك لمعرفة ما إذا كان يمكن إزالة أي تبعيات. إذا لم تنجح إزالة التبعيات، فيمكنك تجنب التبعيات الدائرية عن طريق نقل بعض عمليات التوزيع إلى الموارد التابعة. توزيع الموارد التابعة بعد الموارد التي لها تبعية دائرية. على سبيل المثال، لنفترض أنك تنشر جهازين افتراضيين ولكن يجب عليك تعيين خصائص لكل منهما تشير إلى الآخر. يمكنك توزيعها بالترتيب التالي:
- vm1
- VM2
- يعتمد التمديد على vm1 على vm1 وvm2. يعيّن الملحق القيم على vm1 التي يحصل عليها من vm2.
- يعتمد التمديد على vm2 على vm1 وvm2. يعيّن الملحق القيم على vm2 التي يحصل عليها من vm1.
للحصول على معلومات حول تقييم أمر التوزيع وحل أخطاء التبعية، راجع استكشاف أخطاء توزيع Azure الشائعة وإصلاحها باستخدام Azure Resource Manager.
الخطوات التالية
- للانتقال إلى برنامج تعليمي، راجع البرنامج التعليمي: إنشاء قوالب ARM بموارد تابعة.
- بالنسبة إلى الوحدة النمطية Learn التي تغطي تبعيات الموارد، راجع إدارة عمليات التوزيع السحابية المعقدة باستخدام ميزات قالب ARM المتقدمة.
- للحصول على توصيات عند تعيين التبعيات، راجع أفضل ممارسات نماذج ARM.
- للتعرف على استكشاف أخطاء التبعيات وإصلاحها أثناء التوزيع، راجع استكشاف أخطاء توزيع Azure الشائعة وإصلاحها باستخدام Azure Resource Manager.
- لمعرفة المزيد حول إنشاء قوالب Azure Resource Manager، راجع فهم بنية وبناء جملة قوالب ARM.
- للحصول على قائمة بالدوال المتاحة في قالب، راجع دوال قالب ARM.