原文:
annas-archive.org/md5/0b3cfce43ce7ffb62c4f01cafdc66996译者:飞龙
第十一章:11. 使用 Azure Logic Apps、Event Grid 和 Functions 的 Azure 解决方案
本章接续上一章内容,进一步深入探讨 Azure 中可用的无服务器服务。在上一章中,你详细了解了 Azure Functions、函数即服务、耐久性函数以及 Event Grid。接下来,本章将重点讲解 Logic Apps,并且将展示如何创建一个完整的端到端无服务器解决方案,该解决方案结合了多个无服务器服务及其他服务,例如 Key Vault 和 Azure Automation。
在本章中,我们将通过以下主题进一步探索 Azure 服务:
-
Azure Logic Apps
-
使用无服务器技术创建端到端解决方案
Azure Logic Apps
Logic Apps 是 Azure 提供的一种无服务器工作流服务。它具有所有无服务器技术的特点,例如按使用量计费和无限的可扩展性。Logic Apps 帮助我们通过 Azure 门户轻松构建业务流程和工作流解决方案。它提供了一个拖拽式界面,用于创建和配置工作流。
使用 Logic Apps 是集成服务和数据、创建业务项目以及创建完整逻辑流的首选方式。在构建 Logic Apps 之前,应该理解几个重要的概念。
活动
活动是一个独立的工作单元。活动的例子包括将 XML 转换为 JSON、从 Azure 存储读取 Blob 和写入 Cosmos DB 文档集合。Logic Apps 提供了一个工作流定义,包含多个相关活动按顺序执行。Logic Apps 中有两种类型的活动:
-
触发器:触发器是指启动活动的事件。所有 Logic Apps 都有一个触发器,它是第一个活动。触发器创建 Logic Apps 实例并启动执行。触发器的例子包括 Event Grid 消息的到达、电子邮件、HTTP 请求或计划任务。
-
操作:任何不是触发器的活动都是步骤活动,每个步骤负责执行一个任务。步骤按顺序连接在工作流中。每个步骤都需要完成一个操作,才能继续到下一个步骤。
连接器
连接器是 Azure 资源,用于将 Logic Apps 与外部服务连接。这些服务可以位于云端或本地。例如,有一个连接器可以将 Logic Apps 连接到 Event Grid。同样,还有一个连接器可以连接到 Office 365 Exchange。Logic Apps 中几乎所有类型的连接器都可以用来连接服务。连接器包含连接信息,并利用这些信息提供连接外部服务的逻辑。
所有连接器的完整列表可以在 docs.microsoft.com/connectors 查看。
现在你了解了连接器,你需要了解如何按步骤将它们对齐,以便工作流按预期运行。在接下来的部分,我们将重点介绍逻辑应用的工作原理。
逻辑应用的工作原理
让我们创建一个逻辑应用工作流,当电子邮件账户收到邮件时触发。它会回复发件人一封默认的电子邮件,并对邮件内容进行情感分析。对于情感分析,应该在创建逻辑应用之前配置 Cognitive Services 中的 Text Analytics 资源:
-
导航到 Azure 门户,登录到你的账户,并在资源组中创建一个Text Analytics资源。Text Analytics 是 Cognitive Services 的一部分,提供情感分析、关键短语提取和语言检测等功能。你可以在 Azure 门户中找到该服务,如图 11.1所示:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.1.jpg
图 11.1:从 Azure 门户导航到 Text Analytics 服务
-
提供名称、位置、订阅、资源组和定价层值。我们将在此演示中使用该服务的免费层(F0 层)。
-
资源配置完成后,导航到概览页面,复制端点 URL,并将其存储在临时位置。配置逻辑应用时将需要此值。
-
导航到密钥页面,复制密钥 1的值并将其存储在临时位置。配置逻辑应用时将需要此值。
-
下一步是创建一个逻辑应用。要创建逻辑应用,请在 Azure 门户中导航到应创建逻辑应用的资源组。搜索“Logic App”,并通过提供名称、位置、资源组和订阅值来创建它。
-
创建完逻辑应用后,导航到该资源,点击左侧菜单中的Logic app designer,然后选择当在 Outlook.com 中收到新邮件时模板来创建新工作流。该模板通过添加基本触发器和活动来为你提供一个起点。这将自动向工作流中添加一个 Office 365 Outlook 触发器。
-
点击触发器上的登录按钮,它将打开一个新的 Internet Explorer 窗口。然后,登录到你的账户。成功登录后,将创建一个新的 Office 365 邮件连接器,包含连接到账户的相关信息。
-
点击继续按钮,并将触发器配置为每 3 分钟轮询一次,如图 11.2所示:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.2.jpg
图 11.2:配置触发器为 3 分钟轮询频率
-
在搜索栏中点击
variable。然后,选择初始化变量操作,如图 11.3所示:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.3.jpg图 11.3:添加初始化变量操作
-
接下来,配置变量操作。当点击值框时,会弹出一个窗口,显示动态内容和表达式。动态内容是指当前操作可用的属性,并填充来自先前操作和触发器的运行时值。变量有助于保持工作流的通用性。从此窗口中,选择动态内容中的正文:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.4.jpg
图 11.4:配置变量操作
-
通过点击搜索栏中的
outlook,然后选择回复电子邮件操作,添加另一个操作:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.5.jpg图 11.5:添加回复电子邮件操作
-
配置新操作。确保消息 ID已设置为动态内容,消息 ID,然后在评论框中输入你希望发送给收件人的回复:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.6.jpg
图 11.6:配置回复电子邮件操作
-
添加另一个操作,在搜索栏中输入
text analytics,然后选择检测情感(预览):https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.7.jpg图 11.7:添加检测情感(预览)操作
-
按照图 11.8中的示例配置情感操作——此处应使用端点和密钥值。现在点击创建按钮,如图 11.8所示:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.8.jpg
图 11.8:配置检测情感(预览)操作
-
通过添加动态内容并选择之前创建的变量emailContent,向操作提供文本。然后,点击显示高级选项,并为语言选择en:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.9.jpg
图 11.9:选择情感操作的语言
-
接下来,通过选择Outlook并选择发送电子邮件来添加一个新操作。此操作会将包含情感评分的电子邮件内容发送给原始收件人,并将其作为主题。它应该如图 11.10所示进行配置。如果动态内容窗口中未显示评分,请点击旁边的查看更多链接:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.10.jpg
图 11.10:添加发送电子邮件操作
-
保存逻辑应用,返回概述页面,然后点击运行触发器。该触发器每隔 3 分钟检查一次新邮件,回复发件人,执行情感分析,并将电子邮件发送给原始收件人。一个包含负面含义的电子邮件样本会发送到指定的电子邮件 ID:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.11.jpg
图 11.11:电子邮件示例
-
几秒钟后,逻辑应用执行,发件人收到以下回复:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.12.jpg
图 11.12:回复原始发件人的电子邮件
-
原始收件人收到包含情感评分和原始邮件文本的电子邮件,如图 11.13所示:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.13.jpg
图 11.13:电子邮件消息的 HTML 视图
通过这个活动,我们了解了逻辑应用的工作原理。当用户的收件箱收到电子邮件时,应用会被触发,随后流程按照逻辑应用中给定的步骤顺序执行。在下一节中,您将学习如何使用无服务器技术创建端到端解决方案。
使用无服务器技术创建端到端解决方案
在本节中,我们将创建一个端到端解决方案,包含我们在前几节中讨论的无服务器技术。以下示例将帮助您了解如何智能地实现工作流,避免管理开销。在接下来的活动中,我们将创建一个工作流,当密钥、机密和证书存储在 Azure Key Vault 中时,通知用户。我们将以此为问题陈述,找出解决方案,架构解决方案,并实现它。
问题陈述
我们要解决的问题是,用户和组织未收到关于其密钥保管库中密钥过期的通知,且密钥过期后应用程序会停止工作。用户抱怨 Azure 没有提供监控 Key Vault 密钥、机密和证书的基础设施。
解决方案
解决这个问题的方法是将多个 Azure 服务组合并集成,以便用户能主动收到密钥过期的通知。该解决方案将通过电子邮件和短信两种渠道发送通知。
用于创建此解决方案的 Azure 服务包括:
-
Azure 密钥库
-
Azure 活动目录(Azure AD)
-
Azure 事件网格
-
Azure 自动化
-
逻辑应用
-
Azure 函数
-
SendGrid
-
Twilio 短信
现在您已经了解了解决方案中将使用的服务,让我们开始为这个解决方案创建架构。
架构
在上一节中,我们探索了将用于解决方案的服务列表。如果我们要实现该解决方案,这些服务应按正确的顺序布局。架构将帮助我们开发工作流,并让我们更接近解决方案。
该解决方案的架构由多个服务组成,如图 11.14所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.14.jpg
图 11.14:解决方案架构
让我们逐一了解这些服务,并理解它们在整个解决方案中提供的角色和功能。
Azure 自动化
Azure 自动化提供了运行簿,这些运行簿可以执行逻辑,使用 PowerShell、Python 以及其他脚本语言。脚本可以在本地或云端执行,这为创建脚本提供了丰富的基础设施和工具。这些脚本被称为运行簿。通常,运行簿实现的场景包括停止或启动虚拟机,或创建和配置存储帐户。通过资产如变量、证书和连接,连接到 Azure 环境变得非常简单。
在当前的解决方案中,我们希望连接到 Azure 密钥库,读取其中存储的所有机密和密钥,并获取它们的到期日期。这些到期日期应与今天的日期进行比较,如果到期日期在一个月内,则运行簿应使用事件网格自定义主题在事件网格上触发一个自定义事件。
将实现一个使用 PowerShell 脚本的 Azure 自动化运行簿。与运行簿一起,还将创建一个调度器,每天在凌晨 12:00 执行该运行簿。
自定义 Azure 事件网格主题
一旦运行簿识别到某个机密或密钥将在一个月内到期,它将触发一个新的自定义事件,并将其发布到专门为此目的创建的自定义主题上。我们将在下一节中详细介绍实现的细节。
Azure 逻辑应用
逻辑应用是一种无服务器服务,提供工作流功能。我们的逻辑应用将被配置为在自定义 Event Grid 主题上发布事件时触发。触发后,它将调用工作流并依次执行其中的所有活动。通常,工作流中有多个活动,但为了本例的目的,我们将调用一个 Azure 函数,发送电子邮件和短信通知。在全面实施中,这些通知功能应该在单独的 Azure 函数中分别实现。
Azure Functions
使用 Azure Functions 通知用户和利益相关者有关机密和密钥过期的信息,通过电子邮件和短信发送通知。使用 SendGrid 发送电子邮件,Twilio 用于通过 Azure Functions 发送短信。
在下一部分,我们将了解实施解决方案之前的先决条件。
先决条件
您至少需要一个具有贡献者权限的 Azure 订阅。由于我们仅将服务部署到 Azure,并且没有部署外部服务,因此订阅是唯一的先决条件。现在让我们开始实施解决方案。
实施
应该已经存在一个密钥库。如果没有,需要创建一个。
如果需要配置一个新的 Azure Key Vault 实例,则应该执行此步骤。Azure 提供了多种方式来配置资源,其中突出的方式有 Azure PowerShell 和 Azure CLI。Azure CLI 是一个跨平台的命令行接口。首要任务是配置一个 Azure 密钥库。在本次实施中,我们将使用 Azure PowerShell 来配置密钥库。
在使用 Azure PowerShell 创建密钥库之前,重要的是要登录 Azure,以便后续的命令能够成功执行以创建密钥库。
步骤 1:配置 Azure Key Vault 实例
第一步是为示例准备环境。这包括登录 Azure 门户,选择合适的订阅,然后创建一个新的 Azure 资源组和一个新的 Azure Key Vault 资源:
-
执行
Connect-AzAccount命令以登录 Azure。系统会在新窗口中提示输入凭据。 -
成功登录后,如果提供的登录 ID 有多个订阅,它们都会列出。需要选择一个合适的订阅——可以通过执行
Set-AzContextcmdlet 来完成:Set-AzContext -SubscriptionId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx -
在您选择的区域创建一个新的资源组。此处的资源组名称为
IntegrationDemo,并且它被创建在西欧区域:New-AzResourceGroup -Name IntegrationDemo -Location "West Europe" -Verbose -
创建一个新的 Azure Key Vault 资源——此处的密钥库名称为
keyvaultbook,并且启用了部署、模板部署、磁盘加密、软删除和清除保护功能:New-AzKeyVault -Name keyvaultbook -ResourceGroupName IntegrationDemo -Location "West Europe" -EnabledForDeployment -EnabledForTemplateDeployment -EnabledForDiskEncryption -EnablePurgeProtection -Sku Standard - Verbose
请注意,密钥库名称需要是唯一的。您可能无法为两个密钥库使用相同的名称。成功执行前面的命令后,将创建一个新的 Azure 密钥库资源。下一步是为服务主体提供对密钥库的访问权限。
步骤 2:创建服务主体
Azure 提供服务主体,而不是使用个人账户连接到 Azure,服务主体本质上是服务账户,可以用于连接到 Azure 资源管理器并执行活动。将用户添加到 Azure 目录/租户后,由于 Azure 安全继承的性质,用户在所有资源组和资源中都可用。若不允许用户访问某些资源组,必须显式地从这些资源组中撤销访问权限。服务主体通过分配细粒度的访问权限和控制权限来提供帮助,必要时,可以授予它们订阅级别的访问权限。它们还可以被分配细粒度的权限,如读取者、贡献者或所有者权限。
简而言之,服务主体应成为使用 Azure 服务的首选机制。它们可以通过密码或证书密钥进行配置。可以使用 New-AzAdServicePrinicipal 命令创建服务主体,如下所示:
$sp = New-AzADServicePrincipal -DisplayName "keyvault-book" -Scope "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -Role Owner -StartDate ([datetime]::Now) -EndDate $([datetime]::now.AddYears(1)) -Verbose
重要的配置值是范围和角色。范围决定了服务应用的访问区域——当前显示的是在订阅级别。范围的有效值如下:
/subscriptions/{subscriptionId}/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{parentResourcePath}/{resourceType}/{resourceName}
该角色为分配的范围提供权限。有效值如下:
-
所有者
-
贡献者
-
读取者
-
特定资源权限
在前面的命令中,已将所有者权限提供给新创建的服务主体。
如果需要,我们也可以使用证书。为了简化起见,我们将继续使用密码。
使用我们创建的服务主体时,密钥将被隐藏。要查看密钥,您可以尝试以下命令:
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($sp. Secret)
$UnsecureSecret = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
$UnsecureSecret 将包含您的密钥。
与服务主体一起,将创建一个应用程序目录应用。该应用程序作为我们应用在各个目录中的全局表示,服务主体则像是该应用的本地表示。我们可以使用相同的应用在不同目录中创建多个服务主体。我们可以使用 Get-AzAdApplication 命令获取所创建应用程序的详细信息。我们将该命令的输出保存到一个变量 $app 中,因为稍后我们需要用到它:
$app = Get-AzAdApplication -DisplayName $sp.DisplayName
我们现在已经使用密钥创建了一个服务主体;创建服务主体的另一种安全方式是使用证书。在接下来的部分,我们将使用证书创建服务主体。
步骤 3:使用证书创建服务主体
要使用证书创建服务主体,应执行以下步骤:
-
创建自签名证书或购买证书:自签名证书用于创建此示例的端到端应用程序。对于实际部署,应该从证书授权机构购买有效的证书。
要创建一个自签名证书,可以运行以下命令。自签名证书是可导出的,并存储在本地机器的个人文件夹中——它也有一个到期日期:
$currentDate = Get-Date $expiryDate = $currentDate.AddYears(1)$finalDate = $expiryDate.AddYears(1)$servicePrincipalName = "https://automation.book.com"$automationCertificate = New-SelfSignedCertificate -DnsName $servicePrincipalName -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $finalDate -CertStoreLocation "Cert:\LocalMachine\My" -
Get-Itemcmdlet 从证书存储中读取证书并将其存储在$cert1变量中。Export-PfxCertificatecmdlet 实际上将证书从证书存储导出到文件系统中。在此案例中,它位于C:\book文件夹中。 -
X509Certificate2被创建用于在内存中保存证书,并且数据通过System.Convert函数转换为 Base64 字符串:$newCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList "C:\azureautomation.pfx", $securepfxpwd $newcertdata = [System.Convert]::ToBase64String($newCert.GetRawCertData())我们将使用相同的服务主体从 Azure 自动化帐户连接到 Azure。重要的是,应用程序 ID、租户 ID、订阅 ID 和证书指纹值需要存储在临时位置,以便用于配置后续资源:
$adAppName = "azure-automation-sp"$ServicePrincipal = New-AzADServicePrincipal -DisplayName $adAppName -CertValue $newcertdata -StartDate $newCert.NotBefore -EndDate $newCert.NotAfter Sleep 10 New-AzRoleAssignment -ServicePrincipalName $ServicePrincipal.ApplicationId -RoleDefinitionName Owner -Scope /subscriptions/xxxxx-xxxxxxx-xxxxxx-xxxxxxx
我们已经准备好服务主体。我们创建的密钥保管库没有设置访问策略,这意味着没有用户或应用程序能够访问该保管库。在接下来的步骤中,我们将授予我们创建的应用程序目录应用程序访问密钥保管库的权限。
步骤 4:创建密钥保管库策略
在此阶段,我们已经创建了服务主体和密钥保管库。然而,服务主体仍然没有访问密钥保管库的权限。这个服务主体将用于查询并列出密钥保管库中的所有机密、密钥和证书,它应该拥有执行此操作所需的权限。
为了为新创建的服务主体提供访问密钥保管库的权限,我们将返回 Azure PowerShell 控制台并执行以下命令:
Set-AzKeyVaultAccessPolicy -VaultName keyvaultbook -ResourceGroupName IntegrationDemo -ObjectId $ServicePrincipal.Id -PermissionsToKeys get,list,create -PermissionsToCertificates get,list,import -PermissionsToSecrets get,list -Verbose
参考之前的命令块,请查看以下几点:
Set-AzKeyVaultAccessPolicy提供对用户、组和服务主体的访问权限。它接受密钥保管库名称和服务主体的对象 ID。这个对象与应用程序 ID 不同。服务主体的输出包含Id属性,如下所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.15.jpg
图 11.15:查找服务主体的对象 ID
-
PermissionsToKeys提供对密钥保管库中密钥的访问权限,且为该服务主体提供了get、list和create权限。没有为该主体提供写入或更新权限。 -
PermissionsToSecrets提供对密钥保管库中机密的访问权限,get和list权限已授予此服务主体。此服务主体没有提供写入或更新权限。 -
PermissionsToCertificates提供对密钥保管库中机密的访问权限,并且get、import和list权限已授予此服务主体。此服务主体没有提供写入或更新权限。
此时,我们已配置服务主体以便与 Azure 密钥保管库一起使用。解决方案的下一部分是创建一个自动化帐户。
步骤 5:创建自动化帐户
就像之前一样,我们将使用 Azure PowerShell 在资源组中创建一个新的 Azure 自动化帐户。在创建资源组和自动化帐户之前,应该先建立与 Azure 的连接。不过,这次,我们将使用服务主体的凭据连接到 Azure。步骤如下:
-
使用服务应用程序连接到 Azure 的命令如下。该值来自我们在之前步骤中初始化的变量:
Login-AzAccount -ServicePrincipal -CertificateThumbprint $newCert.Thumbprint -ApplicationId $ServicePrincipal.ApplicationId -Tenant "xxxx-xxxxxx-xxxxx-xxxxx" -
通过检查
Get-AzContext来确保你有权限,如下所示。记下订阅 ID,因为后续命令需要用到它:Get-AzContext -
连接到 Azure 后,应该创建一个包含解决方案资源的新资源以及一个新的 Azure 自动化帐户。你将资源组命名为
VaultMonitoring,并在West Europe区域创建它。其余资源也将创建在此资源组中:$IntegrationResourceGroup = "VaultMonitoring"$rgLocation = "West Europe"$automationAccountName = "MonitoringKeyVault"New-AzResourceGroup -name $IntegrationResourceGroup -Location $rgLocation New-AzAutomationAccount -Name $automationAccountName -ResourceGroupName $IntegrationResourceGroup -Location $rgLocation -Plan Free -
接下来,创建三个自动化变量。它们的值,即订阅 ID、租户 ID 和应用程序 ID,应该已经通过之前的步骤获得:
New-AzAutomationVariable -Name "azuresubscriptionid" -AutomationAccountName $automationAccountName -ResourceGroupName $IntegrationResourceGroup -Value " xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx " -Encrypted $true New-AzAutomationVariable -Name "azuretenantid" -AutomationAccountName $automationAccountName -ResourceGroupName $IntegrationResourceGroup -Value " xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx " -Encrypted $true New-AzutomationVariable -Name "azureappid" -AutomationAccountName $automationAccountName -ResourceGroupName $IntegrationResourceGroup -Value " xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx " -Encrypted $true -
现在是时候上传证书了,这个证书将用于从 Azure 自动化连接到 Azure:
$securepfxpwd = ConvertTo-SecureString -String 'password' -AsPlainText -Force # Password for the private key PFX certificate New-AzAutomationCertificate -Name "AutomationCertifcate" -Path "C:\book\azureautomation.pfx" -Password $securepfxpwd -AutomationAccountName $automationAccountName -ResourceGroupName $IntegrationResourceGroup -
下一步是安装与密钥保管库和事件网格相关的 PowerShell 模块,因为这些模块默认没有安装。
-
从 Azure 门户,点击左侧菜单中的 资源组,然后导航到已经创建的
VaultMonitoring资源组。 -
点击已经配置的 Azure 自动化帐户,
Az.profile模块,所以我们必须先安装它,然后再安装事件网格模块。 -
如 图 11.16 所示,在搜索框中点击
Az.profile:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.16.jpg图 11.16:模块库中的 Az.Profile 模块
-
从搜索结果中,选择
Az.Profile,然后点击顶部菜单中的 导入 按钮。最后,点击 确定 按钮。此步骤需要几秒钟完成。几秒钟后,模块应已安装。 -
可以从 模块 菜单项检查安装状态。图 11.17 展示了如何导入模块:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.17.jpg
图 11.17:Az.Profile 模块状态
-
请再次执行步骤 9、步骤 10和步骤 11,以导入和安装
Az.EventGrid模块。如果在继续操作之前出现安装任何依赖项的提示,请先安装这些依赖项。 -
请再次执行步骤 9、步骤 10和步骤 11,以导入和安装
Az.KeyVault模块。如果在继续操作之前出现安装任何依赖项的提示,请先安装这些依赖项。
由于我们已经导入了必要的模块,接下来让我们创建 Event Grid 主题。
步骤 6:创建 Event Grid 主题
如果你还记得我们使用的架构,我们需要一个 Event Grid 主题。让我们来创建一个。
使用 PowerShell 创建 Event Grid 主题的命令如下:
New-AzEventGridTopic -ResourceGroupName VaultMonitoring -Name azureforarchitects-topic -Location "West Europe"
使用 Azure 门户创建 Event Grid 主题的过程如下:
-
在 Azure 门户中,点击左侧菜单中的资源组,然后导航到已创建的
Vaultmonitoring资源组。 -
接下来,在搜索框中点击
Event Grid Topic。选择它后,点击创建按钮。 -
在生成的表单中填写适当的值,包括提供名称、选择订阅、选择新创建的资源组、位置和事件架构。
正如我们之前讨论的,Event Grid 主题提供了一个端点,源系统将通过该端点发送数据。既然我们已经准备好主题,接下来让我们准备源 Automation 帐户。
步骤 7:设置 Runbook
这一步将重点介绍如何创建 Azure Automation 帐户和 PowerShell Runbooks,这些 Runbooks 包含读取 Azure 密钥保管库并检索其中存储的秘密的核心逻辑。配置 Azure Automation 所需的步骤如下:
-
通过点击左侧菜单中的资源组来访问
Vaultmonitoring资源组。 -
点击已配置好的 Azure Automation 帐户
MonitoringKeyVault,然后在左侧菜单中点击Runbooks,再点击顶部菜单中的**+添加 Runbook**。 -
点击创建新 Runbook并提供一个名称。我们将这个 Runbook 命名为CheckExpiredAssets,然后将Runbook 类型设置为PowerShell:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.18.jpg
图 11.18:创建 Runbook
-
AutomationCertifcate。这些值会从这些存储中获取并赋给变量,如下所示:$subscriptionID = get-AutomationVariable "azuresubscriptionid"$tenantID = get-AutomationVariable "azuretenantid"$applicationId = get-AutomationVariable "azureappid"$cert = get-AutomationCertificate "AutomationCertifcate"$certThumbprint = ($cert.Thumbprint).ToString() -
Runbook 中的下一段代码帮助使用之前声明的变量中的值,通过服务主体登录到 Azure。同时,代码还会选择一个合适的订阅。代码如下所示:
Login-AzAccount -ServicePrincipal -CertificateThumbprint $certThumbprint -ApplicationId $applicationId -Tenant $tenantID Set-AzContext -SubscriptionId $subscriptionID由于 Azure Event Grid 已在本节的步骤 6中进行了配置,因此可以使用
Get-AzEventGridTopic和Get-AzEventGridTopicKeycmdlet 来检索其端点和密钥。Azure Event Grid 会生成两个密钥——一个主密钥和一个辅助密钥。第一个密钥的引用如下:
$eventGridName = "ExpiredAssetsKeyVaultEvents"$eventGridResourceGroup = "VaultMonitoring"$topicEndpoint = (Get-AzEventGridTopic -ResourceGroupName $eventGridResourceGroup -Name $eventGridName).Endpoint $keys = (Get-AzEventGridTopicKey -ResourceGroupName $eventGridResourceGroup -Name $eventGridName ).Key1 -
接下来,使用迭代检索订阅中所有已配置的密钥库。在循环过程中,使用
Get-AzKeyVaultSecretcmdlet 检索所有机密。每个机密的过期日期与当前日期进行比较,如果差异小于一个月,则生成一个 Event Grid 事件,并使用
invoke-webrequest命令发布。对于存储在密钥库中的证书,执行相同的步骤。用于检索所有证书的 cmdlet 是
Get-AzKeyVaultCertificate。发布到 Event Grid 的事件应为 JSON 数组。生成的消息通过
ConvertTo-Jsoncmdlet 转换为 JSON,然后通过添加[和]作为前缀和后缀转换为数组。为了连接到 Azure Event Grid 并发布事件,发送方应在其请求头中提供密钥。如果请求负载中缺少此数据,请求将失败:
$keyvaults = Get-AzureRmKeyVault foreach($vault in $keyvaults) {$secrets = Get-AzureKeyVaultSecret -VaultName $vault.VaultName foreach($secret in $secrets) {if( ![string]::IsNullOrEmpty($secret.Expires) ) {if($secret.Expires.AddMonths(-1) -lt [datetime]::Now){$secretDataMessage = @{id = [System.guid]::NewGuid()subject = "Secret Expiry happening soon !!"eventType = "Secret Expiry"eventTime = [System.DateTime]::UtcNow data = @{"ExpiryDate" = $secret.Expires "SecretName" = $secret.Name.ToString()"VaultName" = $secret.VaultName.ToString()"SecretCreationDate" = $secret.Created.ToString()"IsSecretEnabled" = $secret.Enabled.ToString()"SecretId" = $secret.Id.ToString()}}...Invoke-WebRequest -Uri $topicEndpoint -Body $finalBody -Headers $header -Method Post -UseBasicParsing }}Start-Sleep -Seconds 5 }} -
点击发布按钮发布运行手册,如图 11.19所示:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.19.jpg
图 11.19:发布运行手册
-
调度器:创建一个 Azure Automation 调度器资产,使此运行手册每天在午夜 12:00 执行一次。点击 Azure Automation 左侧菜单中的调度,然后在顶部菜单中点击**+添加调度**。
-
在生成的表单中提供调度信息。
这应该完成 Azure Automation 帐户的配置。
步骤 8:与 SendGrid 合作
在本步骤中,我们将创建一个新的 SendGrid 资源。SendGrid 资源用于从应用程序发送电子邮件,而无需安装**简单邮件传输协议(SMTP)**服务器。它提供一个 REST API 和一个 C# 软件开发工具包(SDK),通过这些工具,发送批量电子邮件变得非常容易。在当前的解决方案中,将使用 Azure Functions 来调用 SendGrid API 发送电子邮件,因此需要配置此资源。该资源有单独的费用,并不包括在 Azure 成本中—可以使用一个免费的层级来发送电子邮件:
-
SendGrid资源的创建方式与其他 Azure 资源相同。搜索sendgrid,我们将在结果中看到SendGrid 电子邮件投递。 -
选择资源并点击创建按钮以打开其配置表单。
-
选择一个合适的定价层。
-
提供适当的联系信息。
-
勾选使用条款复选框。
-
完成表单后,点击创建按钮。
-
在资源配置后,点击顶部菜单中的管理按钮—这将打开 SendGrid 网站。网站可能会请求进行电子邮件配置。然后,从设置部分选择API 密钥,并点击创建 API 密钥按钮:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.20.jpg
图 11.20:为 SendGrid 创建 API 密钥
-
在弹出的窗口中,选择Full Access并点击Create & View按钮。这将为 SendGrid 资源创建密钥;请记下此密钥,因为它将在 Azure Functions 配置中与 SendGrid 一起使用:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.21.jpg
图 11.21:在 SendGrid 门户中设置访问级别
现在我们已经配置好了 SendGrid 的访问级别,接下来让我们配置另一个第三方服务,即 Twilio。
步骤 9:开始使用 Twilio
在此步骤中,我们将创建一个新的 Twilio 帐户。Twilio 用于发送批量短信。要在 Twilio 上创建帐户,请导航到twilio.com并创建一个新帐户。成功创建帐户后,会生成一个可以用来向接收者发送短信的手机号码:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.22.jpg
图 11.22:选择 Twilio 号码
Twilio 帐户提供生产和测试密钥。将测试密钥和令牌复制到临时位置(例如记事本),因为稍后在 Azure Functions 中将需要它们:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.23.jpg
图 11.23:设置 Twilio
我们已经为通知服务配置好了 SendGrid 和 Twilio;然而,我们还需要一些东西来接收事件并通知用户。这就是功能应用程序的作用。在接下来的部分中,我们将创建一个功能应用程序,它将有助于发送短信和电子邮件。
步骤 10:设置功能应用程序
在此步骤中,我们将创建一个新的功能应用程序,用于发送电子邮件和短信通知。功能应用程序在解决方案中的作用是向用户发送关于密钥库中机密到期的通知消息。一个功能将负责发送电子邮件和短信消息——请注意,这本可以分成两个独立的功能。第一步是创建一个新的功能应用程序,并在其中托管一个功能:
-
如我们之前所做,导航到资源组,点击
function app资源。然后点击Create按钮以获取Function App表单。 -
填写Function App表单并点击Create按钮。功能应用程序的名称必须在 Azure 中是唯一的。
-
一旦功能应用程序被配置好,点击左侧菜单中Functions项目旁的**+按钮,创建一个名为
SMSandEMailFunction的新功能。然后,在中央仪表盘中选择In-portal**。 -
选择
SMSandEMailFunction。然后点击Create按钮——Authorization level选项可以是任何值。 -
移除默认代码,替换为以下清单中显示的代码,然后点击顶部菜单中的保存按钮:
#r "SendGrid"#r "Newtonsoft.Json"#r "Twilio.Api"using System.Net;using System;using SendGrid.Helpers.Mail;using Microsoft.Azure.WebJobs.Host;using Newtonsoft.Json;using Twilio;using System.Configuration;public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log, out Mail message,out SMSMessage sms){log.Info("C# HTTP trigger function processed a request.");string alldata = req.Content.ReadAsStringAsync().GetAwaiter().GetResult();message = new Mail();var personalization = new Personalization();personalization.AddBcc(new Email(ConfigurationManager.AppSettings["bccStakeholdersEmail"]));personalization.AddTo(new Email(ConfigurationManager.AppSettings["toStakeholdersEmail"]));var messageContent = new Content("text/html", alldata);message.AddContent(messageContent);message.AddPersonalization(personalization);message.Subject = "Key Vault assets Expiring soon..";message.From = new Email(ConfigurationManager.AppSettings["serviceEmail"]);string msg = alldata;sms = new SMSMessage();sms.Body = msg;sms.To = ConfigurationManager.AppSettings["adminPhone"];sms.From = ConfigurationManager.AppSettings["servicePhone"];return req.CreateResponse(HttpStatusCode.OK, "Hello ");} -
点击左侧菜单中的函数应用名称,然后再次点击主窗口中的应用程序设置链接:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.24.jpg
图 11.24:导航到应用程序设置
-
导航到
adminPhone和servicePhone,这两个号码应该已经在 Twilio 网站上配置。servicePhone是由 Twilio 生成的用于发送短信的电话号码,adminPhone是管理员的电话号码,短信将发送到该号码。还要注意,Twilio 要求目标电话号码根据国家/地区采用特定格式(例如,印度的格式是
+91 xxxxx xxxxx)。请注意号码中的空格和国家代码。我们还需要在应用程序设置中添加 SendGrid 和 Twilio 的密钥。这些设置在以下清单中提到。你可能已经通过之前的步骤获取了这些值:
-
SendGridAPIKeyAsAppSetting的值是 SendGrid 的密钥。 -
TwilioAccountSid是 Twilio 账户的系统标识符。该值已在步骤 9:开始使用 Twilio中复制并存储在临时位置。 -
TwilioAuthToken是 Twilio 账户的令牌。该值已在之前的步骤中复制并存储在临时位置。
-
-
通过点击顶部菜单中的保存按钮保存设置:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.25.jpg
图 11.25:配置应用程序设置
-
点击左侧菜单中函数名称下方的集成链接,然后点击**+ 新输出**。这是为了为 SendGrid 服务添加输出:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.26.jpg
图 11.26:向函数应用添加输出
-
接下来,选择SendGrid;系统可能会要求你安装 SendGrid 扩展。安装扩展,这可能需要几分钟:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.27.jpg
图 11.27:配置函数应用
-
安装扩展后,输出配置表单将出现。表单中的重要配置项是消息参数名称和SendGrid API 密钥应用设置。保持消息参数名称的默认值,然后点击下拉列表选择SendGridAPIKeyAsAppSetting作为 API 应用设置密钥。该配置已在应用设置配置的前一步中完成。表单应按图 11.28所示进行配置,然后点击保存按钮:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.28.jpg
图 11.28:设置 SendGrid
-
再次点击**+ 新建输出**;这是为了为 Twilio 服务添加输出。
-
然后,选择Twilio SMS。系统可能会提示你安装 Twilio SMS 扩展。安装该扩展,安装过程大约需要几分钟。
-
安装扩展后,输出配置表单会出现。此表单中的重要配置项是
sms。这样做是因为message参数已经被用于 SendGrid 服务参数。确保TwilioAccountSid的值以及Auth Token 设置的值是TwilioAuthToken。这些值在应用设置配置的前一个步骤中已经配置过了。该表单应该按图 11.29的示例进行配置,然后点击保存:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.29.jpg
图 11.29:设置 Twilio SMS 输出
我们的 SendGrid 和 Twilio 账户已准备好。现在是时候使用连接器并将其添加到逻辑应用中。在接下来的部分,我们将创建逻辑应用,并使用连接器与我们迄今为止创建的资源进行交互。
步骤 11:创建逻辑应用
在此步骤中,我们将创建一个新的逻辑应用工作流。我们已经编写了一个 Azure 自动化运行簿,它查询所有密钥保管库中的密钥,并在发现其中任何密钥将在一个月内到期时发布事件。逻辑应用的工作流作为这些事件的订阅者:
-
逻辑应用菜单中的第一步是创建一个逻辑应用工作流。
-
点击创建按钮后填写弹出的表单。我们正在将逻辑应用配置到与该解决方案其他资源相同的资源组中。
-
在逻辑应用被配置后,它将打开设计器窗口。请选择空白逻辑应用,该选项位于模板部分。
-
在弹出的窗口中,添加一个可以订阅 Event Grid 的触发器。逻辑应用提供了一个 Event Grid 触发器,你可以搜索它以查看是否可用。
-
接下来,选择**当资源事件发生时(预览)**触发器:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.30.jpg
图 11.30:从 Event Grid 选择触发器
-
在弹出的窗口中,选择与服务主体连接。
提供服务主体详细信息,包括应用 ID(客户端 ID)、租户 ID 和密码。此触发器不接受使用证书进行身份验证的服务主体,它仅接受使用密码的服务主体。在此阶段创建一个使用密码进行身份验证的新服务主体(有关基于密码身份验证的服务主体创建步骤,请参考之前的第 2 步),并使用新创建的服务主体的详细信息进行 Azure Event Grid 配置,如图 11.31所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.31.jpg
图 11.31:提供服务主体的连接详细信息
-
选择订阅。根据服务主体的范围,相关内容会自动填充。选择Microsoft.EventGrid.Topics作为资源类型值,并将自定义主题的名称设置为ExpiredAssetsKeyVaultEvents:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.32.jpg
图 11.32:提供事件网格触发器详细信息
-
上一步将创建一个连接器,连接信息可以通过点击更改连接来修改。
-
事件网格触发器的最终配置应类似于图 11.33:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.33.jpg
图 11.33:事件网格触发器概览
-
在事件网格触发器后添加一个新的解析 JSON活动——此活动需要 JSON 架构。通常,架构不可用,但如果提供有效的 JSON,它会帮助生成架构:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.34.jpg
图 11.34:解析 JSON 活动
-
点击使用示例负载生成架构并提供以下数据:
{"ExpiryDate": "","SecretName": "","VaultName": "","SecretCreationDate": "","IsSecretEnabled": "","SecretId": ""}这里可能会有一个问题,关于示例负载。在此阶段,如何计算事件网格发布者生成的负载?答案在于这个示例负载与在 Azure 自动化运行簿中数据元素所使用的完全相同。你可以再次查看那个代码片段:
data = @{"ExpiryDate" = $certificate.Expires "CertificateName" = $certificate.Name.ToString()"VaultName" = $certificate.VaultName.ToString()"CertificateCreationDate" = $certificate.Created.ToString()"IsCertificateEnabled" = $certificate.Enabled.ToString()"CertificateId" = $certificate.Id.ToString()} -
内容框应包含来自先前触发器的动态内容,如图 11.35所示:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.35.jpg
图 11.35:将动态内容提供给解析 JSON 活动
-
在解析 JSON后添加另一个Azure Functions操作,然后选择选择 Azure 函数。选择先前创建的名为NotificationFunctionAppBook和SMSAndEmailFunction的 Azure 函数应用:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.36.jpg
图 11.36:添加 Azure Functions 操作
-
点击请求正文文本区域,并用以下代码填充它。这是为了在将数据发送到 Azure 函数之前将其转换为 JSON:
{"alldata" :} -
将光标放在前述代码中的
":"后,点击添加动态内容 | 正文,从先前的活动中获取:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.37.jpg图 11.37:在将数据发送到 Azure 函数之前将数据转换为 JSON
-
保存整个逻辑应用程序,它应如下所示:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.38.jpg
图 11.38:逻辑应用程序工作流
一旦保存了逻辑应用程序,您的解决方案就准备好进行测试。如果没有密钥或机密,请尝试添加具有过期日期的密钥或机密,以便您可以确认解决方案是否正常工作。
测试
将一些具有过期日期的机密和证书上传到 Azure Key Vault,并执行 Azure 自动化运行簿。该运行簿已安排按计划运行。此外,运行簿还将向 Event Grid 发布事件。逻辑应用程序应启用,它会捕捉到事件,并最终调用 Azure 函数以发送电子邮件和短信通知。
电子邮件应如下所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Figure_11.39.jpg
图 11.39:关于即将过期密钥的电子邮件
在本练习中,我们遇到了一个问题,设计了一个解决方案并加以实施。这正是架构师角色中会发生的事情。客户会提出具体的需求,基于这些需求,您必须开发解决方案。基于此,我们即将结束本章内容。让我们快速回顾一下我们讨论过的内容。
总结
本章介绍了逻辑应用程序,并展示了使用多个 Azure 服务的完整端到端解决方案。本章重点介绍了创建集成多个 Azure 服务的架构,以实现端到端解决方案。解决方案中使用的服务包括 Azure 自动化、Azure 逻辑应用程序、Azure 事件网格、Azure 函数、SendGrid 和 Twilio。这些服务通过 Azure 门户和 PowerShell 实现,并使用服务主体作为服务帐户。本章还展示了多种使用密码和证书身份验证创建服务主体的方法。
解决问题的方法有多种。您可以在逻辑应用程序中使用 Outlook 触发器,而不是 SendGrid。一个问题有许多解决方案,选择哪一种取决于您采取的方案。您对服务越熟悉,选择的余地就越大。在下一章中,您将学习到事件在 Azure 和 Azure 应用程序架构中的重要性。
第十二章:12. Azure 大数据事件解决方案
事件无处不在!任何改变工作项状态的活动或任务都会生成一个事件。由于基础设施不足以及廉价设备的缺乏,物联网(IoT)此前并未获得太多关注。从历史上看,组织使用的是来自互联网服务提供商(ISP)的托管环境,这些环境上仅有监控系统。这些监控系统产生的事件少之又少。
然而,随着云计算的兴起,事物正在迅速变化。随着云端部署的增加,尤其是平台即服务(PaaS)服务的普及,组织不再需要过多地控制硬件和平台,每当环境发生变化时,都会触发一个事件。随着云事件的出现,物联网变得越来越重要,事件也开始成为中心。
另一个最近的现象是数据可用性迅速增长。数据的速度、种类和数量急剧增加,存储和处理数据的需求也随之上升。多个解决方案和平台相继出现,例如 Hadoop、用于存储的数据湖、用于分析的数据湖和机器学习服务。
除了存储和分析外,还有一种需求是能够从各种来源摄取成千上万事件和消息的服务。还需要能够处理时间数据的服务,而不是处理整个数据快照的服务。例如,事件数据/物联网数据被用于做出基于实时或近实时数据的决策的应用程序,例如交通管理系统或监控温度的系统。
Azure 提供了大量帮助捕获和分析传感器实时数据的服务。在本章中,我们将介绍 Azure 中的几种事件服务,具体如下:
-
Azure Event Hubs
-
Azure Stream Analytics
还有其他事件服务,例如 Azure Event Grid,本章未涉及;然而,它们在*第十章,使用 Azure 函数的 Azure 集成服务(耐久函数和代理函数)*中有广泛介绍。
引入事件
事件是 Azure 和 Azure 应用架构中的重要构件。事件遍布整个软件生态系统。一般来说,任何采取的行动都会导致一个事件的发生,该事件可以被捕捉,然后采取进一步的行动。为了推动这个讨论,首先需要理解事件的基本概念。
事件有助于捕获目标资源的新状态。消息是条件或状态变化的轻量级通知。事件与消息不同。消息与业务功能相关,例如将订单详情发送到另一个系统。它们包含原始数据,并且可能很大。相比之下,事件则不同;例如,虚拟机被停止就是一个事件。图 12.1演示了从当前状态到目标状态的转变:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_01.jpg
图 12.1:由于事件引起的状态转变
事件可以作为历史数据存储在持久存储中,事件还可以用来发现持续出现的模式。事件可以被视为不断流动的数据。为了捕获、摄取和分析一连串的数据,需要特定的基础设施组件,这些组件能够读取一小段数据并提供洞察力,这就是 Stream Analytics 服务的作用所在。
事件流处理
在数据流式传输过程中对事件进行处理,能够提供有关数据的实时洞察。时间窗口可以是 15 分钟或一小时——窗口由用户定义,并取决于要从数据中提取的洞察。例如,信用卡刷卡,每分钟会有成千上万次刷卡事件,欺诈检测可以在流式事件上进行,时间窗口为一到两分钟。
事件流处理指的是能够随时接受数据的服务,而不是按周期性接收数据。例如,事件流应能够随时接收设备发送的温度信息,而不是让数据在队列或暂存环境中等待。
事件流处理还具有在数据传输过程中查询数据的能力。这是暂时存储的数据,查询发生在移动数据上;因此,数据不是静态的。其他数据平台无法实现这一功能,它们只能查询已存储的数据,而无法查询刚刚摄取的临时数据。
事件流服务应能够轻松扩展,接受数百万甚至数十亿个事件。它们应具有高度可用性,使得源可以随时向其发送事件和数据。实时数据摄取并能够在这些数据上工作,而不是在其他位置存储的数据,是事件流处理的关键。
但当我们已经有了许多具备高级查询执行能力的数据平台时,为什么还需要事件流处理呢?事件流处理的主要优势之一是它提供实时洞察和信息,而这些信息的价值依赖于时间。几分钟或几小时后得到的相同信息可能就不那么有用了。让我们考虑一些处理传入数据非常重要的场景。这些场景是现有数据平台无法有效且高效解决的:
-
信用卡欺诈检测:应该在发生欺诈交易时及时进行。
-
来自传感器的遥测信息:对于发送环境关键信息的物联网设备,用户应在发现异常时及时收到通知。
-
实时仪表盘:事件流处理用于创建显示实时信息的仪表盘。
-
数据中心环境遥测:这将让用户知道是否有入侵、安保漏洞、组件故障等问题发生。
企业内应用事件流处理的可能性非常多,它的重要性无法过分强调。
Event Hubs
Azure Event Hubs 是一个流处理平台,提供与流式事件的获取和存储相关的功能。
它可以从多种来源获取数据;这些来源可以是物联网传感器或任何使用 Event Hubs 软件开发工具包 (SDK) 的应用程序。它支持多种协议来获取和存储数据。这些协议是行业标准,包括以下几种:
-
HTTP:这是一种无状态的选项,不需要活动会话。
-
高级消息队列协议 (AMQP):这需要一个活动会话(即通过套接字建立的连接),并与 传输层安全性 (TLS) 和 安全套接字层 (SSL) 一起使用。
-
Apache Kafka:这是一种类似于流分析的分布式流处理平台。然而,流分析旨在对来自多个数据源(如物联网传感器和网站)的数据流进行实时分析。
Event Hubs 是一个事件获取服务。它不能查询请求并将查询结果输出到其他位置。这是 Stream Analytics 的责任,后文将介绍。
要从门户创建 Event Hubs 实例,请在市场中搜索 Event Hubs 并点击 创建。选择一个订阅和现有的资源组(或创建一个新的)。为 Event Hubs 命名空间提供名称,选择首选的 Azure 区域进行托管,定价层级(后文将解释 Basic 或 Standard),以及吞吐量单元的数量(后文将解释):
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_02.jpg
图 12.2:创建 Event Hubs 命名空间
Event Hubs 作为一个 PaaS 服务,具有高度分布式、高可用性和高度可扩展性。
Event Hubs 提供以下两种 SKU 或定价层:
-
基础版:此 SKU 支持一个消费者组,并且可以保留消息 1 天。最多支持 100 个中介连接。
-
标准版:此 SKU 最多支持 20 个消费者组,能够保留消息 1 天,并且可以额外存储 7 天的消息。最多支持 1,000 个中介连接。还可以在此 SKU 中定义策略。
图 12.3展示了在创建新 Event Hubs 命名空间时可用的不同 SKU。它提供了选择适当定价层的选项,以及其他重要细节:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_03.jpg
图 12.3:Event Hubs SKUs
吞吐量也可以在命名空间级别进行配置。命名空间是容器,由同一订阅和区域中的多个事件中心组成。吞吐量以吞吐量单元(TUs)来计算。每个 TU 提供:
-
每秒最多 1 MB 的入站流量,或者每秒最多 1,000 个入站事件和管理操作。
-
每秒最多 2 MB 的出站流量,或者每秒最多 4,096 个事件和管理操作。
-
最多可存储 84 GB 的存储空间。
TUs 的数量可以从 1 到 20 不等,并且按小时计费。
需要注意的是,Event Hubs 命名空间创建后无法更改 SKU。选择 SKU 之前需要进行充分的考虑和规划。规划过程应包括确定所需的消费者组数量以及感兴趣读取事件的应用程序数量。
此外,并非每个区域都提供标准版 SKU。在设计和实现 Event Hub 时应检查其可用性。检查区域可用性的 URL 是azure.microsoft.com/global-infrastructure/services/?products=event-hubs。
Event Hubs 架构
Event Hubs 架构有三个主要组成部分:事件生产者、事件中心和事件消费者,如下图所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_04.jpg
图 12.4:Event Hubs 架构
事件生产者生成事件并将其发送到事件中心。事件中心存储接收的事件,并将这些数据提供给事件消费者。事件消费者是对这些事件感兴趣的任何实体,它连接到事件中心以提取数据。
创建 Event Hubs 时必须先创建 Event Hubs 命名空间。Event Hubs 命名空间作为容器,可以托管多个事件中心。每个 Event Hubs 命名空间提供一个唯一的基于 REST 的端点,供客户端用于向 Event Hubs 发送数据。此命名空间与 Service Bus 组件(如主题和队列)所需的命名空间相同。
事件中心命名空间的连接字符串由其 URL、策略名称和密钥组成。以下代码块展示了一个示例连接字符串:
Endpoint=sb://demoeventhubnsbook.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=M/E4eeBsr7DAlXcvw6ziFqlSDNbFX6E49Jfti8CRkbA=
这个连接字符串可以在命名空间的共享访问签名(SAS)菜单项中找到。命名空间可以定义多个策略,每个策略具有不同的访问级别。访问级别如下:
-
管理:此选项可以从管理角度管理事件中心。它还具有发送和监听事件的权限。
-
发送:此选项可以将事件写入事件中心。
-
监听:此选项可以从事件中心读取事件。
默认情况下,在创建事件中心时会创建RootManageSharedAccessKey策略,如图 12.5所示。策略有助于在事件中心上创建细粒度的访问控制。与每个策略相关联的密钥由消费者用来确定其身份;还可以创建附加策略,并使用之前提到的三种访问级别的任何组合:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_05.jpg
图 12.5:事件中心中的共享访问策略
可以通过执行以下操作,从事件中心命名空间服务中创建事件中心:
-
点击左侧菜单中的事件中心,然后在结果屏幕中点击**+ 事件中心**:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_06.jpg
图 12.6:从 Azure 门户创建事件中心
-
接下来,提供分区数和消息保留字段的值,以及你选择的名称。然后,选择关闭作为捕获选项,如图 12.7所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_07.jpg
图 12.7:创建新的事件中心
创建事件中心后,你将在事件中心列表中看到它,如图 12.8所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_08.jpg
图 12.8:已创建的事件中心列表
事件中心还允许通过名为“捕获”的功能直接将事件存储到存储账户或数据湖中。
捕获功能帮助将摄取的数据自动存储到 Azure 存储账户或 Azure 数据湖中。此功能确保数据的摄取和存储在一个步骤中完成,而不是将数据转移到存储中作为单独的活动:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_09.jpg
图 12.9:捕获功能选项
可以通过在事件中心级别添加新策略,将单独的策略分配给每个事件中心。
创建策略后,可以从 Azure 门户中安全访问签名左侧菜单项获取连接字符串。
由于一个命名空间可以包含多个事件中心,单个事件中心的连接字符串将类似于以下代码块。这里的区别在于密钥值和添加了EntityPath,它指向事件中心的名称:
Endpoint=sb://azuretwittereventdata.servicebus.windows
=rxEu5K4Y2qsi5wEeOKuOvRnhtgW8xW35UBex4VlIKqg=;EntityPath=myeventhub
在创建事件中心时,我们必须保持捕获选项设置为关闭,但在事件中心创建后可以重新打开它。它有助于将事件自动保存到 Azure Blob 存储或 Azure 数据湖存储帐户中。大小和时间间隔的配置如图 12.10所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_10.jpg
图 12.10:选择捕获事件的大小和时间间隔
在创建事件中心时,我们没有涵盖分区和消息保留选项的概念。
分区是与任何数据存储的可扩展性相关的重要概念。事件在事件中心内会保留特定的时间。如果所有事件都存储在同一个数据存储中,那么扩展这个数据存储将变得极其困难。每个事件生产者都会连接到同一个数据存储并将事件发送到其中。与此相比,具有分区能力的数据存储可以将相同的数据分割成多个更小的数据存储,每个存储都有一个唯一的标识值。
更小的数据存储被称为分区,定义该分区的值被称为分区键。这个分区键是事件数据的一部分。
现在,事件生产者可以连接到事件中心,并根据分区键的值,事件中心会将数据存储在适当的分区中。这将允许事件中心同时并行地接收多个事件。
确定分区数量是事件中心可扩展性的一个关键方面。图 12.11 显示了事件中心如何使用分区键将接收到的数据存储在适当的分区中:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_11.jpg
图 12.11:事件中心中的分区
需要理解的是,一个分区可能有多个键。用户决定需要多少个分区,事件中心则会内部决定最佳的方式在这些分区之间分配分区键。每个分区都会使用时间戳按顺序存储数据,较新的事件会附加到分区的末尾。
需要注意的是,一旦事件中心创建完成,就无法更改分区的数量。
还需要记住,分区还可以为读取事件的应用程序带来并行性和并发性。例如,如果有 10 个分区,10 个并行读取器可以同时读取事件,而不会出现性能下降。
消息保留期指的是事件应该存储的时间段。在保留期过后,事件将被丢弃。
消费者组
消费者是从事件中心读取事件的应用程序。消费组是为消费者创建的,以便消费者连接到并读取事件。一个事件中心可以有多个消费组,每个消费组都可以访问事件中心中的所有分区。每个消费组都会针对事件中心中的事件形成一个查询。应用程序可以使用消费组,每个应用程序将看到事件中心事件的不同视图。在创建事件中心时,会自动创建一个默认的$default消费组。为了优化性能,最好将一个消费者与一个消费组关联。然而,每个消费组中的每个分区最多可以有五个读取器:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_12.jpg
图 12.12:消费组中的事件接收器
现在你已经理解了消费组的概念,接下来我们将深入了解 Event Hubs 吞吐量的概念。
吞吐量
分区有助于扩展性,而吞吐量则决定了每秒的容量。那么,在 Event Hubs 中,容量是什么?它是每秒可以处理的数据量。
在 Event Hubs 中,一个单一的 TU 支持以下内容:
-
每秒 1 MB 的数据摄取或每秒 1,000 个事件(以先发生者为准)
-
每秒 2 MB 的数据输出或每秒 4,096 个事件(以先发生者为准)
自动扩展选项在当传入/传出事件的数量或传入/传出的总大小超过阈值时,自动增加吞吐量。吞吐量会随需求自动扩展或收缩,而不是进行限速。在命名空间创建时的吞吐量配置如图 12.13所示。再次强调,决定 TUs 时需要慎重考虑:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_13.jpg
图 12.13:选择 TUs 并启用自动扩展
Stream Analytics 入门
Event Hubs 是一个高度可扩展的数据流平台,因此我们需要另一个可以将这些事件作为流处理的服务,而不仅仅是存储数据。Stream Analytics 帮助处理和检查大数据流,Stream Analytics 作业则帮助执行事件处理。
Stream Analytics 可以处理每秒数百万个事件,而且入门非常简单。Azure Stream Analytics 是一个完全由 Azure 管理的 PaaS 服务。Stream Analytics 的客户无需管理底层硬件和平台。
每个作业包含多个输入、输出和一个查询,该查询将传入数据转换为新的输出。Stream Analytics 的整个架构如图 12.14所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_14.jpg
图 12.14:Azure Stream Analytics 架构
在图 12.14中,事件源显示在最左侧。这些是生成事件的源。它们可以是物联网设备、用任何编程语言编写的自定义应用程序,或者来自其他 Azure 平台的事件,例如 Log Analytics 或 Application Insights。
这些事件必须首先被摄取到系统中,Azure 提供了许多服务来帮助摄取这些数据。我们已经查看了 Event Hubs 以及它们如何帮助摄取数据。还有其他服务,如 IoT Hub,也有助于摄取特定设备和传感器的数据。IoT Hub 和数据摄取的详细信息请参见第十一章,设计物联网解决方案。这些摄取的数据在到达流时会进行处理,处理工作由 Stream Analytics 完成。Stream Analytics 的输出可以传输到展示平台,如 Power BI,向利益相关者展示实时数据,或传输到存储平台,如 Cosmos DB、Data Lake Storage 或 Azure 存储,数据可以稍后通过 Azure Functions 和 Service Bus 队列进行读取和处理。
Stream Analytics 有助于从实时摄取的数据中在时间窗口框架内获取洞察,并帮助识别模式。
它通过三种不同的任务来完成这一过程:
-
输入:数据应该在分析过程中被摄取。数据可以来源于 Event Hubs、IoT Hub 或 Azure Blob 存储。可以使用存储账户和 SQL 数据库的多个独立参考输入来查询数据中的查找数据。
-
查询:这是 Stream Analytics 执行核心任务的地方,它分析摄取的数据并提取有意义的洞察和模式。它通过 JavaScript 用户定义函数、JavaScript 用户定义聚合、Azure 机器学习和 Azure 机器学习工作室来实现。
-
输出:查询结果可以发送到多种不同类型的目标,其中突出的目标包括 Cosmos DB、Power BI、Synapse Analytics、Data Lake Storage 和 Functions:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_15.jpg
图 12.15:Stream Analytics 过程
Stream Analytics 能够每秒摄取数百万个事件,并可以在这些事件上执行查询。
输入数据支持以下三种格式之一:
-
JavaScript 对象表示法(JSON):这是一种轻量级的基于文本的格式,易于人类阅读。它由名称-值对组成;以下是一个 JSON 事件示例:
{ "SensorId" : 2, "humidity" : 60, "temperature" : 26C } -
逗号分隔值(CSV):这些也是纯文本值,使用逗号分隔。图 12.16中展示了一个 CSV 示例。第一行是表头,包含三个字段,后面是两行数据:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_16.jpg
图 12.16:纯文本值
-
Avro:这种格式类似于 JSON;然而,它以二进制格式存储,而不是文本格式:
{ "firstname": "Ritesh", "lastname": "Modi", "email": "ritesh.modi@outlook.com" }
然而,这并不意味着流分析只能使用这三种格式来摄取数据。它还可以创建自定义的 .NET 序列化器,通过这些序列化器,任何格式的数据都可以根据序列化器的实现进行摄取。您可以按照docs.microsoft.com/azure/stream-analytics/custom-deserializer-examples中的步骤编写自定义序列化器。
流分析不仅可以接收事件,还提供对接收到数据的高级查询功能。这些查询可以从时间数据流中提取重要见解并输出。
如图 12.17所示,有一个输入数据集和一个输出数据集;查询将事件从输入移动到输出。INTO 子句指向输出位置,FROM 子句指向输入位置。查询非常类似于 SQL 查询,因此 SQL 程序员的学习曲线不会太陡峭:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_17.jpg
图 12.17:接收 Twitter 数据的流分析查询
事件中心提供了将查询输出发送到目标位置的机制。撰写本文时,流分析支持多种事件和查询输出的目标位置,如前所示。
还可以定义可以在查询中重复使用的自定义函数。提供了四种选项来定义自定义函数。
-
Azure 机器学习
-
JavaScript 用户定义的函数
-
JavaScript 用户定义的聚合
-
Azure 机器学习工作室
托管环境
流分析作业可以在云端运行的主机上运行,也可以在物联网边缘设备上运行。物联网边缘设备是靠近物联网传感器的设备,而不是在云上。图 12.18展示了新建流分析作业面板:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_18.jpg
图 12.18:创建一个新的流分析作业
让我们详细查看流处理单元。
流处理单元
从图 12.18中可以看到,流分析中唯一的配置是流处理单元。流处理单元指的是为运行流分析作业分配的资源(即 CPU 和内存)。最小和最大流处理单元分别为 1 和 120。
流处理单元必须根据数据量和在该数据上执行的查询数量预先分配;否则,作业将失败。
可以通过 Azure 门户向上或向下扩展流处理单元。
使用事件中心和流分析的示例应用程序
在本节中,我们将创建一个包含多个 Azure 服务的示例应用程序,包含 Azure 逻辑应用、Azure 事件中心、Azure 存储和 Azure 流分析。
在这个示例应用程序中,我们将读取所有包含“Azure”一词的推文,并将其存储在 Azure 存储账户中。
要创建这个解决方案,我们首先需要配置所有必要的资源。
配置一个新的资源组
导航到 Azure 门户,使用有效凭据登录,点击 + 创建资源,搜索 资源组。从搜索结果中选择 资源组,然后创建一个新的资源组。接着,提供一个名称并选择一个合适的位置。请注意,所有资源应托管在同一个资源组和位置中,以便于删除它们:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_19.jpg
图 12.19:在 Azure 门户中配置一个新的资源组
接下来,我们将创建一个 Event Hubs 命名空间。
创建一个 Event Hubs 命名空间
点击 + 创建资源,并搜索 Event Hubs。从搜索结果中选择 Event Hubs,然后创建一个新的事件中心。接着,提供一个名称和位置,并根据之前创建的资源组选择一个订阅。选择 Standard 作为定价层,并且勾选 启用自动扩展,如 图 12.20 所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_20.jpg
图 12.20:创建一个 Event Hubs 命名空间
到现在为止,应该已经创建了一个 Event Hubs 命名空间。在创建事件中心之前,必须先有一个命名空间。下一步是配置事件中心。
创建一个事件中心
在 Event Hubs 命名空间服务中,点击左侧菜单中的 Events Hubs,然后点击 + Event Hubs 创建一个新的事件中心。命名为 azuretwitterdata,并提供一个最佳的分区数量和 消息保留 值:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_21.jpg
图 12.21:创建 azuretwitterdata 事件中心
在此步骤之后,您将拥有一个事件中心,用于将事件数据发送到下游服务,这些数据将存储在持久存储中,如数据湖或 Azure 存储帐户中。
配置一个逻辑应用
在资源组配置完成后,点击 + 创建资源,搜索 Logic Apps。从搜索结果中选择 Logic Apps,然后创建一个新的逻辑应用。接着,提供一个名称和位置,并根据之前创建的资源组选择一个订阅。启用 Log Analytics 是一个好习惯。Logic Apps 的详细内容请参考 第十一章,使用 Azure Logic Apps、Event Grid 和 Functions 构建 Azure 解决方案。该逻辑应用负责使用一个账户连接 Twitter 并获取所有包含 Azure 的推文:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_22.jpg
图 12.22:创建一个逻辑应用
创建逻辑应用后,选择设计表面上的 当发布新推文时 触发器,登录并按 图 12.23 中所示进行配置。配置此触发器之前,您需要一个有效的 Twitter 账户:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_23.jpg
图 12.23:配置推文接收频率
接下来,在设计器表面上拖动一个发送事件动作;该动作负责将推文发送到事件中心:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_24.jpg
图 12.24:添加一个动作将推文发送到事件中心
选择先前步骤中创建的事件中心的名称。
内容文本框中指定的值是一个表达式,动态组合了 Logic Apps 提供的函数和 Twitter 数据。点击添加动态内容,会弹出一个对话框,通过它可以构建表达式:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_25.jpg
图 12.25:使用动态表达式配置 Logic Apps 活动
表达式的值如下:
json(concat('{','tweetdata:' ,'"',triggerBody()?['TweetText'],'"', '}'))
在接下来的部分,我们将配置存储账户。
配置存储账户
点击**+ 创建资源并搜索存储账户**。从搜索结果中选择存储账户并创建一个新的存储账户。然后,提供名称和位置,并根据之前创建的资源组选择一个订阅。最后,选择StorageV2作为账户类型,Standard作为性能,并选择本地冗余存储(LRS)作为复制字段。
接下来,我们将创建一个 Blob 存储容器,以存储来自流分析的数据。
创建存储容器
流分析将数据输出为文件,这些文件将存储在 Blob 存储容器中。一个名为twitter的容器将被创建在 Blob 存储中,如图 12.26所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_26.jpg
图 12.26:创建存储容器
我们将在云端创建一个新的流分析作业,并将流单位设置为默认配置。
创建流分析作业
该流分析作业的输入来自事件中心,因此我们需要从输入菜单进行配置:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_27.jpg
图 12.27:创建一个输入流分析作业
流分析作业的输出是一个 Blob 存储账户,因此需要相应地配置输出。提供适合本练习的路径模式;例如,{datetime:ss} 是我们在此练习中使用的路径模式:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_28.jpg
图 12.28:创建一个作为输出的 Blob 存储账户
该查询非常简单;你只是将数据从输入复制到输出:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_29.jpg
图 12.29:查询以复制 Twitter 信息流
虽然这个例子只是涉及数据复制,但也可以有更复杂的查询,用于在将数据加载到目标之前执行转换。
这就完成了应用程序的所有步骤;现在你应该能够运行它了。
运行应用程序
Logic App 应该已经启用,且流分析(Stream Analytics)应该正在运行。现在,运行 Logic App;它会创建一个作业来执行其中的所有活动,如图 12.30所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_30.jpg
图 12.30:GetAzureTwitterData 应用概述
存储账户容器应该获取数据,如图 12.31所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_31.jpg
图 12.31:检查存储账户容器数据
作为一个练习,你可以扩展这个示例解决方案,并每三分钟评估一次推文的情感。这样的 Logic Apps 工作流如下所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_12_32.jpg
图 12.32:分析推文情感的流程图
为了检测情感,你需要使用文本分析 API,且在 Logic Apps 中使用之前需要进行配置。
摘要
本章重点介绍了与事件流和存储相关的主题。事件已经成为整体解决方案架构中的一个重要考虑因素。我们介绍了重要的资源,如事件中心(Event Hubs)和流分析(Stream Analytics),以及一些基础概念,如消费者组(consumer groups)和吞吐量(throughputs),并通过与 Logic Apps 一起使用它们创建了端到端的解决方案。你了解到,事件来自多个源,并且为了实时获取活动及其相关事件的洞察,事件中心和流分析等服务发挥着重要作用。在下一章,我们将学习如何集成 Azure DevOps 和 Jenkins,并在开发解决方案时实施一些行业最佳实践。
第十三章:13. 集成 Azure DevOps
在上一章中,您了解了大数据事件和它与 Azure 的 Event Hubs 和 Stream Analytics 服务的关系。软件开发是一个复杂的工作,涉及多个流程和工具,并且涉及来自不同部门的人们。他们需要共同合作,协调一致。由于有这么多变量,当您向最终客户交付时,风险是非常高的。一个小小的疏漏或配置错误可能导致应用程序崩溃。本章将讨论采纳和实施减少这些风险的实践,确保能够一次又一次地向客户交付高质量的软件。
在深入了解 DevOps 之前,以下是软件公司面临的 DevOps 解决的一些问题:
-
不欢迎变革的僵化组织
-
耗时的过程
-
孤立的团队在信息孤岛中工作
-
单体设计和大爆炸式部署
-
手动执行
-
缺乏创新
在本章中,我们将涵盖以下主题:
-
DevOps
-
DevOps 实践
-
Azure DevOps
-
DevOps 准备
-
DevOps 针对 PaaS 解决方案
-
基于虚拟机的 DevOps(IaaS)解决方案
-
基于容器的 DevOps(IaaS)解决方案
-
Azure DevOps 和 Jenkins
-
Azure 自动化
-
Azure DevOps 工具
DevOps
目前,行业内尚未就 DevOps 的定义达成共识。各组织已经制定了自己的 DevOps 定义,并尝试实施它们。他们有自己的视角,并认为一旦实施了自动化、配置管理,并使用了敏捷流程,就算是实现了 DevOps。
根据我在行业中从事 DevOps 项目的经验,我将 DevOps 定义如下:DevOps 是关于软件系统交付机制的,它涉及将人们聚集在一起,使他们协作和沟通,共同朝着一个共同的目标和愿景努力。它意味着共同承担责任、问责和所有权。它是实施促进协作和服务心态的流程。它使交付机制能够为组织带来敏捷性和灵活性。与普遍的看法相反,DevOps 并非只是关于工具、技术和自动化。这些只是帮助协作、实施敏捷流程并加快更好地交付给客户的促进因素。
网络上有多个 DevOps 的定义,它们并没有错。DevOps 并不提供框架或方法论。它是一组原则和实践,当这些原则和实践在组织、项目或合作中应用时,可以实现 DevOps 及组织的目标和愿景。这些原则和实践不要求使用特定的流程、工具、技术或环境。DevOps 提供的指导可以通过任何工具、技术或流程来实现,尽管某些技术和流程可能比其他技术和流程更适用于实现 DevOps 原则和实践的愿景。
尽管 DevOps 实践可以在任何提供服务和产品的组织中实施,但在本书接下来的部分,我们将从软件开发和任何组织的运维部门的角度来看待 DevOps。
那么,什么是 DevOps?DevOps 被定义为一组原则和实践,将所有团队(包括开发人员和运维人员)从项目一开始就聚集在一起,以更快、更高效、更一致和可预测的方式一次又一次地向最终客户交付价值,从而减少市场推出时间,获得竞争优势。
前述对 DevOps 的定义并未指明或提及任何特定的流程、工具或技术。它也没有规定任何方法论或环境。
在任何组织中实施 DevOps 原则和实践的目标是确保高效且有效地满足利益相关者(包括客户)的需求和期望。
当以下情况发生时,客户的需求和期望得以满足:
-
客户获得他们想要的功能
-
客户在需要的时候获得他们想要的功能
-
客户更快速地获得功能更新
-
交付的质量很高
当一个组织能够满足这些期望时,客户会感到满意并保持忠诚。这反过来又提高了组织的市场竞争力,从而带来更大的品牌和市场估值。它直接影响组织的收入和利润。组织可以进一步投资于创新和客户反馈,带来系统和服务的持续变化,从而保持相关性。
在任何组织中实施 DevOps 原则和实践的过程受到其周围生态系统的指导。这个生态系统由组织所属的行业和领域组成。
DevOps 基于一组原则和实践。我们将在本章稍后的部分详细探讨这些原则和实践。DevOps 的核心原则包括:
-
敏捷性:采用敏捷方法可以增加对变化的整体适应能力,确保能够适应不断变化的环境并保持高效。敏捷流程具有较短的工作周期,且在开发生命周期的早期就能发现问题,而不是在后期,从而减少技术债务。
-
自动化:采用工具和自动化可以提高过程和最终产品的整体效率和可预测性。它有助于更快、更简便且更经济地完成任务。
-
协作:协作指的是共享一个共同的代码库、轮换工作职责、共享数据和信息以及其他有助于提高团队成员生产力的方面,从而支持产品的整体有效交付。
-
反馈:指的是多个团队之间关于有效和无效事物的快速和早期反馈循环。它帮助团队优先处理问题,并在随后的发布版本中修复这些问题。
DevOps 的核心实践包括:
-
持续集成:指的是验证和确认开发人员在代码库中提交的代码质量和正确性的过程。它可以是定时的、手动的或持续的。持续意味着每次开发人员推送代码时,过程都会检查各种质量属性,而定时则意味着按照预定的时间表进行检查。手动是指由管理员或开发人员手动执行。
-
配置管理:这是 DevOps 的重要组成部分,为配置基础设施和应用程序提供指导,配置可以通过从配置管理服务器拉取或按计划推送这些配置来实现。每次执行时,配置管理应将环境恢复到预期的理想状态。
-
持续交付:持续交付指的是应用程序在任何现有环境以及新环境中都能随时准备好部署的状态。它通常通过在开发和测试等较低环境中定义发布来执行。
-
持续部署:持续部署指的是能够自动将环境和应用程序部署到生产环境中的能力。它通常通过生产环境中的发布定义来执行。
-
持续学习:指的是理解运营和客户面临的问题,并确保将这些问题传达给开发和测试团队,以便他们在随后的发布版本中解决这些问题,从而改善应用程序的整体健康和可用性。
DevOps 的本质
DevOps 并不是一种新范式;然而,它正获得越来越多的关注和推广。其采用率处于最高水平,越来越多的公司正在踏上这条道路。我特意将 DevOps 称为“旅程”,因为在 DevOps 的实施过程中有不同的成熟度水平。虽然成功实施持续部署和交付被视为这一旅程中的最高成熟度水平,但采用源代码管理和敏捷软件开发则被视为 DevOps 旅程的第一步。
DevOps 讨论的第一件事之一是打破开发团队和运维团队之间的壁垒。它促使多个团队之间进行紧密合作。DevOps 的核心思想是打破开发者只负责编写代码并在测试完成后将其交给运维进行部署的思维模式。它还意味着打破运维在开发活动中没有角色的观念。运维应当参与产品规划,并且应该清楚即将发布的功能。他们还应持续向开发者提供有关运维问题的反馈,以便在后续版本中进行修复。运维应该影响系统的设计,以改善系统的运作性能。同样,开发者也应当帮助运维团队部署系统,并在发生故障时协助解决问题。
DevOps 的定义提到更快速、更高效地向利益相关者交付系统的端到端流程。但它没有具体说明交付应该多么快速或高效。交付速度应当足够满足组织的领域、行业、客户细分和需求。对于一些组织,季度发布就足够了,而对于其他组织来说,可能需要每周发布。就 DevOps 而言,这两种方式都是有效的,组织可以部署相应的流程和技术来达到他们的发布目标。DevOps 并没有强制规定持续集成/持续交付(CI/CD)的具体时间框架。组织应当根据他们的整体项目、参与情况和组织愿景来识别最适合的 DevOps 原则和实践的实现方式。
定义中还提到了端到端交付。这意味着从系统的规划和交付到服务和运维的各个方面,都应成为 DevOps 采用的一部分。流程应当允许在应用开发生命周期中更大的灵活性、模块化和敏捷性。虽然组织可以自由选择最合适的流程——瀑布模型、敏捷开发、Scrum 等——但通常,组织倾向于采用基于迭代的敏捷流程。这种方式可以在较小的单元中实现更快速的交付,这些单元比大规模交付更容易测试和管理。
DevOps 一直以一致且可预测的方式谈论终端客户。这意味着组织应通过自动化不断交付更新和升级的功能给客户。没有自动化的帮助,我们无法实现一致性和可预测性。手动工作应该不存在,以确保高水平的一致性和可预测性。自动化应当是端到端的,以避免失败。这也表明系统设计应当是模块化的,从而在可靠、可用和可扩展的系统上更快地交付。测试在一致和可预测的交付中扮演着重要角色。
实施这些实践和原则的最终结果是,组织能够满足客户的期望和需求。组织能够比竞争对手更快地增长,并通过持续的创新和改进,进一步提高其产品和服务的质量和能力。
现在,您已经理解了 DevOps 背后的理念,接下来让我们深入了解核心的 DevOps 实践。
DevOps 实践
DevOps 包含多个实践,每个实践为整体流程提供独特的功能。下图展示了它们之间的关系。配置管理、持续集成和持续部署构成了 DevOps 的核心实践。通过结合这三项服务交付软件服务,我们实现了持续交付。持续交付是组织的能力和成熟度,取决于配置管理、持续集成和持续部署的成熟度。持续反馈贯穿于所有阶段,形成反馈环路,帮助提供更优质的客户服务。它贯穿所有 DevOps 实践。接下来,让我们深入了解每项能力和 DevOps 实践:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_01.jpg
图 13.1:DevOps 实践
配置管理
商业应用程序和服务需要一个可以部署的环境。通常,这个环境是由多个服务器、计算机、网络、存储、容器等多个服务组成的基础设施,这些服务共同工作,以便商业应用程序能够在其上部署。商业应用程序被分解成多个服务,这些服务运行在多个服务器上,可以是本地服务器或云服务器,每个服务都有自己的配置以及与基础设施配置相关的需求。简而言之,基础设施和应用程序都是交付系统给客户所需要的,它们都有各自的配置。如果配置发生漂移,应用程序可能无法按预期工作,导致停机和故障。此外,由于应用生命周期管理(ALM)过程要求使用多个阶段和环境,应用程序将被部署到多个不同配置的环境中。应用程序将首先部署到开发环境,供开发人员查看他们工作的结果。然后,它将被部署到多个测试环境,这些环境有不同的配置,用于功能测试、负载和压力测试、性能测试、集成测试等;它还将被部署到预生产环境进行用户验收测试,最后进入生产环境。确保应用程序能够部署到多个环境中而无需进行任何手动配置更改非常重要。
配置管理提供了一套流程和工具,它们帮助确保每个环境和应用程序都有自己的配置。配置管理跟踪配置项,任何从一个环境到另一个环境发生变化的内容都应视为配置项。配置管理还定义了配置项之间的关系,以及一个配置项的变化如何影响其他配置项。
配置管理的使用
配置管理在以下方面提供帮助:
-
基础设施即代码:当通过代码表示基础设施的配置和配置过程,并且相同的代码贯穿整个应用生命周期过程时,这就是基础设施即代码(IaC)。IaC 有助于自动化基础设施的供应和配置。它还以代码的形式表示整个基础设施,可以存储在代码库中并进行版本控制。这使得用户在需要时可以使用先前环境的配置。它还使得能够以一致且可预测的方式多次供应环境。以这种方式供应的所有环境在所有 ALM 阶段中都是一致的和平等的。有许多工具可以帮助实现 IaC,包括 ARM 模板、Ansible 和 Terraform。
-
在服务器上使用
webdeploy包,部署 SQL 服务器架构和数据 (bacpac) 到另一台服务器,并更改 Web 服务器上的 SQL 连接字符串,以指向适当的 SQL 服务器。配置管理为每个部署环境存储应用配置的值。
应用的配置也应当被监控。预期的和期望的配置应始终保持一致。任何偏离预期和期望配置的情况都会使应用不可用。配置管理还能够发现这种偏差,并重新配置应用和环境到其期望的状态。
在实施了自动化配置管理后,团队中的任何人都不需要在生产环境中部署和配置环境及应用。运营团队不再依赖开发团队或繁琐的部署文档。
配置管理的另一个方面是源代码控制。商业应用和服务由代码及其他构件组成,多个团队成员在相同的文件上工作。源代码应始终保持最新,并且应仅由经过身份验证的团队成员访问。代码及其他构件本身就是配置项。源代码控制有助于团队内的协作和沟通,因为每个人都知道其他人的工作内容,并且冲突能够在早期得到解决。
配置管理可以大致分为两类:
-
虚拟机内部
-
虚拟机外部
配置管理工具
接下来讨论虚拟机内部可用的配置管理工具。
所需状态配置
所需状态配置 (DSC) 是微软的一种配置管理平台,作为 PowerShell 的扩展构建。DSC 最初作为 Windows 管理框架 (WMF) 4.0 的一部分发布。它作为 WMF 4.0 和 5.0 的一部分,适用于所有 Windows Server 操作系统,直到 Windows 2008 R2 为止。WMF 5.1 在 Windows Server 2016/2019 和 Windows 10 上开箱即用。
Chef、Puppet 和 Ansible
除了 DSC,还有一系列配置管理工具,如 Chef、Puppet 和 Ansible,这些工具得到 Azure 的支持。本书未涵盖这些工具的详细信息。你可以在这里了解更多:docs.microsoft.com/azure/virtual-machines/windows/infrastructure-automation。
接下来讨论虚拟机外部可用的配置管理工具。
ARM 模板
ARM 模板是 ARM 中资源配置的主要手段。ARM 模板提供了一种声明性模型,通过该模型可以指定资源及其配置、脚本和扩展。ARM 模板基于JavaScript 对象表示法(JSON)格式。它使用 JSON 语法和约定来声明和配置资源。JSON 文件是基于文本的,用户友好且易于阅读。它们可以存储在源代码仓库中,并对其进行版本控制。它们还是表示基础架构即代码的一种方式,可用于在 Azure 资源组中反复地、可预测、一致和统一地配置资源。
模板提供了在设计和实现中保持通用性和模块化的灵活性。模板使我们能够接受用户参数、声明内部变量、帮助定义资源之间的依赖关系、在同一资源组或不同资源组之间链接资源,并执行其他模板。它们还提供了类似脚本语言的表达式和函数,使得模板在运行时动态且可定制。本书有两章专门讲解 ARM 模板:第十五章,使用 ARM 模板进行跨订阅部署 和 第十六章,ARM 模板的模块化设计与实现。
现在是时候关注下一个重要的 DevOps 原则:持续集成。
持续集成
多个开发者编写代码,并最终将其存储在一个公共仓库中。当开发者完成功能开发后,通常会将代码提交到仓库中。这可能在一天内完成,也可能需要几天或几周。一些开发者可能在同一个功能上工作,并且他们可能也会遵循相同的代码推送/提交实践,这些操作可能发生在几天或几周内。这可能会导致代码质量问题。DevOps 的一个原则是尽早发现问题。开发者应该经常将代码提交/推送到仓库,并进行编译检查,确保自己没有引入错误,并且代码与同事编写的代码兼容。如果开发者没有遵循这一实践,他们机器上的代码会变得过于庞大,且很难与其他代码进行集成。此外,如果编译失败,修复过程中产生的问题也会变得困难且耗时。
代码集成
持续集成解决了这些挑战。持续集成通过一系列验证步骤,帮助编译和验证开发人员推送/检查的代码。持续集成创建了一个包含多个步骤的流程。持续集成由持续自动构建和持续自动测试组成。通常,第一个步骤是编译代码。在成功编译之后,每个步骤负责从特定角度验证代码。例如,可以在编译后的代码上执行单元测试,然后执行代码覆盖率测试,检查单元测试执行了哪些代码路径。这些可以揭示是否编写了全面的单元测试,或者是否还有进一步添加单元测试的空间。持续集成的最终结果是可以由持续部署用于将代码部署到多个环境的部署包。
频繁的代码推送
鼓励开发人员每天多次提交代码,而不是几天或几周后才提交。持续集成会在代码提交或推送后立即启动整个管道的执行。如果编译成功,代码测试以及管道中的其他活动会无错误地执行;代码会被部署到测试环境,并进行集成测试。
提高生产力
持续集成提高了开发人员的生产力。开发人员不需要手动编译代码、连续运行多种类型的测试,然后再生成打包文件。它还减少了代码中引入错误的风险,避免代码过时。它为开发人员提供了有关代码质量的早期反馈。总体而言,通过采用持续集成实践,交付的质量更高,交付速度更快。以下是一个持续集成管道的示例:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_02.jpg
图 13.2:持续集成管道
构建自动化
构建自动化由多个任务按顺序执行。通常,第一个任务负责从代码仓库获取最新的源代码。源代码可能包含多个项目和文件。它们会被编译生成构件,如可执行文件、动态链接库和程序集。成功的构建自动化反映了代码中没有编译时错误。
根据项目的性质和类型,构建自动化可能还会包含更多步骤。
测试自动化
测试自动化包括负责验证代码不同方面的任务。这些任务从不同的角度对代码进行测试,并按顺序执行。一般来说,第一步是对代码运行一系列单元测试。单元测试是指通过验证特性在与其他特性隔离的情况下的行为,来测试特性最小单位的过程。它可以是自动化的,也可以是手动的;然而,自动化单元测试更受偏好。
代码覆盖率是另一种自动化测试类型,能够在运行单元测试时执行代码,找出多少代码被执行。它通常以百分比表示,指的是有多少代码可以通过单元测试进行测试。如果代码覆盖率没有接近 100%,那可能是因为开发者没有为该行为编写单元测试,或者未覆盖的代码根本不需要。
测试自动化的成功执行,并且没有出现显著的代码失败后,应开始执行打包任务。根据项目的性质和类型,测试自动化可能还包括更多的步骤。
打包
打包是指生成可部署的工件的过程,例如MSI、NuGet和webdeploy包以及数据库包;对其进行版本控制;然后将它们存储在一个位置,以便其他管道和过程可以使用。
一旦持续集成过程完成,持续部署的过程就会开始,接下来将重点讲解这个过程。
持续部署
当流程达到持续部署时,持续集成已经确保我们拥有完全可用的应用程序部分,接下来可以通过不同的持续部署活动进行处理。持续部署是指通过自动化将业务应用程序和服务部署到预生产环境和生产环境的能力。例如,持续部署可以配置和部署预生产环境,部署应用程序并进行配置。在对预生产环境进行多次有效验证,如功能测试和性能测试后,生产环境将被配置和部署,应用程序通过自动化完成部署。在部署过程中没有手动步骤。每个部署任务都是自动化的。持续部署可以从零开始配置环境并部署应用程序,也可以仅在环境已存在的情况下,部署增量变化。
所有环境都通过自动化使用基础设施即代码(IaC)来配置。这确保了所有环境,无论是开发、测试、预生产还是生产,都是一致的。同样,应用程序通过自动化部署,确保它在所有环境中也被统一部署。这些环境中的配置对于应用程序可能是不同的。
持续部署通常与持续集成集成。当持续集成完成其工作,生成最终的可部署包时,持续部署将启动并开始执行自己的管道。这个管道被称为发布管道。发布管道包含多个环境,每个环境由负责环境配置、环境设置、应用程序部署、应用程序配置、环境操作验证以及在多个环境中测试应用程序的任务组成。
使用持续部署带来了巨大的好处。对整体部署过程有高度的信心,这有助于更快、更无风险地发布到生产环境。出现问题的机会大幅减少。团队的压力也会减轻,如果当前发布存在问题,可以回滚到之前的工作环境:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_03.jpg
图 13.3:持续部署管道
尽管每个系统都要求其发布管道具有自己的配置,但前面图示中展示了一个持续部署的示例。需要注意的是,通常情况下,配置和设置多个环境是发布管道的一部分,并且在进入下一个环境之前,应获取相关的批准。批准过程可以是手动的,也可以是自动的,这取决于组织的成熟度。
接下来,我们将关注与测试环境相关的方面。
测试环境部署
一旦从持续集成中获得构建产物,发布管道就开始启动。发布管道的第一步应该是获取所有的构建产物。此后,发布管道可能会创建一个全新的裸机测试环境,或者重用现有的环境。这再次取决于项目类型和计划在该环境中执行的测试类型。环境会被配置并准备好。应用程序的构建产物会被部署并配置。
测试自动化
在部署应用程序后,可以在环境中执行一系列测试。其中一个测试是功能测试。功能测试主要用于验证应用程序的功能完整性和功能性。这些测试是根据客户需求收集的信息编写的。还可以执行另一组测试,主要与应用程序的可扩展性和可用性相关。这通常包括负载测试、压力测试和性能测试。还应该包括对基础设施环境的操作验证。
预生产环境部署
这与测试环境部署非常相似,唯一的区别是环境和应用程序的配置值会有所不同。
验收测试
验收测试通常由应用程序的相关方进行,可以是手动的,也可以是自动化的。这一步骤是从客户的角度对应用程序功能的正确性和完整性的验证。
部署到生产环境
一旦客户批准,执行与测试和预生产环境部署相同的步骤,唯一的区别是环境和应用程序的配置值专门针对生产环境。部署后进行验证,确保应用程序按照预期运行。
持续交付是一个重要的 DevOps 原则,并且与持续部署非常相似;然而,它们之间还是有一些区别。在下一节中,我们将深入探讨持续交付。
持续交付
持续交付和持续部署听起来可能很相似,但它们并不完全相同。持续部署指的是通过自动化将应用程序部署到多个环境,最终部署到生产环境,而持续交付则是能够生成可随时在任何环境中部署的应用程序包。为了生成可以随时部署的工件,应使用持续集成来生成应用程序工件;然后应使用新的或现有的环境来部署这些工件,并通过自动化进行功能测试、性能测试和用户验收测试。一旦这些活动成功执行且没有错误,应用程序包就被认为是可以随时部署的。持续交付包括持续集成和部署到环境中进行最终验证。它有助于更快地获得来自操作团队和最终用户的反馈,这些反馈可以用于实施后续的迭代。
在下一节中,我们将探讨持续学习。
持续学习
使用之前提到的所有 DevOps 实践,可以创建出色的业务应用程序并将其自动部署到生产环境;然而,如果没有持续改进和反馈原则,DevOps 的好处不会持久。至关重要的是,关于应用程序行为的实时反馈需要从最终用户和运维团队传递给开发团队作为反馈。
反馈应传递给团队,提供有关进展顺利与否的相关信息。
应用程序的架构和设计应考虑到监控、审计和遥测。运维团队应从生产环境收集遥测信息,捕捉任何漏洞和问题,并将其传递给开发团队,以便在随后的版本中修复。
持续学习有助于使应用程序更加健壮,并增强其对故障的韧性。它有助于确保应用程序满足消费者需求。图 13.4 显示了不同团队之间应该实施的反馈循环:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_04.jpg
图 13.4:反馈循环
在了解了与 DevOps 相关的重要实践之后,现在是时候深入了解那些使这些实践成为可能的工具和服务了。
Azure DevOps
让我们来看看另一个顶级在线服务,它能无缝实现持续集成、持续部署和持续交付:Azure DevOps。事实上,称其为一个服务套件并将其整合为一个名称可能更合适。Azure DevOps 是微软提供的 PaaS 服务,托管在云端。相同的服务也可以作为Team Foundation Services(TFS)在本地部署。书中所有示例都使用 Azure DevOps。
根据微软的说法,Azure DevOps 是一个基于云的协作平台,帮助团队共享代码、跟踪工作并发布软件。Azure DevOps 是一个新名称,之前被称为Visual Studio Team Services(VSTS)。Azure DevOps 是一个企业级软件开发工具和服务,使组织能够为其端到端的应用生命周期管理过程提供自动化功能,从规划到部署应用程序,并从软件系统中获取实时反馈。这提高了组织交付高质量软件系统给客户的成熟度和能力。
成功的软件交付涉及高效地将多个流程和活动结合在一起。这包括执行和实施各种敏捷流程、增加团队之间的协作、从一个 ALM 阶段到另一个阶段的无缝自动过渡,以及向多个环境的部署。跟踪和报告这些活动非常重要,以便衡量和改进交付流程。Azure DevOps 使这一切变得简单而易行。它提供了一整套服务,支持以下内容:
-
通过提供整个应用生命周期管理的单一界面,促进每个团队成员之间的协作
-
使用源代码管理服务促进开发团队之间的协作
-
使用测试管理服务促进测试团队之间的协作
-
通过构建管理服务,使用持续集成自动验证代码和打包
-
通过发布管理服务,使用持续部署和交付自动验证应用程序功能、部署和多个环境的配置
-
使用工作管理服务跟踪和管理工作项
以下表格显示了从Azure DevOps左侧导航栏中获取的典型项目可用的所有服务:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/Table_13_01.jpg
表 13.1:Azure DevOps 服务列表
Azure DevOps 中的组织作为一个安全边界和逻辑容器,提供实现 DevOps 策略所需的所有服务。Azure DevOps 允许在一个组织内创建多个项目。默认情况下,项目创建时会创建一个代码库;不过,Azure DevOps 也允许在同一个项目内创建额外的代码库。Azure DevOps 组织、项目和代码库之间的关系如图 13.5所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_05.jpg
图 13.5:Azure DevOps 组织、项目和代码库之间的关系
Azure DevOps 提供两种类型的代码库:
-
Git
-
Team Foundation 版本控制(TFVC)
它还提供了在 Git 或 TFVC 源代码管理库之间进行选择的灵活性。在一个项目内,可能会有 TFS 和 TFVC 代码库的组合。
TFVC
TFVC 是传统的集中式版本控制实现方式,采用中央仓库,开发人员直接在连接模式下对其进行操作,提交更改。如果中央仓库处于离线状态或无法访问,开发人员无法提交代码,只能等待仓库恢复在线并可用。其他开发人员只能看到已提交的代码。开发人员可以将多个更改组合成一个单独的变更集,用于提交逻辑上归为一类的代码更改。TFVC 会锁定正在编辑的代码文件。其他开发人员可以读取已锁定的文件,但无法编辑。必须等待前一个编辑完成并释放锁,才能进行编辑。提交和更改的历史记录保存在中央仓库中,而开发人员拥有文件的工作副本,但没有历史记录。
TFVC 非常适合大团队在同一项目中协作工作。这能够在中央位置控制源代码。它也特别适用于长期项目,因为历史记录可以在中央位置进行管理。TFVC 在处理大文件和二进制文件时没有问题。
Git
另一方面,Git 是一种现代的分布式版本控制实现方式,开发人员可以在离线模式下使用自己的本地代码副本和历史记录。开发人员可以在本地克隆的代码上离线工作。每个开发人员都拥有代码和整个历史记录的本地副本,他们在此本地仓库上进行更改。开发人员可以将代码提交到本地仓库。根据需要,他们可以连接到中央仓库,同步本地仓库。这使得每个开发人员都可以在任何文件上工作,因为他们是在本地副本上工作。Git 中的分支不会创建代码的另一个副本,且创建速度极快。
Git 对于小团队和大团队都非常适用。Git 提供的高级选项使得分支和合并变得轻松。
Git 是推荐的源代码控制方式,因为它提供了丰富的功能。在本书中,我们将使用 Git 作为示例应用程序的仓库。在下一节中,我们将详细概述如何通过 DevOps 实现自动化。
准备 DevOps
展望未来,我们将重点关注通过不同模式在 Azure 中实现过程和部署自动化。这些模式包括以下内容:
-
DevOps 适用于 IaaS 解决方案
-
DevOps 适用于 PaaS 解决方案
-
DevOps 适用于基于容器的解决方案
通常,存在一些共享服务,这些服务并不特定于某一个应用程序。这些服务由来自不同环境(如开发、测试和生产)的多个应用程序使用。每个应用程序中这些共享服务的生命周期不同。因此,它们有不同的版本控制库、不同的代码库以及构建和发布管理。它们有自己的一套计划、设计、构建、测试和发布的周期。
该组的资源是使用 ARM 模板、PowerShell 和 DSC 配置进行配置的。
构建这些公共组件的整体流程如图所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_06.jpg
图 13.6:构建公共组件的整体流程
发布过程如图 13.7所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_07.jpg
图 13.7:发布过程
在 DevOps 之旅中,理解并在开始任何软件开发、产品或服务之前配置共享组件和服务非常重要。
开始使用 Azure DevOps 的第一步是配置一个组织。
Azure DevOps 组织
需要一个版本控制系统来进行代码级的协作。Azure DevOps 提供了集中式和分散式版本控制系统。Azure DevOps 还提供了用于构建和执行构建与发布流水线的编排服务。这是一个成熟的平台,组织了所有与 DevOps 相关的版本控制以及构建和发布工作项相关的工件。在 Azure DevOps 中配置一个组织后,应该创建一个 Azure DevOps 项目来存储所有与项目相关的工件。
可以通过访问dev.azure.com来创建 Azure DevOps 组织。
Azure DevOps 组织是提供安全性、访问权限和组织内团队成员之间协作的顶级管理边界。一个组织可以包含多个项目,每个项目包含多个团队。
配置 Azure Key Vault
不建议将密钥、证书、凭据或其他敏感信息存储在代码配置文件、数据库或任何其他通用存储系统中。建议将这些重要数据存储在专门设计用于存储密钥和凭据的保险库中。Azure Key Vault 提供了这样的服务。Azure Key Vault 作为 Azure 提供的资源和服务是可用的。现在,让我们继续探索配置的存储选项。
配置管理服务器/服务的配置
提供配置存储并将这些配置应用于不同环境的配置管理服务器/服务始终是自动化部署的好策略。自定义虚拟机上的 DSC 和来自 Azure 自动化、Chef、Puppet 以及 Ansible 的 DSC 是一些选项,并且可以在 Azure 上无缝使用,适用于 Windows 和 Linux 环境。本书将 DSC 作为配置管理工具,适用于所有目的,并提供一个拉取服务器,用于存放所有示例应用程序的配置文档(MOF 文件)。它还维护着所有配置并与拉取服务器注册的虚拟机和容器的数据库,以便从中拉取配置文档。目标虚拟机和容器上的本地配置管理器会定期检查新配置的可用性,以及当前配置中的漂移,并向拉取服务器报告。它还具有内置的报告功能,提供有关虚拟机内合规节点以及不合规节点的信息。拉取服务器是一个托管 DSC 拉取服务器端点的通用 Web 应用程序。在下一个主题中,我们将讨论一种实时监控进程的技术,使用日志分析。
日志分析
日志分析是 Azure 提供的一个审计和监控服务,用于获取虚拟机和容器中发生的所有更改、漂移和事件的实时信息。它为 IT 管理员提供了一个集中式工作区和仪表板,用于查看、搜索并深入分析所有发生在这些虚拟机上的更改、漂移和事件。它还提供了可以部署在目标虚拟机和容器上的代理。一旦部署,这些代理就会开始将所有更改、事件和漂移信息发送到集中式工作区。接下来,让我们来看看部署多个应用程序的存储选项。
Azure 存储帐户
Azure 存储是 Azure 提供的一项服务,用于将文件存储为 Blob。用于自动化基础设施和示例应用程序的预配、部署和配置的所有脚本和代码都存储在 Azure DevOps Git 仓库中,并打包后部署到 Azure 存储帐户中。Azure 提供了 PowerShell 脚本扩展资源,可以在执行 ARM 模板时自动下载 DSC 和 PowerShell 脚本并在虚拟机上执行。此存储作为多个应用程序部署中所有部署的公共存储。将脚本和模板存储在存储帐户中,可以确保它们可以跨 Azure DevOps 中的项目使用。接下来,让我们探讨一下镜像在下一节中的重要性。
Docker 和操作系统镜像
虚拟机和容器镜像应作为公共服务的构建和发布流水线的一部分来构建。可以使用 Packer 和 Docker Build 等工具来生成这些镜像。
管理工具
所有管理工具,如 Kubernetes、DC/OS、Docker Swarm 和 ITIL 工具,应该在构建和部署解决方案之前进行配置。
我们将在本节 DevOps 准备中以管理工具做总结。DevOps 生态系统中每项活动都有多种选择,我们应该在 DevOps 旅程中启用它们——这不应是事后的考虑,而是 DevOps 规划的一部分。
PaaS 解决方案的 DevOps
Azure PaaS 应用服务的典型架构基于图 13.8:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_08.jpg
图 13.8:典型的 Azure PaaS 应用服务架构
该架构展示了参与 Azure 应用服务基础的云解决方案架构的一些重要组件——例如 Azure SQL、存储帐户和版本控制系统。这些工件应该通过 ARM 模板创建。ARM 模板应该是整体配置管理策略的一部分。它可以拥有自己的构建和发布管理管道,类似于图 13.9所示的管道:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_09.jpg
图 13.9:为应用服务选择部署选项
现在我们已经探索了各种部署源选项,让我们继续深入了解如何在 Azure 上部署云解决方案。
Azure 应用服务
Azure 应用服务提供了云解决方案的托管服务。它是一个完全托管的平台,负责云解决方案的配置和部署。Azure 应用服务消除了创建和管理基础设施的负担,并为托管您的云解决方案提供了最低限度的服务级别协议(SLA)。
部署槽
Azure 应用服务提供了部署槽,使得部署变得无缝和简单。提供了多个槽,并且在槽之间的切换是通过 DNS 层面完成的。这意味着任何生产槽中的内容都可以通过切换 DNS 条目与暂存槽互换。这有助于将定制的云解决方案部署到暂存环境中,并在所有检查和测试完成后,如果确认没有问题,可以切换到生产环境。然而,在切换后如果生产环境出现任何问题,可以通过再次切换恢复先前在生产环境中的良好值。接下来让我们深入了解 Azure 的数据库服务及其一些关键特性。
Azure SQL
Azure SQL 是 Azure 提供的 SQL PaaS 服务,用于托管数据库。Azure 提供了一个安全的平台来托管数据库,并全面负责管理服务的可用性、可靠性和可扩展性。使用 Azure SQL,无需配置自定义虚拟机、部署 SQL 服务器并进行配置。相反,Azure 团队会在幕后完成这些操作并代表您进行管理。它还提供了防火墙服务,增强了安全性;只有防火墙允许的 IP 地址才能连接服务器并访问数据库。为托管 Web 应用程序而配置的虚拟机有各自的公共 IP 地址,并会动态添加到 Azure SQL 防火墙规则中。Azure SQL 服务器及其数据库将在执行 ARM 模板时创建。接下来,我们将介绍构建和发布管道。
构建和发布管道
在本节中,创建了一个新的构建管道,该管道编译并验证 ASP.NET MVC 应用程序,然后生成部署包。在生成包之后,发布定义确保在持续部署的过程中,首次部署发生在应用服务和 Azure SQL 环境中。
有两种方式可以编写构建和发布管道:
-
使用经典编辑器
-
使用 YAML 文件
YAML 文件为编写构建和发布管道提供了更大的灵活性。
示例应用程序的项目结构如 图 13.10 所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_10.jpg
图 13.10:示例应用程序的项目结构
在此项目中,有一个 ASP.NET MVC 应用程序——主应用程序——它由多个应用程序页面组成。Web Deploy 包将通过构建管道从该项目生成,并最终部署到 Web 应用程序中。该解决方案中还包含其他项目,如下所述:
-
单元测试项目:用于对 ASP.NET MVC 应用程序进行单元测试的代码。此项目生成的程序集将在构建执行中生成并执行。
-
DacPac文件将通过构建定义从该项目中生成。 -
Azure 资源组项目:ARM 模板和参数代码,用于配置 ASP.NET MVC 应用程序和 SQL 表格所在的整个 Azure 环境。
构建管道如 图 13.11 所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_11.jpg
图 13.11:ASP.NET MVC 应用程序的构建管道
每个任务的配置如 表 13.2 所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/13.2_29.jpghttps://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/13.2_30.jpghttps://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/13.2_31.jpghttps://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/13.2_32.jpg
表 13.2:构建管道任务的配置
构建管道已配置为在持续集成过程中自动执行,如 图 13.12 所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_12.jpg
图 13.12:在构建管道中启用持续集成
发布定义包含多个环境,如开发、测试、系统集成测试(SIT)、用户验收测试(UAT)、预生产和生产。各个环境中的任务非常相似,但会增加一些特定环境的任务。例如,测试环境会有更多与 UI 相关的任务,以及功能性和集成测试任务,而这些在开发环境中是没有的。
该应用程序的发布定义如图 13.13所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_13.jpg
图 13.13:发布定义
单个环境的发布任务如图 13.14所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_14.jpg
图 13.14:单个环境的发布任务
这里列出了每个任务的配置:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/13.3_34.jpghttps://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/13.3_35.jpghttps://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/13.3_36.jpghttps://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/13.3_37.jpg
表 13.3:发布管道任务的配置
本节介绍了如何在 Azure DevOps 中配置构建和发布管道。从下一节开始,将重点介绍不同的架构,如 IaaS、容器以及不同的场景。
IaaS 的 DevOps
IaaS 涉及基础设施和应用程序的管理与维护,这需要在多个环境中配置、部署多个资源和组件。在继续之前,理解架构是非常重要的。
这里展示了典型的基于 IaaS 虚拟机的解决方案架构:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_15.jpg
图 13.15:基于 IaaS 虚拟机的解决方案架构
架构中列出的每个组件将在下一节及之后的内容中进行讨论。
Azure 虚拟机
托管网页应用、应用服务器、数据库和其他服务的 Azure 虚拟机器是通过 ARM 模板进行配置的。它们附加到一个虚拟网络,并拥有来自同一网络的私有 IP 地址。虚拟机器的公共 IP 地址是可选的,因为它们已附加到公共负载均衡器。操作洞察代理被安装到虚拟机器上,用于监控这些虚拟机器。PowerShell 脚本也会在这些虚拟机器上执行,这些脚本是从另一个资源组中的存储帐户下载的,用于打开相关防火墙端口、下载适当的包并安装本地证书,以通过 PowerShell 安全访问。这些虚拟机器上的网页应用配置为在提供的端口上运行。网页应用的端口号和所有配置都从 DSC 拉取服务器中获取,并动态分配。
Azure 公共负载均衡器
公共负载均衡器被附加到一些虚拟机器上,以便以轮询的方式向它们发送请求。这通常需要用于前端网页应用和 API。可以为负载均衡器分配公共 IP 地址和 DNS 名称,这样它就可以处理来自互联网的请求。它在不同的端口上接受 HTTP 网页请求,并将其路由到虚拟机器。它还会通过提供的应用路径探测 HTTP 协议的某些端口。网络地址转换(NAT)规则也可以应用,这样就可以通过远程桌面登录到虚拟机器。
Azure 公共负载均衡器的替代资源是 Azure 应用程序网关。应用程序网关是七层负载均衡器,提供 SSL 终止、会话亲和力和基于 URL 的路由等功能。我们将在下一节讨论构建流水线。
构建流水线
以下是基于 IaaS 虚拟机解决方案的典型构建流水线。发布流水线在开发人员将代码推送到仓库时开始。构建流水线会作为持续集成的一部分自动启动。它编译并构建代码,执行单元测试,检查代码质量,并从代码注释生成文档。它将新的二进制文件部署到开发环境中(注意,开发环境并不是新创建的),更改配置,执行集成测试,并生成构建标签以便于识别。然后,它将生成的工件放入发布流水线可以访问的位置。如果在流水线的任何步骤执行过程中出现问题,会作为构建流水线反馈传达给开发人员,以便他们重新修改并重新提交更改。构建流水线应根据问题的严重性判断失败或成功,而这在不同组织之间可能有所不同。一个典型的构建流水线如图 13.16所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_16.jpg
图 13.16:典型的 IaaS 构建流水线
类似于构建流水线,让我们来了解一下发布流水线的实现。
发布流水线
下一部分展示了基于 IaaS 虚拟机部署的典型发布流水线。发布流水线在构建流水线完成后开始。发布流水线的第一步是收集构建流水线生成的工件,通常是可部署的程序集、二进制文件和配置文档。发布流水线执行并创建或更新第一个环境,通常是测试环境。它使用 ARM 模板来配置 Azure 上的所有 IaaS 和 PaaS 服务和资源,并对其进行配置。它们还帮助在创建虚拟机后执行脚本和 DSC 配置作为后创建步骤。这有助于配置虚拟机内的环境和操作系统。在这一阶段,构建流水线中的应用程序二进制文件将被部署和配置。执行各种自动化测试以检查解决方案,若测试结果令人满意,流水线将在获得必要的批准后将部署转移到下一个环境。相同的步骤将在下一个环境中执行,包括生产环境。最后,在生产环境中执行操作验证测试,以确保应用程序按预期工作,并且没有任何偏差。
在这一阶段,如果出现任何问题或错误,应该予以修复,并且整个周期需要重新执行;但是,如果在规定的时间内没有完成,应该在生产环境中恢复最后已知的快照,以尽量减少停机时间。典型的发布流水线如图 13.17所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_17.jpg
图 13.17:典型的 IaaS 发布流水线
本节总结了 IaaS 解决方案的 DevOps 流程,下一章将重点介绍虚拟机上的容器。请注意,容器也可以在像 App Service 和 Azure Functions 这样的 PaaS 上运行。
DevOps 与容器
在典型的架构中,容器运行时被部署在虚拟机上,容器在其中运行。基于 IaaS 容器解决方案的典型架构如图所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_18.jpg
图 13.18:基于 IaaS 的容器解决方案架构
这些容器由容器编排器(如 Kubernetes)管理。监控服务由 Log Analytics 提供,所有的密钥和机密存储在 Azure Key Vault 中。此外,还有一个拉取服务器,可以是虚拟机或 Azure Automation,它向虚拟机提供配置信息。
容器
容器是一种虚拟化技术;然而,它们并不虚拟化物理服务器。相反,容器是一种操作系统级的虚拟化。这意味着容器共享其主机提供的操作系统内核,并且彼此以及与主机共享该内核。在主机(无论是物理的还是虚拟的)上运行多个容器时,容器共享主机的操作系统内核。主机提供一个操作系统内核,所有在其上运行的容器共享这个内核。
容器与其主机和其他容器完全隔离,类似于虚拟机。容器使用操作系统命名空间(在 Linux 上使用控制组)来提供一个新的操作系统环境的感知,并在 Windows 上使用特定的操作系统虚拟化技术。每个容器都拥有自己的一份操作系统资源。
Docker
Docker 提供了容器的管理功能。它包含两个可执行文件:
-
Docker 守护进程
-
Docker 客户端
Docker 守护进程是管理容器的主力军。它是一个管理服务,负责管理与容器相关的所有主机活动。Docker 客户端与 Docker 守护进程进行交互,负责捕获输入并将其发送给 Docker 守护进程。Docker 守护进程提供运行时、库、图形驱动程序、用于创建、管理和监控容器的引擎,以及主机服务器上的镜像。它还可以创建自定义镜像,用于构建和交付应用程序到多个环境。
Dockerfile
Dockerfile 是创建容器镜像的主要构建模块。它是一个简单的基于文本的、可读性强的文件,没有扩展名,甚至被命名为 Dockerfile。尽管有一种机制可以将其命名为其他名字,但通常它被命名为 Dockerfile。Dockerfile 包含了使用基础镜像创建自定义镜像的指令。这些指令会从上到下由 Docker 守护进程依次执行。指令包括命令及其参数,如 COPY、ADD、RUN 和 ENTRYPOINT。Dockerfile 通过将应用程序部署和配置转化为可以版本化并存储在源代码库中的指令,支持 IaC(基础设施即代码)实践。接下来让我们查看构建步骤。
构建管道
从构建的角度来看,容器和基于虚拟机的解决方案没有区别。构建步骤保持不变。一个典型的 IaaS 容器部署发布管道如下所示。
发布管道
IaaS 容器部署的典型发布流水线与发布流水线之间的唯一区别是容器镜像管理以及使用 Dockerfile 和 Docker Compose 创建容器。像 Docker Swarm、DC/OS 和 Kubernetes 这样的高级容器管理工具,也可以作为发布管理的一部分进行部署和配置。不过,值得注意的是,这些容器管理工具应该是共享服务发布流水线的一部分,如前面所讨论的那样。图 13.19展示了一个基于容器的解决方案的典型发布流水线:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_19.jpg
图 13.19:基于容器的发布流水线
下一部分的重点是与其他工具集的集成,如 Jenkins。
Azure DevOps 与 Jenkins
Azure DevOps 是一个开放的平台编排器,可以无缝集成其他编排工具。它提供了与 Jenkins 良好集成所需的所有基础设施和功能。已经建立了基于 Jenkins 的 CI/CD 流水线的组织,可以利用 Azure DevOps 的先进但简单的功能来编排这些流水线。
Jenkins 可以用作存储库,并且可以在 Azure DevOps 中执行 CI/CD 流水线,同时也可以在 Azure DevOps 中拥有一个存储库,并在 Jenkins 中执行 CI/CD 流水线。
Jenkins 配置可以作为服务钩子添加到 Azure DevOps 中,每当任何代码更改被提交到 Azure DevOps 存储库时,它可以触发 Jenkins 中的流水线。图 13.20展示了来自 Azure DevOps 服务钩子配置部分的 Jenkins 配置:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_20.jpg
图 13.20:Jenkins 配置
在 Jenkins 中有多种触发器可以执行流水线;其中之一是代码推送,如图 13.21所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_21.jpg
图 13.21:执行的代码推送触发器
也可以将其部署到 Azure 虚拟机并执行 Azure DevOps 发布流水线,具体说明见:docs.microsoft.com/azure/virtual-machines/linux/tutorial-build-deploy-jenkins。
在任何场景中使用 Jenkins 之前,应该先进行部署。Linux 上的部署过程可以在docs.microsoft.com/azure/virtual-machines/linux/tutorial-jenkins-github-docker-cicd找到。
下一部分将更加关注与配置管理相关的工具和服务。Azure 自动化提供与 DSC 相关的服务,如拉取服务器。
Azure 自动化
Azure Automation 是微软的自动化平台,适用于云端、本地和混合部署的所有自动化实现。Azure Automation 是一个成熟的自动化平台,提供了以下方面的丰富功能:
-
定义资产,如变量、连接、凭据、证书和模块
-
使用 Python、PowerShell 脚本和 PowerShell 工作流实现运行手册
-
提供创建运行手册的用户界面
-
管理完整的运行手册生命周期,包括构建、测试和发布
-
调度运行手册
-
在任何地方运行运行手册的能力——无论是在云端还是本地
-
DSC 作为配置管理平台
-
管理和配置环境——Windows 和 Linux、应用程序以及部署
-
通过导入自定义模块扩展 Azure Automation 的能力
Azure Automation 提供一个 DSC 拉取服务器,帮助创建一个集中式配置管理服务器,包含节点/虚拟机及其组成部分的配置。
它实现了中心和分支模式,其中节点可以连接到 DSC 拉取服务器,下载分配给它们的配置,并重新配置自己以反映其期望状态。节点中的任何变化或偏差将在下一次运行时由 DSC 代理自动修正。这确保了管理员无需主动监控环境,以便发现任何偏差。
DSC 提供了一种声明性语言,您在其中定义意图和配置,而不是如何运行和应用这些配置。这些配置基于 PowerShell 语言,简化了配置管理的过程。
在本节中,我们将介绍如何使用 Azure Automation DSC 配置虚拟机,安装并配置 Web 服务器 (IIS),并创建一个 index.htm 文件,告知用户网站正在维护中。
接下来,您将学习如何配置 Azure Automation 帐户。
配置 Azure Automation 帐户
在 Azure 门户或 PowerShell 中,从现有或新资源组创建一个新的 Azure Automation 帐户。您可能会注意到在图 13.22中,Azure Automation 提供了有关 DSC 的菜单项:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_22.jpg
图 13.22:Azure Automation 帐户中的 DSC
它提供了以下功能:
-
DSC 节点:这些列出了当前 Azure Automation DSC 拉取服务器所注册的所有虚拟机和容器。通过当前的 DSC 拉取服务器的配置来管理这些虚拟机和容器。
-
DSC 配置:这些列出了所有导入并上传到 DSC 拉取服务器的原始 PowerShell 配置。它们是人类可读格式,并未编译。
-
DSC 节点配置:这些列出了所有可以分配给节点(虚拟机和容器)的 DSC 配置的编译版本,节点可以从拉取服务器获取。DSC 配置经过编译后会生成 MOF 文件,最终用于配置节点。
在配置 Azure Automation 账户后,我们可以创建一个示例 DSC 配置,如下一部分所示。
创建 DSC 配置
下一步是使用任意 PowerShell 编辑器编写 DSC 配置,以反映配置的意图。对于此示例,创建了一个名为 ConfigureSiteOnIIS 的配置。它导入了基本的 DSC 模块 PSDesiredStateConfiguration,该模块包含配置中使用的资源。它还声明了一个节点 web 服务器。当这个配置被上传并编译后,它将生成一个名为 ConfigureSiteOnIISwebserver 的 DSC 配置。该配置随后可以应用于节点。
该配置包含几个资源。这些资源配置目标节点。资源安装了 web 服务器、ASP.NET 和框架,并在 inetpub\wwwroot 目录中创建了一个 index.htm 文件,文件内容用于显示网站正在维护中。有关编写 DSC 配置的更多信息,请参阅 docs.microsoft.com/powershell/scripting/dsc/getting-started/wingettingstarted?view=powershell-7。
下一段代码列出了前述配置的完整内容。该配置将被上传到 Azure Automation 账户:
Configuration ConfigureSiteOnIIS {
Import-DscResource -ModuleName 'PSDesiredStateConfiguration'
Node WebServer {
WindowsFeature IIS
{
Name = "Web-Server"
Ensure = "Present"
}
WindowsFeature AspDotNet
{
Name = "net-framework-45-Core"
Ensure = "Present"
DependsOn = "[WindowsFeature]IIS"
}
WindowsFeature AspNet45
{
Ensure = "Present"
Name = "Web-Asp-Net45"
DependsOn = "[WindowsFeature]AspDotNet"
}
File IndexFile
{
DestinationPath = "C:\inetpub\wwwroot\index.htm"
Ensure = "Present"
Type = "File"
Force = $true
Contents = "<HTML><HEAD><Title> Website under construction.</Title></HEAD><BODY> '
<h1>If you are seeing this page, it means the website is under maintenance and DSC Rocks !!!!!</h1></BODY></HTML>"
}
}
}
在创建了一个示例 DSC 配置后,应将其导入到 Azure Automation 中,如下一部分所示。
导入 DSC 配置
该 DSC 配置仍未为 Azure Automation 所知。它目前存在于一些本地机器上。应将其上传到 Azure Automation 的 DSC 配置中。Azure Automation 提供了 Import-AzureRMAutomationDscConfiguration cmdlet 来将配置导入到 Azure Automation:
Import-AzureRmAutomationDscConfiguration -SourcePath "C:\DSC\AA\DSCfiles\ConfigureSiteOnIIS.ps1" -ResourceGroupName "omsauto" -AutomationAccountName "datacenterautomation" -Published -Verbose
这些命令将会在 Azure Automation 中导入配置。导入后,DSC 配置应被编译,以便可以分配给服务器进行合规性检查和自动修复。
编译 DSC 配置
在 Azure Automation 中可用 DSC 配置后,可以请求编译。Azure Automation 提供了另一个 cmdlet 用于此操作。使用 Start-AzureRmAutomationDscCompilationJob cmdlet 来编译已导入的配置。配置名称应与上传的配置名称匹配。编译会创建一个名为配置和节点名称组合的 MOF 文件,在此案例中是 ConfigureSiteOnIIS web 服务器。命令执行过程如下所示:
Start-AzureRmAutomationDscCompilationJob -ConfigurationName ConfigureSiteOnIIS -ResourceGroupName "omsauto" -AutomationAccountName "datacenterautomation" -Verbose
现在你已经完成了 DSC 节点配置。在接下来的部分中,你将学习如何将配置分配给节点。
将配置分配给节点
编译后的 DSC 配置可以应用于节点。使用 Register-AzureRmAutomationDscNode 将配置分配给节点。NodeConfigurationName 参数标识应应用于节点的配置名称。这是一个强大的 cmdlet,它还可以在节点下载配置并应用之前,配置 DSC 代理,即 localconfigurationmanager。有多个可以配置的 localconfigurationmanager 参数,详细信息可查看 devblogs.microsoft.com/powershell/understanding-meta-configuration-in-windows-powershell-desired-state-configuration。
让我们看看下面的配置:
Register-AzureRmAutomationDscNode -ResourceGroupName "omsauto" -AutomationAccountName "datacenterautomation" -AzureVMName testtwo -ConfigurationMode ApplyAndAutocorrect -ActionAfterReboot ContinueConfiguration -AllowModuleOverwrite $true -AzureVMResourceGroup testone -AzureVMLocation "West Central US" -NodeConfigurationName "ConfigureSiteOnIIS.WebServer" -Verbose
现在,我们可以通过使用浏览器浏览新部署的网站来测试配置是否已应用到服务器上。在测试成功完成后,我们继续验证连接。
验证
如果适当,网络安全组和防火墙应为端口 80 开放并启用,并且为虚拟机分配公共 IP。可以通过该 IP 地址浏览默认网站。否则,登录到用于应用 DSC 配置的虚拟机,并导航至 http://localhost。
它应该显示以下页面:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_23.jpg
图 13.23:本地主机
这就是配置管理的力量:无需编写任何复杂的代码,编写一次配置后,可以多次应用于相同或多个服务器,并且可以确保它们会在所需状态下运行,无需人工干预。在下一节中,我们将查看适用于 Azure DevOps 的各种工具。
DevOps 工具
如前所述,Azure 是一个功能丰富且成熟的平台,支持以下内容:
-
多种语言选择
-
多种操作系统选择
-
多种工具和实用程序的选择
-
多种部署解决方案的模式(例如虚拟机、应用服务、容器和微服务)
在如此众多的选项和选择中,Azure 提供了以下内容:
-
开放云:它对开源、微软以及非微软的产品、工具和服务都是开放的。
-
灵活云:它足够简单,既适合终端用户,也适合开发人员,能够利用现有的技能和知识进行使用。
-
统一管理:它提供无缝的监控和管理功能。
这里提到的所有服务和功能对于 DevOps 的成功实施至关重要。图 13.24 展示了可以用于管理应用生命周期和 DevOps 各个阶段的开源工具和实用程序:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_24.jpg
图 13.24:开源工具和实用程序
图 13.24 显示了可以用于管理应用生命周期和 DevOps 各个阶段的 Microsoft 工具和实用程序。再次强调,这只是所有工具和实用程序的一小部分——实际上有许多其他选项,例如以下内容:
-
Azure DevOps 构建编排,用于构建构建管道
-
Microsoft 测试管理器和 Pester 用于测试
-
DSC、PowerShell 和 ARM 模板用于部署或配置管理
-
日志分析、应用洞察以及系统中心操作管理器 (SCOM) 用于警报和监控
-
Azure DevOps 和系统中心服务管理器用于管理流程:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_13_25.jpg
图 13.25:Microsoft 工具和实用程序
每个 DevOps 实践都有许多可用的工具,在本节中,您已经了解了一些工具及其配置方式。
小结
DevOps 在行业中获得了极大的关注和势头。大多数组织已经意识到其好处,并希望实施 DevOps。与此同时,他们中的大多数正在向云迁移。作为云平台,Azure 提供了丰富且成熟的 DevOps 服务,使组织更容易实现 DevOps。
在本章中,我们讨论了 DevOps 及其核心实践,如配置管理、持续集成、持续交付和部署。我们还讨论了基于 PaaS 的不同云解决方案、虚拟机 IaaS 和容器 IaaS,以及它们各自的 Azure 资源、构建和发布管道。
本章还解释了配置管理,以及如何使用来自 Azure 自动化的 DSC 服务和拉取服务器自动配置虚拟机。最后,我们讨论了 Azure 在语言、工具和操作系统选择方面的开放性和灵活性。
在下一章中,我们将详细讲解 Kubernetes 及其组件和交互,此外还将讨论 Kubernetes 上的应用设计和部署注意事项。
第十四章:14. 设计 Azure Kubernetes 解决方案
容器是过去十年中最受讨论的基础设施组件之一。容器并不是新技术,它们已经存在了一段时间。它们在 Linux 世界中已经流行了超过二十年。由于其复杂性以及相关文档的匮乏,容器曾在开发者社区中不太为人知。然而,在本世纪初,即 2013 年,一家名为 Docker 的公司推出了改变开发者世界对容器认知和采纳的局面。
Docker 在现有的 Linux LXC 容器之上编写了一个强大的 API 封装,简化了开发者从命令行界面创建、管理和销毁容器的过程。当容器化应用时,容器的数量会随着时间大幅增加,可能达到需要管理数百个甚至数千个容器的程度。这时,容器编排工具就发挥了作用,而 Kubernetes 就是其中之一。使用 Kubernetes,我们可以自动化容器的部署、扩展、网络配置和管理。
本章将讨论:
-
容器的基本概念
-
Kubernetes 的概念
-
使 Kubernetes 能够正常工作的关键要素
-
使用 Azure Kubernetes 服务构建解决方案
现在你已经知道 Kubernetes 的用途,我们从头开始讨论容器是什么,如何使用 Kubernetes 对它们进行编排等内容。
容器简介
容器被称为操作系统级虚拟化系统。它们托管在运行于物理服务器或虚拟服务器上的操作系统中。实现的性质取决于宿主操作系统。例如,Linux 容器受 cgroups 启发;而 Windows 容器几乎是轻量级虚拟机,具有小巧的占用空间。
容器真正实现了跨平台。容器化应用可以在任何平台上运行,如 Linux、Windows 或 Mac,且无需任何修改,这使得它们具有高度的可移植性。这使得它们成为组织采用的完美技术,因为它们与平台无关。
此外,容器可以在任何云环境或本地环境中运行,无需修改。这意味着如果组织将容器作为其云托管平台,它们也不会被束缚于单一云提供商。它们可以将环境从本地迁移并直接迁移到云端。
容器提供了虚拟机通常具备的所有优势。它们有自己的 IP 地址、DNS 名称、身份、网络堆栈、文件系统以及其他组件,这些都使得用户有使用全新操作系统环境的错觉。在后台,Docker 运行时通过虚拟化多个操作系统内核级别的组件来提供这种错觉。
所有这些优势为采用容器技术的组织提供了巨大的好处,而 Docker 在这方面是先行者之一。还有其他容器运行时选项可供选择,如 CoreOS Rkt(发音为 Rocket,已停产)、Mesos Containerizer 和 LXC 容器。组织可以选择他们感到舒适的技术。
容器在 Windows 系统中之前是不可用的,仅在 Windows 10 和 Windows Server 2016 中才开始支持。然而,现在容器已经成为 Windows 系统中的一等公民。
如介绍中所述,容器应像生态系统中的任何其他基础设施组件一样,进行监控、治理和管理。必须部署一个编排工具,如 Kubernetes,帮助你轻松实现这一点。在接下来的章节中,你将了解 Kubernetes 的基础知识,包括它的优势。
Kubernetes 基础知识
许多组织仍然问,“我们需要 Kubernetes,还是需要任何容器编排工具?” 当我们考虑大规模容器管理时,我们需要考虑多个方面,比如扩展、负载均衡、生命周期管理、持续交付、日志记录和监控等。
你可能会问,“容器不应该完成这些工作吗?” 答案是,容器只是这一拼图的低级组成部分。真正的好处是通过那些位于容器之上的工具获得的。最终,我们需要一些工具来帮助我们进行编排。
Kubernetes 是一个希腊词,κυβερνήτης,意思是“舵手”或“船长”。延续 Docker 容器的海洋主题,Kubernetes 就是这艘船的船长。Kubernetes 通常缩写为 K8s,其中 8 代表单词 “Kubernetes” 中 “K” 和 “s” 之间的八个字母。
如前所述,容器比虚拟机更具灵活性。它们可以在几秒钟内创建,并且同样可以快速销毁。它们的生命周期与虚拟机类似;然而,它们需要在环境中主动进行监控、治理和管理。
使用你现有的工具集来管理容器是可行的;尽管如此,像 Kubernetes 这样的专用工具能够提供宝贵的好处:
-
Kubernetes 本质上是自愈的。当 Kubernetes 环境中的一个 Pod(现在可以理解为“容器”)故障时,Kubernetes 会确保在同一节点或另一个节点上创建一个新的 Pod 来响应应用程序的请求。
-
Kubernetes 还简化了应用程序升级的过程。它提供了开箱即用的功能,帮助你在保留原始配置的情况下执行多种类型的升级。
-
它有助于实现蓝绿部署。在这种部署方式中,Kubernetes 会将新版本的应用程序与旧版本一起部署,一旦确认新应用程序按预期工作,就会进行 DNS 切换,切换到新版本的应用程序。旧的应用程序部署可以继续存在,以便回滚使用。
-
Kubernetes 还帮助实施滚动升级部署策略。在这种策略中,Kubernetes 会逐个服务器地部署新版本的应用程序,并逐个服务器地拆除旧版本部署。它会一直执行此操作,直到旧版本的部署没有服务器为止。
-
Kubernetes 可以通过 基础设施即服务(IaaS)模式在本地数据中心或云上进行部署。这意味着开发人员首先创建一组虚拟机并在其上部署 Kubernetes。还有一种替代方法是将 Kubernetes 用作 平台即服务(PaaS)提供。Azure 提供了一项名为 Azure Kubernetes 服务(AKS)的 PaaS 服务,提供了一个开箱即用的 Kubernetes 环境,供开发人员使用。
在部署方面,Kubernetes 可以通过两种方式进行部署:
-
非托管集群:非托管集群可以通过在裸机或虚拟机上安装 Kubernetes 及其他相关软件包来创建。在非托管集群中,将有主节点和工作节点,前身叫做从节点。主节点和工作节点共同协作管理容器。如果你想知道这是如何实现的,接下来我们将在本章中探索 Kubernetes 的完整架构。现在,你只需要知道有主节点和工作节点即可。
-
托管集群:托管集群通常由云服务提供商提供;云服务提供商为你管理基础设施。在 Azure 中,这项服务被称为 AKS。Azure 将提供关于补丁和基础设施管理的主动支持。使用 IaaS 时,组织必须自行确保节点和基础设施的可用性和可扩展性。在 AKS 中,主组件不可见,因为它由 Azure 管理。然而,工作节点(从节点)是可见的,并且会被部署到单独的资源组中,因此你可以在需要时访问这些节点。
使用 AKS 而不是非托管集群的一些关键好处包括:
-
如果你使用的是非托管集群,你需要努力使解决方案具有高可用性和可扩展性。除此之外,你还需要有合适的更新管理机制来安装更新和补丁。另一方面,在 AKS 中,Azure 完全管理这一切,使得开发人员可以节省时间,更加高效。
-
与其他服务的原生集成,例如 Azure 容器注册表用于安全存储容器镜像,Azure DevOps 用于集成 CI/CD 管道,Azure Monitor 用于日志记录,Azure Active Directory 用于安全性。
-
可扩展性和更快的启动速度。
-
支持虚拟机规模集。
尽管这两种部署方式在基本功能上没有差异,但 IaaS 部署形式提供了灵活性,可以立即添加新的插件和配置,而这可能需要 Azure 团队在 AKS 中推出一段时间才能实现。此外,Kubernetes 的新版本在 AKS 中发布也相对迅速,几乎没有延迟。
我们已经涵盖了 Kubernetes 的基础内容。此时,您可能会想,Kubernetes 是如何实现这一切的。在接下来的章节中,我们将探讨 Kubernetes 的组件以及它们是如何协同工作的。
Kubernetes 架构
理解 Kubernetes 的第一步是了解它的架构。我们将在下一节详细讲解每个组件,但先了解架构的高级概览将有助于您理解各个组件之间的互动。
Kubernetes 集群
Kubernetes 需要物理或虚拟节点来安装两种类型的组件:
-
Kubernetes 控制平面组件,或主控组件
-
Kubernetes 工作节点(从属节点),或非主控组件
图 14.1 是一个提供 Kubernetes 架构高级概览的图表。稍后我们将详细介绍各个组件:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_01.jpg
图 14.1:Kubernetes 集群概览
控制平面组件负责管理和治理 Kubernetes 环境以及 Kubernetes 从属节点。
所有节点——包括主控节点和从属节点——共同构成了集群。换句话说,集群是节点的集合。它们可以是虚拟的或物理的,彼此连接,并通过 TCP 网络栈相互访问。外部世界无法得知您的集群的大小、能力,甚至工作节点的名称。节点唯一知道的是与集群互动的 API 服务器的地址。对它们来说,集群就是运行其应用程序的一台大计算机。
正是 Kubernetes 内部决定了一个合适的策略,通过控制器来选择一个有效、健康的节点,以便平稳地运行应用程序。
控制平面组件可以安装在高可用配置中。到目前为止,我们已经讨论了集群及其工作原理。在接下来的章节中,我们将深入了解集群的组件。
Kubernetes 组件
Kubernetes 组件分为两类:主组件和节点组件。主组件也被称为集群的控制平面。控制平面负责管理集群中的工作节点和 Pod。集群的决策权由控制平面掌控,它还负责集群事件的检测和响应。图 14.2 描述了 Kubernetes 集群的完整架构:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_02.jpg
图 14.2:Kubernetes 架构
你需要理解每一个组件,才能正确地管理一个集群。接下来,让我们讨论一下主组件:
-
API 服务器:API 服务器无疑是 Kubernetes 的大脑。它是启用 Kubernetes 内部所有活动的核心组件。每个客户端请求(少数例外)最终都会由 API 服务器处理,API 服务器决定请求的流向。它唯一负责与 etcd 服务器进行交互。
-
etcd:etcd 是 Kubernetes 的数据存储。只有 API 服务器被允许与 etcd 进行通信,API 服务器可以对 etcd 执行 创建、读取、更新 和 删除(CRUD)操作。当请求最终到达 API 服务器时,经过验证后,API 服务器可以根据 etcd 请求执行任何 CRUD 操作。etcd 是一个分布式、高可用的数据存储。可以有多个 etcd 实例,每个实例都有一份数据副本,它们中的任何一个都可以为 API 服务器的请求提供服务。在 图 14.3 中,你可以看到在控制平面中运行多个实例来提供高可用性:https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_03.jpg
图 14.3:使控制平面高度可用
-
控制器管理器:控制器管理器是 Kubernetes 的工作马车。API 服务器接收请求时,Kubernetes 中的实际工作由控制器管理器完成。顾名思义,控制器管理器是控制器的管理者。Kubernetes 主节点中有多个控制器,每个控制器负责管理一个单一的资源。
控制器的主要职责是管理 Kubernetes 环境中的单一资源。例如,有一个用于管理副本控制器资源的副本控制器管理器,以及一个用于管理 Kubernetes 环境中 ReplicaSets 的 ReplicaSet 控制器。控制器监控 API 服务器,当它收到一个请求来管理某个资源时,控制器就会执行相应的操作。
控制器的主要职责之一是保持循环运行,并确保 Kubernetes 处于所需状态。如果与所需状态出现任何偏差,控制器应该将其恢复到所需状态。部署控制器监视 API 服务器创建的任何新的部署资源。如果发现新的部署资源,部署控制器将创建一个新的 ReplicaSet 资源,并确保 ReplicaSet 始终处于所需状态。复制控制器会一直运行,并检查环境中实际的 Pods 数量是否与所需的 Pods 数量匹配。如果某个 Pod 因为某种原因死亡,复制控制器会发现实际数量减少了一个,并会在相同或其他节点上调度一个新的 Pod。
-
调度器:调度器的工作是将 Pods 调度到 Kubernetes 工作节点上。它不负责创建 Pods,仅负责将 Pods 分配到 Kubernetes 工作节点。它会根据节点的当前状态、节点的繁忙程度、可用资源以及 Pod 的定义来进行调度。Pod 可能会对特定节点有偏好,调度器在将 Pods 调度到节点时会考虑这些请求。
我们现在将探索在集群中每个工作节点上部署的节点组件:
-
Kubelet:API 服务器、调度器、控制器和 etcd 部署在主节点上,而 kubelet 部署在工作节点上。它们充当 Kubernetes 主组件的代理,并负责在节点上本地管理 Pods。每个节点上都有一个 kubelet。kubelet 接收来自主组件的命令,同时还向主组件(如 API 服务器和控制器管理器)提供有关节点和 Pods 的健康状况、监控信息和更新信息。它们是主节点与工作节点之间管理通信的中介。
-
kube-proxy:kube-proxy 就像 kubelet 一样,部署在工作节点上。它负责监控 Pods 和 Services,并在 Pods 和 Services 的可用性发生变化时更新本地的 iptables 和 netfilter 防火墙规则。这确保了节点上的路由信息在创建新的 Pods 和 Services 或删除现有 Pods 和 Services 时能够及时更新。
-
容器运行时:如今,生态系统中有许多容器供应商和提供商。Docker 是其中最著名的,尽管其他容器运行时也在逐渐获得人气。因此,在我们的架构中,我们用 Docker 的标志来表示容器运行时。Kubernetes 是一个通用的容器调度器,它不能与任何单一的容器供应商(如 Docker)紧密耦合。它应该能够在工作节点上使用任何容器运行时来管理容器的生命周期。
为了在 Pod 中运行容器,已经开发了一种基于行业标准的 容器运行时接口 (CRI),并被所有领先公司使用。该标准提供了与 Kubernetes 等调度器互操作时应遵循的规则。Kubelet 不知道节点上安装了哪些容器二进制文件。它们可以是 Docker 二进制文件,也可以是任何其他二进制文件。
由于这些容器运行时是基于行业标准开发的,无论你使用的是哪种运行时,kubelet 都能与容器运行时进行通信。这将容器管理与 Kubernetes 集群管理解耦。容器运行时的职责包括创建容器、管理容器的网络栈以及管理桥接网络。由于容器管理与集群管理是分离的,Kubernetes 不会干扰容器运行时的职责。
我们讨论的组件适用于无管理的集群以及 AKS 管理的集群。然而,主组件不会暴露给最终用户,因为在 AKS 的情况下,Azure 会管理所有这些内容。本章稍后将介绍 AKS 的架构。你将了解无管理集群,并更清晰地理解这些系统之间的区别。
接下来,你将学习一些最重要的 Kubernetes 资源,也称为原语,这些知识适用于无管理的集群和 AKS 集群。
Kubernetes 原语
你已经了解 Kubernetes 是一个用于部署和管理容器的调度系统。Kubernetes 定义了一组构建块,也称为原语。这些原语一起可以帮助我们部署、维护和扩展容器化应用程序。让我们逐一了解这些原语及其角色。
Pod
Pod 是 Kubernetes 中最基本的部署单元。一个好奇的心灵自然会产生一个问题:Pod 和容器有什么区别?Pod 是容器的封装。换句话说,容器是包含在 Pod 内的。一个 Pod 内可以包含多个容器;然而,最佳实践是保持一个 Pod 对应一个容器。这并不意味着一个 Pod 里不能有多个容器。一个 Pod 中有多个容器也是可以的,只要有一个主容器,其他都是辅助容器。也有一些模式,比如 sidecar 模式,可以在多容器 Pod 中实现。
每个 Pod 都有自己的 IP 地址和网络栈。所有容器共享同一网络接口和栈。Pod 内的所有容器可以通过主机名在本地访问。
以下是 YAML 格式的一个简单 Pod 定义示例:
---
apiVersion: v1
kind: Pod
metadata:
name: tappdeployment
labels:
appname: tapp
ostype: linux
spec:
containers:
- name: mynewcontainer
image: "tacracr.azurecr.io/tapp:latest"
ports:
- containerPort: 80
protocol: TCP
name: http
显示的 Pod 定义有一个名称,并定义了几个标签,这些标签可以由服务资源用来暴露给其他 Pods、节点和外部自定义资源。它还定义了一个基于 Azure 容器注册表中存储的自定义镜像的单个容器,并为该容器打开端口 80。
服务
Kubernetes 允许创建多个实例的 Pods。这些 Pods 应该可以从集群中的任何 Pod 或节点访问。可以直接使用 Pod 的 IP 地址访问 Pod。然而,这远非理想做法。Pods 是短暂的,如果先前的 Pod 已经崩溃,它们可能会获得一个新的 IP 地址。在这种情况下,应用程序容易出现故障。Kubernetes 提供了 Services,将 Pod 实例与其客户端解耦。Pods 可以创建或销毁,但 Kubernetes 服务的 IP 地址保持不变和稳定。客户端可以连接到服务的 IP 地址,该服务为每个 Pod 提供一个端点,用于发送请求。如果有多个 Pod 实例,每个 Pod 的 IP 地址都将作为端点对象提供给服务。当 Pod 崩溃时,端点会更新,以反映当前的 Pod 实例及其 IP 地址。
服务与 Pods 之间有很高的解耦。服务的主要目的是为那些在其服务选择器定义中具有标签的 Pods 排队。服务定义了标签选择器,根据标签选择器,Pod 的 IP 地址被添加到服务资源中。Pods 和服务可以独立管理。
服务提供多种类型的 IP 地址方案。有四种类型的服务:ClusterIP、NodePort、LoadBalancer 和使用应用程序网关的 Ingress Controller。
最基本的方案称为 ClusterIP,它是一个只能从集群内部访问的内部 IP 地址。ClusterIP 方案如 图 14.4 所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_04.jpg
图 14.4:ClusterIP 的工作原理
ClusterIP 还允许创建 NodePort,通过 NodePort,它会获得一个 ClusterIP。然而,它也可以在集群中的每个节点上打开一个端口。Pods 可以通过 ClusterIP 地址访问,也可以通过节点 IP 和节点端口的组合来访问:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_05.jpg
图 14.5:NodePort 的工作原理
服务不仅可以指向 Pods,还可以指向外部端点。最后,服务还允许创建基于负载均衡器的服务,能够接收外部请求并通过 ClusterIP 和 NodePort 内部将请求重定向到 Pod 实例:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_06.jpg
图 14.6:负载均衡器的工作原理
有一种最终类型的服务被称为 Ingress 控制器,它提供了诸如基于 URL 的路由等高级功能,如图 14.7所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_07.jpg
图 14.7:Ingress 控制器的工作原理
这里展示了一个 YAML 格式的服务定义:
apiVersion: v1
kind: Service
metadata:
name: tappservice
labels:
appname: tapp
ostype: linux
spec:
type: LoadBalancer
selector:
appname: myappnew
ports:
- name: http
port: 8080
targetPort: 80
protocol: TCP
此服务定义使用标签选择器创建基于负载均衡器的服务。
部署
与 ReplicaSets 和 Pods 相比,Kubernetes 的 Deployment 是更高级的资源。Deployment 提供了与应用程序升级和发布相关的功能。Deployment 资源会创建一个 ReplicaSet,而 ReplicaSet 管理 Pods。理解当 ReplicaSets 已经存在时,为什么还需要 Deployment 资源是非常重要的。
部署在应用程序升级中起着重要作用。如果应用程序已经投入生产并且需要部署新版本的应用程序,你有几种选择:
-
删除现有的 Pods 并创建新的 Pods——这种方法会导致应用程序的停机,因此只有在可以接受停机的情况下才应使用此方法。如果 Deployment 中存在错误并且需要回滚到先前的版本,则停机时间可能会增加。
-
蓝绿部署——在此方法中,现有的 Pods 继续运行,并且创建一组新版本的 Pods。这些新 Pods 对外不可访问。一旦测试成功完成,Kubernetes 开始指向这一组新的 Pods。旧的 Pods 可以保持不变,或者可以随后删除。
-
滚动升级——在此方法中,现有的 Pods 会逐个删除,同时为新应用版本创建新的 Pods。新 Pods 会逐步部署,而旧 Pods 会逐步减少,直到它们的数量为零。
如果没有 Deployment 资源,所有这些方法都必须手动执行。Deployment 资源自动化了整个发布和升级过程。如果当前的 Deployment 出现问题,它还可以帮助自动回滚到先前的版本。
以下代码列出了 Deployment 定义:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tappdeployment
labels:
appname: tapp
ostype: linux
spec:
replicas: 3
selector:
matchLabels:
appname: myappnew
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
name: mypod
labels:
appname: myappnew
spec:
containers:
- name: mynewcontainer
image: "tacracr.azurecr.io/tapp:latest"
ports:
- containerPort: 80
protocol: TCP
name: http
需要注意的是,Deployment 具有一个 strategy 属性,该属性决定是使用 recreate 还是 RollingUpdate 策略。recreate 会删除所有现有的 Pods 并创建新的 Pods。它还通过提供一次执行中可以创建和销毁的最大 Pods 数量,包含与 RollingUpdate 相关的配置细节。
副本控制器和 ReplicaSet
Kubernetes 的复制控制器资源确保集群内始终有指定数量的 Pod 实例在运行。复制控制器监控任何与期望状态的偏差,并创建新的 Pod 实例以满足期望状态。
ReplicaSets 是复制控制器的新版本。ReplicaSets 提供与复制控制器相同的功能,并增加了一些高级功能。其中最主要的功能是可以丰富地定义与 Pod 相关的选择器。使用 ReplicaSets,可以定义复制控制器中没有的动态表达式。
推荐使用 ReplicaSets 而不是复制控制器。
下一个代码示例展示了如何定义一个 ReplicaSet 资源:
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: tappdeployment
labels:
appname: tapp
ostype: linux
spec:
replicas: 3
selector:
matchLabels:
appname: myappnew
template:
metadata:
name: mypod
labels:
appname: myappnew
spec:
containers:
- name: mynewcontainer
image: "tacracr.azurecr.io/tapp:latest"
ports:
- containerPort: 80
protocol: TCP
name: http
需要注意的是,ReplicaSets 有一个 replicas 属性,决定 Pod 实例的数量,selector 属性,定义哪些 Pods 应该由 ReplicaSet 管理,最后是 template 属性,定义 Pod 本身。
ConfigMaps 和 Secrets
Kubernetes 提供了两种重要的资源来存储配置信息。ConfigMaps 用于存储不涉及安全的普通配置信息。诸如文件夹名、卷名和 DNS 名称等通用应用配置数据可以存储在 ConfigMaps 中。另一方面,敏感数据,如凭证、证书和机密,应存储在 Secrets 资源中。这些 Secrets 数据会加密并存储在 Kubernetes 的 etcd 数据存储中。
ConfigMaps 和 Secrets 数据可以作为环境变量或在 Pods 中的卷提供。
想要使用这些资源的 Pod 定义应该包括对它们的引用。我们现在已经介绍了 Kubernetes 的基本构件以及每个构件的角色。接下来,你将学习 AKS 的架构。
AKS 架构
在上一节中,我们讨论了无管理集群的架构。现在,我们将探讨 AKS 的架构。当你阅读完这一节后,你将能够指出无管理集群与管理集群(在此案例中为 AKS)架构之间的主要区别。
当创建 AKS 实例时,只会创建工作节点。主控组件由 Azure 管理。主控组件包括 API 服务器、调度器、etcd 和控制器管理器,这些我们之前已经讨论过。kubelets 和 kube-proxy 部署在工作节点上。节点与主控组件之间的通信通过 kubelets 实现,kubelets 充当 Kubernetes 集群的代理:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_08.jpg
图 14.8:AKS 架构
当用户请求一个 Pod 实例时,用户请求会到达 API 服务器。API 服务器检查并验证请求的详细信息,将其存储在 etcd(集群的数据存储)中,并且还会创建部署资源(如果 Pod 请求是围绕部署资源包装的)。部署控制器监视任何新部署资源的创建。如果它发现新资源,它会根据用户请求中提供的定义创建一个 ReplicaSet 资源。
ReplicaSet 控制器监视任何新 ReplicaSet 资源的创建,并在看到资源被创建时,要求调度器调度 Pods。调度器有自己的过程和规则,用于找到合适的节点来托管 Pods。调度器将节点信息通知 kubelet,kubelet 然后获取 Pod 的定义并使用节点上安装的容器运行时创建 Pods。最终,Pod 在其定义中创建容器。
kube-proxy 帮助维护本地节点上 Pod 和 Service 信息的 IP 地址列表,并更新本地防火墙和路由规则。为了快速回顾我们到目前为止讨论的内容,我们从 Kubernetes 架构开始,然后转向基本组件,接着讨论了 AKS 的架构。既然你已经清楚这些概念,我们接下来在下一部分创建 AKS 集群。
部署 AKS 集群
AKS 可以通过 Azure 门户、Azure CLI(命令行界面)、Azure PowerShell cmdlets、ARM 模板、支持语言的 SDKs(软件开发工具包)甚至 Azure ARM REST API 来进行配置。
Azure 门户是创建 AKS 实例最简单的方法;然而,为了启用 DevOps,最好使用 ARM 模板、CLI 或 PowerShell 来创建 AKS 实例。
创建 AKS 集群
让我们创建一个资源组来部署我们的 AKS 集群。从 Azure CLI 使用 az group create 命令:
az group create -n AzureForArchitects -l southeastasia
这里,-n 表示资源组的名称,-l 表示位置。如果请求成功,你将看到类似下面的响应:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_09.jpg
图 14.9:资源组创建
现在我们已经准备好了资源组,我们将使用 az aks create 命令继续创建 AKS 集群。以下命令将在 AzureForArchitects 资源组中创建一个名为 AzureForArchitects-AKS 的集群,节点数为 2。--generate-ssh-keys 参数将允许创建 RSA(Rivest–Shamir–Adleman)密钥对,这是一个公钥加密系统:
az aks create --resource-group AzureForArchitects \
--name AzureForArchitects-AKS \
--node-count 2 \
--generate-ssh-keys
如果命令成功,你将能够看到类似的输出:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_10.jpg
图 14.10:创建集群
在查看集群时,你会看到一行项,内容是 "nodeResourceGroup": "MC_AzureForArchitects_AzureForArchitects-AKS_southeastasia"。创建 AKS 集群时,会自动创建第二个资源来存储节点资源。
我们的集群已经配置好。现在我们需要连接到集群并与其互动。为了控制 Kubernetes 集群管理器,我们将使用 kubectl。在接下来的章节中,我们将快速了解一下 kubectl。
Kubectl
Kubectl 是开发人员和基础设施顾问与 AKS 互动的主要工具。Kubectl 帮助创建一个包含 HTTP 头和正文的 REST 请求,并将其提交到 API 服务器。头部包含认证信息,如令牌或用户名/密码组合。正文包含实际的 JSON 格式有效负载。
kubectl 命令提供了丰富的日志细节,当与详细开关一起使用时,开关会接受一个从 0 到 9 的整数输入,可以从详细日志中查看。
连接到集群
若要本地连接到集群,我们需要安装 kubectl。Azure Cloud Shell 已经预装了 kubectl。如果你想在本地连接,请使用 az aks install-cli 来安装 kubectl。
为了配置 kubectl 连接到我们的 Kubernetes 集群,我们需要下载凭证并用它们配置 CLI。可以使用 az aks get-credentials 命令来完成。使用如下命令:
az aks get-credentials \
--resource-group AzureForArchitects \
--name AzureForArchitects-AKS
现在,我们需要验证是否已连接到集群。如前所述,我们将使用 kubectl 与集群通信,kubectl get nodes 将显示集群中节点的列表。在创建时,我们将节点数量设置为 2,所以输出应该有两个节点。同时,我们需要确保节点的状态为 Ready。输出应类似于图 14.11:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_11.jpg
图 14.11:获取节点列表
由于我们的节点处于 Ready 状态,让我们继续创建一个 Pod。在 Kubernetes 中创建资源有两种方法。它们是:
-
使用
kubectl run和kubectl expose命令来创建资源。 -
使用
kubectl apply命令来创建资源,文件中声明的资源将被创建。
让我们首先采用命令式方法,创建一个名为 webserver 的 Pod,运行一个暴露 80 端口的 NGINX 容器:
kubectl run webserver --restart=Never --image nginx --port 80
命令成功完成后,CLI 将告知你状态:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_12.jpg
图 14.12:创建一个 Pod
既然我们已经尝试了命令式方法,现在让我们采用声明式方法。你可以使用我们在 Kubernetes 原语 部分的 Pod 小节中讨论的 YAML 文件结构,并根据需求进行修改。
我们将使用 NGINX 镜像,Pod 将命名为webserver-2。
你可以使用任何文本编辑器创建这个文件。最终的文件将类似于这样:
apiVersion: v1
kind: Pod
metadata:
name: webserver-2
labels:
appname: nginx
ostype: linux
spec:
containers:
- name: wenserver-2-container
image: nginx
ports:
- containerPort: 80
protocol: TCP
name: http
在kubectl apply命令中,我们将把文件名传递给-f参数,如图 14.13所示,你可以看到 Pod 已经创建:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_13.jpg
图 14.13:使用声明式方法创建 Pod。
由于我们已经创建了 Pods,我们可以使用kubectl get pods命令列出所有的 Pods。Kubernetes 使用命名空间的概念来逻辑隔离资源。默认情况下,所有命令都指向default命名空间。如果你想对特定命名空间执行操作,可以通过-n参数传递命名空间的名称。在图 14.14中,你可以看到kubectl get pods返回的是我们在前一个示例中创建的 Pods,它们位于默认命名空间中。此外,当我们使用--all-namespaces时,输出会返回所有命名空间中的 Pods:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_14.jpg
图 14.14:列出所有 Pods
现在我们将创建一个简单的 Deployment,运行 NGINX,并通过负载均衡器将其暴露到互联网。YAML文件将如下所示:
#Creating a deployment that runs six replicas of nginx
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-server
spec:
replicas: 6
selector:
matchLabels:
app: nginx-server
template:
metadata:
labels:
app: nginx-server
spec:
containers:
- name: nginx-server
image: nginx
ports:
- containerPort: 80
name: http
---
#Creating Service
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
ports:
- port: 80
selector:
app: nginx-server
---
apiVersion: v1
kind: Service
metadata:
name: nginx-lb
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: nginx-server
我们将使用kubectl apply命令并将YAML文件传递给-f参数。
成功后,将创建所有三个服务,如果你执行kubectl get deployment nginx-server命令,你将看到六个副本在运行,如图 14.15所示,从而使服务具有高可用性:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_15.jpg
图 14.15:检查 Deployment
由于我们的 Deployment 已经配置好,我们需要检查我们创建的负载均衡器的公共 IP。我们可以使用kubectl get service nginx-lb --watch命令。当负载均衡器初始化时,EXTERNAL-IP将显示为<pending>,--wait参数将使命令在前台运行,当公共 IP 分配完毕时,我们将看到一行新的信息,如下所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_16.jpg
图 14.16:查找负载均衡器的公共 IP
现在我们有了公共 IP,我们可以打开浏览器,应该能看到 NGINX 登录页面,如图 14.17所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_17.jpg
图 14.17:NGINX 登录页面
同样,你可以使用我们在Kubernetes 基础组件部分讨论的YAML文件来创建不同类型的资源。
有许多命令,如 logs、describe、exec 和 delete,管理员需要在 kubectl 命令中使用。本节的目标是帮助你创建一个 AKS 集群,连接到集群,并部署一个简单的 web 应用。
在接下来的部分,我们将讨论 AKS 网络。
AKS 网络
网络是 Kubernetes 集群中的核心组件。主组件应该能够访问从属节点及其上运行的 Pods,而工作节点则应该能够相互通信并与主组件进行通信。
可能会让你感到惊讶的是,核心 Kubernetes 并不管理网络栈。这是节点上容器运行时的工作。
Kubernetes 制定了三个重要原则,任何容器运行时都应遵守。这些原则如下:
-
Pods 应该能够与其他 Pods 进行通信,而无需改变其源地址或目标地址,这是通过使用网络地址转换(NAT)来实现的。
-
像 kubelet 这样的代理应该能够直接与节点上的 Pods 进行通信。
-
直接托管在主机网络上的 Pods 仍然应该能够与集群中的所有 Pods 进行通信。
每个 Pod 在 Kubernetes 集群中都会获得一个唯一的 IP 地址,并拥有一个完整的网络栈,类似于虚拟机。它们都连接到由容器网络接口(CNI)组件创建的本地桥接网络。CNI 组件还会创建 Pod 的网络栈。然后,桥接网络与主机网络进行通信,并成为 Pods 与网络之间流量传输的通道,反之亦然。
CNI 是由云原生计算基金会(CNCF)管理和维护的标准,有许多提供商提供其自定义实现。Docker 就是其中之一。还有其他提供商,例如 rkt(读作 rocket)、weave、calico 等。每个提供商都有自己的能力,并独立决定网络功能,同时确保完全遵循 Kubernetes 网络的主要原则。
AKS 提供两种不同的网络模型:
-
Kubenet
-
Azure CNI
Kubenet
Kubenet 是 AKS 中的默认网络框架。在 Kubenet 模式下,每个节点从它们所连接的虚拟网络的子网中获取一个 IP 地址。Pods 不会从子网中获取 IP 地址。相反,使用一个独立的寻址方案为 Pods 和 Kubernetes 服务提供 IP 地址。在创建 AKS 实例时,重要的是为 Pods 和服务设置 IP 地址范围。由于 Pods 不在与节点相同的网络中,因此来自 Pods 或指向 Pods 的请求总是会通过 NAT 转换或路由,将源 Pod 的 IP 地址替换为节点的 IP 地址,反之亦然。
在用户定义的路由中,Azure 可以支持最多 400 条路由,且集群中的节点数不能超过 400 个。图 14.18 显示了 AKS 节点如何从虚拟网络获取 IP 地址,但不包括在节点中创建的 Pods:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_18.jpg
图 14.18:AKS 中的网络
默认情况下,这个 Kubenet 配置为每个节点 110 个 Pods。这意味着默认情况下,在 Kubernetes 集群中最多可以有 110 * 400 个 Pods。每个节点的最大 Pods 数量是 250。
当 IP 地址的可用性和用户定义的路由不是限制条件时,应该使用此方案。
在 Azure CLI 中,你可以执行以下命令来使用此网络堆栈创建 AKS 实例:
az aks create \
--resource-group myResourceGroup \
--name myAKSCluster \
--node-count 3 \
--network-plugin kubenet \
--service-cidr 10.0.0.0/16 \
--dns-service-ip 10.0.0.10 \
--pod-cidr 10.244.0.0/16 \
--docker-bridge-address 172.17.0.1/16 \
--vnet-subnet-id $SUBNET_ID \
--service-principal <appId> \
--client-secret <password>
请注意,所有的 IP 地址都明确地为服务资源、Pods、节点和 Docker 桥接提供。这些是非重叠的 IP 地址范围。同时请注意,Kubenet 被用作网络插件。
Azure CNI(高级网络)
使用 Azure CNI 时,每个节点和 Pod 会直接从网络子网分配一个 IP 地址。这意味着,可以根据子网中可用的唯一 IP 地址数量来拥有尽可能多的 Pods。这使得在这种网络策略下,IP 地址范围规划变得更加重要。
需要注意的是,Windows 主机仅能使用 Azure CNI 网络堆栈。此外,某些 AKS 组件,如虚拟节点和虚拟 kubelet,也依赖于 Azure CNI 堆栈。根据将要创建的 Pods 数量,可能需要提前预留 IP 地址。子网中应该始终有额外的 IP 地址,以避免 IP 地址耗尽,或者避免因应用需求而需要重新构建集群来支持更大的子网。
默认情况下,此网络堆栈配置为每个节点 30 个 Pods,并且可以配置为每个节点最多支持 250 个 Pods。
用于创建 AKS 实例的命令如下所示:
az aks create \
--resource-group myResourceGroup \
--name myAKSCluster \
--network-plugin azure \
--vnet-subnet-id <subnet-id> \
--docker-bridge-address 172.17.0.1/16 \
--dns-service-ip 10.2.0.10 \
--service-cidr 10.2.0.0/24 \
--generate-ssh-keys
请注意,所有的 IP 地址都明确地为服务资源、Pods、节点和 Docker 桥接提供。这些是非重叠的 IP 地址范围。同时,注意 Azure 被用作网络插件。
到目前为止,你已经学习了如何部署解决方案并管理 AKS 集群的网络。安全性是另一个需要解决的重要因素。在下一部分,我们将重点介绍 AKS 的访问和身份验证选项。
AKS 的访问和身份验证
Kubernetes 集群可以通过多种方式进行安全保护。
服务账户是 Kubernetes 中的主要用户类型之一。Kubernetes API 管理服务账户。授权的 Pod 可以使用服务账户的凭证与 API 服务器通信,这些凭证作为 Kubernetes Secrets 存储。Kubernetes 没有自己的数据存储或身份提供者,它将认证的责任委托给外部软件。它提供了一个认证插件,用于检查给定的凭证并将其映射到可用的组。如果认证成功,请求会传递给另一组授权插件,以检查用户在集群上的权限级别,以及命名空间范围内的资源。
对于 Azure,最佳的安全集成方式是使用 Azure AD。使用 Azure AD,您还可以将本地身份带入 AKS,以提供账户和安全的集中管理。Azure AD 集成的基本工作流程如 图 14.19 所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_19.jpg
图 14.19:Azure AD 集成的基本工作流程
用户或组可以被授予访问命名空间内或跨集群的资源的权限。在上一节中,我们使用了 az aks get-credential 命令来获取凭证和 kubectl 配置上下文。当用户尝试与 kubectl 交互时,系统会提示他们使用 Azure AD 凭证进行登录。Azure AD 验证凭证并为用户发放令牌。根据他们的访问级别,他们可以访问集群或命名空间中的资源。
此外,您可以利用 Azure 基于角色的访问控制 (RBAC) 来限制对资源组内资源的访问。
在下一节中,我们将讨论虚拟 kubelet,它是扩展集群的最快方式之一。
虚拟 kubelet
虚拟 kubelet 目前处于预览阶段,由 CNCF 组织管理。它是 AKS 用于扩展性目的的一种创新方法。虚拟 kubelet 作为一个 Pod 部署在 Kubernetes 集群中。运行在 Pod 内的容器使用 Kubernetes SDK 创建一个新的节点资源,并将自己作为节点呈现给整个集群。集群组件,包括 API 服务器、调度器和控制器,认为它是一个节点,并在其上调度 Pods。
然而,当一个 Pod 被调度到这个伪装成节点的节点上时,它会与其后端组件(称为提供者)进行通信,以创建、删除和更新 Pods。Azure 上的一个主要提供者是 Azure 容器实例。Azure 批量处理也可以作为提供者使用。这意味着容器实际上是在容器实例或 Azure 批量处理上创建的,而不是在集群本身上;然而,它们仍由集群管理。虚拟 kubelet 的架构如 图 14.20 所示:
https://github.com/OpenDocCN/freelearn-devops-pt4-zh/raw/master/docs/az-arch-3e/img/B15432_14_20.jpg
图 14.20:虚拟 kubelet 架构
请注意,虚拟 kubelet 在集群内表现为一个节点,并且能够像普通的 kubelet 一样帮助托管和管理 Pods。然而,虚拟 kubelet 有一个局限性;这就是我们将在下一节中讨论的内容。
虚拟节点
虚拟 kubelet 的一个局限性是,部署在虚拟 kubelet 提供者上的 Pods 是隔离的,无法与集群中的其他 Pods 通信。如果这些提供者上的 Pods 需要与集群中的其他 Pods 和节点进行通信,反之亦然,则应该创建虚拟节点。虚拟节点会在与 Kubernetes 集群节点所在虚拟网络的同一虚拟网络上,使用不同的子网创建,这样可以启用 Pods 之间的通信。到目前为止,仅支持 Linux 操作系统与虚拟节点协作。
虚拟节点提供了一个节点的感知;然而,节点并不存在。任何在这样的节点上调度的任务实际上会在 Azure 容器实例中创建。虚拟节点基于虚拟 kubelet,但具有额外的功能,即集群与 Azure 容器实例之间的无缝双向通信。
在虚拟节点上部署 Pods 时,Pod 定义应该包含适当的节点选择器,以引用虚拟节点,并且还应包含容忍设置,如下一个代码片段所示:
nodeSelector:
kubernetes.io/role: agent
beta.kubernetes.io/os: linux
type: virtual-kubelet
tolerations:
- key: virtual-kubelet.io/provider
operator: Exists
- key: azure.com/aci
effect: NoSchedule
在这里,节点选择器使用 type 属性引用虚拟 kubelet,而 tolerations 属性则通知 Kubernetes,带有污点 virtual-kubelet.io/provider 的节点应允许这些 Pods 的部署。
概述
Kubernetes 是最广泛使用的容器编排工具,并与不同的容器和网络运行时一起工作。在本章中,您了解了 Kubernetes 的基础知识、其架构以及一些重要的基础设施组件,如 etcd、API 服务器、控制器管理器和调度器,以及它们的作用。此外,我们还介绍了可以用于管理应用程序的重要资源,如 Pods、复制控制器、ReplicaSets、Deployments 和 Services。
AKS 提供了几种不同的网络栈——Azure CNI 和 Kubenet。它们为 Pods 分配 IP 地址提供了不同的策略。Azure CNI 从底层子网为 Pods 提供 IP 地址,而 Kubenet 仅使用虚拟 IP 地址。
我们还介绍了 Azure 独有的一些功能,如虚拟节点,以及虚拟 kubelet 的相关概念。在下一章中,我们将学习如何通过 ARM 模板配置和管理资源。
1103

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



