原文:
annas-archive.org/md5/0b3cfce43ce7ffb62c4f01cafdc66996译者:飞龙
第十五章:15. 使用 ARM 模板进行跨订阅部署
Azure 资源管理器(ARM)模板是配置和管理 Azure 上资源的首选机制。
ARM 模板有助于实现一种相对较新的范式,称为 基础设施即代码(IaC)。ARM 模板将基础设施及其配置转化为代码,具有众多优势。IaC 为跨环境的部署带来了高度一致性和可预测性。它还确保在投入生产之前可以对环境进行测试,最终,它使得部署过程、维护和治理更具信心。
本章将涵盖以下主题:
-
ARM 模板
-
使用 ARM 模板部署资源组
-
跨订阅和资源组部署资源
-
使用链接模板进行跨订阅和资源组部署
-
为 PaaS、数据和 IaaS 解决方案创建 ARM 模板
ARM 模板
IaC 的一个显著优势是它可以进行版本控制。它还可以跨环境复用,这在部署中提供了高度的一致性和可预测性,并确保无论模板部署多少次,部署 ARM 模板的影响和结果都是相同的。这个特性被称为 幂等性。
ARM 模板随着 ARM 规范的引入而首次亮相,并且自那时以来功能逐渐丰富,成熟度也在不断提高。需要理解的是,实际资源配置与 ARM 模板中配置的可用性之间通常存在几周到几个月的功能差距。
每个资源都有自己的配置。此配置可以通过多种方式进行更改,包括使用 Azure PowerShell、Azure CLI、Azure SDK、REST API 和 ARM 模板。
每种技术都有其独立的开发和发布生命周期,这与实际资源的开发不同。让我们通过一个例子来理解这一点。
Azure Databricks 资源有其自身的发布周期和开发生命周期。使用该资源的消费者也有自己的开发生命周期,这与实际资源的开发周期不同。如果 Databricks 在 12 月 31 日首次发布,那么针对它的 Azure PowerShell cmdlet 可能在同一天无法使用,甚至可能在次年的 1 月 31 日才发布;同样,这些功能在 REST API 和 ARM 模板中的可用性可能是在 1 月 15 日左右。
ARM 模板是基于 JSON 的文档,执行时会调用 Azure 管理平面上的 REST API 并提交整个文档。REST API 有自己的开发生命周期,而资源的 JSON 架构也有自己的生命周期。
这意味着,资源中的功能开发至少需要在三个不同的组件中进行,才能从 ARM 模板中使用。包括:
-
该资源本身
-
该资源的 REST API
-
ARM 模板资源架构
每个 ARM 模板中的资源都有apiVersion属性。该属性帮助确定应使用的 REST API 版本,以便配置和部署该资源。图 15.1 显示了从 ARM 模板到负责创建、更新和删除资源的资源 API 请求流:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_15.1.jpg
图 15.1:请求流
资源配置,例如 ARM 模板中的存储帐户,格式如下:
{ "type": "Microsoft.Storage/storageAccounts", "apiVersion": "2019-04-01", "name": "[variables('storage2')]", "location": "[resourceGroup().location]", "kind": "Storage", "sku": { "name": "Standard_LRS" }}
在前面的代码中,定义 sku 的架构可用性基于 ARM 模板架构的开发。REST API 的可用性及其版本号由 apiVersion 决定,版本为2019-04-01。实际资源由 type 属性决定,该属性包括以下两个部分:
-
资源提供者命名空间:Azure 中的资源托管在命名空间内,相关的资源也托管在相同的命名空间内。
-
资源类型:资源通过其类型名称进行引用。
在这种情况下,资源通过其提供者名称和类型来识别,类型为Microsoft.Storage/storageaccounts。
以前,ARM 模板要求在部署之前资源组必须已存在。它们也仅限于在单一订阅的单一资源组中进行部署。
这意味着,直到最近,ARM 模板只能在单一资源组内部署所有资源。现在,Azure ARM 模板增加了将资源部署到同一订阅内的多个资源组或多个订阅的功能。现在可以在 ARM 模板中创建资源组,这意味着现在可以将资源部署到多个区域的不同资源组中。
我们为什么需要在 ARM 模板中创建资源组?为什么需要同时进行跨订阅和跨资源组的部署?
为了理解创建资源组和跨订阅部署的价值,我们需要了解这些功能可用之前是如何进行部署的。
部署 ARM 模板之前,资源组是一个前提条件。资源组应该在模板部署之前创建。开发人员可以使用 PowerShell、Azure CLI 或 REST API 创建资源组,然后启动 ARM 模板的部署。这意味着任何端到端的部署都包括多个步骤。第一步是创建资源组,接下来的步骤是将 ARM 模板部署到这个新创建的资源组。这些步骤可以通过单个 PowerShell 脚本执行,或者通过 PowerShell 命令行中的独立步骤执行。PowerShell 脚本应该包含与异常处理相关的代码,考虑到边缘情况,并确保在脚本可以被称为企业级之前没有任何错误。需要注意的是,资源组可以从 Azure 中删除,下次脚本运行时可能会假设资源组已经存在并失败。简而言之,部署 ARM 模板到资源组应该是一个原子步骤,而不是多个步骤。
将这一点与能够在相同的 ARM 模板中创建资源组及其组成资源进行比较。每次部署模板时,它都会确保如果资源组尚未存在,则创建它,并在创建后继续向其中部署资源。
我们还来看看这些新功能如何帮助消除与灾难恢复站点相关的一些技术限制。
在这些新功能之前,如果你需要部署一个以灾难恢复为设计目标的解决方案,会有两个独立的部署:一个是主区域的部署,另一个是备用区域的部署。例如,如果你使用 App Service 部署一个 ASP.NET MVC 应用程序,你会创建一个应用服务并为主区域配置它,然后使用相同的模板在另一个区域进行另一个部署,并使用不同的parameters文件。当在另一个区域部署一组资源时,如前所述,模板使用的参数应该有所不同,以反映两个环境之间的差异。这些参数包括像 SQL 连接字符串、域名和 IP 地址以及其他特定于环境的配置项。
随着跨订阅和资源组部署功能的引入,您可以在创建主站点的同时创建灾难恢复站点。这消除了两个部署的需要,并确保相同的配置可以在多个站点上使用。
使用 ARM 模板部署资源组
在本节中,将编写并部署一个 ARM 模板,该模板将在同一订阅内创建几个资源组。
要使用 PowerShell 部署包含资源组和跨订阅资源的模板,应使用最新版本的 PowerShell。编写时,使用的是 Azure 模块版本 3.3.0:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_15.2.jpg
图 15.2:验证最新的 Azure 模块版本
如果没有安装最新的 Azure 模块,可以使用以下命令进行安装:
install-module -Name az -Force
现在是创建一个 ARM 模板的时机,该模板将在同一订阅内创建多个资源组。ARM 模板的代码如下:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "resourceGroupInfo": { "type": "array" }, "multiLocation": { "type": "array" } }, "resources": [ { "type": "Microsoft.Resources/resourceGroups", "location": "[parameters('multiLocation')[copyIndex()]]", "name": "[parameters('resourceGroupInfo')[copyIndex()]]", "apiVersion": "2019-10-01", "copy": { "name": "allResourceGroups", "count": "[length(parameters('resourceGroupInfo'))]" }, "properties": {} } ], "outputs": {}}
代码的第一部分是 ARM 模板所期望的参数。这些是必需的参数,任何部署这些模板的人都应提供相应的值。必须为这两个参数提供数组值。
第二个主要部分是 resources JSON 数组,它可以包含多个资源。在此示例中,我们正在创建资源组,因此它声明在 resources 部分内。由于使用了 copy 元素,资源组在循环中被创建。copy 元素确保资源运行指定次数,并在每次迭代中创建新的资源。如果我们为 resourceGroupInfo 数组参数传递两个值,则数组长度为二,copy 元素将确保 resourceGroup 资源执行两次。
模板中的所有资源名称在同一资源类型内应唯一。copyIndex 函数用于将当前迭代编号分配给资源的整体名称,并确保其唯一性。此外,我们希望资源组在不同区域中创建,使用作为参数传递的不同区域名称。每个资源组的名称和位置分配是通过 copyIndex 函数完成的。
parameters 文件的代码如下所示。该代码相当简单,并为之前模板中预期的两个参数提供了数组值。此文件中的值应根据你的环境更改所有参数:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "resourceGroupInfo": { "value": [ "firstResourceGroup", "SeocndResourceGroup" ] }, "multiLocation": { "value": [ "West Europe", "East US" ] } }}
部署 ARM 模板
要使用 PowerShell 部署此模板,使用以下命令登录 Azure 并提供有效的凭据:
Login-AzAccount
有效的凭据可以是用户帐户或服务主体。然后,使用新发布的 New-AzDeployment cmdlet 来部署模板。部署脚本可在 multipleResourceGroups.ps1 文件中找到:
New-AzDeployment -Location "West Europe" -TemplateFile "c:\users\rites\source\repos\CrossSubscription\CrossSubscription\multipleResourceGroups.json" -TemplateParameterFile "c:\users\rites\source\repos\CrossSubscription\CrossSubscription\multipleResourceGroups.parameters.json" -Verbose
需要注意的是,不能使用 New-AzResourceGroupDeployment cmdlet,因为 New-AzResourceGroupDeployment cmdlet 的作用范围是资源组,并且它期望资源组已经存在作为前提条件。为了在订阅级别部署资源,Azure 发布了一个新的 cmdlet,可以超越资源组范围进行操作。这个新的 cmdlet new-AzDeployment 是在订阅级别运行的。同时,也可以在管理组级别进行部署。管理组处于比订阅更高的层级,使用 New-AzManagementGroupDeployment cmdlet 进行部署。
使用 Azure CLI 部署模板
同一个模板也可以使用 Azure CLI 进行部署。以下是使用 Azure CLI 部署模板的步骤:
-
使用最新版本的 Azure CLI,通过 ARM 模板创建资源组。在撰写本文时,部署时使用的是版本 2.0.75,如下所示:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_15.3.jpg
图 15.3:检查 Azure CLI 版本
-
使用以下命令登录 Azure,并选择正确的订阅进行使用:
az login -
如果登录用户有多个订阅的访问权限,可以使用以下命令选择合适的订阅:
az account set –subscription xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -
使用以下命令执行部署。部署脚本可以在
multipleResourceGroupsCLI.txt文件中找到:C:\Users\Ritesh>az deployment create—location westus—template-file "C:\users\rites\source\repos\CrossSubscription\CrossSubscription\azuredeploy.json—parameters @"C:\users\rites\source\repos\CrossSubscription\CrossSubscription\azuredeploy.parameters.json"—verbose
一旦命令执行完成,ARM 模板中定义的资源应该会在 Azure 门户中显示出来。
在不同订阅和资源组之间部署资源
在上一节中,资源组是作为 ARM 模板的一部分创建的。Azure 还有一个功能,可以通过单个部署从单一 ARM 模板同时在多个订阅中提供资源。在本节中,我们将为两个不同的订阅和资源组提供一个新的存储帐户。部署 ARM 模板的人将选择其中一个订阅作为基础订阅,利用该订阅发起部署,并将存储帐户同时提供到当前订阅和另一个订阅。部署此模板的前提条件是,部署者必须至少拥有对两个订阅的访问权限,并且在这些订阅中拥有贡献者权限。以下是代码清单,代码也可以在随附代码中的 CrossSubscriptionStorageAccount.json 文件中找到:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "storagePrefix1": { "type": "string", "defaultValue": "st01" ... "type": "string", "defaultValue": "rg01" }, "remoteSub": { "type": "string", "defaultValue": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" } ... } } ], "outputs": {} } } } ], "outputs": {}}
需要注意的是,代码中使用的资源组名称应已在各自的订阅中存在。如果资源组不存在,代码将抛出错误。此外,资源组的名称必须与 ARM 模板中的名称完全匹配。
部署此模板的代码如下所示。在这种情况下,我们使用 New-AzResourceGroupDeployment,因为部署的范围是一个资源组。部署脚本可以在代码包中的 CrossSubscriptionStorageAccount.ps1 文件中找到:
New-AzResourceGroupDeployment -TemplateFile "<< path to your CrossSubscriptionStorageAccount.json file >>" -ResourceGroupName "<<provide your base subscription resource group name>>" -storagePrefix1 <<provide prefix for first storage account>> -storagePrefix2 <<provide prefix for first storage account>> -verbose
一旦命令执行完成,ARM 模板中定义的资源应在 Azure 门户中反映出来。
跨订阅和资源组部署的另一个示例
在本节中,我们将在一个 ARM 模板和单次部署中,从两个不同的订阅、资源组和区域创建两个存储帐户。我们将使用嵌套模板方法,并结合 copy 元素为这些资源组提供不同的名称和位置,部署到不同的订阅中。
然而,在执行下一组 ARM 模板之前,应先配置一个 Azure Key Vault 实例,并向其中添加一个密钥。这是因为存储帐户的名称是从 Azure Key Vault 中获取的,并作为参数传递给 ARM 模板,以便部署存储帐户。
要使用 Azure PowerShell 配置 Azure Key Vault,可以执行以下一组命令。以下命令的代码可以在 CreateKeyVaultandSetSecret.ps1 文件中找到:
New-AzResourceGroup -Location <<replace with location of your key vault>> -Name <<replace with name of your resource group for key vault>> -verbose New-AzureRmKeyVault -Name <<replace with name of your key vault>> -ResourceGroupName <<replace with name of your resource group for key vault>> -Location <<replace with location of your key vault>> -EnabledForDeployment -EnabledForTemplateDeployment -EnabledForDiskEncryption -EnableSoftDelete -EnablePurgeProtection -Sku Standard -Verbose
你应该注意,从 New-AzKeyVault cmdlet 的结果中记录下 ResourceID 值。这个值需要在 parameters 文件中进行替换。有关详细信息,请参见 图 15.4:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_15.4.jpg
图 15.4:创建 Key Vault 实例
执行以下命令,将新密钥添加到新创建的 Azure Key Vault 实例中:
Set-AzKeyVaultSecret -VaultName <<replace with name of your key vault>> -Name <<replace with name of yoursecret>> -SecretValue $(ConvertTo-SecureString -String <<replace with value of your secret>> -AsPlainText -Force ) -Verbose
代码列表可以在代码包中的 CrossSubscriptionNestedStorageAccount.json 文件中找到:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "hostingPlanNames": { "type": "array", "minLength": 1 }, ... "type": "Microsoft.Resources/deployments", "name": "deployment01", "apiVersion": "2019-10-01", "subscriptionId": "[parameters('subscriptions')[copyIndex()]]", "resourceGroup": "[parameters('resourceGroups')[copyIndex()]]", "copy": { "count": "[length(parameters('hostingPlanNames'))]", "name": "mywebsites", "mode": "Parallel" }, ... "kind": "Storage", "properties": { } } ]...
这是 parameters 文件的代码。它可以在 CrossSubscriptionNestedStorageAccount.parameters.json 文件中找到:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "hostingPlanNames": { ... "storageKey": { "reference": { "keyVault": { "id": "<<replace it with the value of Key vault ResourceId noted before>>" }, "secretName": "<<replace with the name of the secret available in Key vault>>" } } }}
这是部署前面模板的 PowerShell 代码。部署脚本可以在 CrossSubscriptionNestedStorageAccount.ps1 文件中找到:
New-AzResourceGroupDeployment -TemplateFile "c:\users\rites\source\repos\CrossSubscription\CrossSubscription\CrossSubscriptionNestedStorageAccount.json" -ResourceGroupName rg01 -TemplateParameterFile "c:\users\rites\source\repos\CrossSubscription\CrossSubscription\CrossSubscriptionNestedStorageAccount.parameters.json" -Verbose
一旦命令执行完成,ARM 模板中定义的资源应在 Azure 门户中反映出来。
使用链接模板部署跨订阅和资源组的部署
前面的示例使用了嵌套模板进行多订阅和资源组的部署。在下一个示例中,我们将使用链接模板在不同的订阅和资源组中部署多个应用服务计划。链接模板存储在 Azure Blob 存储中,并通过策略进行保护。这意味着只有存储账户密钥的持有者或有效的共享访问签名(SAS)才能访问此模板。访问密钥存储在 Azure 密钥保管库中,并通过parameters文件中的storageKey元素引用进行访问。你应该将website.json文件上传到 Azure Blob 存储中的一个容器。website.json文件是一个链接模板,负责为应用服务计划和应用服务提供配置。该文件通过armtemplates进行保护,并设置为使用私有策略:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_15.5.jpg
图 15.5:为容器设置私有策略
该文件只能使用共享访问签名(SAS)密钥访问。可以从 Azure 门户的存储账户中使用左侧菜单中的共享访问签名项生成 SAS 密钥。你应该点击生成 SAS 和连接字符串按钮以生成 SAS 令牌。需要注意的是,SAS 令牌只会显示一次,并且不会存储在 Azure 中。因此,必须复制并将其存储在其他地方,以便可以上传到 Azure 密钥保管库中。图 15.6展示了生成 SAS 令牌的过程:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_15.6.jpg
图 15.6:在 Azure 门户中生成 SAS 令牌
我们将使用在上一节中创建的相同密钥保管库实例。只需确保密钥保管库实例中有两个密钥可用。第一个密钥是StorageName,另一个是StorageKey。在密钥保管库实例中创建这些密钥的命令如下:
Set-AzKeyVaultSecret -VaultName "testkeyvaultbook" -Name "storageName" -SecretValue $(ConvertTo-SecureString -String "uniquename" -AsPlainText -Force ) -Verbose Set-AzKeyVaultSecret -VaultName "testkeyvaultbook" -Name "storageKey" -SecretValue $(ConvertTo-SecureString -String "?sv=2020-03-28&ss=bfqt&srt=sco&sp=rwdlacup&se=2020-03-30T21:51:03Z&st=2020-03-30T14:51:03Z&spr=https&sig=gTynGhj20er6pDl7Ab%2Bpc29WO3%2BJhvi%2BfF%2F6rHYWp4g%3D" -AsPlainText -Force ) -Verbose
建议根据你的存储账户更改密钥保管库实例和密钥值的名称。
在确保密钥保管库实例具有必要的密钥后,可以使用 ARM 模板文件代码在多个订阅和资源组中部署嵌套模板。
ARM 模板代码可以在CrossSubscriptionLinkedStorageAccount.json文件中找到,并且在这里也有展示。建议你更改该文件中templateUrl变量的值。它应该更新为有效的 Azure Blob 存储文件位置:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "hostingPlanNames": { "type": "array", "minLength": 1 ... "type": "Microsoft.Resources/deployments", "name": "fsdfsdf", "apiVersion": "2019-10-01", "subscriptionId": "[parameters('subscriptions')[copyIndex()]]", "resourceGroup": "[parameters('resourceGroups')[copyIndex()]]", "copy": { "count": "[length(parameters('hostingPlanNames'))]", "name": "mywebsites", "mode": "Parallel" ... ]}
parameters 文件的代码如下所示。建议您更改参数的值,包括 Key Vault 实例的 resourceid 和密钥名称。应用服务的名称应该是唯一的,否则模板将无法部署。parameters 文件的代码可以在 CrossSubscriptionLinkedStorageAccount.parameters.json 代码文件中找到:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "hostingPlanNames": { "value": [ "firstappservice", "secondappservice" ] ... "storageKey": { "reference": { "keyVault": { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/keyvaluedemo/providers/Microsoft.KeyVault/vaults/forsqlvault1" }, "secretName": "storageKey" } } }}
这是部署模板的命令。部署脚本可以在 CrossSubscriptionLinkedStorageAccount.ps1 文件中找到:
New-AzureRmResourceGroupDeployment -TemplateFile "c:\users\rites\source\repos\CrossSubscription\CrossSubscription\CrossSubscriptionLinkedStorageAccount.json" -ResourceGroupName <<replace with the base subscription resource group name >> -TemplateParameterFile "c:\users\rites\source\repos\CrossSubscription\CrossSubscription\CrossSubscriptionLinkedStorageAccount.parameters.json" -Verbose
一旦命令执行,ARM 模板中定义的资源应该会在 Azure 门户中反映出来。
现在您已经知道如何跨资源组和订阅配置资源,接下来我们将了解使用 ARM 模板创建的一些解决方案。
使用 ARM 模板的虚拟机解决方案
基础设施即服务(IaaS)资源和解决方案可以通过 ARM 模板进行部署和配置。与 IaaS 相关的主要资源是虚拟机资源。
创建虚拟机资源依赖于 Azure 中的多个其他资源。创建虚拟机所需的一些资源包括:
-
存储账户或用于托管操作系统和数据磁盘的托管磁盘
-
虚拟网络以及子网
-
网络接口卡
还有其他可选的资源,包括:
-
Azure 负载均衡器
-
网络安全组
-
公共 IP 地址
-
路由表等
本节将讲解如何使用 ARM 模板创建虚拟机。正如本节前面提到的,我们需要在创建虚拟机资源之前,先创建一些虚拟机资源所依赖的其他资源。
需要注意的是,并非总是需要创建依赖资源。只有在依赖资源不存在时,才应该创建它们。如果它们已经存在于 Azure 订阅中,可以通过引用这些依赖资源来配置虚拟机资源。
模板依赖于几个参数,这些参数应该在执行模板时提供。这些变量与资源的位置以及某些配置值有关。由于这些值可能会在不同的部署中发生变化,因此使用参数可以使模板保持通用。
第一步是创建一个存储账户,如以下代码所示:
{
"type": "Microsoft.Storage/storageAccounts", "name": "[variables('storageAccountName')]", "apiVersion": "2019-04-01", "location": "[parameters('location')]", "sku": { "name": "Standard_LRS" }, "kind": "Storage", "properties": {} },
创建存储账户后,应该在 ARM 模板中定义一个虚拟网络。需要注意的是,存储账户和虚拟网络之间没有依赖关系,它们可以并行创建。虚拟网络资源具有一个子网作为其子资源。它们都配置了自己的 IP 范围;子网通常比虚拟网络的 IP 范围小:
{
"apiVersion": "2019-09-01",
"type": "Microsoft.Network/virtualNetworks",
"name": "[variables('virtualNetworkName')]",
"location": "[parameters('location')]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[variables('addressPrefix')]"
]
},
"subnets": [
{
"name": "[variables('subnetName')]",
"properties": {
"addressPrefix": "[variables('subnetPrefix')]"
}
}
]
}
},
如果虚拟机需要通过公共互联网访问,还可以创建公共 IP 地址,如以下代码所示。同样,它是一个完全独立的资源,并可以与存储帐户和虚拟网络并行创建:
{
"apiVersion": "2019-11-01",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[variables('publicIPAddressName')]",
"location": "[parameters('location')]",
"properties": {
"publicIPAllocationMethod": "Dynamic",
"dnsSettings": {
"domainNameLabel": "[parameters('dnsLabelPrefix')]"
}
}
},
在创建虚拟网络、存储帐户和公共 IP 地址后,可以创建网络接口。网络接口依赖于虚拟网络和子网资源。它也可以选择性地与公共 IP 地址关联。如下代码所示:
{
"apiVersion": "2019-11-01",
"type": "Microsoft.Network/networkInterfaces",
"name": "[variables('nicName')]",
"location": "[parameters('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": "[variables('subnetRef')]"
}
}
}
]
}
},
需要注意的是,公共 IP 地址和子网通过其独特的 Azure 标识符来引用。
在创建网络接口后,我们就拥有了创建虚拟机所需的所有资源。接下来的代码块展示了如何使用 ARM 模板创建虚拟机。它依赖于网络卡和存储帐户,这间接地创建了对虚拟网络、子网和公共 IP 地址的依赖。
对于虚拟机,我们配置必需的资源配置,包括type、apiVersion、location和name,以及任何依赖项,如以下代码所示:
{
"apiVersion": "2019-07-01",
"type": "Microsoft.Compute/virtualMachines",
"name": "[variables('vmName')]",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "VirtualMachine"
},
"dependsOn": [
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
"[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
],
"properties": {
"hardwareProfile": { "vmSize": "[variables('vmSize')]" },
"availabilitySet": {
"id": "[resourceId('Microsoft.Compute/availabilitySets', parameters('adAvailabilitySetName'))]"
},
"osProfile": {
"computerName": "[variables('vmName')]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "[variables('imagePublisher')]",
"offer": "[variables('imageOffer')]",
"sku": "[parameters('windowsOSVersion')]",
"version": "latest"
},
"osDisk": { "createOption": "FromImage" },
"copy": [
{
"name": "dataDisks",
"count": 3,
"input": {
"lun": "[copyIndex('dataDisks')]",
"createOption": "Empty",
"diskSizeGB": "1023",
"name": "[concat(variables('vmName'), '-datadisk', copyIndex('dataDisks'))]"
}
}
]
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
}
]
}
}
}
在前面的代码中,虚拟机被配置为:
-
硬件配置——虚拟机的大小。
-
操作系统配置——用于登录虚拟机的名称和凭据。
-
存储配置——存储虚拟机的虚拟硬盘(VHD)文件的存储帐户,包括数据磁盘。
-
网络配置——指向网络接口卡的引用。
接下来的部分将展示如何使用 ARM 模板配置一个平台即服务解决方案的示例。
使用 ARM 模板的 PaaS 解决方案
平台即服务(PaaS)资源和解决方案可以通过 ARM 模板进行部署。与 PaaS 相关的主要资源之一是 Azure Web 应用程序,在本节中,我们将重点介绍如何使用 ARM 模板在 Azure 上创建 Web 应用程序。
模板执行时需要提供一些参数。所需的参数包括应用服务计划的 SKU、托管资源的 Azure 区域和应用服务计划的 SKU 容量。
模板中声明了一些变量,以使其更加通用和可维护。第一个变量hostingPlanName是应用服务计划的名称,第二个变量webSiteName是应用服务本身的名称。
至少有两个资源应该被声明并配置,以便在 Azure 中创建一个可用的 Web 应用程序。它们是:
-
Azure 应用服务计划
-
Azure 应用服务
在 Azure 上创建 Web 应用的第一步是定义 Azure 应用服务计划的配置。以下代码定义了一个新的应用服务计划。值得注意的是,资源类型是 Microsoft.Web/serverfarms。计划的多数配置值,如 location、name 和 capacity,都作为参数传递给 ARM 模板:
{
"apiVersion": "2019-08-01",
"name": "[variables('hostingPlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[parameters('location')]",
"tags": {
"displayName": "HostingPlan"
},
"sku": {
"name": "[parameters('skuName')]",
"capacity": "[parameters('skuCapacity')]"
},
"properties": {
"name": "[variables('hostingPlanName')]"
}
},
在计划之后,应该预配的下一个资源是应用服务本身。重要的是要在这两个资源之间创建一个依赖关系,以确保在创建应用服务之前,计划已经创建:
{
"apiVersion": "2019-08-01",
"name": "[variables('webSiteName')]",
"type": "Microsoft.Web/sites",
"location": "[parameters('location')]",
"dependsOn": [
"[variables('hostingPlanName')]"
],
"properties": {
"name": "[variables('webSiteName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
},
"resources": [
{
"apiVersion": "2019-08-01",
"type": "config",
"name": "connectionstrings",
"dependsOn": [
"[variables('webSiteName')]"
],
"properties": {
"DefaultConnection": {
"value": "[concat( 'sql connection string here')]",
"type": "SQLAzure"
}
}
}
]
}
在上面的代码中,定义了一个类型为 Microsoft.Web/sites 的资源,并且它依赖于计划。它还使用了应用服务计划,并通过 serverFarmId 与之关联。它进一步声明了一个连接字符串,可用于连接到 SQL Server。
本节展示了如何使用 ARM 模板在 Azure 上创建 PaaS 解决方案的示例。同样,其他 PaaS 解决方案,包括 Azure Function 应用、Kubernetes 服务和 Service Fabric 等,均可使用 ARM 模板创建。
使用 ARM 模板的数据相关解决方案
在 Azure 中,有许多与数据管理和存储相关的资源。一些重要的与数据相关的资源包括 Azure SQL、Azure Cosmos DB、Azure Data Lake 存储、Data Lake Analytics、Azure Synapse、Databricks 和 Data Factory。
所有这些资源都可以通过 ARM 模板进行预配和配置。在本节中,我们将创建一个 ARM 模板,以预配一个数据工厂资源,负责通过存储过程将数据从 Azure Blob 存储迁移到 Azure SQL 数据库。
你将会找到参数文件与模板一起提供。这些值可能会在每次部署之间发生变化;我们将保持模板的通用性,以便你可以轻松地自定义并在其他部署中使用。
本节的完整代码可以在 github.com/Azure/azure-quickstart-templates/blob/master/101-data-factory-blob-to-sql-copy-stored-proc 找到。
第一步是声明 ARM 模板中数据工厂的配置,如下代码所示:
"name": "[variables('dataFactoryName')]",
"apiVersion": "2018-06-01",
"type": "Microsoft.DataFactory/datafactories",
"location": "[parameters('location')]",
每个数据工厂都有多个连接的服务。这些连接的服务充当连接器,将数据引入数据工厂,或者数据工厂可以将数据发送到它们。以下代码列出了为 Azure 存储账户创建的一个连接服务,从中读取 Blob 数据进入数据工厂,以及为 Azure SQL 数据库创建的另一个连接服务:
{
"type": "linkedservices",
"name": "[variables('storageLinkedServiceName')]",
"apiVersion": "2018-06-01",
"dependsOn": [
"[variables('dataFactoryName')]"
],
"properties": {
"type": "AzureStorage",
"description": "Azure Storage Linked Service",
"typeProperties": {
"connectionString":
"[concat('DefaultEndpointsProtocol=https; AccountName=',parameters('storageAccountName'),'; AccountKey=',parameters('storageAccountKey'))]"
}
}
},
{
"type": "linkedservices",
"name": "[variables('sqlLinkedServiceName')]",
"apiVersion": "2018-06-01",
"dependsOn": [
"[variables('dataFactoryName')]"
],
"properties": {
"type": "AzureSqlDatabase",
"description": "Azure SQL linked service",
"typeProperties": {
"connectionString": "[concat('Data Source=tcp:', parameters('sqlServerName'), '.database.windows.net,1433;Initial Catalog=', parameters('sqlDatabaseName'), ';Integrated Security=False;User ID=', parameters('sqlUserId'), ';Password=', parameters('sqlPassword'), ';Connect Timeout=30;Encrypt=True')]"
}
}
},
在链接服务之后,是时候为 Azure 数据工厂定义数据集了。数据集有助于识别应读取并放入数据工厂的数据。它们还可以表示在转换过程中需要由数据工厂存储的临时数据,甚至是数据将写入的目标位置。接下来的代码块创建了三个数据集——分别代表刚才提到的各个数据集方面。
读取数据集在以下代码块中显示:
{
"type": "datasets",
"name": "[variables('storageDataset')]",
"dependsOn": [
"[variables('dataFactoryName')]",
"[variables('storageLinkedServiceName')]"
],
"apiVersion": "2018-06-01",
"properties": {
"type": "AzureBlob",
"linkedServiceName": "[variables('storageLinkedServiceName')]",
"typeProperties": {
"folderPath": "[concat(parameters('sourceBlobContainer'), '/')]",
"fileName": "[parameters('sourceBlobName')]",
"format": {
"type": "TextFormat"
}
},
"availability": {
"frequency": "Hour",
"interval": 1
},
"external": true
}
},
中间数据集在以下代码行中显示:
{
"type": "datasets",
"name": "[variables('intermediateDataset')]",
"dependsOn": [
"[variables('dataFactoryName')]",
"[variables('sqlLinkedServiceName')]"
],
"apiVersion": "2018-06-01",
"properties": {
"type": "AzureSqlTable",
"linkedServiceName": "[variables('sqlLinkedServiceName')]",
"typeProperties": {
"tableName": "[variables('intermediateDataset')]"
},
"availability": {
"frequency": "Hour",
"interval": 1
}
}
},
最终,用于目标的数据集在这里显示:
{
"type": "datasets",
"name": "[variables('sqlDataset')]",
"dependsOn": [
"[variables('dataFactoryName')]",
"[variables('sqlLinkedServiceName')]"
],
"apiVersion": "2018-06-01",
"properties": {
"type": "AzureSqlTable",
"linkedServiceName": "[variables('sqlLinkedServiceName')]",
"typeProperties": {
"tableName": "[parameters('sqlTargetTable')]"
},
"availability": {
"frequency": "Hour",
"interval": 1
}
}
},
最后,我们需要在数据工厂中创建一个管道,能够将所有数据集和链接服务汇集在一起,帮助创建提取-转换-加载(ETL)数据解决方案。管道由多个活动组成,每个活动完成特定任务。所有这些活动都可以在 ARM 模板中定义,正如你接下来看到的。第一个活动将存储帐户中的 Blob 复制到一个中间 SQL 服务器,如下所示的代码:
{
"type": "dataPipelines",
"name": "[variables('pipelineName')]",
"dependsOn": [
"[variables('dataFactoryName')]",
"[variables('storageLinkedServiceName')]",
"[variables('sqlLinkedServiceName')]",
"[variables('storageDataset')]",
"[variables('sqlDataset')]"
],
"apiVersion": "2018-06-01",
"properties": {
"description": "Copies data from Azure Blob to Sql DB while invoking stored procedure",
"activities": [
{
"name": "BlobtoSqlTableCopyActivity",
"type": "Copy",
"typeProperties": {
"source": {
"type": "BlobSource"
},
"sink": {
"type": "SqlSink",
"writeBatchSize": 0,
"writeBatchTimeout": "00:00:00"
}
},
"inputs": [
{
"name": "[variables('storageDataset')]"
}
],
"outputs": [
{
"name": "[variables('intermediateDataset')]"
}
]
},
{
"name": "SqlTabletoSqlDbSprocActivity",
"type": "SqlServerStoredProcedure",
"inputs": [
{
"name": "[variables('intermediateDataset')]"
}
],
"outputs": [
{
"name": "[variables('sqlDataset')]"
}
],
"typeProperties": {
"storedProcedureName": "[parameters('sqlWriterStoredProcedureName')]"
},
"scheduler": {
"frequency": "Hour",
"interval": 1
},
"policy": {
"timeout": "02:00:00",
"concurrency": 1,
"executionPriorityOrder": "NewestFirst",
"retry": 3
}
}
],
"start": "2020-10-01T00:00:00Z",
"end": "2020-10-02T00:00:00Z"
}
}
]
}
最后一个活动将数据从中间数据集复制到最终目标数据集。
还有管道运行期间的开始和结束时间。
本节重点介绍了为数据相关解决方案创建 ARM 模板。在下一节中,我们将讨论用于在 Azure 上创建数据中心的 ARM 模板,涉及 Active Directory 和 DNS。
在 Azure 上创建带有 Active Directory 和 DNS 的 IaaS 解决方案
在 Azure 上创建 IaaS 解决方案意味着创建多个虚拟机,将虚拟机提升为域控制器,并使其他虚拟机加入该域控制器,成为域连接节点。还意味着安装一个用于名称解析的 DNS 服务器,并可以选择安装一个跳板服务器,以安全访问这些虚拟机。
模板在虚拟机上创建一个 Active Directory 林。它根据提供的参数创建多个虚拟机。
模板创建:
-
一些可用性集
-
一个虚拟网络
-
网络安全组用于定义允许和不允许的端口及 IP 地址
模板执行以下操作:
-
配置一个或两个域。默认情况下创建根域;子域是可选的
-
为每个域配置两个域控制器
-
执行所需的状态配置脚本,将虚拟机提升为域控制器
我们可以使用在 使用 ARM 模板的虚拟机解决方案 部分讨论的方法创建多个虚拟机。但是,如果这些虚拟机需要高可用性,它们应当是可用性集的一部分。需要注意的是,可用性集为部署在这些虚拟机上的应用程序提供 99.95% 的可用性,而可用性区域则提供 99.99% 的可用性。
可以按照以下代码配置可用性集:
{
"name": "[variables('adAvailabilitySetNameRoot')]",
"type": "Microsoft.Compute/availabilitySets",
"apiVersion": "2019-07-01",
"location": "[parameters('location')]",
"sku": {
"name": "Aligned"
},
"properties": {
"PlatformUpdateDomainCount": 3,
"PlatformFaultDomainCount": 2
}
},
一旦可用性集创建完成,就需要在虚拟机配置中添加一个附加配置文件,以将虚拟机与可用性集关联,具体代码如下所示:
"availabilitySet" : {
"id": "[resourceId('Microsoft.Compute/availabilitySets', parameters('adAvailabilitySetName'))]"
}
你应该注意,使用负载均衡器与虚拟机配合时,可用性集是强制性的。
虚拟网络配置中需要的另一个更改是添加 DNS 信息,如下所示的代码所示:
{
"name": "[parameters('virtualNetworkName')]",
"type": "Microsoft.Network/virtualNetworks",
"location": "[parameters('location')]",
"apiVersion": "2019-09-01",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('virtualNetworkAddressRange')]"
]
},
"dhcpOptions": {
"dnsServers": "[parameters('DNSServerAddress')]"
},
"subnets": [
{
"name": "[parameters('subnetName')]",
"properties": {
"addressPrefix": "[parameters('subnetRange')]"
}
}
]
}
},
最后,要将虚拟机转换为 Active Directory,应该在虚拟机上执行 PowerShell 脚本或 期望状态配置(DSC)脚本。即使是将其他虚拟机加入域,也应该在那些虚拟机上执行另一组脚本。
可以使用 CustomScriptExtension 资源在虚拟机上执行脚本,具体代码如下所示:
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(parameters('adNextDCVMName'),'/PrepareNextDC')]",
"apiVersion": "2018-06-01",
"location": "[parameters('location')]",
"properties": {
"publisher": "Microsoft.Powershell",
"type": "DSC",
"typeHandlerVersion": "2.21",
"autoUpgradeMinorVersion": true,
"settings": {
"modulesURL": "[parameters('adNextDCConfigurationModulesURL')]",
"configurationFunction": "[parameters('adNextDCConfigurationFunction')]",
"properties": {
"domainName": "[parameters('domainName')]",
"DNSServer": "[parameters('DNSServer')]",
"DNSForwarder": "[parameters('DNSServer')]",
"adminCreds": {
"userName": "[parameters('adminUserName')]",
"password": "privateSettingsRef:adminPassword"
}
}
},
"protectedSettings": {
"items": {
"adminPassword": "[parameters('adminPassword')]"
}
}
}
},
在本节中,我们使用 IaaS 模式在 Azure 上创建了一个数据中心。我们创建了多个虚拟机,并将其中一台转换为域控制器,安装了 DNS,并为其分配了域。现在,网络上的其他虚拟机可以加入该域,并可以在 Azure 上形成一个完整的数据中心。
请参考 github.com/Azure/azure-quickstart-templates/tree/master/301-create-ad-forest-with-subdomain 获取在 Azure 上创建数据中心的完整代码清单。
总结
使用单一部署将资源部署到多个订阅、资源组和区域的选项,提供了增强的部署能力,减少了部署中的错误,并能访问高级功能,如创建灾难恢复站点和实现高可用性。
在本章中,你了解了如何使用 ARM 模板创建几种不同类型的解决方案。这包括创建一个基于基础架构的解决方案,其中包含虚拟机;使用 Azure App Service 创建的基于平台的解决方案;使用数据工厂资源(及其配置)创建的数据相关解决方案;以及在 Azure 上创建的一个数据中心,其中虚拟机上安装了 Active Directory 和 DNS。
在下一章,我们将专注于创建模块化 ARM 模板,这是架构师们希望将 ARM 模板提升到更高水平时必须掌握的关键技能。本章还将向你展示设计 ARM 模板的各种方式,并教你如何创建可重用和模块化的 ARM 模板。
第十六章:16. ARM 模板的模块化设计与实现
我们知道,有多种方法可以编写Azure 资源管理器(ARM)模板。使用 Visual Studio 和 Visual Studio Code 编写一个能够在 Azure 中配置所有必要资源的模板是相当容易的。一个单独的 ARM 模板可以包含 Azure 上解决方案所需的所有资源。这个单一的 ARM 模板可以小到仅几个资源,或者大到包含许多资源的模板。
尽管编写一个包含所有资源的单一模板非常具有诱惑力,但建议事先规划将 ARM 模板实现分成多个较小的 ARM 模板,以便避免未来与之相关的麻烦。
在本章中,我们将学习如何以模块化的方式编写 ARM 模板,以便它们能够随着时间的推移不断演进,且在变更、测试和部署时所需的参与和努力最小化。
然而,在编写模块化模板之前,最好先了解通过模块化编写模板所解决的问题。
本章将涵盖以下话题:
-
单模板的问题
-
理解嵌套和链接部署
-
链接模板
-
嵌套模板
-
自由流配置
-
已知配置
现在,让我们详细探讨上述话题,这将帮助您使用行业最佳实践编写模块化模板。
单模板方法的问题
表面上看,单个包含所有资源的大模板似乎不会有什么问题,但将来可能会出现一些问题。让我们讨论使用单个大模板时可能会遇到的问题。
更改模板时灵活性降低
使用包含所有资源的单个大模板使得将来进行更改变得困难。将所有依赖项、参数和变量都放在一个模板中,与较小的模板相比,更改模板可能需要花费大量时间。这些更改可能会影响模板的其他部分,且可能会被忽视,甚至引入错误。
排查大模板问题
大模板难以排查。这是一个已知的事实。模板中的资源数量越多,排查模板的问题就越困难。一个模板部署了所有资源,找到错误通常需要反复部署模板。开发人员在等待模板部署完成时会降低生产力。
此外,部署单个模板比部署较小的模板更加耗时。开发人员必须等待包含错误的资源部署完成后,才能采取任何行动。
依赖滥用
在较大的模板中,资源之间的依赖关系也往往变得更加复杂。由于 ARM 模板的工作方式,滥用 dependsOn 功能是很容易的。模板中的每个资源可以引用它之前的所有资源,而不是构建依赖关系树。ARM 模板在一个资源依赖于所有其他资源时并不会报错,尽管这些其他资源之间可能有相互依赖关系。这使得更改 ARM 模板容易引入 bug,有时甚至无法进行更改。
降低敏捷性
通常,一个项目中有多个团队,每个团队负责其在 Azure 中的资源。这些团队会发现很难使用单一 ARM 模板,因为应该由单个开发人员来更新这些模板。多个团队同时更新一个模板可能会导致冲突和难以解决的合并问题。拥有多个小模板可以使每个团队独立编写自己的 ARM 模板部分。
无法重用
如果你只有一个模板,那么你只能使用这个模板,并且使用这个模板意味着部署所有资源。没有办法直接选择单个资源,除非进行一些额外操作,比如添加条件资源。单一的大模板失去了重用性,因为你只能选择所有资源或没有资源。
了解单一大模板存在的诸多问题后,编写模块化模板是一种好习惯,这样我们可以获得以下好处:
-
多个团队可以在隔离的环境中独立工作各自的模板。
-
模板可以跨项目和解决方案重复使用。
-
模板易于调试和故障排除。
既然我们已经讨论了单一大模板的一些问题,接下来我们将探讨模块化模板的核心,并且它们如何帮助开发人员实现高效部署。
理解单一职责原则
单一职责原则是 SOLID 设计原则中的核心原则之一。它指出,一个类或代码段应该只负责单一功能,并且应完全拥有该功能。代码只有在当前功能发生功能变化或出现 bug 时才应发生更改或演变,而不是因为与当前组件无关的其他组件或代码的变化而改变。
将相同的原则应用于 ARM 模板有助于我们创建仅负责部署单一资源或功能的模板,而不是部署所有资源和完整解决方案。
使用这一原则将帮助你创建多个模板,每个模板负责一个单一资源或一小部分资源,而不是所有资源。
更快的故障排除和调试
每个模板的部署在 Azure 中都是一个独立的活动,是由输入、输出和日志组成的单独实例。当多个模板被部署来实现一个解决方案时,每个模板的部署都有独立的日志条目以及其输入和输出描述。与单个大型模板相比,使用来自多个部署的独立日志来隔离错误和排除故障要容易得多。
模块化模板
当一个单一的大型模板被拆解成多个模板,每个小模板负责自己的资源,而这些资源仅由包含它的模板拥有、维护并负责时,我们可以说这是模块化模板。每个模板都遵循单一职责原则。
在学习如何将一个大型模板拆分为多个小型可重用模板之前,理解创建小型模板背后的技术以及如何组合它们来部署完整解决方案是非常重要的。
部署资源
ARM 提供了一种链接模板的功能。尽管我们已经详细讲解了链接模板,但我还是在这里提一下,以帮助你理解链接模板如何帮助我们实现模块化、组合和重用。
ARM 模板提供了专门的资源,称为 Microsoft.Resources 命名空间。ARM 模板中的部署资源看起来非常类似于以下的代码片段:
"resources": [ { "apiVersion": "2019-10-01", "name": "linkedTemplate", "type": "Microsoft.Resources/deployments", "properties": { "mode": "Incremental", <nested-template-or-external-template> } }]
这个模板不言自明,模板资源中最重要的两个配置项是类型和属性。这里的类型指的是部署资源,而不是任何特定的 Azure 资源(如存储、虚拟机等),属性则指定了部署配置,包括链接模板部署或嵌套模板部署。
然而,部署资源的作用是什么呢?部署资源的工作是部署另一个模板。另一个模板可以是一个独立的外部模板,位于一个单独的 ARM 模板文件中,也可以是一个嵌套模板。这意味着可以像函数调用一样,从一个模板中调用其他模板。
ARM 模板中可以有嵌套级别的部署。这意味着一个模板可以调用另一个模板,而被调用的模板又可以调用另一个模板,这样的嵌套调用最多可以有五个级别:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_16.1.jpg
图 16.1:模板拆分成更小的模板
现在我们已经理解了大型模板可以通过将资源分布在不同的模板中实现模块化,我们需要将它们链接在一起,以便在 Azure 上部署资源。链接模板和嵌套模板是将多个模板组合在一起的方式。
链接模板
链接模板是调用外部模板的模板。外部模板存储在不同的 ARM 模板文件中。以下是链接模板的示例:
"resources": [ { "apiVersion": "2019-10-01", "name": "linkedTemplate", "type": "Microsoft.Resources/deployments", "properties": { "mode": "Incremental", "templateLink": { "uri":"https://mystorageaccount.blob.core.windows.net/AzureTemplates/newStorageAccount.json", "contentVersion":"1.0.0.0" }, "parametersLink": { "uri":"https://mystorageaccount.blob.core.windows.net/AzureTemplates/newStorageAccount.parameters.json", "contentVersion":"1.0.0.0" } } }]
相较于前一个模板,这个模板中重要的额外属性是templateLink和parametersLink。现在,templateLink指向外部模板文件的实际 URL,而parametersLink是相应parameters文件的 URL 位置。需要注意的是,调用模板应该有访问被调用模板位置的权限。例如,如果外部模板存储在 Azure Blob 存储中,并且该存储受到密钥保护,则调用模板必须能够使用适当的安全访问签名(SAS)密钥才能访问链接的模板。
也可以提供显式的内联参数,而不是parametersLink值,如下所示:
"resources": [ { "apiVersion": "2019-10-01", "name": "linkedTemplate", "type": "Microsoft.Resources/deployments", "properties": { "mode": "Incremental", "templateLink": { "uri":"https://mystorageaccount.blob.core.windows.net/AzureTemplates/newStorageAccount.json", "contentVersion":"1.0.0.0" }, "parameters": { "StorageAccountName":{"value": " [parameters('StorageAccountName')]"} } } }]
现在你对链接模板有了较好的理解。一个紧密相关的话题是嵌套模板,下一节将详细讨论这一点。
嵌套模板
相较于外部链接模板,嵌套模板是 ARM 模板中的一个相对较新的功能。
嵌套模板不会在外部文件中定义资源。资源是在调用模板本身和部署资源中定义的,如下所示:
"resources": [ { "apiVersion": "2019-10-01", "name": "nestedTemplate", "type": "Microsoft.Resources/deployments", "properties": { "mode": "Incremental", "template": { "$schema": "https://schema.management.azure.com/schemas/2015- 01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "resources": [ { "type": "Microsoft.Storage/storageAccounts", "name": "[variables('storageName')]", "apiVersion": "2019-04-01", "location": "West US", "properties": { "accountType": "Standard_LRS" } } ] } } }]
在这个代码段中,我们可以看到存储账户资源被嵌套在原始模板内,作为部署资源的一部分。与使用templateLink和parametersLink属性不同,这里使用resources数组作为单个部署的一部分来创建多个资源。使用嵌套部署的优势是,可以通过使用资源的名称来重新配置父级内的资源。通常,一个带有名称的资源在模板中只能存在一次。嵌套模板允许我们在同一个模板内使用它们,并确保所有模板都是自给自足的,而不是分别存储,并且这些模板可能或可能无法访问外部文件。
现在我们了解了模块化 ARM 模板背后的技术,应该如何将一个大型模板分解为更小的模板呢?
有多种方式可以将一个大型模板分解成更小的模板。微软推荐以下模式用于 ARM 模板的分解:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_16.2.jpg
图 16.2:模板分解策略
当我们将一个大型模板分解成更小的模板时,总是会有一个主模板,用于部署解决方案。这个主模板或母模板内部调用其他嵌套或链接的模板,这些模板又会调用其他模板,最终,包含 Azure 资源的模板会被部署。
主模板可以调用已知配置资源模板,后者又会调用包含 Azure 资源的模板。已知配置资源模板是特定于项目或解决方案的,且与之相关的可重用因素较少。成员资源模板是由已知配置资源模板调用的可重用模板。
如果需要,主模板可以调用共享资源模板和其他资源模板(如果它们存在)。
理解已知配置非常重要。模板可以作为已知配置或自由流配置来编写。
自由流配置
ARM 模板可以作为通用模板进行编写,其中大多数(如果不是全部)分配给变量的值都作为参数获取。这允许使用该模板的人传递他们认为必要的任何值来在 Azure 中部署资源。例如,部署模板的人可以选择任何大小的虚拟机、任何数量的虚拟机以及任何存储和网络配置。这被称为自由流配置,其中大多数配置是允许的,模板中的配置来自用户,而不是声明在模板内部。
这种配置方式有其挑战性。最大的问题是,并非所有配置都能在每个 Azure 区域和数据中心中得到支持。如果某些资源不允许在特定位置或区域创建,那么模板将无法创建这些资源。自由流配置的另一个问题是,用户可以提供他们认为必要的任何值,模板会尊重这些值,从而增加了成本和部署的负担,即使这些值并不是完全必需的。
已知配置
另一方面,已知配置是通过 ARM 模板部署环境的特定预设配置。这些预设配置被称为T 恤尺码配置。类似于 T 恤有小号、中号和大号等预设尺码,ARM 模板也可以预配置为部署小型、中型或大型环境,具体取决于需求。这意味着用户不能为环境选择任何随机的自定义尺寸,但可以从提供的选项中进行选择,并且在运行时执行的 ARM 模板将确保提供合适的环境配置。
因此,创建模块化 ARM 模板的第一步是决定环境的已知配置。
例如,以下是 Azure 上数据中心部署的配置:
表 16.1:Azure 上数据中心部署的配置
现在我们了解了这些配置,就可以创建模块化 ARM 模板了。
编写模块化 ARM 模板有两种方法:
-
组合模板:组合模板链接到其他模板。组合模板的示例包括主模板和中间模板。
-
叶级模板:叶级模板是包含单一 Azure 资源的模板。
ARM 模板可以根据以下内容分为模块化模板:
-
技术
-
功能
决定如何编写 ARM 模板的模块化方法的理想方式如下:
-
定义资源级或叶级模板,这些模板由单一资源组成。在接下来的图示中,最右侧的模板是叶级模板。在图中,虚拟机、虚拟网络、存储等位于同一列中,表示叶级模板。
-
使用叶级模板组合特定于环境的模板。这些特定于环境的模板提供了一个 Azure 环境,例如 SQL Server 环境、App Service 环境或数据中心环境。我们进一步探讨一下这个话题。以 Azure SQL 环境为例。要创建一个 Azure SQL 环境,需要多个资源。至少需要一个逻辑 SQL Server,一个 SQL 数据库和一些 SQL 防火墙资源。所有这些资源都在叶级模板中定义。这些资源可以组合在一起,形成一个单一的模板,从而能够创建 Azure SQL 环境。任何想要创建 SQL 环境的人都可以使用这个组合模板。图 16.3中有数据中心、消息传递和App Service作为特定于环境的模板。
-
创建具有更高抽象层次的模板,将多个特定于环境的模板组合成解决方案。这些模板是由前一步创建的特定于环境的模板组成的。例如,要创建一个需要 App Service 环境和 SQL 环境的电子商务库存解决方案,可以将两个环境模板——App Service 和 SQL Server 组合在一起。图 16.3中包含了功能 1和功能 2模板,这些模板是由子模板组成的。
-
最后,应该创建一个主模板,它由多个模板组成,每个模板都能够部署一个解决方案。
上述创建模块化设计模板的步骤,可以通过图 16.3轻松理解:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_16.3.jpg
图 16.3:模板和资源映射
现在,我们将实现上图所示的部分功能。在此实现中,我们将通过模块化的方法为虚拟机提供脚本扩展。自定义脚本扩展部署 Docker 二进制文件,并在 Windows Server 2016 虚拟机上准备一个容器环境。
现在,我们将使用模块化方法通过 ARM 模板创建一个解决方案。如前所述,第一步是创建单独的资源模板。这些单独的资源模板将用于组合成能够创建环境的其他模板。这些模板将用于创建虚拟机。所有此处展示的 ARM 模板都可以在随书章节代码中找到。这些模板的名称和代码如下:
-
Storage.json -
virtualNetwork.json -
PublicIPAddress.json -
NIC.json -
VirtualMachine.json -
CustomScriptExtension.json
首先,让我们看看 Storage.json 模板的代码。此模板提供了一个存储帐户,每个虚拟机都需要它来存储操作系统和数据磁盘文件:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "storageAccountName": { "type": "string", "minLength": 1 }, "storageType": { "type": "string", "minLength": 1 }, ... "outputs": { "resourceDetails": { "type": "object", "value": "[reference(parameters('storageAccountName'))]" } }}
接下来,让我们看看公共 IP 地址模板的代码。一个需要通过互联网访问的虚拟机需要将公共 IP 地址资源分配给其网络接口卡。尽管将虚拟机暴露到互联网是可选的,但该资源可能会在创建虚拟机时使用。以下代码位于 PublicIPAddress.json 文件中:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "publicIPAddressName": { "type": "string", "minLength": 1 }, "publicIPAddressType": { "type": "string", "minLength": 1 ... } } ], "outputs": { "resourceDetails": { "type": "object", "value": "[reference(parameters('publicIPAddressName'))]" } }}
接下来,让我们看看虚拟网络的代码。Azure 上的虚拟机需要虚拟网络进行通信。此模板将用于在 Azure 上创建一个虚拟网络,具有预定义的地址范围和子网。以下代码位于 virtualNetwork.json 文件中:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "virtualNetworkName": { "type": "string", "minLength": 1 ... }, "subnetPrefix": { "type": "string", "minLength": 1 }, "resourceLocation": { "type": "string", "minLength": 1 } ... "subnets": [ { "name": "[parameters('subnetName')]", "properties": { "addressPrefix": "[parameters('subnetPrefix')]" } } ] } } ], "outputs": { "resourceDetails": { "type": "object", "value": "[reference(parameters('virtualNetworkName'))]" } }}
接下来,让我们看看网络接口卡的代码。虚拟机需要一个虚拟网络卡来连接虚拟网络,并接收和发送来自互联网的请求。以下代码位于 NIC.json 文件中:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "nicName": { "type": "string", "minLength": 1 }, "publicIpReference": { "type": "string", "minLength": 1 ...[resourceId(subscription().subscriptionId,resourceGroup().name, 'Microsoft.Network/publicIPAddresses', parameters('publicIpReference'))]", "vnetRef": "[resourceId(subscription().subscriptionId,resourceGroup().name, 'Microsoft.Network/virtualNetworks', parameters('virtualNetworkReference'))]", "subnet1Ref": "[concat(variables('vnetRef'),'/subnets/', parameters('subnetReference'))]" }, ... "id": "[variables('subnet1Ref')]" } } } ] } } ], "outputs": { "resourceDetails": { "type": "object", "value": "[reference(parameters('nicName'))]" } }}
接下来,让我们看看创建虚拟机的代码。每个虚拟机都是 Azure 中的一个资源,并且请注意,此模板与存储、网络、公共 IP 地址或之前创建的其他资源没有关联。这个引用和组合将在本节稍后通过另一个模板完成。以下代码位于 VirtualMachine.json 文件中:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01 01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "vmName": { "type": "string", "minLength": 1 ... }, "imageOffer": { "type": "string", "minLength": 1 }, "windowsOSVersion": { "type": "string", "minLength": 1 }, ... "outputs": { "resourceDetails": { "type": "object", "value": "[reference(parameters('vmName'))]" } }
}
接下来,让我们看看创建自定义脚本扩展的代码。此资源在虚拟机配置后执行 PowerShell 脚本。此资源提供了在 Azure 虚拟机中执行后配置任务的机会。以下代码位于 CustomScriptExtension.json 文件中:
{ "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "VMName": { "type": "string", "defaultValue": "sqldock", "metadata": {... "commandToExecute": "[concat('powershell -ExecutionPolicy Unrestricted -file docker.ps1')]" }, "protectedSettings": { } } } ], "outputs": { }}
接下来,我们将查看准备 Docker 环境的自定义脚本扩展 PowerShell 代码。请注意,在执行 PowerShell 脚本时,可能会发生虚拟机重启,具体取决于 Windows 容器功能是否已经安装。以下脚本安装了 NuGet 包、DockerMsftProvider 提供程序和 Docker 可执行文件。docker.ps1 文件随章节代码提供:
## docker.ps1 #Install-PackageProvider -Name Nuget -Force -ForceBootstrap -Confirm:$false Install-Module -Name DockerMsftProvider -Repository PSGallery -Force -Confirm:$false -verboseInstall-Package -Name docker -ProviderName DockerMsftProvider -Force -ForceBootstrap -Confirm:$false
所有之前看到的链接模板应上传到 Azure Blob 存储帐户中的一个容器内。该容器可以应用私有访问策略,正如你在上一章中看到的那样;然而,在此示例中,我们将访问策略设置为 container。这意味着这些链接模板可以在没有 SAS 令牌的情况下访问。
最后,让我们集中讨论编写主模板。在主模板中,所有的链接模板将被组合在一起,创建一个解决方案——部署虚拟机并在其中执行脚本。相同的方法也可以用于创建其他解决方案,比如提供一个由多个相互连接的虚拟机组成的数据中心。以下代码可以在 Master.json 文件中找到:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "storageAccountName": { "type": "string", "minLength": 1 ... }, "subnetName": { "type": "string", "minLength": 1 }, "subnetPrefix": { "type": "string", "minLength": 1 ... "windowsOSVersion": { "type": "string", "minLength": 1 }, "vhdStorageName": { "type": "string", "minLength": 1 }, "vhdStorageContainerName": { "type": "string", "minLength": 1 ...[concat('https://',parameters('storageAccountName'),'armtfiles.blob.core.windows.net/',variables('containerName'),'/Storage.json')]", "contentVersion": "1.0.0.0" }, "parameters": { "storageAccountName": { "value": "[parameters('storageAccountName')]" }, "storageType": { "value": "[parameters('storageType')]" }, "resourceLocation": { "value": "[resourceGroup().location]" ... "outputs": { "resourceDetails": { "type": "object", "value": "[reference('GetVM').outputs.resourceDetails.value]" } }}
主模板调用外部模板,并协调它们之间的相互依赖关系。
外部模板应存放在一个众所周知的位置,以便主模板可以访问并调用它们。在此示例中,外部模板存储在 Azure Blob 存储容器中,并通过参数将此信息传递给 ARM 模板。
存储在 Azure Blob 存储中的外部模板可以通过设置访问策略来进行访问保护。用于部署主模板的命令如下所示。它可能看起来是一个复杂的命令,但大多数值是作为参数使用的。在运行命令之前,建议你更改这些参数的值。已将链接模板上传到名为 st02gvwldcxm5suwe 的存储帐户中的 armtemplates 容器。如果资源组当前不存在,应先创建资源组。第一个命令用于在 West Europe 区域创建一个新的资源组:
New-AzResourceGroup -Name "testvmrg" -Location "West Europe" -Verbose
剩余的参数值是配置每个资源所需的。存储帐户名称和 dnsNameForPublicIP 值在 Azure 中应是唯一的:
New-AzResourceGroupDeployment -Name "testdeploy1" -ResourceGroupName testvmrg -Mode Incremental -TemplateFile "C:\chapter 05\Master.json" -storageAccountName "st02gvwldcxm5suwe" -storageType "Standard_LRS" -publicIPAddressName "uniipaddname" -publicIPAddressType "Dynamic" -dnsNameForPublicIP "azureforarchitectsbook" -virtualNetworkName vnetwork01 -addressPrefix "10.0.1.0/16" -subnetName "subnet01" -subnetPrefix "10.0.1.0/24" -nicName nic02 -vmSize "Standard_DS1" -adminUsername "sysadmin" -adminPassword $(ConvertTo-SecureString -String sysadmin@123 -AsPlainText -Force) -vhdStorageName oddnewuniqueacc -vhdStorageContainerName vhds -OSDiskName mynewvm -vmName vm10 -windowsOSVersion 2012-R2-Datacenter -imagePublisher MicrosoftWindowsServer -imageOffer WindowsServer -containerName armtemplates -Verbose
本节中,我们介绍了将大型模板拆分为较小的可重用模板的最佳实践,并在运行时将它们组合在一起,以便在 Azure 上部署完整的解决方案。在书中的后续章节中,我们将逐步修改 ARM 模板,直到探索其核心部分。我们使用了 Azure PowerShell cmdlet 来启动模板在 Azure 上的部署。
让我们继续讨论 copy 和 copyIndex 的话题。
理解 copy 和 copyIndex
有许多情况下需要多个实例的特定资源或资源组。例如,你可能需要配置 10 个相同类型的虚拟机。在这种情况下,反复部署模板来创建这些实例并不可取。更好的替代方法是使用 ARM 模板中的 copy 和 copyIndex 功能。
copy 是每个资源定义的一个属性。这意味着它可以用于创建某种资源类型的多个实例。
让我们通过一个在单个 ARM 模板部署中创建多个存储帐户的示例来理解这一点。
下一个代码片段按顺序创建了 10 个存储帐户。它们本可以通过将 mode 属性设置为 Parallel 来并行创建,而不是 Serial:
"resources": [
{
"apiVersion": "2019-06-01",
"type": "Microsoft.Storage/storageAccounts",
"location": "[resourceGroup().location]",
"name": "[concat(variables('storageAccountName'), copyIndex())]",
"tags":{
"displayName": "[variables('storageAccountName')]"
},
"sku":{
"name":"Premium_ZRS"
},
"kind": "StorageV2",
"copy":{
"name": "storageInstances",
"count": 10,
"mode": "Serial"
}
}
],
在前面的代码中,copy 用于按顺序创建 10 个存储帐户实例,即一个接一个地创建。所有 10 个实例的存储帐户名称必须是唯一的,copyIndex 被用来通过将原始存储名称与索引值连接起来使它们唯一。copyIndex 函数返回的值在每次迭代时都会变化;它从 0 开始,并持续 10 次迭代。这意味着它在最后一次迭代时会返回 9。
现在我们已经了解了如何创建多个 ARM 模板实例,接下来我们将深入探讨如何保护这些模板免受已知的安全漏洞。
保护 ARM 模板
与创建企业 ARM 模板相关的另一个重要方面是对其进行适当的安全保护。ARM 模板包含资源配置和基础设施的关键信息,因此它们不应被破坏或被未经授权的人访问。
保护 ARM 模板的第一步是将它们存储在存储帐户中,并停止对存储帐户容器的任何匿名访问。此外,应该为存储帐户生成 SAS 令牌,并在 ARM 模板中使用这些令牌来调用链接的模板。这将确保只有持有 SAS 令牌的人才能访问这些模板。此外,这些 SAS 令牌应该存储在 Azure Key Vault 中,而不是硬编码到 ARM 模板中。这样可以确保即使是负责部署的人也无法访问 SAS 令牌。
保护 ARM 模板的另一个步骤是确保任何敏感信息和机密,如数据库连接字符串、Azure 订阅和租户标识符、服务主体标识符、IP 地址等,不应硬编码到 ARM 模板中。它们应全部作为参数,并且值应在运行时从 Azure Key Vault 中提取。然而,在使用这种方法之前,确保这些机密已经在 Key Vault 中存储好,是非常重要的。
以下代码展示了在运行时使用参数文件从 Azure Key Vault 中提取值的方式之一:
{ "$schema": https://schema.management.azure.com/schemas/2016-01-01/deploymentParameters.json#, "contentVersion": "1.0.0.0", "parameters": { "storageAccountName": { "reference": { "keyVault": { "id": "/subscriptions/--subscription id --/resourceGroups/rgname/providers/Microsoft.KeyVault/vaults/keyvaultbook"), "secretName": "StorageAccountName" } } } }}
在这个代码示例中,定义了一个参数,用于引用 Azure Key Vault,以便在部署过程中运行时获取值。Azure Key Vault 的标识符和秘密名称已作为输入值提供。
现在您已经了解了如何保护 ARM 模板,接下来我们来看看如何识别它们之间的各种依赖关系,以及如何启用多个模板之间的通信。
在 ARM 模板之间使用输出
使用链接模板时,一个容易被忽视的重要方面是可能会存在资源依赖性。例如,SQL Server 资源可能位于与虚拟机资源不同的链接模板中。如果我们希望为虚拟机 IP 地址打开 SQL Server 防火墙,那么在配置虚拟机后,我们应该能够将此信息动态传递给 SQL Server 防火墙资源。
如果 SQL Server 和虚拟机资源在同一个模板中,可以通过使用REFERENCES函数简单地引用 IP 地址资源来实现此功能。
如果我们希望在不同模板之间共享运行时属性值,那么在链接模板的情况下,情况会稍微复杂一些。
ARM 模板提供了outputs配置,它负责从当前模板部署生成输出并将其返回给用户。例如,我们可以使用reference函数输出一个完整的对象,如下所示,或者我们也可以仅输出一个 IP 地址作为字符串值:
"outputs": {
"storageAccountDetails": {
"type": "object",
"value": "[reference(resourceid ('Microsoft.Storage/storageAccounts', variables('storageAccountName')))]",
"virtualMachineIPAddress": {
"type": "string",
"value": "[reference(variables ('publicIPAddressName')).properties.ipAddress]"
}
}
}
链接模板中的参数可以被主模板利用。当调用链接模板时,输出将可供主模板使用,并可以作为参数传递给下一个链接模板或嵌套模板。通过这种方式,能够将资源的运行时配置值从一个模板传递到另一个模板。
主模板中的代码将类似于这里所展示的代码;这是用于调用第一个模板的代码:
{ "type": "Microsoft.Resources/deployments", "apiVersion": "2017-05-10", "name": "createvm", "resoureceGroup": "myrg", "dependsOn": [ "allResourceGroups" ], "properties":{ "mode": "Incremental", "templateLink":{ "uri": "[variables( 'templateRefSharedServicesTemplateUri')]", "contentVersion": "1.0.0.0" }, "parameters": { "VMName": { "value": "[variables('VmName')]" } } }}
前面的代码片段来自主模板,它调用了一个负责配置虚拟机的嵌套模板。该嵌套模板有一个输出部分,提供虚拟机的 IP 地址。主模板将在其模板中包含另一个部署资源,该资源将获取输出值并在运行时将其作为参数传递给下一个嵌套模板,从而传递 IP 地址。如下所示:
{ "type": "Microsoft,Resources/deployments", "apiVersion": "2017-05-10", "name": "createSQLServer", "resourceGroup": "myrg", "dependsOn": [ "createvm" ], "properties": { "mode": "Incremental", "templateLink": { "uri": "[variables('templateRefsql')]", "contentVersion": "1.0.0.0" }, "parameters": { "VMName": { "value": "[reference ('createvm').outputs.virtualMachineIPAddress.value]" } } }}
在前面的代码列表中,调用了一个嵌套模板,并且一个参数被传递给它。这个参数的值来自前一个链接模板的输出,该输出被命名为virtualMachineIPAddress。现在,嵌套模板将动态获取虚拟机的 IP 地址,并可以将其用作白名单中的 IP 地址。
使用这种方法,我们可以将运行时值从一个嵌套模板传递到另一个嵌套模板。
总结
ARM 模板是 Azure 中首选的资源配置方式。它们具有幂等性,为环境创建带来了一致性、可预测性和可重用性。在本章中,我们探讨了如何创建一个模块化的 ARM 模板。对于团队来说,花时间以适当的方式设计 ARM 模板非常重要,这样多个团队可以共同协作。ARM 模板具有高度的可重用性,并且只需最小的修改即可发展。在本章中,我们学习了如何创建具有安全设计的模板,如何在单次部署中配置多个资源实例,以及如何通过 ARM 模板的 outputs 部分将输出从一个嵌套模板传递到另一个模板。
下一章将转向 Azure 中另一种非常流行的技术——无服务器架构。Azure Functions 是 Azure 的主要无服务器资源之一,接下来我们将对其进行深入探讨,包括 Durable Functions(持久化函数)。
在上一章中,你学习了 ARM 模板,到目前为止,我们一直在处理 Azure 中的架构问题及其解决方案。然而,本章并非基于通用的架构。事实上,它探讨了本世纪最具颠覆性的技术之一。本章将讨论物联网(IoT)和 Azure 的细节。
Azure 物联网指的是一组由微软管理的云服务,这些服务可以连接、监控和控制数十亿个物联网资产。换句话说,物联网解决方案包括一个或多个物联网设备,这些设备会不断与云端的一台或多台后端服务器进行通信。
本章将涵盖以下主题:
-
Azure 与物联网
-
Azure 物联网概述
-
设备管理
-
注册设备
-
设备与物联网中心的通信
-
扩展物联网解决方案
-
IoT 解决方案的高可用性
-
物联网协议
-
使用消息属性路由消息
第十七章:物联网(IoT)
互联网是在 1980 年代发明的,随后逐渐变得普及。几乎每个人都开始在互联网上建立自己的存在,并开始创建自己的静态网页。最终,静态内容变得动态,可以根据上下文即时生成。在几乎所有的情况下,都需要一个浏览器才能访问互联网。当时有大量的浏览器可供选择,没有它们,使用互联网将变得困难重重。
在本世纪的第一个十年中,出现了一个有趣的发展——手持设备的兴起,如手机和平板电脑。手机开始变得更加便宜,并且无处不在。这些手持设备的硬件和软件能力得到了显著提高,甚至人们开始使用手机浏览器而非桌面浏览器。但一个特别明显的变化是移动应用的兴起。这些移动应用从商店下载,并通过互联网连接到后端系统。在上个十年末期,市场上涌现了数百万个应用,几乎每一种可想象的功能都被内置其中。这些应用的后端系统建立在云上,以便快速扩展。这是应用程序与服务器连接的时代。
但这就是创新的巅峰吗?互联网的下一个发展是什么?实际上,另一个范式现在正逐步成为主流:物联网。与仅有移动设备和平板设备连接互联网不同,为什么其他设备不能连接互联网呢?过去,这类设备仅在特定市场中可用;它们昂贵,难以普及,且硬件和软件功能有限。然而,自本十年初以来,这些设备的商业化正在大规模发展。这些设备变得越来越小,硬件和软件能力更强,存储和计算能力更大,可以通过多种协议连接互联网,并且几乎可以附加到任何物体上。这是连接设备到服务器、应用程序和其他设备的时代。
这促使了一个观点的形成,即物联网应用可以改变各行业的运作方式。以前闻所未闻的全新解决方案现在开始得以实现。现在,这些设备可以连接到任何东西;它们可以获取信息并将其发送到后端系统,后端系统能够从所有设备中整合信息,并对其采取行动或报告事件。
物联网传感器和控制设备可以在许多商业应用场景中得到利用。例如,它们可以用于车辆追踪系统,这些系统可以追踪车辆的所有重要参数,并将这些数据发送到集中式数据存储进行分析。智能城市计划也可以利用各种传感器来追踪污染水平、温度和街道拥堵情况。物联网还在农业相关活动中找到了应用,比如测量土壤肥力、湿度等。你可以访问 microsoft.github.io/techcasestudies/#technology=IoT&sortBy=featured 了解关于组织如何利用 Azure IoT 的真实案例。
在我们探索与物联网相关的工具和服务之前,我们将首先详细介绍物联网架构。
物联网架构
在深入了解与物联网相关的 Azure 及其功能和服务之前,了解构建端到端物联网解决方案所需的各种组件非常重要。
想象一下,全球范围内的物联网设备每秒都在向集中数据库发送数百万条消息。为什么要收集这些数据呢?答案是为了提取关于事件、异常和离群值的丰富信息,这些都与这些设备监控的内容相关。
让我们更详细地理解这一点。
物联网架构可以分为以下几个不同的阶段:
-
连接性:此阶段涉及设备与物联网服务之间的连接。
-
身份: 连接到物联网服务后,首先进行设备的识别,并确保它被允许向物联网服务发送设备遥测数据。这通过认证过程完成。
-
捕获: 在这个阶段,设备遥测数据被捕获并被物联网服务接收。
-
摄入: 在这个阶段,物联网服务摄取设备遥测数据。
-
存储: 设备遥测数据被存储。它可以是临时存储或永久存储。
-
转换: 遥测数据被转换以供进一步处理。这包括增加现有数据和推断数据。
-
分析: 转换后的数据用于发现模式、异常和洞见。
-
呈现: 洞见以仪表板和报告的形式展示。此外,还可以生成新的警报,可能会调用自动化脚本和流程。
图 17.1展示了一个通用的基于物联网的架构。数据由设备生成或收集,并发送到云网关。云网关将数据发送到多个后端服务进行处理。云网关是可选组件;当设备本身由于资源限制或缺乏可靠网络而无法向后端服务发送请求时,应使用它们。这些云网关可以整合多个设备的数据并将其发送到后端服务。然后,后端服务可以处理数据并向用户显示为洞察或仪表板:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_17_01.jpg
图 17.1:一个通用的物联网应用架构
现在我们清楚了架构,让我们继续了解物联网设备如何与其他设备通信。
连通性
物联网设备需要通信以连接到其他设备。有各种各样的连接类型;例如,设备之间可以在一个区域内连接,设备与集中网关之间可以连接,设备与物联网平台之间也可以连接。
在所有这些情况下,物联网设备需要连接能力。这种能力可以是互联网连接、蓝牙、红外线或任何其他近设备通信形式。
然而,一些物联网设备可能无法连接到互联网。在这些情况下,它们可以连接到一个有能力连接到互联网的网关。
物联网设备使用协议发送消息。主要协议包括高级消息队列协议(AMQP)和消息队列遥测传输协议(MQTT)。
设备数据应发送到 IT 基础设施。MQTT 协议是一种设备到服务器的协议,设备可以使用它将遥测数据和其他信息发送到服务器。一旦服务器通过 MQTT 协议接收到消息,它需要使用基于消息和队列的可靠技术将消息传输到其他服务器。AMQP 是将消息可靠且可预测地传输到 IT 基础设施中其他服务器的首选协议:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_17_02.jpg
图 17.2:MQTT 和 AMQP 协议的工作原理
接收来自物联网设备初始消息的服务器应将这些消息发送到其他服务器进行必要的处理,如保存日志、评估、分析和展示。
一些设备无法连接到互联网,或者不支持与其他服务器技术兼容的协议。为了使这些设备能够与物联网平台和云端协同工作,可以使用中间网关。网关有助于接入那些连接性差、网络能力不稳定的设备;这些设备可能使用非标准的协议,或者它们在资源和功率方面可能有局限。
在这种情况下,当设备需要额外的基础设施来连接到后端服务时,可以部署客户端网关。这些网关接收来自接近设备的消息,并将其转发(或推送)到 IT 基础设施和物联网平台进行进一步处理。这些网关在需要时能够进行协议转换。
在本节中,你了解了如何与其他设备进行通信以及网关在通信中扮演的角色。在下一节中,我们将讨论身份。
身份
物联网设备应在云平台上注册。未注册的设备不应允许连接到云平台。设备应注册并分配一个身份。设备在连接云时应发送其身份信息。如果设备未能发送此身份信息,则连接应失败。在本章后面的内容中,你将看到如何使用模拟应用为设备生成身份。正如你已经知道的,物联网设备用于捕获信息,在下一节中,我们将简要讨论捕获过程。
捕获
IoT 设备应能够捕捉信息。例如,它们应该能够读取或监控空气或土壤中的水分含量。此类信息可以基于频率进行捕捉——也许甚至每秒一次。信息捕获后,设备应能够将其发送到 IoT 平台进行处理。如果设备无法直接连接到 IoT 平台,它可以连接到中介云网关,并通过该网关将捕获的信息推送出去。
捕获数据的大小和捕获频率是设备最重要的因素。设备是否应该具备本地存储,以便暂时存储捕获的数据,是另一个需要考虑的重要方面。例如,如果设备有足够的本地存储,它可以在离线模式下工作。即使是移动设备,有时也作为连接到各种仪器的 IoT 设备,并且具备存储数据的能力。一旦我们捕获了数据,我们需要将其注入到 IoT 平台进行进一步分析,在下一节中,我们将探索注入。
注入
设备捕获和生成的数据应当发送到能够摄取和消费这些数据的 IoT 平台,以从中提取有意义的信息和见解。注入服务是至关重要的服务,因为其可用性和可扩展性会影响传入数据的吞吐量。如果由于可扩展性问题而导致数据被限制,或由于可用性问题无法摄取数据,那么数据将会丢失,数据集可能会受到偏倚或失真。我们已经捕获了数据,需要一个地方来存储这些数据。在下一节中,你将了解存储。
存储
IoT 解决方案通常处理数百万甚至数十亿条记录,涉及数 TB 甚至 PB 级别的数据。这些数据是有价值的,可以提供有关运营及其健康状况的见解。必须以这样的方式存储这些数据,以便能够对其进行分析。存储应当能随时供分析、应用程序和服务使用。存储解决方案应该从性能角度提供足够的吞吐量和延迟,并且要具有高可用性、可扩展性和安全性。下一节将讨论数据转换,这是存储和分析数据所必需的。
转换
IoT 解决方案通常是数据驱动的,并且需要处理大量数据。假设每辆车都有一个设备,并且每个设备每五秒钟发送一次消息。如果有一百万辆车发送消息,这相当于每天 2.88 亿条消息,每月 80 亿条消息。所有这些数据中都隐藏着大量信息和见解;然而,仅仅通过查看这些数据来理解它是非常困难的。
物联网设备捕获并存储的数据可以用来解决业务问题,但并非所有捕获的数据都很重要。只需要一部分数据就能解决问题。此外,物联网设备收集的数据可能也不一致。为了确保数据的一致性,并避免偏差或失真,应该对其进行适当的转换,使其准备好进行分析。在转换过程中,数据会被过滤、排序、删除、丰富并转化为结构化格式,以便下游的组件和应用能够使用。我们需要对转换后的数据进行一些分析,然后再进行呈现。作为工作流程中的下一步,我们将讨论分析。
分析
在前一步骤中转换的数据成为分析步骤的输入。根据手头的问题,可以对转换后的数据执行不同类型的分析。
以下是可以执行的不同类型的分析:
-
描述性分析:这种分析有助于发现物联网设备的状态和整体健康状况的模式和细节。此阶段识别并总结数据,以供更高级的分析阶段进一步使用。它有助于数据总结、与概率相关的统计分析、偏差识别以及其他统计任务。
-
诊断性分析:这种分析比描述性分析更为先进。它在描述性分析的基础上,尝试回答为什么某些事情会发生的问题。也就是说,它试图找出事件的根本原因。它使用高级概念,如假设和相关性,来寻找答案。
-
预测性分析:这种分析尝试预测未来发生的高概率事件。它基于过去的数据生成预测;回归分析是基于过去数据的一个例子。例如,预测汽车的价格、股市中的股票行为、汽车轮胎何时会爆裂等。
-
规范性分析:这种分析是最先进的。此阶段帮助识别应采取的行动,以确保设备和解决方案的健康状况不会恶化,并识别需要采取的预防措施。此阶段的分析结果有助于避免未来的问题并从根本上消除问题。
在最后阶段,分析结果以人类可读的方式呈现,供更广泛的受众理解和解读。在接下来的部分,我们将讨论呈现。
呈现
分析有助于基于数据识别答案、模式和见解。这些见解还需要以相关方能够理解的格式呈现给所有利益相关者。为此,仪表板和报告可以以统计或动态的方式生成,并展示给利益相关者。利益相关方可以利用这些报告采取进一步行动,并不断改进他们的解决方案。
为了快速回顾前面的步骤,我们首先从连接性开始,介绍了用于将数据从不支持标准协议的设备发送到网关的方法。接着,我们讨论了身份验证和数据捕获。捕获的数据随后会被摄取并存储,以便进一步转换。转换后,数据将进行分析,最后呈现给所有相关方。由于我们正在使用 Azure,在下一节中,我们将介绍什么是 Azure IoT,并从 Azure 的角度回顾我们至今所学的基本概念。
Azure IoT
现在,您已经了解了端到端物联网解决方案的各个阶段;每个阶段都至关重要,正确的实施对于任何解决方案的成功都是必须的。Azure 为这些阶段提供了大量服务。除了这些服务,Azure 还提供了 Azure IoT Hub,这是 Azure 的核心物联网服务和平台。它能够托管复杂、高可用、可扩展的物联网解决方案。我们将在深入了解其他服务后,进一步探讨 IoT Hub:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_17_03.jpg
图 17.3:物联网解决方案的设备和服务列表
在下一节中,我们将遵循与之前讨论物联网架构时相似的模式,学习如何通过 Azure IoT 进行通信、身份验证、数据捕获、数据摄取、存储、转换、分析和呈现。
连接性
IoT Hub 提供了所有重要的协议套件,使设备能够连接到 IoT 中心。它提供:
-
HTTPS:超文本传输安全协议(HTTPS)方法使用由一对密钥组成的证书,称为私钥和公钥,用于加密和解密设备与 IoT Hub 之间的数据。它提供从设备到云的一种单向通信。
-
AMQP:AMQP 是一种行业标准,用于在应用程序之间发送和接收消息。它提供了丰富的基础设施来确保消息的安全性和可靠性,这也是它在物联网领域广泛使用的原因之一。它提供设备到 IoT Hub 和 IoT Hub 到设备的双向通信能力,设备可以使用 基于声明的安全性(CBS)或 简单身份验证和安全层(SASL)进行身份验证。它主要用于存在现场网关的场景,在这些场景中,多个设备关联的单一身份可以将遥测数据传输到云端。
-
MQTT:MQTT 是用于在应用程序之间发送和接收消息的行业标准。它提供设备到 Hub 以及 Hub 到设备的功能。它主要用于每个设备都有自己身份并直接与云进行身份验证的场景。
在下一部分,我们将讨论身份和设备如何进行身份验证。
身份
IoT Hub 提供设备身份验证服务。它提供一个接口,用于为每个设备生成唯一的身份哈希。当设备发送包含哈希的消息时,IoT Hub 可以通过检查其数据库中是否存在该哈希来进行身份验证。接下来,我们将了解数据是如何被捕获的。
捕获
Azure 提供 IoT 网关,使得不符合 IoT Hub 标准的设备能够适配并推送数据。可以在设备附近部署本地或中介网关,使多个设备能够连接到单一网关以捕获并发送它们的信息。同样,可以部署多个设备集群及其本地网关。还可以在云端部署云网关,能够从多个来源捕获和接收数据,并将其摄取到 IoT Hub。正如前面讨论的那样,我们需要摄取我们捕获的数据。在下一部分,你将学习如何使用 IoT Hub 进行数据摄取。
摄取
IoT 中心可以作为设备和其他应用程序的单一接入点。换句话说,IoT 消息的摄取是 IoT Hub 服务的责任。还有其他服务,例如事件中心和服务总线消息传递基础设施,也可以摄取传入的消息;然而,使用 IoT Hub 来摄取 IoT 数据的好处远大于使用事件中心和服务总线消息传递的好处。事实上,IoT Hub 的设计就是为了在 Azure 生态系统内摄取 IoT 消息,以便其他服务和组件可以对其进行处理。摄取的数据被存储到存储中。在进行任何形式的转换或分析之前,我们将在下一部分探讨存储在工作流中的作用。
存储
Azure 提供多种存储 IoT 设备消息的方式。这些方式包括存储关系数据、无模式的 NoSQL 数据和 Blob:
-
SQL 数据库:SQL 数据库提供关系型数据、JSON 和 XML 文档的存储。它提供丰富的 SQL 查询语言,并且使用完整的 SQL 服务器作为服务。如果设备数据定义明确且模式不需要频繁更改,它可以存储在 SQL 数据库中。
-
Azure 存储:Azure 存储提供表格存储和 Blob 存储。表格存储帮助以实体的形式存储数据,其中模式不重要。Blob 存储帮助将文件以 Blob 的形式存储在容器中。
-
Cosmos DB:Cosmos DB 是一个完整的企业级 NoSQL 数据库。它作为一项服务提供,能够存储无模式的数据。它是一个全球分布式数据库,可以跨洲提供数据的高可用性和可扩展性。
-
外部数据源:除了 Azure 服务外,客户还可以使用自己的数据存储,如在 Azure 虚拟机上的 SQL 服务器,并将其用于以关系格式存储数据。
下一部分将讲解转换与分析。
转换与分析
Azure 提供多个资源来执行对输入数据的作业和活动。以下是其中的一些:
-
数据工厂:Azure 数据工厂是一个基于云的数据集成服务,允许我们在云中创建基于数据的工作流,用于协调和自动化数据移动和数据转换。Azure 数据工厂帮助创建和安排基于数据的工作流(称为管道),这些工作流可以从不同的数据存储中提取数据;通过使用计算服务(如 Azure HDInsight、Hadoop、Spark、Azure 数据湖分析、Azure Synapse Analytics 和 Azure 机器学习)处理和转换数据;并将输出数据发布到数据仓库,用于 商业智能 (BI) 应用,而不是传统的 提取-转换-加载 (ETL) 平台。
-
Azure Databricks:Databricks 提供一个完整的、托管的端到端 Spark 环境。它可以通过 Scala 和 Python 帮助进行数据转换。它还提供了一个 SQL 库,使用传统的 SQL 语法来操作数据。它比 Hadoop 环境更具性能。
-
Azure HDInsight:微软和 Hortonworks 联手为公司提供一个大数据分析平台与 Azure 结合使用。HDInsight 是一个由 Apache Hadoop 和 Apache Spark 提供支持的强大、完全托管的云服务环境,利用 Microsoft Azure HDInsight。它帮助通过 Microsoft 和 Hortonworks 的行业领先的大数据云服务无缝加速工作负载。
-
Azure Stream Analytics:这是一个完全托管的实时数据分析服务,帮助对流数据进行计算和转换。Stream Analytics 可以检查来自设备或流程的海量数据,提取数据流中的信息,并寻找模式、趋势和关系。
-
机器学习:机器学习是一种数据科学技术,允许计算机使用现有数据预测未来的行为、结果和趋势。通过机器学习,计算机根据我们创建的模型学习行为。Azure 机器学习是一个基于云的预测分析服务,使得快速创建和部署预测模型成为可能。它提供了一个现成的算法库,可以在连接互联网的 PC 上创建模型并快速部署预测解决方案。
-
Azure Synapse Analytics:前身为 Azure 数据仓库。Azure Synapse Analytics 提供适用于企业数据仓库和大数据分析的分析服务。它支持直接流式数据摄取,并可以与 Azure IoT Hub 集成。
现在,您已经熟悉了 Azure 中用于处理 IoT 设备摄取数据的转换和分析工具,接下来我们来学习如何呈现这些数据。
演示
在对数据进行适当分析后,数据应该以可供利益相关者消费的格式呈现。有多种方式可以呈现数据洞察,包括通过使用 Azure App Service 部署的 Web 应用程序呈现数据,向通知中心发送数据,然后通知移动应用程序等。然而,展示和消费洞察的理想方法是使用 Power BI 报告和仪表板。Power BI 是微软的可视化工具,用于在互联网上呈现动态报告和仪表板。
总结来说,Azure IoT 与物联网架构的基本概念紧密契合。它遵循相同的流程;然而,Azure 赋予我们根据需求选择不同服务和依赖项的自由。在下一节中,我们将重点介绍 Azure IoT Hub,这是一个托管在云中的服务,由 Azure 完全管理。
Azure IoT Hub
物联网项目通常具有较高的复杂性。这种复杂性源于设备和数据的庞大数量。设备遍布全球,例如用于存储数据的监控和审计设备,处理和分析 PB 级数据,并最终根据洞察采取行动。此外,这些项目通常周期长,其需求因时间表的变化而不断变化。
如果企业希望尽早开始物联网项目,它将很快意识到我们提到的问题并非易于解决。这些项目需要足够的计算和存储硬件来应对,并且需要能够处理大量数据的服务。
IoT Hub 是一个旨在实现更快速、更优质、更简便的物联网项目交付的平台。它提供了所有必要的功能和服务,包括以下内容:
-
设备注册
-
设备连接
-
现场网关
-
云网关
-
实现行业协议,如 AMQP 和 MQTT 协议
-
存储传入消息的中心
-
基于消息属性和内容的消息路由
-
用于不同类型处理的多个端点
-
与 Azure 上其他服务的连接,用于实时分析等
我们已经概述了 Azure IoT Hub,现在让我们深入了解协议以及设备如何在 Azure IoT Hub 中注册。
协议
Azure IoT Hub 原生支持通过 MQTT、AMQP 和 HTTP 协议进行通信。在某些情况下,设备或现场网关可能无法使用这些标准协议之一,并需要协议适配。在这种情况下,可以部署自定义网关。Azure IoT 协议网关可以通过桥接流量到 IoT Hub,启用 IoT Hub 端点的协议适配。下一部分将讨论设备如何注册到 Azure IoT Hub。
设备注册
设备在向 IoT Hub 发送消息之前需要进行注册。设备注册可以通过 Azure 门户手动完成,也可以通过 IoT Hub SDK 自动完成。Azure 还提供了示例模拟应用程序,通过这些应用程序,可以轻松地为开发和测试目的注册虚拟设备。此外,还有一个可以作为虚拟设备使用的树莓派在线模拟器,当然,其他可以连接到 IoT Hub 的物理设备也可以进行配置。
如果你想模拟一个通常用于开发和测试目的的本地 PC 设备,可以在 Azure 文档中找到多种语言的教程。这些教程可在docs.microsoft.com/azure/iot-hub/iot-hub-get-started-simulated访问。
树莓派在线模拟器可在docs.microsoft.com/azure/iot-hub/iot-hub-raspberry-pi-web-simulator-get-started访问,对于需要在 IoT Hub 注册的物理设备,应使用docs.microsoft.com/azure/iot-hub/iot-hub-get-started-physical中给出的步骤。
要通过 Azure 门户手动添加设备,IoT Hub 提供了IoT 设备菜单,可以用来配置新设备。选择新建选项将允许你创建一个新设备,如图 17.4所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_17_04.jpg
图 17.4:通过 Azure 门户添加设备
创建设备身份后,应使用 IoT Hub 的主密钥连接字符串将每个设备连接到 IoT Hub:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_17_05.jpg
图 17.5:为每个设备创建连接字符串
在此阶段,设备已成功注册到 IoT Hub,我们的下一个任务是实现设备与 IoT Hub 之间的通信。下一部分将详细介绍如何进行消息管理。
消息管理
设备注册到 IoT Hub 后,就可以开始与其进行交互。消息管理指的是 IoT 设备与 IoT Hub 之间如何进行通信或交互。这种交互可以是设备向云端发送数据,也可以是云端向设备发送数据。
设备到云端消息传递
在这种通信中必须遵循的最佳实践之一是,尽管设备可能会捕获大量信息,但只有那些重要的数据应传输到云端。消息的大小在物联网解决方案中非常重要,因为物联网解决方案通常有非常大的数据量。即使是多出的 1 KB 数据流动,也可能导致浪费 GB 级的存储和处理能力。每条消息都有属性和有效负载;属性定义了消息的元数据。此元数据包含关于设备、标识、标签以及其他有助于路由和识别消息的属性的数据。
设备或云网关应连接到 IoT Hub 以传输数据。IoT Hub 提供可以供设备使用的公共端点,设备可以连接并发送数据。IoT Hub 应作为后端处理的第一个接触点。IoT Hub 能够将这些消息进一步传输并路由到多个服务。默认情况下,消息存储在事件中心中。可以为不同类型的消息创建多个事件中心。设备用来发送和接收数据的内置端点可以在 IoT Hub 中的内置端点选项卡中查看。图 17.6 展示了如何找到内置端点:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_17_06.jpg
图 17.6:创建多个事件中心
消息可以根据消息头和正文属性路由到不同的端点,如图 17.7所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_17_07.jpg
图 17.7:向不同的端点添加新路由
IoT Hub 中的消息默认保存七天,消息的大小可以达到 256 KB。
微软提供了一个示例模拟器,用于模拟将消息发送到云端。它支持多种语言;可以在 docs.microsoft.com/azure/iot-hub/iot-hub-csharp-csharp-c2d 查看 C# 版本。
云端到设备消息传递
IoT Hub 是一个托管服务,提供双向消息传递基础设施。消息可以从云端发送到设备,然后设备根据消息执行相应操作。
有三种类型的云端到设备消息传递模式:
-
直接方法需要立即确认结果。直接方法通常用于设备的互动控制,例如开关车库百叶窗。它们遵循请求-响应模式。
-
使用 Azure 物联网设置设备属性时,提供 设备双胞胎 属性。例如,您可以将遥测发送间隔设置为 30 分钟。设备双胞胎是存储设备状态信息的 JSON 文档(例如元数据、配置和条件)。物联网中心为每个设备在物联网中心中持久化一个设备双胞胎。
-
云到设备的消息用于单向通知设备应用程序。此模式遵循“发送后忘记”模式。
在每个组织中,安全性都是一个重要问题,即使是在物联网设备和数据的情况下,这个问题依然存在。我们将在下一部分讨论安全性。
安全性
安全性是基于物联网的应用程序中的一个重要方面。基于物联网的应用程序包括使用公共互联网进行连接的设备,这些设备连接到后端应用程序。保护设备、后端应用程序及连接免受恶意用户和黑客攻击应被视为这些应用程序成功的首要任务。
物联网中的安全性
物联网应用程序主要围绕互联网构建,安全性在确保解决方案不被妥协方面起着至关重要的作用。影响物联网架构的一些重要安全决策列举如下:
-
关于使用 HTTP 和 HTTPS REST 端点的设备,受到证书保护的 REST 端点可确保从设备到云端及其反向传输的消息得到良好的加密和签名。这些消息对于入侵者来说应该毫无意义,并且极难破解。
-
如果设备连接到本地网关,则本地网关应使用安全的 HTTP 协议连接到云端。
-
设备必须先注册到物联网中心,才能发送任何消息。
-
传递到云端的信息应存储在受保护和安全的存储中。应使用存储在 Azure Key Vault 中的适当 SAS 令牌或连接字符串进行连接。
-
应使用 Azure Key Vault 存储所有的机密、密码和凭证,包括证书。
-
Azure 安全中心 for IoT 提供针对每个设备、IoT Edge 和 IoT Hub 的威胁防护和分析,涵盖您的物联网资产。我们可以根据安全评估在 Azure 安全中心中构建自己的仪表板。一些关键功能包括来自 Azure 安全中心的集中管理、自适应威胁保护和智能威胁检测。在实施安全的物联网解决方案时,考虑使用 Azure 安全中心是一种最佳实践。
接下来,我们将探讨物联网中心(IoT Hub)的可扩展性方面。
可扩展性
物联网中心的可扩展性与其他服务略有不同。在物联网中心,有两种类型的消息:
-
传入:设备到云的消息
-
传出:云到设备的消息
两者在可扩展性方面都需要考虑。
IoT Hub 在配置时提供了一些选项来配置可扩展性。这些选项在配置后也可用,可以更新以更好地满足解决方案的可扩展性要求。
IoT Hub 提供的可扩展性选项如下:
-
库存单位(SKU)版本,即 IoT Hub 的大小
-
单位数量
我们将首先查看 SKU 版本选项。
SKU 版本
IoT Hub 中的 SKU 决定了每个单位每天能处理的消息数量,包括入站和出站消息。共有四个层级,具体如下:
-
免费版:此版本允许每个单位每天处理 8,000 条消息,并支持双向消息(入站和出站)。最多可配置 1 个单位。此版本适用于熟悉和测试 IoT Hub 服务的功能。
-
标准版 (S1):此版本允许每个单位每天处理 400,000 条消息,并支持双向消息(入站和出站)。最多可配置 200 个单位。此版本适用于少量消息。
-
标准版 (S2):此版本允许每个单位每天处理 600 万条消息,并支持双向消息(入站和出站)。最多可配置 200 个单位。此版本适用于大量消息。
-
标准版 (S3):此版本允许每个单位每天处理 3 亿条消息,并支持双向消息(入站和出站)。最多可配置 10 个单位。此版本适用于非常大量的消息。
升级和扩展选项可以在 Azure 门户中的 IoT Hub 定价和规模 页面找到。这些选项将以 图 17.8 所示的形式展示给您:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_17_08.jpg
图 17.8:选择定价和规模层级
您可能会注意到,标准版 S3 层级最多只允许 10 个单位,而其他标准层级则允许 200 个单位。这与为运行 IoT 服务所配置的计算资源的大小直接相关。标准版 S3 的虚拟机的大小和能力远高于其他层级,而其他层级的大小保持不变。
单位
单位定义了每个 SKU 在服务后端运行的实例数量。例如,2 个 标准版 S1 SKU 单位意味着 IoT Hub 每天可以处理 400K * 2 = 800K 消息。
增加单位数量将提高应用程序的可扩展性。图 17.9 来自 IoT Hub 的 定价和规模 页面,您可以在其中看到当前的定价层级和单位数量:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_17_09.jpg
图 17.9:调整或迁移 IoT Hub 单位的选项
目前在 Azure IoT Hub 中蓬勃发展的服务之一是 Azure IoT Edge,它是一个完全托管的服务,建立在 Azure IoT Hub 之上。我们将在下一部分探讨什么是 Azure IoT Edge。
Azure IoT Edge
Microsoft Azure IoT Edge 利用边缘计算实现物联网解决方案。边缘计算是指您本地网络上可用的计算资源,位于网络的末端,公共互联网开始的地方。可以将其部署在您的主网络或具有防火墙隔离的来宾网络上。
Azure IoT Edge 包括 IoT Edge 运行时,需要安装在计算机或设备上。Docker 将安装在计算机上;计算机可以运行 Windows 或 Linux。Docker 的作用是运行 IoT Edge 模块。
Azure IoT Edge 依赖于混合云概念,您可以在本地硬件上部署和管理物联网解决方案,并轻松将其与 Microsoft Azure 集成。
Microsoft 为 Azure IoT Edge 提供了全面的文档,包括快速入门模板和安装模块的指导。文档链接是docs.microsoft.com/azure/iot-edge。
在下一部分,我们将了解在 Azure IoT Hub 的情况下,如何管理基础设施以及如何为客户提供高可用性。
高可用性
IoT Hub 是 Azure 提供的平台即服务(PaaS)产品。客户和用户不会直接与运行 IoT Hub 服务的虚拟机的数量和大小进行交互。用户决定地区、IoT Hub 的 SKU 和其应用程序所需的单位数量。其余配置由 Azure 在后台确定并执行。Azure 确保每个 PaaS 服务默认是高度可用的。它通过确保多个虚拟机在数据中心内的不同机架上提供服务,从而实现这一点。通过将这些虚拟机放置在可用性集中,并置于单独的故障域和更新域中,Azure 确保了计划内和计划外维护的高可用性。可用性集确保了数据中心级别的高可用性。
在下一部分,我们将讨论 Azure IoT Central。
Azure IoT Central
Azure IoT Central 提供了一个平台,用于构建企业级物联网应用程序,以安全、可靠和可扩展的方式满足您的业务需求。IoT Central 消除了开发、维护和管理物联网解决方案的成本。
IoT Central 提供集中管理,您可以管理和监控设备、设备状态、规则创建和设备数据。在图 17.10中,您可以看到在创建 IoT Central 应用程序时,Azure 门户中可用的一些模板:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_17_10.jpg
图 17.10 创建 Azure IoT Central 应用程序
模板将为您提供一个起点,您可以根据需求进行自定义。这将在开发阶段为您节省大量时间。
IoT Central 在撰写时提供七天的试用期,您可以在这里查看该服务的定价:azure.microsoft.com/pricing/details/iot-central/?rtc=1。
Azure IoT Central 对于每个开发 IoT 应用程序的组织来说都是一项福音。
总结
IoT 是本十年最大的新兴技术之一,已经开始颠覆各行各业。曾经看似不可能的事情,现在突然变得可能。
本章中,我们探讨了 IoT Hub,并讨论了如何以比其他解决方案更快、更好、更便宜的方式将 IoT 解决方案交付给客户。我们还介绍了 IoT 如何加速整个开发生命周期,帮助公司缩短上市时间。最后,您了解了 Azure IoT Edge 和 Azure IoT Central。
为了帮助您有效分析日益增长的数据量,我们将在下一章讨论 Azure Synapse Analytics。
17. 设计 IoT 解决方案
第十八章:18. Azure Synapse Analytics for architects
Azure Synapse Analytics 是 Azure SQL Data Warehouse 的一个突破性进化。Azure Synapse 是一个完全托管的集成数据分析服务,将数据仓库、数据集成和大数据处理与加速洞察时间结合,形成一个单一的服务。
在本章中,我们将通过以下主题来探索 Azure Synapse Analytics:
-
Azure Synapse Analytics 概述
-
介绍 Synapse 工作区和 Synapse Studio
-
从现有的遗留系统迁移到 Azure Synapse Analytics
-
将现有的数据仓库模式和数据迁移到 Azure Synapse Analytics
-
使用 Azure Data Factory 重新开发可扩展的 ETL 流程
-
常见的迁移问题及解决方案
-
安全性考虑
-
帮助迁移到 Azure Synapse Analytics 的工具
Azure Synapse Analytics
如今,由于存储便宜且具有高弹性存储能力,组织正在比以往任何时候都要积累更多的数据。设计一个解决方案来分析如此庞大的数据量,以提供有关业务的有意义的洞察可能是一个挑战。许多企业面临的一个障碍是需要管理和维护两种类型的分析系统:
-
数据仓库:这些提供了关于业务的重要洞察。
-
数据湖:这些通过各种分析方法提供有关客户、产品、员工和流程的有意义的洞察。
这两个分析系统对企业至关重要,但它们是独立运行的。同时,企业需要从所有组织数据中获得洞察,以保持竞争力并创新流程,以获取更好的结果。
对于需要构建端到端数据管道的架构师,必须采取以下步骤:
-
从各种数据源中摄取数据。
-
将所有这些数据源加载到数据湖中进行进一步处理。
-
对不同数据结构和类型的数据进行清理。
-
准备、转换和建模数据。
-
通过 BI 工具和应用程序将清洗后的数据提供给成千上万的用户。
直到现在,每个步骤都需要不同的工具。不言而喻,市场上有如此多不同的服务、应用程序和工具,选择最适合的工具可能是一个令人畏惧的任务。
有许多可用于摄取、加载、准备和提供数据的服务。有无数基于开发人员所选择的语言的数据清洗服务。此外,一些开发人员可能更倾向于使用 SQL,一些可能希望使用 Spark,而其他人可能更喜欢使用无代码环境来转换数据。
即使选择了看似合适的工具,使用这些工具时仍然常常会面临陡峭的学习曲线。此外,由于不兼容,建筑师可能会遇到在不同平台和语言上维护数据管道时出现的意外后勤挑战。面对如此多的问题,实施和维护基于云的分析平台可能是一个困难的任务。
Azure Synapse Analytics 解决了这些问题及更多问题。它简化了整个现代数据仓库模式,使建筑师能够专注于在统一的环境中构建端到端的分析解决方案。
建筑师常见的场景
建筑师面临的最常见场景之一是制定迁移现有传统数据仓库解决方案到现代企业分析解决方案的计划。凭借无限的可扩展性和统一的体验,Azure Synapse 已成为许多建筑师考虑的首选。稍后在本章中,我们还将讨论从现有传统数据仓库解决方案迁移到 Azure Synapse Analytics 的常见架构考虑因素。
在接下来的部分中,我们将提供 Azure Synapse Analytics 关键特性技术概述。对于新接触 Azure Synapse 生态系统的建筑师来说,阅读本章后他们将获得关于 Synapse 所需的知识。
Azure Synapse Analytics 概述
Azure Synapse Analytics 使数据专业人员能够构建端到端的分析解决方案,同时利用统一的体验。它为 SQL 开发人员提供丰富的功能、无服务器按需查询、机器学习支持、原生嵌入 Spark、协作笔记本和数据集成等功能,且都集中在一个服务中。开发人员可以通过不同的引擎选择多种支持的语言(例如 C#、SQL、Scala 和 Python)。
Azure Synapse Analytics 的主要功能包括:
-
SQL 分析与池(完全配置)和按需(无服务器)。
-
完全支持 Python、Scala、C# 和 SQL 的 Spark。
-
数据流与无需编码的大数据转换体验。
-
数据集成与编排,实现数据集成并使代码开发过程自动化。
-
由 Azure Synapse Link 提供的云原生混合事务/分析处理(HTAP)版本。
为了访问上述所有功能,Azure Synapse Studio 提供了一个统一的网页 UI。
这个单一集成的数据服务对企业非常有利,因为它加速了 BI、AI、机器学习、物联网和智能应用的交付。
Azure Synapse Analytics 可以以极快的速度从数据仓库和大数据分析系统中获取并提供所有数据的洞察。它使数据专业人员能够使用熟悉的语言,如 SQL,来查询关系型和非关系型数据库,支持 PB 级别的数据规模。此外,诸如无限并发、智能工作负载管理和工作负载隔离等高级功能帮助优化所有关键工作负载查询的性能。
什么是工作负载隔离?
在大规模运行企业数据仓库的关键特性之一是工作负载隔离。这是指确保在计算集群中预留资源,使多个团队可以在数据上工作而互不干扰,如图 18.1所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_18_01.jpg
图 18.1:工作负载隔离示例
你可以通过设置几个简单的阈值在集群中创建工作负载组。这些阈值会根据工作负载和集群的不同自动调整,但它们始终能确保用户运行工作负载时获得优质的体验。有关在 Azure Synapse Analytics 中配置工作负载隔离的更多信息,请参考techcommunity.microsoft.com/t5/data-architecture-blog/configuring-workload-isolation-in-azure-synapse-analytics/ba-p/1201739。
为了充分理解 Azure Synapse 的优势,我们首先来看看 Synapse 工作区和 Synapse Studio。
Synapse 工作区和 Synapse Studio 介绍
Azure Synapse 的核心是工作区。工作区是数据仓库中构建分析解决方案的顶级资源。Synapse 工作区同时支持关系型和大数据处理。
Azure Synapse 提供一个统一的 Web UI,供数据准备、数据管理、数据仓库、大数据分析、商业智能(BI)和人工智能(AI)任务使用,这个界面被称为 Synapse Studio。与 Synapse 工作区一起,Synapse Studio 是数据工程师和数据科学家共享和协作分析解决方案的理想环境,如图 18.2所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_18_02.jpg
图 18.2:Azure Synapse Studio 中的 Synapse 工作区
以下部分将重点介绍 Synapse 工作区和 Synapse Studio 的功能、关键特性、平台细节和最终用户服务:
功能:
-
一个快速、高度弹性且安全的数据仓库,具备行业领先的性能和安全性
-
使用 SQL 按需(无服务器)和 SQL 查询,能够通过熟悉的 T-SQL 语法来探索 Azure Data Lake 存储和数据仓库
-
Apache Spark 集成 Azure 机器学习
-
混合数据集成,旨在加速数据摄取和分析过程的操作化(摄取、准备、转换和服务)
-
与 Power BI 集成的商业报告生成和提供服务。
关键特性:
-
创建和操作数据摄取与编排的管道。
-
直接通过 Synapse Studio 探索 Azure Data Lake Storage 或数据仓库中的数据,以及任何外部连接到工作区的数据。
-
使用笔记本和 T-SQL 查询编辑器编写代码。
-
无需编写代码的数据转换工具,如果你不想自己编写代码。
-
监控、保护并管理你的工作区,无需离开环境。
-
面向整个分析解决方案的基于 Web 的开发体验。
-
Azure Synapse SQL 池中的备份和恢复功能允许创建恢复点,使得恢复或将数据仓库复制到先前状态变得更加简单。
-
通过 SQL 池在数 PB 的数据上并行运行 T-SQL 查询,以服务 BI 工具和应用程序。
-
按需 SQL 提供无服务器 SQL 查询,方便在 Azure Data Lake Storage 中进行数据探索和分析,无需任何基础设施的设置或维护。
-
满足从数据工程到数据科学的全方位分析需求,支持多种语言,如 Python、Scala、C#和 Spark SQL。
-
Spark 池简化了集群的复杂设置和维护,并简化了 Spark 应用程序的开发和 Spark 笔记本的使用。
-
提供 Spark 和 SQL 之间的深度集成,允许数据工程师在 Spark 中准备数据,将处理结果写入 SQL 池,并结合使用 Spark 和 SQL 进行数据工程和分析,内置支持 Azure Machine Learning。
-
高度可扩展的混合数据集成功能,通过自动化的数据管道加速数据摄取和操作化。
-
提供无摩擦的集成服务,统一的安全性、部署、监控和计费。
平台
-
支持配置计算和无服务器计算。配置计算的示例包括 SQL 计算和 Spark 计算。
-
配置的计算资源允许团队将计算资源分割,以便控制成本和使用情况,更好地与组织结构对齐。
-
另一方面,无服务器计算允许团队按需使用服务,而无需配置或管理任何底层基础设施。
-
Spark 和 SQL 引擎之间的深度集成。
在以下部分,我们将介绍 Azure Synapse 的其他功能,包括 Synapse 的 Apache Spark、Synapse SQL、按需 SQL、Synapse 管道和 Azure Synapse Link for Cosmos DB。
Synapse 的 Apache Spark
对于需要 Apache Spark 的客户,Azure Synapse 通过 Azure Databricks 提供第一方支持,并由 Azure 完全管理。Apache Spark 的最新版本将自动提供给用户,并包含所有安全补丁。你可以快速创建带有你选择的语言的笔记本,如 Python、Scala、Spark SQL 和.NET for Spark。
如果您在 Azure Synapse Analytics 中使用 Spark,它将作为一种软件即服务(SaaS)提供。例如,您可以在不设置或管理自己的服务(如虚拟网络)的情况下使用 Spark。Azure Synapse Analytics 将为您处理底层基础设施。这使您能够立即在 Azure Synapse Analytics 环境中使用 Spark。
在接下来的部分中,我们将探讨 Synapse SQL。
Synapse SQL
Synapse SQL 允许使用 T-SQL 查询和分析数据。有两种模型可供选择:
-
完全配置的模型
-
按需 SQL(无服务器)模型
按需 SQL
按需 SQL 提供无服务器 SQL 查询。这使得在 Azure 数据湖存储中更容易进行探索和数据分析,而无需任何设置或基础设施维护:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_18.1.jpg
表 18.1:不同基础设施的比较
关键特性:
-
分析师可以专注于分析数据,而无需担心管理任何基础设施。
-
客户可以受益于简单灵活的定价模型,因为他们只需为实际使用的部分付费。
-
它使用熟悉的 T-SQL 语言语法和市场上最好的 SQL 查询优化器。SQL 查询优化器是查询引擎背后的大脑。
-
随着需求的增长,您可以独立地扩展计算和存储资源。
-
通过元数据同步和本地连接器与 SQL Analytics Pool 和 Spark 无缝集成。
Synapse 管道
Synapse 管道允许开发人员构建端到端的数据移动和数据处理工作流。Azure Synapse Analytics 使用Azure 数据工厂(ADF)技术提供数据集成功能。ADF 中的关键功能对于现代数据仓库管道至关重要,并且这些功能也在 Azure Synapse Analytics 中可用。所有这些功能都通过 Azure Synapse Analytics 工作区中的统一安全模型基于角色的访问控制(RBAC)进行封装。
图 18.3 展示了一个数据管道的示例以及直接集成在 Azure Synapse Analytics 环境中的 ADF 活动:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_18_03.jpg
图 18.3:Azure Synapse Analytics 中的数据管道
关键特性:
-
用于管理、安全、监控和元数据管理的集成平台服务。
-
Spark 与 SQL 之间的本地集成。使用一行代码从/向 SQL Analytics 读取和写入 Spark 数据。
-
可以创建一个 Spark 表并使用 SQL Analytics 即时查询,而无需定义模式。
-
"免密钥"环境。通过单点登录和 Azure Active Directory 透传,无需密钥或登录即可与Azure 数据湖存储(ADLS)/数据库进行交互。
在接下来的部分中,我们将介绍 Azure Synapse Link for Cosmos DB。
Azure Synapse Link for Cosmos DB
Azure Synapse Link 是 HTAP 的云原生版本。它是 Azure Synapse 的扩展。正如我们之前所了解的,Azure Synapse 是一个用于对数据湖和数据仓库进行分析的单一托管服务,采用无服务器和预配计算方式。通过 Azure Synapse Link,这一覆盖面也可以扩展到操作性数据源。
Azure Synapse Link 消除了传统操作和分析系统中的瓶颈。Azure Synapse 通过在其所有数据服务中将计算与存储分离,使这一切成为可能。在事务处理方面,Cosmos DB 是一个高性能、地理复制的多模型数据库服务。在分析方面,Azure Synapse 提供无限的可扩展性。您可以独立地为事务和分析扩展资源。两者结合起来,使得云原生 HTAP 成为现实。一旦用户指明希望在 Cosmos DB 中提供的分析数据,该数据便会出现在 Synapse 中。它会自动将您希望分析的操作数据转化为面向分析的列式版本。因此,Cosmos DB 中对操作数据的任何更改都会持续更新到 Link 数据和 Synapse 中。
使用 Azure Synapse Link 的最大好处是,它消除了对计划性批处理或需要构建和维护操作管道的需求。
如前所述,Azure Synapse 是架构师在将现有遗留数据仓库解决方案迁移到现代企业分析解决方案时最常选择的平台。在下一节中,我们将讨论从现有遗留数据仓库解决方案迁移到 Azure Synapse Analytics 的常见架构考虑事项。
从现有遗留系统迁移到 Azure Synapse Analytics
如今,许多组织正在将其遗留数据仓库解决方案迁移到 Azure Synapse Analytics,以便获得 Azure Synapse 提供的高可用性、安全性、速度、可扩展性、成本节省和性能等好处。
对于使用遗留数据仓库系统(如 Netezza)的公司来说,情况更加严峻,因为 IBM 已宣布终止对 Netezza 的支持 (www.ibm.com/support/pages/end-support-dates-netezza-5200-netezza-8x50z-series-and-netezza-10000-series-appliances)。
许多年前,一些公司选择了 Netezza 来管理和分析大量数据。今天,随着技术的进步,基于云的数据仓库解决方案的好处远远超过了本地解决方案。Azure Synapse 是一个无限制的云分析服务,具有无与伦比的洞察时间,能够加速为企业提供商业智能、人工智能和智能应用程序。凭借其多集群和分离的计算与存储架构,Azure Synapse 可以以传统系统(如 Netezza)无法做到的方式即时扩展。
本节涵盖了规划、准备和执行将现有传统数据仓库系统成功迁移到 Azure Synapse Analytics 的架构考虑因素和高层次方法论。适当时,将给出一些具体示例并引用 Netezza。本章并不打算成为一个全面的逐步迁移手册,而是一个实用的概述,帮助你进行迁移规划和项目范围界定。
本章还识别了一些常见的迁移问题及其可能的解决方案。还提供了关于 Netezza 和 Azure Synapse Analytics 之间差异的技术细节。它们应该作为迁移计划的一部分加以考虑。
为什么你应该将传统数据仓库迁移到 Azure Synapse Analytics
通过迁移到 Azure Synapse Analytics,使用传统数据仓库系统的公司可以利用云技术的最新创新,并将基础设施维护和平台升级等任务委托给 Azure。
已经迁移到 Azure Synapse 的客户,已经获得了许多好处,包括以下内容。
性能
Azure Synapse Analytics 通过使用大规模并行处理(MPP)和自动内存缓存等技术,提供了最佳的关系数据库性能。如需更多信息,请查看 Azure Synapse Analytics 架构(docs.microsoft.com/azure/synapse-analytics/sql-data-warehouse/massively-parallel-processing-mpp-architecture)。
速度
数据仓库是一个处理密集型的过程。它涉及数据摄取、数据转化、数据清洗、数据聚合、数据集成以及数据可视化和报告的生成。将数据从原始来源转移到数据仓库的许多过程是复杂且相互依赖的。单一的瓶颈可能会减缓整个流程,而数据量的突增则加大了对速度的需求。当数据的时效性至关重要时,Azure Synapse Analytics 满足了对快速处理的需求。
提高的安全性和合规性
Azure 是一个全球可用、高度可扩展、安全的云平台。它提供许多安全功能,包括 Azure Active Directory、RBAC、托管身份和托管私有端点。Azure Synapse Analytics 位于 Azure 生态系统内,继承了所有上述的好处。
弹性和成本效率
在数据仓库中,工作负载处理的需求可能会波动。有时,这些波动可能在峰值和谷值之间有很大差异。例如,假期季节时,销售数据量可能会突然激增。云的弹性使得 Azure Synapse 能够根据需求快速增加或减少其容量,而不会影响基础设施的可用性、稳定性、性能和安全性。最棒的是,您只需为实际使用量付费。
托管基础设施
消除数据中心管理和运营的开销,使公司能够将宝贵的资源重新分配到创造价值的地方,专注于使用数据仓库提供最佳的信息和洞察力。这降低了总体拥有成本,并提供了更好的运营费用控制。
可扩展性
数据仓库中的数据量通常随着时间的推移和历史数据的积累而增长。Azure Synapse Analytics 可以通过根据数据和工作负载的增加逐步添加资源来扩展以应对这种增长。
节省成本
运营本地遗留数据中心成本高昂(考虑到服务器和硬件、网络、物理空间、电力、冷却和人员成本)。这些费用可以通过 Azure Synapse Analytics 显著减少。由于计算和存储层的分离,Azure Synapse 提供了非常有吸引力的性价比。
Azure Synapse Analytics 为您提供真正的按需付费云可扩展性,随着数据或工作负载的增长,无需复杂的重新配置。
现在您已经了解了迁移到 Azure Synapse Analytics 的好处,我们将开始讨论迁移过程。
三步迁移过程
一个成功的数据迁移项目始于一个精心设计的计划。有效的计划考虑到需要考虑的众多组件,特别关注架构和数据准备。以下是三步迁移过程计划。
准备工作
-
定义要迁移的范围。
-
创建数据和迁移过程的清单。
-
定义数据模型的变化(如果有的话)。
-
定义源数据提取机制。
-
确定适用的 Azure(和第三方)工具和服务。
-
尽早对员工进行新平台的培训。
-
设置 Azure 目标平台。
迁移
-
从小规模、简单的项目开始。
-
尽可能进行自动化。
-
利用 Azure 内置的工具和功能来减少迁移工作量。
-
迁移表格和视图的元数据。
-
迁移需要维护的历史数据。
-
迁移或重构存储过程和业务流程。
-
迁移或重构 ETL/ELT 增量加载流程。
迁移后
-
监控并记录过程的所有阶段。
-
利用获得的经验为未来的迁移构建模板。
-
如有需要,重新设计数据模型。
-
测试应用程序和查询工具。
-
基准测试和优化查询性能。
接下来,我们将讨论这两种迁移策略。
两种迁移策略
架构师应通过评估现有数据仓库来开始迁移规划,以确定哪种迁移策略最适合他们的情况。需要考虑两种迁移策略。
提升和迁移策略
对于“提升和迁移”策略,现有数据模型不做更改地迁移到新的 Azure Synapse Analytics 平台。这种做法旨在通过将变更的范围缩小到最低限度,最大程度地减少迁移的风险和所需时间。
“提升和迁移”是一种适用于遗留数据仓库环境(如 Netezza)的良好策略,特别是在以下任一条件成立时:
-
一个单独的数据集市需要迁移。
-
数据已经采用了良好的星型或雪花型架构。
-
移动到现代云环境面临着迫切的时间和成本压力。
重新设计策略
在遗留数据仓库经过一段时间的演变后,可能需要重新设计,以维持最佳的性能水平或支持新类型的数据。这可能包括改变底层数据模型。
为了最小化风险,建议首先使用“提升和迁移”策略进行迁移,然后逐步在 Azure Synapse Analytics 上使用重新设计策略现代化数据仓库数据模型。完全改变数据模型会增加风险,因为这会影响源到数据仓库的 ETL 作业以及下游的数据集市。
在下一节中,我们将提供一些关于如何在迁移前减少现有遗留数据仓库复杂性的建议。
在迁移前减少现有遗留数据仓库的复杂性
在上一节中,我们介绍了两种迁移策略。作为最佳实践,在初步评估步骤中,务必留意任何简化现有数据仓库的方法并记录下来。目标是在迁移前减少现有遗留数据仓库系统的复杂性,以便简化迁移过程。
这里是一些关于如何减少现有遗留数据仓库复杂性的建议:
-
迁移前删除并归档未使用的表:避免迁移不再使用的数据。这将有助于减少迁移的数据总量。
-
将物理数据集市转换为虚拟数据集市:最大限度地减少需要迁移的内容,降低总体拥有成本,提高灵活性。
在下一节中,我们将详细讨论为什么你应该考虑将物理数据集市转换为虚拟数据集市。
将物理数据集市转换为虚拟数据集市
在迁移遗留数据仓库之前,考虑将当前的物理数据集市转换为虚拟数据集市。通过使用虚拟数据集市,您可以消除物理数据存储和数据集市的 ETL 作业,而不会在迁移前失去任何功能。这里的目标是减少要迁移的数据存储数量,减少数据副本,降低总拥有成本,并提高灵活性。为此,您需要在迁移数据仓库之前,将物理数据集市转换为虚拟数据集市。我们可以将其视为迁移前的数据仓库现代化步骤。
物理数据集市的缺点
-
相同数据的多个副本
-
更高的总拥有成本
-
难以更改,因为 ETL 作业会受到影响
虚拟数据集市的优点
-
简化数据仓库架构
-
无需存储数据副本
-
更高的灵活性
-
更低的总拥有成本
-
使用下推优化技术,利用 Azure Synapse Analytics 的强大功能
-
易于变更
-
容易隐藏敏感数据
在下一节中,我们将讨论如何将现有数据仓库模式迁移到 Azure Synapse Analytics。
将现有数据仓库模式迁移到 Azure Synapse Analytics
迁移现有遗留数据仓库的模式涉及到现有暂存表、遗留数据仓库和相关数据集市模式的迁移。
为了帮助您理解模式迁移的规模和范围,我们建议您先创建现有遗留数据仓库和数据集市的清单。
以下是帮助您收集必要信息的清单:
-
行数
-
暂存、数据仓库和数据集市的数据大小:表和索引
-
数据压缩比
-
当前硬件配置
-
表(包括分区):识别小的维度表
-
数据类型
-
视图
-
索引
-
对象依赖
-
对象使用情况
-
功能:包括现成的函数和用户自定义函数(UDFs)
-
存储过程
-
可扩展性要求
-
增长预测
-
工作负载要求:并发用户
完成清单后,您可以决定要迁移哪个模式。基本上,对于遗留数据仓库模式迁移,您有四个选择:
-
一次迁移一个数据集市:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_18_04.jpg
图 18.4:一次迁移一个数据集市
-
一次性迁移所有数据集市,然后是数据仓库:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_18_05.jpg
图 18.5:一次迁移所有数据集市,然后是数据仓库
-
同时迁移数据仓库和暂存区:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_18_06.jpg
图 18.6:同时迁移数据仓库和暂存区
-
一次性迁移所有内容:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_18_07.jpg
图 18.7:一次性迁移所有内容
在选择迁移选项时,请记住目标是实现一个物理数据库设计,该设计在性能上能够匹配或超过您当前遗留数据仓库系统的性能,并且最好以更低的成本实现。
总结一下,以下是一些关于模式迁移的建议:
-
避免迁移不必要的对象或过程。
-
考虑使用虚拟数据集市,以减少或消除物理数据集市的数量。
-
尽可能实现自动化。在迁移到 Azure Synapse 时,应考虑实施 DataOps。
-
使用遗留数据仓库系统中的系统目录表元数据来生成 Azure Synapse Analytics 的 数据定义语言(DDL)。
-
在 Azure Synapse Analytics 上执行任何必要的数据模型更改或数据映射优化。
在下一节中,我们将讨论如何将历史数据从遗留数据仓库迁移到 Azure Synapse Analytics。
将历史数据从遗留数据仓库迁移到 Azure Synapse Analytics
一旦确定了模式迁移的范围,我们就可以开始决定如何迁移历史数据。
迁移历史数据的步骤如下:
-
在 Azure Synapse Analytics 上创建目标表。
-
迁移现有的历史数据。
-
根据需要迁移功能和存储过程。
-
迁移增量加载(ETL/ELT)暂存和处理即将到来的数据。
-
根据需要应用任何性能调优选项。
表 18.2 概述了四种数据迁移选项及其优缺点:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_18.2.jpg
表 18.2:数据迁移选项及其优缺点
在下一节中,我们将讨论如何将现有的 ETL 过程迁移到 Azure Synapse Analytics。
将现有 ETL 过程迁移到 Azure Synapse Analytics
有多种选项可用于将现有的 ETL 过程迁移到 Azure Synapse Analytics。表 18.3 概述了一些基于现有 ETL 作业构建方式的 ETL 迁移选项:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_18.3.jpg
表 18.3:ETL 迁移选项
在下一节中,我们将讨论如何使用 ADF 重新开发可扩展的 ETL 过程。
使用 ADF 重新开发可扩展的 ETL 过程
处理现有遗留 ETL 过程的另一种选择是通过使用 ADF 重新开发它们。ADF 是 Azure 的数据集成服务,用于创建数据驱动的工作流(称为管道),以协调和自动化数据移动和数据转换。您可以使用 ADF 创建并安排管道,从不同的数据存储中提取数据。ADF 可以通过使用计算服务(如 Spark、Azure 机器学习、Azure HDInsight Hadoop 和 Azure 数据湖分析)来处理和转换数据:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Image74376.jpg
图 18.8:使用 ADF 重新开发可扩展的 ETL 过程
下一节将提供一些关于迁移查询、BI 报告、仪表板和其他可视化的建议。
关于迁移查询、BI 报告、仪表板和其他可视化的建议
如果旧版系统使用标准 SQL,从旧版数据仓库迁移查询、BI 报告、仪表板和其他可视化到 Azure Synapse Analytics 是直接的。
然而,通常情况下并非如此。在这种情况下,必须采取不同的策略:
-
确定优先迁移的报告。
-
使用使用情况统计数据来识别从未使用的报告。
-
避免迁移任何不再使用的内容。
-
一旦你列出了要迁移的报告、它们的优先级以及要跳过的未使用报告,请与相关方确认该列表。
-
对于正在迁移的报告,及早识别不兼容问题,以评估迁移工作量。
-
考虑使用数据虚拟化,以保护 BI 工具和应用程序免受在迁移过程中可能发生的数据仓库和/或数据集市数据模型结构变化的影响。
常见迁移问题及解决方案
在迁移过程中,你可能会遇到一些需要克服的问题。在本节中,我们将突出一些常见问题,并为你提供可以实施的解决方案。
问题 #1:不支持的数据类型及解决方法
表 18.4 显示了旧版数据仓库系统中不支持的数据类型,以及 Azure Synapse Analytics 的适用解决方法:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_18.4.jpg
表 18.4:Azure Synapse Analytics 中不支持的数据类型及适用的解决方法
问题 #2:Netezza 和 Azure Synapse 之间的数据类型差异
表 18.5 将 Netezza 数据类型映射到其 Azure Synapse 对应的数据类型:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_18.5.jpg
表 18.5:Netezza 数据类型及其 Azure Synapse 对应类型
问题 #3:完整性约束差异
密切关注你的旧版数据仓库或数据集市与 Azure Synapse Analytics 之间的完整性约束差异。在图 18.9中,左侧表示带有主键和外键约束的旧版数据仓库系统,右侧是新的 Azure Synapse Analytics 环境:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Image74470.jpg
图 18.9:完整性约束差异
下一节将全面介绍在从旧版数据仓库迁移到 Azure Synapse Analytics 过程中如何解决其他常见的 SQL 不兼容问题。
常见 SQL 不兼容问题及解决方案
本节将提供有关传统数据仓库系统与 Azure Synapse Analytics 之间常见 SQL 不兼容性及其解决方案的技术细节。本节将解释并比较这些差异,并通过一个快速参考表提供解决方案,供您在开始迁移项目时参考。
我们将涵盖的主题如下:
-
SQL 数据定义语言 (DDL) 差异与解决方案
-
SQL 数据操作语言 (DML) 差异与解决方案
-
SQL 数据控制语言 (DCL) 差异与解决方案
-
扩展 SQL 差异与解决方法
SQL DDL 差异与解决方案
在本节中,我们将讨论传统数据仓库系统与 Azure Synapse Analytics 之间 SQL DDL 的差异与解决方案。
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_18.6.jpg
表 18.6:传统系统与 Azure Synapse 之间的 SQL DDL 差异
SQL DML 差异与解决方案
在本节中,我们将讨论传统数据仓库系统与 Azure Synapse Analytics 之间 SQL DML 的差异及其解决方案:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_18.7.jpg
表 18.7:Netezza 与 Azure Synapse 之间的 SQL DML 差异
接下来,我们将讨论传统数据仓库系统与 Azure Synapse Analytics 之间 SQL DCL 的差异与解决方案。
SQL DCL 差异与解决方案
在本节中,我们将讨论传统数据仓库系统与 Azure Synapse Analytics 之间 SQL DCL 的差异与解决方案。Netezza 支持两类访问权限:管理权限和对象权限。表 18.8 映射了 Netezza 访问权限及其对应的 Azure Synapse 权限,供快速参考。
将 Netezza 管理权限映射到 Azure Synapse 对应权限
表 18.8 映射了 Netezza 管理权限与 Azure Synapse 对应权限:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_18.8A.jpghttps://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_18.8B.jpg
表 18.8:Netezza 管理权限及其 Azure Synapse 对应权限
将 Netezza 对象权限映射到其 Azure Synapse 对应权限
表 18.9 映射了 Netezza 对象权限与 Azure Synapse 对应权限,供快速参考:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_18.9.jpg
表 18.9:Netezza 对象权限及其 Azure Synapse 对应权限
扩展 SQL 差异与解决方法
表 18.10 描述了迁移到 Azure Synapse Analytics 时的扩展 SQL 差异和可能的解决方法:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_18.10.jpg
表 18.10:扩展 SQL 差异与解决方法
在本节中,我们讨论了架构师在迁移项目中可能遇到的常见迁移问题及其解决方案。在下一节中,我们将查看架构师应关注的安全性考虑因素。
安全性考虑因素
保护和安全管理您的数据资产在任何数据仓库系统中都是至关重要的。在规划数据仓库迁移项目时,必须考虑安全性、用户访问管理、备份和恢复等因素。例如,数据加密可能是行业和政府法规(如 HIPAA、PCI 和 FedRAMP)以及非监管行业中的强制要求。
Azure 提供许多标准功能,这些功能在传统的数据仓库产品中通常需要自定义构建。Azure Synapse 标准支持数据静态加密和数据传输加密。
数据静态加密
-
透明数据加密(TDE)可以启用,以动态加密和解密 Azure Synapse 数据、日志及相关备份。
-
Azure 数据存储还可以自动加密非数据库数据。
数据传输中的加密
所有连接到 Azure Synapse Analytics 的连接默认都使用行业标准协议,如 TLS 和 SSH 进行加密。
此外,动态数据屏蔽(DDM)可以基于数据屏蔽规则,为特定类别的用户混淆数据。
作为最佳实践,如果您的传统数据仓库包含复杂的权限层次结构、用户和角色,请考虑在迁移过程中使用自动化技术。您可以使用传统系统中的现有元数据生成必要的 SQL,以便在 Azure Synapse Analytics 上迁移用户、组和权限。
在本章的最后一节,我们将回顾一些架构师可以选择的工具,帮助从传统数据仓库系统迁移到 Azure Synapse Analytics。
帮助迁移到 Azure Synapse Analytics 的工具
现在我们已经讨论了规划与准备工作以及迁移过程的概述,接下来我们来看看你可以用来将传统数据仓库迁移到 Azure Synapse Analytics 的工具。我们将讨论以下工具:
-
ADF
-
Azure 数据仓库迁移工具
-
微软物理数据传输服务
-
微软数据导入服务
让我们开始吧。
ADF
ADF 是一项完全托管、按需付费的混合数据集成服务,用于云规模的 ETL 处理。它提供以下功能:
-
在内存中并行处理和分析数据,以实现规模化并最大化吞吐量
-
创建数据仓库迁移管道,协调和自动化数据迁移、数据转换和数据加载到 Azure Synapse Analytics 中
-
也可以通过将数据导入到 Azure Data Lake、按规模处理和分析数据,并将数据加载到数据仓库中,来现代化您的数据仓库
-
支持基于角色的用户界面,用于 IT 专业人员的数据流映射,以及业务用户的自助数据处理。
-
可以连接多个跨数据中心、云和 SaaS 应用程序的数据存储
-
提供 90 多个原生构建且无需维护的连接器可用(
azure.microsoft.com/services/data-factory) -
可以在同一管道中混合和匹配数据处理和映射数据流,以大规模准备数据。
-
ADF 编排可以控制数据仓库迁移到 Azure Synapse Analytics。
-
可以执行 SSIS ETL 包
Azure 数据仓库迁移工具
Azure 数据仓库迁移工具可以将数据从本地 SQL Server 数据仓库迁移到 Azure Synapse。它提供以下功能:
-
使用向导式方法执行从本地 SQL Server 数据仓库的模式和数据的“提升和转移”迁移。
-
您可以选择包含要导出到 Azure Synapse 的表格的本地数据库。然后,您可以选择要迁移的表格并迁移模式。
-
自动生成创建 Azure Synapse 中等效空数据库和表所需的 T-SQL 代码。一旦提供了 Azure Synapse 的连接详细信息,您可以运行生成的 T-SQL 代码迁移模式。
-
创建模式后,您可以使用该工具迁移数据。此操作会将数据从本地 SQL Server 数据仓库导出,并生成批量复制程序(BCP)命令,将数据加载到 Azure Synapse 中。
用于物理数据传输的 Microsoft 服务
在本节中,我们将介绍常用的 Microsoft 服务,这些服务可用于物理数据传输,包括 Azure ExpressRoute、AzCopy 和 Azure Databox。
Azure ExpressRoute
Azure ExpressRoute 允许您在数据中心与 Azure 之间建立私人连接,而无需通过公共互联网。它提供以下功能:
-
带宽高达 100 Gbps
-
低延迟
-
直接连接到您的广域网(WAN)
-
私有连接到 Azure
-
提高速度和可靠性
AzCopy
AzCopy 是一个命令行工具,用于将文件和 Blob 复制到/从存储帐户。它提供以下功能:
-
能够通过互联网将数据复制到/从 Azure。
-
将 AzCopy 与所需的 ExpressRoute 带宽结合使用,可能是数据传输到 Azure Synapse 的最佳解决方案。
Azure Data Box
Azure Data Box 允许您快速、可靠且具有成本效益地将大量数据传输到 Azure。它提供以下功能:
-
能够传输大量数据(数十 TB 到数百 TB)
-
没有网络连接限制
-
非常适合一次性迁移和初始大批量传输
用于数据摄取的 Microsoft 服务
在本节中,我们将介绍常用的 Microsoft 服务,这些服务可用于数据摄取,包括:
-
PolyBase
-
BCP
-
SqlBulkCopy API
-
标准 SQL
PolyBase(推荐方法)
PolyBase 提供了最快速且可扩展的大数据批量加载到 Azure Synapse Analytics 的方式。它提供了以下功能:
-
使用并行加载以提供最快的吞吐量
-
可以从 Azure Blob 存储中的平面文件或通过连接器从外部数据源读取
-
与 ADF 紧密集成
-
使用 CREATE TABLE AS 或 INSERT … SELECT
-
可以将临时表定义为 HEAP 类型以加快加载速度
-
支持最多 1 MB 长度的行
BCP
BCP 可用于从任何 SQL Server 环境(包括 Azure Synapse Analytics)导入和导出数据。它提供了以下功能:
-
支持长度超过 1 MB 的行
-
最初为早期版本的 Microsoft SQL Server 开发
请参考docs.microsoft.com/sql/tools/bcp-utility了解有关 BCP 工具的更多信息。
SqlBulkCopy API
SqlBulkCopy API 是 BCP 功能的 API 等效版本。它提供了以下功能:
-
允许通过编程方式实现加载过程
-
能够批量加载 SQL Server 表格,数据来自选定的来源
请参考docs.microsoft.com/dotnet/api/system.data.sqlclient.sqlbulkcopy了解有关此 API 的更多信息。
标准 SQL 支持
Azure Synapse Analytics 支持标准 SQL,包括以下功能:
-
将单独的行或
SELECT语句的结果加载到数据仓库表中。 -
使用
INSERT … SELECT语句通过 PolyBase 从外部数据源提取数据,并批量插入到数据仓库表中。
本节提供了规划、准备和执行现有遗留数据仓库系统成功迁移到 Azure Synapse Analytics 的架构考虑和高层次方法论。它包含了许多信息,你可以在迁移项目过程中作为参考。
总结
Azure Synapse Analytics 是一个无限制的分析服务,具有无与伦比的洞察力交付时间,能够加速企业 BI、AI 和智能应用的交付。通过将现有的遗留数据仓库迁移到 Azure Synapse Analytics,你将获得许多好处,包括性能、速度、提高的安全性和合规性、弹性、托管基础设施、可扩展性以及成本节约。
通过 Azure Synapse,各种技能水平的数据专业人员可以轻松协作、管理和分析他们最重要的数据——所有操作都在同一服务内进行。从与强大且可信的 SQL 引擎集成的 Apache Spark,到无代码的数据集成和管理,Azure Synapse 为每一位数据专业人员打造。
本章提供了架构考虑和高层次的方法论,以帮助准备和执行将现有遗留数据仓库系统迁移到 Azure Synapse Analytics 的工作。
成功的数据迁移项目始于一个精心设计的计划。一个有效的计划需要考虑多个组件,特别关注架构和数据准备。
成功迁移到 Azure Synapse 后,您可以在丰富的 Azure 分析生态系统中探索更多 Microsoft 技术,进一步现代化您的数据仓库架构。
以下是一些值得思考的想法:
-
将您的暂存区域和 ELT 处理卸载到 Azure Data Lake 和 ADF。
-
一次构建受信任的数据产品,采用统一的数据模型格式,并且可以在任何地方使用——不仅仅是在数据仓库中。
-
通过使用 ADF 映射和数据清洗流,实现业务和 IT 之间的数据准备管道的协作开发。
-
在 ADF 中构建分析管道,以批处理和实时分析数据。
-
构建并部署机器学习模型,为您已有的知识增加更多洞察。
-
将您的数据仓库与实时流数据集成。
-
通过使用 PolyBase 创建逻辑数据仓库,简化对多个 Azure 分析数据存储中数据和洞察的访问。
在下一章中,您将详细了解 Azure 认知服务,重点介绍以智能为核心引擎的解决方案架构。
第十九章:19. 架构智能解决方案
云技术改变了许多事情,包括以灵活、可扩展、按需付费的方式创建智能应用程序。云技术兴起之前的应用程序通常没有内嵌智能,主要是因为:
-
它既耗时又容易出错。
-
持续编写、测试和实验算法是困难的。
-
缺乏足够的数据。
-
这非常昂贵。
在过去的十年里,有两件事发生了变化,导致了比以往更加智能的应用程序的诞生。这两件事是云计算的按需无限可扩展性以及数据在体积、种类和速度上的可用性。
在本章中,我们将探讨能够帮助在 Azure 上构建智能应用程序的架构。本章涵盖的一些主题包括:
-
AI 的演变
-
Azure AI 流程
-
Azure 认知服务
-
构建光学字符识别服务
-
使用 Cognitive Search .NET SDK 构建视觉特征服务
AI 的演变
AI 并不是一个新兴的知识领域。实际上,这项技术是几十年的创新和研究的结果。然而,过去几十年的实施面临以下挑战:
-
成本:AI 实验本质上非常昂贵,而且当时没有云技术。所有基础设施要么是购买的,要么是从第三方租赁的。实验的设置也非常耗时,并且需要大量技能才能入门。大量的存储和计算能力也被要求,而这些在整个社区中通常缺乏,只掌握在少数几个人手中。
-
数据不足:几乎没有智能手持设备和传感器生成数据。数据本质上是有限的,并且需要采购,这再次使得 AI 应用程序成本高昂。数据的可靠性也较差,普遍缺乏对数据本身的信任。
-
难度:AI 算法的文档化程度不足,主要存在于数学家和统计学家的领域。它们难以创建并在应用程序中使用。试想 15 年前创建一个光学字符识别(OCR)系统,当时几乎没有任何库、数据、处理能力或开发 OCR 应用程序所需的技能。
尽管随着时间的推移数据的流入不断增加,但仍缺乏能够以有助于商业价值的方式理解数据的工具。此外,优秀的 AI 模型基于足够准确的数据,并通过算法进行训练,以便解决现实生活中的问题。云技术以及大量的传感器和手持设备重新定义了这一格局。
借助云技术,能够为基于 AI 的应用程序提供按需存储和计算资源。云基础设施提供大量的数据迁移、存储、处理和计算资源,同时生成洞察,并最终提供报告和仪表盘。所有这些都以最低的成本和更快的速度完成,因为没有涉及任何物理设备。让我们深入了解构建基于 AI 的应用程序背后的过程。
Azure AI 处理
每个基于 AI 的项目都需要经过一定的步骤,才能投入使用。让我们来了解这七个阶段:
数据摄取
在这个阶段,数据从多个来源采集并存储,以便在下一阶段使用。数据在存储之前会进行清洗,并且任何偏离常规的数据都会被忽略。这是数据准备的一部分。数据可以具有不同的速度、种类和规模。它可以像关系型数据库一样是结构化的,像 JSON 文档一样是半结构化的,或像图片、Word 文档等一样是非结构化的。
数据转化
所摄取的数据会被转化成另一种格式,因为它可能无法以当前格式使用。数据转化通常包括清洗和过滤数据,去除数据偏差,通过与其他数据集结合来增强数据,基于现有数据创建额外数据等。这也是数据准备的一部分。
分析
最后一阶段的数据会被重新用于分析。分析阶段包括在数据中寻找模式、进行探索性数据分析,并从中生成进一步的洞察。这些洞察与现有数据一起存储,以便在下一阶段使用。这是模型包装过程的一部分。
数据建模
一旦数据被增强和清洗,适当且必要的数据会提供给 AI 算法,以生成有助于实现整体目标的模型。这是一个迭代过程,称为通过使用不同数据组合(特征工程)进行实验,以确保数据模型的健壮性。这也是模型包装过程的一部分。
数据被输入到学习算法中,以识别模式。这个过程称为训练模型。随后,使用测试数据验证模型的有效性和效率。
验证模型
一旦模型创建完成,就会使用一组测试数据来检验其有效性。如果从测试数据中得到的分析结果反映了现实情况,那么该模型是健全且可用的。测试是 AI 过程中的一个重要环节。
部署
模型被部署到生产环境,以便实时数据能够输入模型并获得预测输出。然后,这些输出可以在应用程序中使用。
监控
部署到生产环境中的模型会持续进行监控,用于对所有进入的数据进行未来分析,并重新训练和提升模型的效果。
AI 的各个阶段和过程本质上是耗时且迭代的。因此,基于它们的应用程序具有固有的风险,可能会长时间运行、处于实验阶段、资源密集,并且可能出现成本超支和延期,成功的几率较低。
记住这些要点后,应该有现成的基于 AI 的解决方案,供开发人员在其应用程序中使用,使它们变得更加智能。这些 AI 解决方案应该易于从应用程序中消费,并具备以下特性:
-
跨平台:使用任何平台的开发者都应该能够消费这些服务。它们应该能够在 Linux、Windows 或 Mac 平台上进行部署和使用,而不会出现兼容性问题。
-
跨语言:开发者应该能够使用任何语言来消费这些解决方案。这样,开发者不仅能遇到较短的学习曲线,而且也不需要更改自己偏好的编程语言来使用这些解决方案。
这些解决方案应该作为服务进行部署,使用行业标准和协议。通常,这些服务作为 HTTP REST 端点提供,可以使用任何编程语言和平台进行调用。
有许多此类服务可以被建模并部署以供开发者使用。以下是一些示例:
-
语言翻译:在此类服务中,用户提供一种语言的文本,并获得该文本对应的另一种语言的输出。
-
字符识别:这些服务接受图像并返回其中的文本内容。
-
语音转文本转换:这些服务可以将输入的语音转换为文本。
现在我们已经详细了解了构建基于 AI/ML 的项目,让我们深入探讨一下 Azure 提供的各种认知服务的应用。
Azure 认知服务
Azure 提供了一个名为 Azure 认知服务的总服务。Azure 认知服务是一组服务,开发者可以在他们的应用程序中使用这些服务,将应用程序转变为智能应用程序。
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_19.1.jpg
表 19.1:Azure 认知服务
根据服务的性质,这些服务已被分为五大类。这五大类如下:
视觉
这个 API 提供了图像分类的算法,并通过提供有意义的信息来帮助图像处理。计算机视觉可以从图像中提供关于不同物体、人物、字符、情感等的多种信息。
搜索
这些 API 有助于与搜索相关的应用程序。它们可以基于文本、图像、视频进行搜索,并提供自定义搜索选项。
语言
这些 API 基于自然语言处理,帮助提取用户提交文本的意图信息及实体检测。它们还帮助进行文本分析和翻译成不同语言。
语音
这些 API 有助于将语音转换为文本、将文本转换为语音以及语音翻译。它们可以用于接收音频文件并基于内容为用户执行操作。Cortana 是一个使用类似服务,根据语音为用户执行操作的例子。
决策
这些 API 有助于异常检测和内容审核。它们可以检查图像、视频和文本中的内容,并找出需要突出显示的模式。此类应用的一个例子是显示有关成人内容的警告。
现在你已经理解了认知服务的核心内容,接下来我们将详细讨论它们的工作原理。
理解认知服务
Azure 认知服务由接受请求并将响应发送回调用者的 HTTP 端点组成。几乎所有的请求都是 HTTP POST 请求,包含请求头和请求体。
认知服务的配置会生成两个重要的产物,帮助调用者成功调用端点。它生成一个端点 URL 和一个唯一的密钥。
URL 的格式是 https://{azure location}.api.cognitive.microsoft.com/{cognitive type}/{version}/{sub type of service}?{query parameters}。一个示例 URL 如下:
https://eastus.api.cognitive.microsoft.com/vision/v2.0/ocr?language=en&detectOrientation=true
认知服务在美国东部 Azure 区域配置。服务类型为计算机视觉,使用版本 2,子类型为 OCR。每个顶级类别通常有几个子类型。最后,还有一些查询字符串参数,如 language 和 detectOrientation。这些查询参数对于每个服务类别和子类别都是不同的。
无论是请求头还是查询参数,都应该提供密钥值,以确保端点调用成功。
密钥值应该与请求一起分配给 Ocp-Apim-Subscription-Key 请求头。
请求体的内容可以是简单字符串、二进制数据或两者的组合。根据值的不同,应该在请求中设置适当的 content-type 头。
可能的头部值包括:
-
Application/octet-stream -
multipart/form-data -
application/json
当发送二进制数据时,请使用 octet-stream,发送字符串值时使用 json。form-data 可用于发送二进制和文本的多种组合值。
密钥是一个唯一的字符串,用于验证调用者是否被授权调用 URL。这个密钥必须受到保护,确保不应有权限调用端点的人员无法访问它。稍后你将在本章中看到如何保护这些密钥的方法。
使用认知服务
有两种方式可以使用认知服务:
-
直接使用 HTTP 端点:在这种情况下,直接通过构造适当值的标头和请求体来调用端点。然后解析返回值并提取数据。认知服务中的所有 AI 服务都是 REST API。它们接受 JSON 格式的 HTTP 请求及其他格式,并以 JSON 格式回复。
-
使用 SDK:Azure 提供了多个软件开发工具包(SDKs)。.NET、Python、Node.js、Java 和 Go 语言都有可用的 SDK。
在接下来的章节中,我们将探讨如何通过两种方式使用认知服务之一。我们将通过构建一些 AI 服务并使用 HTTP 端点来探索这一点。
构建 OCR 服务
在本节中,我们将使用 C# 和 PowerShell 展示如何使用 HTTP 端点直接调用一些 AI 服务。下一节将重点介绍使用 .NET SDK 完成相同的操作。
在构建使用认知服务的项目之前,第一步是配置 API 本身。
光学字符识别作为视觉 API 提供,并可以通过 Azure 门户进行配置,如下所示。通过导航到认知服务 > 计算视觉 > 创建来创建视觉 API,如图 19.1所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_19.2.jpg
图 19.1:创建视觉 API
一旦 API 配置完成,概述页面会提供所有用于使用该 API 的详细信息。它提供基础 URL 和密钥信息。请记下该密钥,后续会用到:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_19.3.jpg
图 19.2:概述页面
它还提供了一个 API 控制台,方便快速测试 API。点击它会打开一个新窗口,显示所有与该服务相关的端点。点击 POST 方法后,URL 会指向位于东美国 Azure 区域的端点。它还与视觉 API 组版本 2 和 OCR 端点相关。
订阅密钥会通过名为ocp-apim-subscription-key的标头传递。标头还包含 application/json 作为值的 content-type 密钥。这是因为请求体包含 JSON 字符串。请求体是 JSON 格式,包含需要提取文本的图像 URL:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_19.4.jpg
图 19.3:请求 URL
可以通过点击发送按钮将请求发送到端点。如果一切正常,将返回 HTTP 响应 200 OK,如下所示。如果请求值有错误,响应将是一个错误的 HTTP 代码:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_19.5.jpg
图 19.4:HTTP 响应 200 OK
响应包含与计费使用相关的详细信息、由端点生成的内部请求 ID、内容长度、响应内容类型(为 JSON)以及响应的日期和时间。响应的内容是一个 JSON 负载,包含文本的坐标和实际文本。
使用 PowerShell
相同的请求可以通过 PowerShell 创建。以下 PowerShell 代码可以通过 PowerShell ISE 执行。
代码使用 Invoke-WebRequest cmdlet 通过 POST 方法传递 URL 到 Uri 参数来调用认知服务端点,并添加上一节中讨论的适当头信息,最后是包含 JSON 格式数据的请求体。数据使用 ConvertTo-Json cmdlet 转换为 JSON 格式:
$ret = Invoke-WebRequest -Uri "https://eastus.api.cognitive.microsoft.com/vision/v2.0/ocr?language=en&detectOrientation=true" -Method Post -Headers @{"Ocp-Apim-Subscription-Key"="ff0cd61f27d8452bbadad36942570c48"; "Content-type"="application/json"} -Body $(ConvertTo-Json -InputObject @{"url"="https://ichef.bbci.co.uk/news/320/cpsprodpb/F944/production/_109321836_oomzonlz.jpg"})
$val = Convertfrom-Json $ret.content
foreach ($region in $val.regions) {
foreach($line in $region.lines) {
foreach($word in $line.words) {
$word.text
}
}
}
来自 cmdlet 的响应被保存在一个变量中,该变量也包含 JSON 格式的数据。使用 Convertfrom-Json cmdlet 将数据转换为 PowerShell 对象,并循环遍历以查找文本中的单词。
使用 C#
在本节中,我们将构建一个服务,该服务应接受用户请求,提取图像的 URL,构建 HTTP 请求并将其发送到认知服务端点。认知服务端点返回一个 JSON 响应。响应中提取适当的文本内容并返回给用户。
架构与设计
智能应用程序是一个 ASP.NET Core MVC 应用程序。MVC 应用程序由开发人员在开发机上构建,通过持续集成和交付管道,生成 Docker 镜像,并将 Docker 镜像上传到 Azure 容器注册表。在这里,解释了应用程序的主要组件及其使用方法:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/19.6.jpg
图 19.5:智能应用程序的工作流程
Docker
Docker 是容器技术中的重要组成部分,并且支持跨平台,包括 Linux、Windows 和 Mac。以容器化为思路开发应用程序和服务,提供了跨云和不同位置以及本地部署的灵活性。它还消除了对宿主平台的依赖,这样就减少了对平台即服务的依赖。Docker 有助于创建自定义镜像,容器可以从这些镜像中创建。这些镜像包含使应用程序或服务能够运行的所有依赖项、二进制文件和框架,并且它们是完全自给自足的。这使得它们成为微服务等服务的优秀部署目标。
Azure 容器注册表
Azure 容器注册表是一个类似于 Docker Hub 的注册表,用于存储容器镜像。可以创建多个存储库并上传多个镜像。每个镜像都有一个名称和版本号,合起来形成一个完整的名称,用于在 Kubernetes Pod 定义中引用它们。这些镜像可以被任何 Kubernetes 生态系统访问和下载。前提是已经为拉取镜像创建了适当的密钥。容器注册表不需要与 Kubernetes 节点在同一网络中,实际上,创建和使用 Azure 容器注册表时无需网络。
Azure Kubernetes Service
接受图像 URL 并提取其中文本的智能应用程序可以托管在普通虚拟机上,甚至可以在 Azure App Service 中运行。然而,在 Azure Kubernetes Service 中部署提供了许多优势,这些内容在第八章,Azure Kubernetes 解决方案架构中有详细介绍。目前,重要的是要知道,这些应用程序天生具有自愈能力,Kubernetes 主节点会自动维护最小数量的实例,并提供多种方式来更新它们,包括蓝绿部署和金丝雀更新。
Pods、副本集和部署
开发人员还创建了一个与 Kubernetes 部署相关的 YAML 文件,该文件引用了 Pod 规范中的镜像,并提供了副本集的规范。它还提供了与更新策略相关的自定义规范。
运行时设计
架构和设计与前一部分相同;然而,当应用程序或服务已经上线并运行时,它已经从 Azure 容器注册表下载了镜像,并在其中创建了运行容器的 Pod。当用户提供一个图像 URL 以解码其中的文本时,Pod 中的应用程序调用 Azure Cognitive Services 计算机视觉 API,并将 URL 传递给它,等待服务响应:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/19.7.jpg
图 19.6 智能应用的工作流
一旦收到服务返回的 JSON 响应,它就可以提取信息并返回给用户。
开发过程
开发环境可以是 Windows 或 Linux。它可以在 Windows 10 和 Windows 2016/19 服务器上运行。在使用 Windows 时,部署 Docker for Windows 非常有用,这样它会创建 Linux 和 Windows 两种 Docker 环境。
使用 Visual Studio 2019 创建 ASP.NET Core Web 应用程序项目时,Dockerfile的主要区别是基础镜像名称。它使用不同的镜像来支持 Linux 和 Windows。
安装 Docker for Windows 时,它还会安装一个 Linux 虚拟机,因此启用 Hyper-V 虚拟化程序非常重要。
在此示例中,图像被下载而不是将数据作为 JSON 字符串发送,并且二进制数据被发送到认知服务终结点。
它具有一个接受字符串输入的功能,用于 URL 值。然后,它调用认知服务,并使用适当的头部值和包含 URL 的请求体。头部值应包含认知服务在配置服务时提供的密钥。请求体中的值可以包含以 JSON 形式表示的普通字符串值,也可以包含二进制图像数据。content-type 头部属性应相应设置。
代码声明了与认知服务相关的 URL 和密钥。这里只是为了演示 purposes,URL 和密钥应放在配置文件中。
使用 HttpClient 对象,下载用户提供的 URL 对应的图像并将其存储在 responseMessage 变量中。然后实例化另一个 HttpClient 对象,并用 Ocp-Apim-Subscription-Key 和 content-type 密钥填充其头部。由于传递的是二进制数据,因此 content-type 头部的值应设置为 application/octet-stream。
提取 responseMessage 变量中的内容后,发出一个 POST 请求,并将其作为请求体传递给认知服务终结点。
控制器操作的代码如下所示:
[HttpPost]
public async Task<string> Post([FromBody] string value)
{
string myurl = " https://eastus.api.cognitive.microsoft.com/vision/v2.0/ocr?language=en&detectOrientation=true
string token = "…………………………";
using (HttpClient httpClient = new HttpClient())
{
var responseMessage = await httpClient.GetAsync(value);
using (var httpClient1 = new HttpClient())
{
httpClient1.BaseAddress = new Uri(myurl);
httpClient1.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", token);
HttpContent content = responseMessage.Content;
content.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/octet-stream");
var response = await httpClient1.PostAsync(myurl, content);
var responseContent = await response.Content.ReadAsByteArrayAsync();
string ret = Encoding.ASCII.GetString(responseContent, 0, responseContent.Length);
dynamic image = JsonConvert.DeserializeObject<object>(ret);
string temp = "";
foreach (var regs in image.regions)
{
foreach (var lns in regs.lines)
{
foreach (var wds in lns.words)
{
temp += wds.text + " ";
}
}
}
return temp;
}
}
}
在终结点完成处理后,它返回一个带有 JSON 有效负载的响应。上下文被提取并反序列化为 .NET 对象。编写了多个循环来从响应中提取文本。
在本节中,我们创建了一个简单的应用程序,利用认知服务通过 OCR API 提供从特征中提取单词的功能,并将其部署到 Kubernetes Pods 中。此过程和架构可以用于任何想要调用认知服务 API 的应用程序。接下来,我们将了解另一个认知服务 API,称为视觉特征。
使用 Cognitive Search .NET SDK 构建视觉特征服务
上一节介绍了创建一个使用 OCR 认知终结点返回图像中文本的服务。在本节中,将创建一个新的服务,该服务返回图像中的视觉特征,例如描述、标签和对象。
使用 PowerShell
PowerShell 中的代码与之前的 OCR 示例类似,因此在此不再重复。URL 与之前的代码示例不同:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_19.8.jpg
图 19.7:请求 URL
请求使用 POST 方法,并且 URL 指向东部美国 Azure 区域的终结点。它还使用版本 2,并调用视觉 API。
认知服务访问密钥是 HTTP 头部的一部分,名为 ocp-apim-subscription-key。该头部还包含名为 content-type 的头信息,值为 application/json。这是因为请求的正文包含 JSON 格式的数据。正文中包含提取文本所需的图像 URL。
响应将以 JSON 格式返回,包含图像内容和描述。
使用 .NET
这个示例再次是一个 ASP.NET Core MVC 应用程序,已安装 Microsoft.Azure.CognitiveServices.Vision.ComputerVision NuGet 包:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_19.9.jpg
图 19.8:带有 Microsoft.Azure.CognitiveServices.Vision.ComputerVision NuGet 包的 ASP.NET Core MVC 应用程序
控制器操作的代码如下所示。在这段代码中,声明了认知服务和密钥,还声明了 ComputerVisionClient 和 VisionType 对象的变量。它创建了一个 ComputerVisionClient 类型的实例,提供了 URL 和密钥。
VisionTypes 列表包含了从图像中提取的多种数据类型——标签、描述和对象等。只有这些参数会从图像中提取。
创建一个 HttpClient 对象,通过用户提供的 URL 下载图像,并使用 ComputerVisionClient 类型的 AnalyzeImageInStreamAsync 函数将这些二进制数据发送到认知服务端点:
[HttpPost]
public string Post([FromBody] string value)
{
private string visionapiurl = " https://eastus.api.cognitive.microsoft.com/vision/v2.0/analyze?visualFeaure=tags,description,objects&language=en";
private string apikey = "e55d36ac228f4d718d365f1fcddc0851";
private ComputerVisionClient client;
private List<VisualFeatureTypes> visionType = new List<VisualFeatureTypes>();
client = new ComputerVisionClient(new ApiKeyServiceClientCredentials(apikey)) {
Endpoint = visionapiurl
};
visionType.Add(VisualFeatureTypes.Description);
visionType.Add(VisualFeatureTypes.Tags);
visionType.Add(VisualFeatureTypes.Objects);
string tags = "";
string descrip = "";
string objprop = "";
using (HttpClient hc = new HttpClient()) {
var responseMessage = hc.GetAsync(value).GetAwaiter().GetResult();
Stream streamData = responseMessage.Content.ReadAsStreamAsync().GetAwaiter().GetResult();
var result = client.AnalyzeImageInStreamAsync(streamData, visionType).GetAwaiter().GetResult();
foreach (var tag in result.Tags) {
tags += tag.Name + " ";
}
foreach (var caption in result.Description.Captions)
{
descrip += caption.Text + " ";
}
foreach (var obj in result.Objects)
{
objprop += obj.ObjectProperty + " ";
}
}
return tags;
// return descrip or objprop
}
对结果进行循环处理并将标签返回给用户。同样,描述和对象属性也可以返回给用户。现在让我们来看一下如何保护服务密钥的暴露。
保护认知服务密钥
有多种方法可以保护密钥不被其他方暴露。可以通过 Azure 中的 API 管理资源来实现,也可以通过 Azure Functions 代理来实现。
使用 Azure Functions 代理
Azure Functions 代理可以引用任何 URL,无论是内部还是外部。当请求到达 Azure Functions 代理时,它会使用认知服务的 URL 和密钥来调用认知服务端点,并会覆盖请求参数,将传入的图像 URL 作为 POST 数据附加到认知端点 URL 上。当服务返回响应时,它会覆盖响应,移除头信息,并将 JSON 数据传递回用户。
使用认知服务
使用认知服务遵循一致的模式。每个认知服务都可以通过 REST API 提供,每个 API 需要不同的参数集。调用这些 URL 的客户端应查阅相关文档以获取参数,并为它们提供相应的值。直接使用 URL 调用是使用认知服务的一种相对原始的方法。Azure 为每项服务提供了 SDK,并支持多种编程语言。客户端可以使用这些 SDK 来与认知服务进行交互。
https://{luis resource name}-authoring.cognitiveservices.azure.com/ 和生产 API 可在此访问
https://{azure region}.api.cognitive.microsoft.com/luis/prediction/v3.0/apps/{application id}/slots/production/predict?subscription-key={cognitive key} &verbose=true&show-all-intents=true&log=true&query=YOUR_QUERY_HERE。
同样,Face API 可在 https://{endpoint}/face/v1.0/detect[?returnFaceId][&returnFaceLandmarks][&returnFaceAttributes][&recognitionModel][&returnRecognitionModel][&detectionModel] 访问。
有许多认知服务 API,每个 API 在 URL 方面有不同的版本,了解这些 URL 的最佳方式是使用 Azure 文档。
概述
在本章中,您了解了在 Azure 中创建智能应用程序的部署架构和应用程序架构。Azure 提供了大量的认知服务端点——每个端点负责执行与 AI 相关的算法并提供输出。几乎所有的认知服务端点在处理 HTTP 请求和响应方面工作方式相似。这些端点也可以通过 Azure 提供的不同语言 SDK 进行调用,您已看到使用这些 SDK 获取视觉特征的示例。Azure 提供了超过 50 个不同的端点,建议您通过 Azure 提供的 API 控制台功能来了解端点的性质。
1103

被折叠的 条评论
为什么被折叠?



