最近AZURE發布了ARM模式(Azure Resource Manager),其中包含了對於Resource Manager Template的支持。什么是Resource Template?我們先來看一下AZURE在ARM模式下的邏輯架構。
對於Day1接觸共有雲的小伙伴,通常會習慣通過Azure Portal門戶來完成相關服務及資源的配置交付(如創建虛擬雲主機,虛擬網絡,MySql數據庫服務等),通常我們可以把以上創建的服務及資源抽象為一套配置模板,用於描述所創建的服務及資源。由上面的圖示可見,ASM模式下用戶與Azure雲平台交互界面的接口包括Portal,CLI,Visual Studio等,通過以上接口用戶給出的服務及資源的描述,Azure平台通過資源描述中間件(Resource Provider Contract)將客戶的描述轉譯為平台資源描述並執行服務及資源創建。Azure Portal通過交互式的GUI方式可以友好方便的幫助用戶上手,但是在批量及復雜服務及資源創建時就有些捉襟見肘啦。那么在批量及復雜服務及資源創建時有沒有好的解決辦法呢?Infrastructure As Code,腳本部署是可行的方案之一,類似所有自動化事務的執行,我們可以將復雜的服務及資源逐一創建並通過腳本實現自動化執行。但是本文在這里不推薦大家使用上述方法,原因有二:1. 服務及資源的抽象不夠,我們在定義服務及資源的時候希望通過更高級的抽象給出簡單的接口,以便更便捷的定義復雜的服務及資源;2.傳統的腳本語言的執行以串行順序方式執行,對於復雜的服務及資源定義如果希望實現並行及依賴關系定義是比較復雜的。這里給大家介紹的Azure Resource Template可以很好的解決上述問題,幫助大家簡單快捷的實現復雜的服務及資源交付,它通過JSON語言高級抽象描述資源定義大大降低了用戶的復雜度,同時將並行任務的拆解交給Azure平台資源描述中間件來實現高效,實現Infrastructure as Code。好啦閑話已經扯了不少,我們進入主題吧。為方便大家理解,本文后面的內容按照如下順序編排,工具方法介紹,舉個栗子快速開始,總結及課題延展。
工具方法介紹:
工欲善其事必先利其器,得力順手的工具可以讓我們事半功倍。Infrastructure as Code,和其他編程語言一樣,一個好的IDE可以為我們保駕護航。MSFT為Azure Resource Template提供了Visual Studio + Azure SDK的工具組合,使用戶可以在VS環境下實現開發。主要功能如下:
- 格式檢查。幫助用戶檢查JSON格式;
- 基礎模板。微軟已經將AZURE服務及資源的標准模板定義好,方便客戶調運。另外Github上還有海量的模板示例作為參考示例(https://github.com/Azure/azure-quickstart-templates),VS已經跟Github做了打通,在創建新項目的時候可以直接引用Github的模板,並且模板可以直接通過VS調用Powershell進行執行;
- 自動補全及函數庫查詢。在VS中可以幫助用戶做索引、函數的補全。
VS的安裝與設置這里就不給大家贅述了,大家可以參加如下文章進行配置安裝:
https://github.com/Microsoft/HealthClinic.biz/wiki/Deploy-and-manage-Azure-resources
https://www.azure.cn/documentation/articles/developerdifferences/#confdevcomp (中國區AZURE的連接需要修改VS的配置文件,可以參考此鏈接,如果使用Global Azure可以忽略)。
舉個栗子快速開始
開始之前我們先來設定一個目標場景,在Azure Portal上目前我們無法創建多網卡的虛擬機,我們的目標就是通過Template部署來實現多網卡虛擬機的交付,同時為了實現模板的復用,希望用戶可以自定義操作系統類型,VM的規格,以及網卡的數量。
1.打開Visual Studio,創建項目,選擇Cloud -> Azure資源組
選擇100-blank-template空白模板(此示例里面使用空白模板進行介紹,小伙伴們也可以在此處直接選用內置模板及Github上的模板作為基礎模板進行修改)
2.開始編寫模板,點擊azuredeploy.json
大家可以看到基礎的模板框架已經出現:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
},
"variables": {
},
"resources": [
],
"outputs": {
}
}
Azure Resource Template模板主要分為4部分:
參數(parameters)- 為定義模板的通配性,可以定義可配置變量,用戶在部署模板時候可以更改變量參數實現自定義。以我們要完成的模板為例,可以通過參數來實現用戶自定義VM規格、VM操作系統、網卡數量,從而模板實現通用化,便於用戶交付不同要求的資源。
變量(variables)- 類似編程語言中的環境變量,方便用戶對參數值的引用。如定義VM的操作系統類型,通過命名友好可讀的名稱,方便在資源編寫時進行調用。
資源(resources)- Infrastructure as Code的主體,所有Azure的服務及資源均通過resource來定義,通過定義中不同的參數描述實現不同的Infrastructure的部署。
輸出(outputs)- 模板部署完畢后可以給出輸出,如環境訪問方式,成功消息等。
在VS環境中,客戶在編寫資源的時候無需從零寫起,可以通過快速添加的方式,VS會直接將添加的資源基礎模板引入的項目中,我們可以直接在上面進行參數的編輯修改即可。下面以添加一個虛擬機資源為例
在選擇虛擬機模板后,向導問詢輸入虛擬機名稱,存儲賬戶,及虛擬網絡。這里是VS環境下編寫模板相較其他TEXT Editor的優勢之一,幫用戶自動創建依賴關系。在Azure上的資源可能與其他資源存在依賴關系,如當我們想創建一個虛擬機的時候,我們需要依賴與存儲賬號資源,虛擬網絡資源。當我們創建虛擬機資源的時候,VS會自動將依賴關系的資源模板進行引入,方便客戶開發。
在向導中輸入依賴資源的相關參數后,模板主體Resource部分,除去VirtualMachine部分外還出現了StorageAccount、VirtualNetwork、NetworkNic資源定義。
"resources": [
{
"name": "[variables('DemoStorageAccountName')]",
"type": "Microsoft.Storage/storageAccounts",
"location": "[resourceGroup().location]",
"apiVersion": "2016-01-01",
"sku": {
"name": "[parameters('DemoStorageAccountType')]"
},
"dependsOn": [ ],
"tags": {
"displayName": "DemoStorageAccount"
},
"kind": "Storage"
},
{
"name": "demoVnet",
"type": "Microsoft.Network/virtualNetworks",
"location": "[resourceGroup().location]",
"apiVersion": "2016-03-30",
"dependsOn": [ ],
"tags": {
"displayName": "demoVnet"
},
"properties": {
"addressSpace": {
"addressPrefixes": [
"[variables('demoVnetPrefix')]"
]
},
"subnets": [
{
"name": "[variables('demoVnetSubnet1Name')]",
"properties": {
"addressPrefix": "[variables('demoVnetSubnet1Prefix')]"
}
},
{
"name": "[variables('demoVnetSubnet2Name')]",
"properties": {
"addressPrefix": "[variables('demoVnetSubnet2Prefix')]"
}
}
]
}
},
{
"name": "[variables('DemoVirtualMachineNicName')]",
"type": "Microsoft.Network/networkInterfaces",
"location": "[resourceGroup().location]",
"apiVersion": "2016-03-30",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', 'demoVnet')]"
],
"tags": {
"displayName": "DemoVirtualMachineNic"
},
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[variables('DemoVirtualMachineSubnetRef')]"
}
}
}
]
}
},
{
"name": "[parameters('DemoVirtualMachineName')]",
"type": "Microsoft.Compute/virtualMachines",
"location": "[resourceGroup().location]",
"apiVersion": "2015-06-15",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('DemoStorageAccountName'))]",
"[resourceId('Microsoft.Network/networkInterfaces', variables('DemoVirtualMachineNicName'))]"
],
"tags": {
"displayName": "DemoVirtualMachine"
},
"properties": {
"hardwareProfile": {
"vmSize": "[variables('DemoVirtualMachineVmSize')]"
},
"osProfile": {
"computerName": "[parameters('DemoVirtualMachineName')]",
"adminUsername": "[parameters('DemoVirtualMachineAdminUsername')]",
"adminPassword": "[parameters('DemoVirtualMachineAdminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "[variables('DemoVirtualMachineImagePublisher')]",
"offer": "[variables('DemoVirtualMachineImageOffer')]",
"sku": "[parameters('DemoVirtualMachineUbuntuOSVersion')]",
"version": "latest"
},
"osDisk": {
"name": "DemoVirtualMachineOSDisk",
"vhd": {
"uri": "[concat(reference(resourceId('Microsoft.Storage/storageAccounts', variables('DemoStorageAccountName')), '2016-01-01').primaryEndpoints.blob, variables('DemoVirtualMachineStorageAccountContainerName'), '/', variables('DemoVirtualMachineOSDiskName'), '.vhd')]"
},
"caching": "ReadWrite",
"createOption": "FromImage"
}
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('DemoVirtualMachineNicName'))]"
}
]
}
}
}
],
在AZURE中創建一個虛擬機需要將系統盤,網卡關聯到虛擬機上,網卡需要連接的虛擬網絡上。通過以上的過程我們可以看到,相關的依賴關系通過VS工具已經自動幫助我們完成。依賴關系在模板中非常重要,因為依賴關系定義的資源創建的先后順序,從而保證資源的順利創建。在上述模板中VirtualMachine我們可以看到dependsOn部分就是來描述依賴關系的
{
"name": "[parameters('DemoVirtualMachineName')]",
"type": "Microsoft.Compute/virtualMachines",
"location": "[resourceGroup().location]",
"apiVersion": "2015-06-15",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('DemoStorageAccountName'))]", #定義虛擬機資源依賴於存儲賬號資源
"[resourceId('Microsoft.Network/networkInterfaces', variables('DemoVirtualMachineNicName'))]" #定義虛擬機依賴於虛擬網絡資源
],
到此我們已經將一個虛擬機創建的基本模板框架搭建完畢,后面我們都基於這個框架來進行修改來達成我們之前預設的目標,通過Template部署來實現多網卡虛擬機的交付,同時為了實現模板的復用,希望用戶可以自定義操作系統類型,VM的規格,以及網卡的數量。下面我們先給出最終的實現模板,然后展開介紹,后面的介紹主要側重一些特殊語法的說明,以便大家可以自行編排自己的模板。
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminUsername": {
"type": "string",
"metadata": {
"description": "User name for the Virtual Machine."
}
},
"adminPassword": {
"type": "securestring",
"metadata": {
"description": "Password for the Virtual Machine."
}
},
"dnsLabelPrefix": {
"type": "string",
"metadata": {
"description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
}
},
"LinuxPublisher": {
"type": "string",
"allowedValues": [ "Ubuntu", "CentOS" ]
},
"ubuntuOSVersion": {
"type": "string",
"defaultValue": "16.04.0-LTS",
"allowedValues": [
"12.04.5-LTS",
"14.04.5-LTS",
"15.10",
"16.04.0-LTS"
],
"metadata": {
"description": "The Ubuntu version for the VM. This will pick a fully patched image of this given Ubuntu version."
}
},
"centOSVersion": {
"type": "string",
"defaultValue": "7.3",
"allowedValues": [
"6.9",
"7.1",
"7.2",
"7.3"
],
"metadata": {
"description": "The CentOS version for the VM. This will pick a fully patched image of this given CentOS version."
}
},
"Standard_A2": {
"type": "int",
"defaultValue": 2,
"minValue": 1,
"maxValue": 2,
"allowedValues": [ 1, 2 ]
},
"Standard_D3_v2": {
"type": "int",
"defaultValue": 4,
"minValue": 1,
"maxValue": 4,
"allowedValues": [ 1, 2, 3, 4 ]
},
"vmSize": {
"type": "string",
"defaultValue": "Standard_A2",
"allowedValues": [
"Standard_A2",
"Standard_D3_v2"
]
}
},
"variables": {
"linuxtype": "[variables(concat('linux', parameters('LinuxPublisher')))]",
"linuxUbuntu": {
"imagePublisher": "Canonical",
"imageOffer": "UbuntuServer",
"OSVersion": "[parameters('ubuntuOSVersion')]",
"VMsize": "[parameters('vmSize')]",
"NicNumber": "[parameters(parameters('vmSize'))]"
},
"linuxCentOS": {
"imagePublisher": "OpenLogic",
"imageOffer": "CentOS",
"OSVersion": "[parameters('centOSVersion')]",
"VMsize": "[parameters('vmSize')]",
"NicNumber": "[parameters(parameters('vmSize'))]"
},
"storageAccountName": "[concat('demo',uniquestring(resourceGroup().id))]",
"nicName": "DemoVMNic",
"addressPrefix": "10.0.0.0/16",
"subnetName": "Subnet",
"subnetPrefix": "10.0.0.0/24",
"storageAccountType": "Standard_LRS",
"publicIPAddressName": "DemoPublicIP",
"publicIPAddressType": "Dynamic",
"vmName": "DemoLinuxVM",
"virtualNetworkName": "DemoVNET",
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables('storageAccountName')]",
"apiVersion": "2017-06-01",
"location": "[resourceGroup().location]",
"sku": {
"name": "[variables('storageAccountType')]"
},
"kind": "Storage",
"properties": {}
},
{
"apiVersion": "2017-04-01",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[variables('publicIPAddressName')]",
"location": "[resourceGroup().location]",
"properties": {
"publicIPAllocationMethod": "[variables('publicIPAddressType')]",
"dnsSettings": {
"domainNameLabel": "[parameters('dnsLabelPrefix')]"
}
}
},
{
"apiVersion": "2017-04-01",
"type": "Microsoft.Network/virtualNetworks",
"name": "[variables('virtualNetworkName')]",
"location": "[resourceGroup().location]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[variables('addressPrefix')]"
]
},
"copy": [
{
"name": "subnets",
"count": "[variables('linuxtype').NicNumber]",
"input": {
"name": "[concat(variables('subnetName'),copyIndex('subnets'))]",
"properties": {
"addressPrefix": "[concat('10.0.',copyIndex('subnets'),'.0/24')]"
}
}
}
]
}
},
{
"apiVersion": "2017-04-01",
"type": "Microsoft.Network/networkInterfaces",
"name": "[concat(variables('nicName'),'0')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
"[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"publicIPAddress": {
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]"
},
"subnet": {
"id": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'),'0')]"
}
}
}
]
}
},
{
"apiVersion": "2017-04-01",
"condition": "[greater(variables('linuxtype').NicNumber,1)]",
"type": "Microsoft.Network/networkInterfaces",
"name": "[concat(variables('nicName'),copyIndex(1))]",
"location": "[resourceGroup().location]",
"copy": {
"name": "nicloop",
"count": "[sub(variables('linuxtype').NicNumber,1)]"
},
"dependsOn": [
"[resourceId('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
"[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'),copyIndex(1))]"
}
}
}
]
}
},
{
"apiVersion": "2017-03-30",
"type": "Microsoft.Compute/virtualMachines",
"name": "[variables('vmName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]"
],
"properties": {
"hardwareProfile": {
"vmSize": "[variables('linuxtype').VMsize]"
},
"osProfile": {
"computerName": "[variables('vmName')]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "[variables('linuxtype').imagePublisher]",
"offer": "[variables('linuxtype').imageOffer]",
"sku": "[variables('linuxtype').OSVersion]",
"version": "latest"
},
"osDisk": {
"name": "osdisk",
"vhd": {
"uri": "[concat('http://', variables('storageAccountName'), '.blob.core.windows.net/vhds/', 'osdisk', '.vhd')]"
},
"createOption": "FromImage"
}
},
"networkProfile": {
"copy": [
{
"name": "networkInterfaces",
"count": "[variables('linuxtype').NicNumber]",
"input": {
"id": "[replace(reference(concat(variables('nicName'),copyIndex('networkInterfaces'))).ipConfigurations[0].id,'/ipConfigurations/ipconfig1','')]",
"properties": {
"primary": "[less(copyIndex('networkInterfaces'),1)]"
}
}
}
]
}
}
}
],
"outputs": {
"result": {
"type": "string",
"value": "success"
}
}
}
對於操作系統類型的定義可通過定義參數完成,通過allowedValues的定義可以在最終使用模板時實現在交互頁面進行參數選擇以避免手工輸入帶來的錯誤。同理操作系統版本,VM規格以及網卡數量均可采用類似方法定義。
"LinuxPublisher": {
"type": "string",
"allowedValues": [ "Ubuntu", "CentOS" ]
},
變量套用式引用,在Resource模板定義中會通過調用參數或變量的方式來實現模板的通用。在此用例中目標創建的虛擬機的操作系統由於有客戶變量來進行選定,所以在虛擬機資源描述部分里面設計的操作系統的相關描述都需要隨之而變。因為Ubuntu和CentOS兩個選項對應選項背后,相應的操作系統發行商,操作系統版本等參數都要隨之改變,為了實現資源描述部分的通用性,避免反復寫兩次資源描述來覆蓋不同操作系統場景,我們采用變量套用式引用。通過定義linuxUbuntu和linuxCentOS變量來分別描述不同操作系統下相關變量參數,同時定義linuxtype變量,其中linuxtype的值等於linux+用戶輸入的LinuxPublisher參數選項,客戶選定LinuPublisher選項后linuxtype的最終值將等於linuxUbuntu或linuxCentOS,在后面的虛擬機資源描述的操作系統部分只需要調用linuxtype變量對象及可實現對客戶選定操作系統的變量值抽取,以"publisher": "[variables('linuxtype').imagePublisher]"為例,通過對linuxtype.imagePublisher的抽取實現相應操作系統發布商信息的提取,而且整個資源描述只需要編寫一次。
"linuxtype": "[variables(concat('linux', parameters('LinuxPublisher')))]",
"linuxUbuntu": {
"imagePublisher": "Canonical",
"imageOffer": "UbuntuServer",
"OSVersion": "[parameters('ubuntuOSVersion')]",
"VMsize": "[parameters('vmSize')]",
"NicNumber": "[parameters(parameters('vmSize'))]"
},
"linuxCentOS": {
"imagePublisher": "OpenLogic",
"imageOffer": "CentOS",
"OSVersion": "[parameters('centOSVersion')]",
"VMsize": "[parameters('vmSize')]",
"NicNumber": "[parameters(parameters('vmSize'))]"
},
循環描述copy可以實現多資源創建,在此例子中客戶可以自定義創建網卡的數量並且每個網卡關聯不同的子網,所以無法預先通過靜態反復定義的方式將虛擬網絡子網資源描述寫死,通過copy描述配以客戶輸入的網卡數量NicNumber變量作為循環次數count,實現動態創建多個資源的目標。
{
"apiVersion": "2017-04-01",
"type": "Microsoft.Network/virtualNetworks",
"name": "[variables('virtualNetworkName')]",
"location": "[resourceGroup().location]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[variables('addressPrefix')]"
]
},
"copy": [
{
"name": "subnets",
"count": "[variables('linuxtype').NicNumber]",
"input": {
"name": "[concat(variables('subnetName'),copyIndex('subnets'))]",
"properties": {
"addressPrefix": "[concat('10.0.',copyIndex('subnets'),'.0/24')]"
}
}
}
]
}
},
使用條件語句實現if or not邏輯,在上述例子中虛擬機在多網卡場景下只有主網卡綁定公網IP,在網卡資源描述中,需要公網地址的描述和不需要公網地址的描述是不同的,所以這里的做法是先靜態描述一塊帶公網地址的網卡資源(因為客戶至少創建1塊網卡),在將剩余的網卡資源描述引入條件語句從而實現當客戶輸入大於1塊網卡時("condition": "[greater(variables('linuxtype').NicNumber,1)]"),剩余網卡都按照無公網地址方式進行創建。
{
"apiVersion": "2017-04-01",
"condition": "[greater(variables('linuxtype').NicNumber,1)]",
"type": "Microsoft.Network/networkInterfaces",
"name": "[concat(variables('nicName'),copyIndex(1))]",
"location": "[resourceGroup().location]",
"copy": {
"name": "nicloop",
"count": "[sub(variables('linuxtype').NicNumber,1)]"
},
"dependsOn": [
"[resourceId('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
"[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'),copyIndex(1))]"
}
}
}
]
}
},
動態依賴關系的定義,通常在資源描述中通過dependsOn來表示依賴關系,如虛擬機資源需要依賴存儲賬戶及網卡資源。但本例中網卡的數量是變量無法預知,所以在描述依賴關系的時候無法靜態將所依賴的資源ID全部放上。這里采用調用reference函數實現隱性依賴關系的描述,在虛擬機資源的dependsOn描述中移除網卡的依賴描述,在虛擬機描述中的networkProfile部分中定義id時,通過reference函數抓取ID,reference函數會在模板執行過程中抓取runtime的id值進行返回,只有當相應資源創建完畢時reference才會有返回值,從而實現資源依賴關系的隱性描述。
"networkProfile": {
"copy": [
{
"name": "networkInterfaces",
"count": "[variables('linuxtype').NicNumber]",
"input": {
"id": "[replace(reference(concat(variables('nicName'),copyIndex('networkInterfaces'))).ipConfigurations[0].id,'/ipConfigurations/ipconfig1','')]",
"properties": {
"primary": "[less(copyIndex('networkInterfaces'),1)]"
}
3.部署模板
至此通過本例中幾個基本目標給大家介紹了在模板中常用的一些高級功能,這些功能有助於大家描述定義復雜的服務和資源,實現Infrastructure as Code的目標。最后模板一切就緒可以來部署了,Azure支持通過在Portal,PowerShell,CLI中部署模板,其中Powershell可以直接在VS環境中調用,各種部署方法大家可以參閱如下鏈接:https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-deploy。本文介紹通過Portal的方式進行部署,以便幫助大家理解在模板中定義的參數Parameter部分。
打開Azure Portal,搜索Template Deployment
點擊Create創建,選擇Build your own template in the editor
將在VS模式下編寫的模板粘貼至Portal並保存
進入參數Parameter輸入頁面,模板中參數Parameter部分定義的參數選項均出現在該頁面下,客戶可以自定義輸入預期值,如操作系統類型,虛擬機大小,網卡數量等。
勾選確認條款點擊Purchase,模板即開始部署。
部署開始后可以在Portal中看到部署任務的實時狀態,在未完成前STATUS為Deploying狀態,Outputs為空。
部署成功后,STATUS變為Succeeded,Outputs部分給出模板中Outputs部分給出的定義描述(可查看前面例子中Outputs部分的描述)。
總結及課題延展:
通過上述例子大家對Azure Resource Template應該已經有了一定的了解。有了這些了解大家可以着手開始自己的Infrastructure as Code的旅程,下面這些資源應該會幫到大家。
- Azure Resource Template使用指南,基本使用方法幫助快速上手:https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-overview
- Azure Resource Template 最佳實踐,介紹Template定義的一些常用方法提高效率:https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-template-best-practices
- Azure Resource Template 高級函數使用指南,介紹Template內置函數幫助實現復雜邏輯:https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions?toc=%2fazure%2ftemplates%2ftoc.json&bc=%2Fazure%2Ftemplates%2Fbreadcrumb%2Ftoc.json
- Azure Resource Template 服務及資源原始模板參考,不知道每種服務及資源額如何定義描述時可作為字典參考:https://docs.microsoft.com/en-us/azure/templates/microsoft.analysisservices/servers
- Azure Resource Template Github,你想做的內容別人可能已經做了七八成,彎道超車搞起:https://github.com/Azure/azure-quickstart-templates
- Azure Resource Portal 查閱現有Resource的模板作為參考:https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-export-template
最后我們再來談一談延伸的話題,有不少小伙伴也許用過其他的雲平台也有類似的模板工具,那么在多雲場景下豈不是需要維護兩套語言邏輯,這里給大家簡單提一下Terraform,它是一個跨平台的模板語言工具,它可以適配如AWS,AZURE,Alicloud等雲廠商提供的template接口,不僅僅如此,它還可以適配操作系統配置,應用配置等終端對象,其通過標准的模板描述語言抽象從而實現雲平台無關以及更復雜的Infrastructure as Code,有興趣的同學可以自行科學上網查詢更多相關資料。好啦,准備好手頭的工具開始自己的Infrastructure as Code之旅吧。