Azure Managed Disk 共享不灵,EventGrid + LogicApp 来搞

前言:

        童鞋们估计已经抱怨过n次这个问题,为啥托管磁盘不能被用来制作镜像或者制作快照后在其他订阅或其它区域(Region)来创建虚拟机,说好的 Infrastructure as a code 呢,刚刚激动的做好了镜像,把应用架构描述成 infra code,一键点亮。跨了订阅,跨了区域玩不转啦,XX**。不要慌,这个事儿并非没有解,就是稍微麻烦,你可以把托管磁盘做导出到目标订阅或区域的存储账户,然后在目标订阅内或区域内创建镜像。一两个订阅还好,一大把订阅那不是很坑,本文后面就带大家以玩的心态,边了解 Azure 的新服务 EventGrid,LogicApp,ACI,然后一起来配合使用来实现跨订阅或跨地域的托管磁盘的自动导出拷贝。

架构逻辑:

技术分享图片

        通过 EventGrid 来监听 VM 创建事件,当事件发生后,LogicApp 作为该事件的 Subscriber 消费者,触发自动化流水线,将该虚拟机的磁盘拷贝到目的订阅或目的区域的存储账户中,拷贝过程通过azcopy来完成,选择azcopy的原因速度块。整个架构中采用 Severless 的思路,所以将 azcopy 封装到一个做好的容器镜像中,在调用时通过在 Serverless 的 Azure Container Instance 中进行执行,执行完毕资源回收,可以享受容器启动的敏捷性的同时实现按市场付费计算资源的要求。

逻辑实现细节:

        整个逻辑实现的重点在LogicApp,也就是自动化流水线的实现,流水线的规程可以参阅如下 LogicApp 的 Code,大家可以导入自己的环境在里面进行学习和修改。犯懒的童鞋也别难过,借此安利一把,Image 共享这个服务 Azure 平台马上会当作功能给到大家 Preview,点我了解更多

 1 { 2  "$connections": { 3  "value": { 4  "aci": { 5  "connectionId": "/subscriptions/c04b3c63-8dfe-4f98-be18-e71ff67a1f4e/resourceGroups/eventgrid/providers/Microsoft.Web/connections/aci", 6  "connectionName": "aci", 7  "id": "/subscriptions/c04b3c63-8dfe-4f98-be18-e71ff67a1f4e/providers/Microsoft.Web/locations/southeastasia/managedApis/aci" 8  }, 9  "arm": { 10  "connectionId": "/subscriptions/c04b3c63-8dfe-4f98-be18-e71ff67a1f4e/resourceGroups/eventgrid/providers/Microsoft.Web/connections/arm", 11  "connectionName": "arm", 12  "id": "/subscriptions/c04b3c63-8dfe-4f98-be18-e71ff67a1f4e/providers/Microsoft.Web/locations/southeastasia/managedApis/arm" 13  }, 14  "azureeventgrid": { 15  "connectionId": "/subscriptions/c04b3c63-8dfe-4f98-be18-e71ff67a1f4e/resourceGroups/eventgrid/providers/Microsoft.Web/connections/azureeventgrid", 16  "connectionName": "azureeventgrid", 17  "id": "/subscriptions/c04b3c63-8dfe-4f98-be18-e71ff67a1f4e/providers/Microsoft.Web/locations/southeastasia/managedApis/azureeventgrid" 18  } 19  } 20  }, 21  "definition": { 22  "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", 23  "actions": { 24  "Compose": { 25  "inputs": { 26  "vmname": "@substring(body(‘Parse_JSON‘)?[‘subject‘],add(16,lastIndexOf(body(‘Parse_JSON‘)?[‘subject‘],‘virtualMachines/‘)),sub(length(body(‘Parse_JSON‘)?[‘subject‘]),add(16,lastIndexOf(body(‘Parse_JSON‘)?[‘subject‘],‘virtualMachines/‘))))" 27  }, 28  "runAfter": { 29  "Parse_JSON": [ 30  "Succeeded" 31  ] 32  }, 33  "type": "Compose" 34  }, 35  "Compose_2": { 36  "inputs": "@triggerBody()", 37  "runAfter": {}, 38  "type": "Compose" 39  }, 40  "Compose_3": { 41  "inputs": "@body(‘Parse_JSON_3‘)?[‘storageProfile‘][‘osDisk‘]", 42  "runAfter": { 43  "Parse_JSON_3": [ 44  "Succeeded" 45  ] 46  }, 47  "type": "Compose" 48  }, 49  "Create_container_group": { 50  "inputs": { 51  "body": { 52  "location": "southeastasia", 53  "properties": { 54  "containers": [ 55  { 56  "name": "@{concat(‘azcp‘,rand(1,100))}", 57  "properties": { 58  "command": [ 59  "/bin/bash", 60  "-c", 61  "azcopy --destination $destination --source $source --dest-key $destkey" 62  ], 63  "environmentVariables": [ 64  { 65  "name": "destination", 66  "value": "@{concat(‘https://diskclone.blob.core.windows.net/diskclone/‘,outputs(‘Compose_3‘)?[‘name‘])}" 67  }, 68  { 69  "name": "source", 70  "value": "@body(‘mdsasurl‘)?[‘accessSAS‘]" 71  }, 72  { 73  "name": "destkey", 74  "value": "yrbf9VRMOFN70+tAmoianfx1TGwJPAp+26aQ2g7EdB+4UqNBSoa3bJP9uEwJy2eGUz5y1NPnZx8XuKJP0W3p8w==" 75  } 76  ], 77  "image": "acrbuildpilot.azurecr.io/azcopy:v1", 78  "resources": { 79  "requests": { 80  "cpu": 1, 81  "memoryInGB": 1 82  } 83  } 84  } 85  } 86  ], 87  "imageRegistryCredentials": [ 88  { 89  "password": "iKccXllxyrn8aoSfPtQdUZTzDLIh/VRv", 90  "server": "acrbuildpilot.azurecr.io", 91  "username": "acrbuildpilot" 92  } 93  ], 94  "osType": "Linux", 95  "restartPolicy": "Never" 96  } 97  }, 98  "host": { 99  "connection": {100  "name": "@parameters(‘$connections‘)[‘aci‘][‘connectionId‘]"101  }102  },103  "method": "put",104  "path": "/subscriptions/@{encodeURIComponent(‘4507938f-a0ac-4571-978e-7cc741a60af8‘)}/resourceGroups/@{encodeURIComponent(‘aci‘)}/providers/Microsoft.ContainerInstance/containerGroups/@{encodeURIComponent(concat(‘azcp‘, rand(1, 100)))}",105  "queries": {106  "x-ms-api-version": "2017-10-01-preview"107  }108  },109  "runAfter": {110  "mdsasurl": [111  "Succeeded"112  ]113  },114  "type": "ApiConnection"115  },116  "Parse_JSON": {117  "inputs": {118  "content": "@outputs(‘Compose_2‘)",119  "schema": {120  "properties": {121  "data": {122  "properties": {123  "authorization": {124  "properties": {125  "action": {126  "type": "string"127  },128  "evidence": {129  "properties": {130  "role": {131  "type": "string"132  }133  },134  "type": "object"135  },136  "scope": {137  "type": "string"138  }139  },140  "type": "object"141  },142  "claims": {143  "properties": {144  "aio": {145  "type": "string"146  },147  "appid": {148  "type": "string"149  },150  "appidacr": {151  "type": "string"152  },153  "aud": {154  "type": "string"155  },156  "e_exp": {157  "type": "string"158  },159  "exp": {160  "type": "string"161  },162  "groups": {163  "type": "string"164  },165  "http://schemas.microsoft.com/2012/01/devicecontext/claims/identifier": {166  "type": "string"167  },168  "http://schemas.microsoft.com/claims/authnclassreference": {169  "type": "string"170  },171  "http://schemas.microsoft.com/claims/authnmethodsreferences": {172  "type": "string"173  },174  "http://schemas.microsoft.com/identity/claims/objectidentifier": {175  "type": "string"176  },177  "http://schemas.microsoft.com/identity/claims/scope": {178  "type": "string"179  },180  "http://schemas.microsoft.com/identity/claims/tenantid": {181  "type": "string"182  },183  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname": {184  "type": "string"185  },186  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": {187  "type": "string"188  },189  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": {190  "type": "string"191  },192  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname": {193  "type": "string"194  },195  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn": {196  "type": "string"197  },198  "iat": {199  "type": "string"200  },201  "in_corp": {202  "type": "string"203  },204  "ipaddr": {205  "type": "string"206  },207  "iss": {208  "type": "string"209  },210  "name": {211  "type": "string"212  },213  "nbf": {214  "type": "string"215  },216  "onprem_sid": {217  "type": "string"218  },219  "puid": {220  "type": "string"221  },222  "uti": {223  "type": "string"224  },225  "ver": {226  "type": "string"227  }228  },229  "type": "object"230  },231  "correlationId": {232  "type": "string"233  },234  "operationName": {235  "type": "string"236  },237  "resourceProvider": {238  "type": "string"239  },240  "resourceUri": {241  "type": "string"242  },243  "status": {244  "type": "string"245  },246  "subscriptionId": {247  "type": "string"248  },249  "tenantId": {250  "type": "string"251  }252  },253  "type": "object"254  },255  "dataVersion": {256  "type": "string"257  },258  "eventTime": {259  "type": "string"260  },261  "eventType": {262  "type": "string"263  },264  "id": {265  "type": "string"266  },267  "metadataVersion": {268  "type": "string"269  },270  "subject": {271  "type": "string"272  },273  "topic": {274  "type": "string"275  }276  },277  "type": "object"278  }279  },280  "runAfter": {281  "Compose_2": [282  "Succeeded"283  ]284  },285  "type": "ParseJson"286  },287  "Parse_JSON_2": {288  "inputs": {289  "content": "@outputs(‘Compose‘)",290  "schema": {291  "properties": {292  "vmname": {293  "type": "string"294  }295  },296  "type": "object"297  }298  },299  "runAfter": {300  "Compose": [301  "Succeeded"302  ]303  },304  "type": "ParseJson"305  },306  "Parse_JSON_3": {307  "inputs": {308  "content": "@body(‘Read_a_resource‘)?[‘properties‘]",309  "schema": {310  "properties": {311  "hardwareProfile": {312  "properties": {313  "vmSize": {314  "type": "string"315  }316  },317  "type": "object"318  },319  "networkProfile": {320  "properties": {321  "networkInterfaces": {322  "items": {323  "properties": {324  "id": {325  "type": "string"326  }327  },328  "required": [329  "id"330  ],331  "type": "object"332  },333  "type": "array"334  }335  },336  "type": "object"337  },338  "osProfile": {339  "properties": {340  "adminUsername": {341  "type": "string"342  },343  "computerName": {344  "type": "string"345  },346  "linuxConfiguration": {347  "properties": {348  "disablePasswordAuthentication": {349  "type": "boolean"350  }351  },352  "type": "object"353  },354  "secrets": {355  "type": "array"356  }357  },358  "type": "object"359  },360  "provisioningState": {361  "type": "string"362  },363  "storageProfile": {364  "properties": {365  "dataDisks": {366  "type": "array"367  },368  "imageReference": {369  "properties": {370  "offer": {371  "type": "string"372  },373  "publisher": {374  "type": "string"375  },376  "sku": {377  "type": "string"378  },379  "version": {380  "type": "string"381  }382  },383  "type": "object"384  },385  "osDisk": {386  "properties": {387  "caching": {388  "type": "string"389  },390  "createOption": {391  "type": "string"392  },393  "diskSizeGB": {394  "type": "number"395  },396  "managedDisk": {397  "properties": {398  "id": {399  "type": "string"400  },401  "storageAccountType": {402  "type": "string"403  }404  },405  "type": "object"406  },407  "name": {408  "type": "string"409  },410  "osType": {411  "type": "string"412  }413  },414  "type": "object"415  }416  },417  "type": "object"418  },419  "vmId": {420  "type": "string"421  }422  },423  "type": "object"424  }425  },426  "runAfter": {427  "Read_a_resource": [428  "Succeeded"429  ]430  },431  "type": "ParseJson"432  },433  "Read_a_resource": {434  "inputs": {435  "host": {436  "connection": {437  "name": "@parameters(‘$connections‘)[‘arm‘][‘connectionId‘]"438  }439  },440  "method": "get",441  "path": "/subscriptions/@{encodeURIComponent(‘c04b3c63-8dfe-4f98-be18-e71ff67a1f4e‘)}/resourcegroups/@{encodeURIComponent(‘eventgrid‘)}/providers/@{encodeURIComponent(‘Microsoft.Compute‘)}/@{encodeURIComponent(concat(‘virtualMachines/‘, body(‘Parse_JSON_2‘)?[‘vmname‘]))}",442  "queries": {443  "x-ms-api-version": "2017-12-01"444  }445  },446  "runAfter": {447  "Parse_JSON_2": [448  "Succeeded"449  ]450  },451  "type": "ApiConnection"452  },453  "deallocate_vm": {454  "inputs": {455  "host": {456  "connection": {457  "name": "@parameters(‘$connections‘)[‘arm‘][‘connectionId‘]"458  }459  },460  "method": "post",461  "path": "/subscriptions/@{encodeURIComponent(‘c04b3c63-8dfe-4f98-be18-e71ff67a1f4e‘)}/resourcegroups/@{encodeURIComponent(‘eventgrid‘)}/providers/@{encodeURIComponent(‘Microsoft.Compute‘)}/@{encodeURIComponent(concat(‘virtualMachines/‘, body(‘Parse_JSON_2‘)?[‘vmname‘]))}/@{encodeURIComponent(‘deallocate‘)}",462  "queries": {463  "x-ms-api-version": "2017-12-01"464  }465  },466  "runAfter": {467  "Compose_3": [468  "Succeeded"469  ]470  },471  "type": "ApiConnection"472  },473  "mdsasurl": {474  "inputs": {475  "content": "@body(‘storage_sasurl‘)",476  "schema": {477  "properties": {478  "accessSAS": {479  "type": "string"480  }481  },482  "type": "object"483  }484  },485  "runAfter": {486  "storage_sasurl": [487  "Succeeded"488  ]489  },490  "type": "ParseJson"491  },492  "storage_sasurl": {493  "inputs": {494  "body": {495  "access": "Read",496  "durationInSeconds": 3600497  },498  "host": {499  "connection": {500  "name": "@parameters(‘$connections‘)[‘arm‘][‘connectionId‘]"501  }502  },503  "method": "post",504  "path": "/subscriptions/@{encodeURIComponent(‘c04b3c63-8dfe-4f98-be18-e71ff67a1f4e‘)}/resourcegroups/@{encodeURIComponent(‘eventgrid‘)}/providers/@{encodeURIComponent(‘Microsoft.Compute‘)}/@{encodeURIComponent(concat(‘disks/‘, outputs(‘Compose_3‘)?[‘name‘]))}/@{encodeURIComponent(‘beginGetAccess‘)}",505  "queries": {506  "x-ms-api-version": "2017-03-30"507  }508  },509  "runAfter": {510  "deallocate_vm": [511  "Succeeded"512  ]513  },514  "type": "ApiConnection"515  }516  },517  "contentVersion": "1.0.0.0",518  "outputs": {},519  "parameters": {520  "$connections": {521  "defaultValue": {},522  "type": "Object"523  }524  },525  "triggers": {526  "When_a_resource_event_occurs": {527  "inputs": {528  "body": {529  "properties": {530  "destination": {531  "endpointType": "webhook",532  "properties": {533  "endpointUrl": "@{listCallbackUrl()}"534  }535  },536  "filter": {537  "includedEventTypes": [538  "Microsoft.Resources.ResourceWriteSuccess"539  ],540  "subjectBeginsWith": "/subscriptions/c04b3c63-8dfe-4f98-be18-e71ff67a1f4e/resourcegroups/eventgrid/providers/Microsoft.Compute/virtualMachines"541  },542  "topic": "/subscriptions/c04b3c63-8dfe-4f98-be18-e71ff67a1f4e/resourceGroups/eventgrid"543  }544  },545  "host": {546  "connection": {547  "name": "@parameters(‘$connections‘)[‘azureeventgrid‘][‘connectionId‘]"548  }549  },550  "path": "/subscriptions/@{encodeURIComponent(‘c04b3c63-8dfe-4f98-be18-e71ff67a1f4e‘)}/providers/@{encodeURIComponent(‘Microsoft.Resources.ResourceGroups‘)}/resource/eventSubscriptions",551  "queries": {552  "x-ms-api-version": "2017-09-15-preview"553  }554  },555  "splitOn": "@triggerBody()",556  "type": "ApiConnectionWebhook"557  }558  }559  }560 }

参考资料:

       因为 EventGrid 和 LogicApp 学习成本都非常低,所以没有 Step by Step 给大家说明操作步骤,这里为了方便大家学习,给大家列举几个文档,帮助大家快速上手。

EventGrid 入门:https://docs.microsoft.com/en-us/azure/event-grid/overview

EventGrid 消息格式:https://docs.microsoft.com/en-us/azure/event-grid/event-schema

LogicApp 入门:https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-overview

LogicApp Connector 手册:https://docs.microsoft.com/en-us/connectors/

LogicApp 内置函数手册:https://docs.microsoft.com/en-us/azure/logic-apps/workflow-definition-language-functions-reference

 

相关文章