你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

高级 Azure Kubernetes 服务 (AKS) 微服务体系结构

Azure 应用程序网关
Azure 容器注册表
Azure Kubernetes 服务 (AKS)
Azure 虚拟网络

此参考体系结构详细说明了在 Azure Kubernetes 服务上运行微服务时要考虑的几项配置。 主题包括配置网络策略、pod 自动缩放,以及在整个基于微服务的应用程序中进行分布式跟踪。

此体系结构是基于 AKS 基线体系结构(Microsoft 建议的 Azure Kubernetes 服务 (AKS) 基础结构起点)构建的。 AKS 基线详细说明了 Microsoft Entra 工作负载 ID、入口和出口限制、资源限制和其他安全 AKS 基础结构配置等基础结构功能。 本文档未涵盖这些基础结构详细信息。 建议先熟悉 AKS 基线,然后再继续处理微服务内容。

GitHub 徽标 GitHub 中提供了此体系结构的参考实现。

体系结构

显示具有两个对等虚拟网络的中心辐射型网络以及此实现使用的 Azure 资源的网络图。

下载此体系结构的 Visio 文件

如果你希望从 AKS 上更基本的微服务示例开始,请参阅 AKS 上的微服务体系结构

工作流

此请求流实现发布者-订阅者竞争使用者网关路由云设计模式。 消息传递流的处理方式如下:

  1. 提交 HTTPS 请求以安排无人机取件。 该请求通过 Azure 应用程序网关传入到引入 Web 应用程序,该应用程序在 AKS 中作为群集内微服务运行。

  2. 引入 Web 应用程序生成一条消息并将其发送到服务总线消息队列。

  3. 后端系统分配无人机并通知用户。 该工作流:

    • 使用来自服务总线消息队列的消息信息。
    • 将 HTTPS 请求发送到交付微服务,后者将数据传递到 Azure Cache for Redis 外部数据存储。
    • 将 HTTPS 请求发送到无人机调度程序微服务。
    • 将 HTTPS 请求发送到包裹微服务,后者将数据传递到 MongoDB 外部数据存储。
  4. HTTPS GET 请求用于返回交付状态。 此请求通过应用程序网关传入交付微服务。

  5. 交付微服务从 Azure Cache for Redis 读取数据。

组件

此体系结构使用以下 Azure 组件:

Azure Kubernetes 服务是提供托管 Kubernetes 群集的 Azure 服务。 使用 AKS 时,Kubernetes API 服务器由 Azure 管理。 Kubernetes 节点或节点池可供访问,并可以由群集操作员管理。

此体系结构中使用的 AKS 基础结构功能包括:

Azure 虚拟网络 是独立且高度安全的环境,用于运行虚拟机(VM)和应用程序。 此参考体系结构使用对等互连的中心辐射型虚拟网络拓扑。 中心虚拟网络包含 Azure 防火墙和 Azure Bastion 子网。 支路虚拟网络包含 AKS 系统和用户节点池子网,以及 Azure 应用程序网关子网。

Azure 专用链接分配特定的专用 IP 地址,以从 AKS 系统和用户节点池子网内的专用终结点访问 Azure 容器注册表和密钥保管库。

带有 Web 应用程序防火墙 (WAF) 的 Azure 应用程序网关将 HTTP(S) 路由公开给 AKS 群集,并对发往 Web 应用程序的 Web 流量进行负载均衡。 此体系结构使用 Azure 应用程序网关入口控制器 (AGIC) 作为 Kubernetes 入口控制器。

Azure Bastion 使用安全套接字层 (SSL) 提供对虚拟网络中 VM 的安全远程桌面协议 (RDP) 和安全外壳 (SSH) 访问,而无需通过公共 IP 地址公开 VM。

Azure 防火墙是保护所有 Azure 虚拟网络资源的网络安全服务。 防火墙仅允许已获批准的服务和完全限定域名 (FQDN) 作为出口流量。

外部存储和其他组件:

Azure 密钥保管库存储和管理 AKS 服务的安全密钥。

Azure 容器注册表存储可在 AKS 群集中运行的专用容器映像。 AKS 使用其 Microsoft Entra 托管标识对容器注册表进行身份验证。 也可以使用其他容器注册表,例如 Docker Hub。

Azure Cosmos DB 使用开源的 Azure Cosmos DB for MongoDB 存储数据。 微服务通常是无状态的,它们将自身的状态写入外部数据存储。 Azure Cosmos DB 是一个 NoSQL 数据库,具有适用于 MongoDB 和 Cassandra 的开源 API。

Azure 服务总线提供可靠的云消息传递即服务和简单的混合集成。 服务总线支持微服务应用程序中常用的异步消息传递模式。

Azure Cache for Redis 在应用程序体系结构中添加一个缓存层,以提高繁重流量负载的速度和性能。

Azure Monitor 收集并存储指标和日志,包括应用程序遥测数据以及 Azure 平台和服务指标。 可以使用此数据来监视应用程序、设置警报和仪表板,以及针对故障执行根本原因分析。

其他操作支持系统 (OSS) 组件:

Kubernetes 的包管理器 Helm,它将 Kubernetes 对象捆绑为单个可发布、部署、进行版本控制和更新的单元。

Azure 密钥保管库机密存储 CSI 提供程序,它获取存储在 Azure 密钥保管库中的机密,并使用机密存储 CSI 驱动程序接口将这些机密装载到 Kubernetes pod 中。

Flux,它是一种开放且可扩展的 Kubernetes 持续交付解决方案,由 GitOps 工具包提供支持。

方案详细信息

上图中显示的示例 Fabrikam 无人机交货应用将实现本文中所述的体系结构组件和实践。 在此示例中,虚构公司 Fabrikam Inc. 管理一个无人机群。 商家可以注册该服务,用户可以请求无人机收取要交付的商品。 当客户安排取件时,后端系统会分配一架无人机,并将估计的交付时间告知用户。 在交付过程中,客户可以通过持续更新的 ETA 跟踪无人机的位置。

可能的用例

此解决方案是飞机、航空航天和航空工业的理想选择。

建议

在部署高级 AKS 微服务体系结构时请实施这些建议。

应用程序网关入口控制器 (AGIC)

API 网关路由是一种常规微服务设计模式。 API 网关充当反向代理,用于将请求从客户端路由到微服务。 Kubernetes 入口资源和入口控制器通过以下方式处理大多数 API 网关功能:

将客户端请求路由到正确的后端服务可为客户端提供单个终结点,并帮助将客户端与服务解耦。

  • 将多个请求聚合成单个请求,以减少客户端与后端之间的通信频率。
  • 从后端服务卸载 SSL 终止、身份验证、IP 限制和客户端速率限制或节流等功能。

AKS 群集的状态将转换为特定于应用程序网关的配置,并通过 Azure 资源管理器应用。

外部入口控制器可以简化将流量引入 AKS 群集的过程、提高安全性和性能,并节省资源。 此体系结构使用 Azure 应用程序网关入口控制器 (AGIC) 进行入口控制。 如果使用应用程序网关来处理所有流量,就不需要额外的负载均衡器。 由于 pod 与应用程序网关建立直接连接,因此减少了所需的跃点数,从而提高了性能。

应用程序网关具有内置的自动缩放功能,这与群集内入口控制器不同,对于后者,如果它们需要消耗意外数量的计算资源,则必须将其横向扩展。 应用程序网关可以执行第 7 层路由和 SSL 终止,并与内置 Web 应用程序防火墙 (WAF) 保持端到端的传输层安全性 (TLS) 集成。

对于 AGIC 入口选项,必须在配置 AKS 群集时启用 CNI 网络,因为应用程序网关已部署到 AKS 虚拟网络中的子网内。 多租户工作负荷或支持开发和测试环境的单个群集可能需要更多入口控制器。

零信任网络策略

网络策略指定允许 AKS pod 如何相互通信以及与其他网络终结点通信。 默认情况下,允许传入和传出 pod 的所有入口和出口流量。 在设计微服务相互之间以及它们与其他终结点通信的方式时,请考虑遵循零信任原则,该原则要求完成显式配置才能对任何服务、设备、应用程序或数据存储库进行访问。

实施零信任策略的一种战略是创建一个网络策略,以便拒绝发往目标命名空间中所有 pod 的所有入口和出口流量。 以下示例显示了一个应用于 backend-dev 命名空间中所有 pod 的“全部拒绝策略”。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: backend-dev
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

实施限制策略后,请开始定义特定的网络规则,以允许流量传入和传出微服务中的每个 pod。 在以下示例中,网络策略应用于 backend-dev 命名空间中标签与 app.kubernetes.io/component: backend 匹配的任何 pod。 该策略拒绝任何流量,除非来自标签与 app.kubernetes.io/part-of: dronedelivery 匹配的 pod。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: package-v010-dev-np-allow-ingress-traffic
  namespace: backend-dev
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/component: backend
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app.kubernetes.io/part-of: dronedelivery
    ports:
    - port: 80
      protocol: TCP

有关 Kubernetes 网络策略的详细信息和潜在默认策略的更多示例,请参阅 Kubernetes 文档中的“网络策略”

资源配额

管理员可以通过资源配额在开发团队或项目中保留和限制资源。 可以针对命名空间设置资源配额,并使用这些配额针对以下资源设置限制:

  • 计算资源:例如 CPU 和内存,或 GPU。
  • 存储资源:包括给定存储类的卷数或磁盘空间量。
  • 对象计数,例如可创建的机密、服务或作业数上限。

一旦资源请求或限制的累积总数超过分配的配额,则所有后续部署都不会成功。

资源配额确保分配给命名空间的 pod 总数不能超过命名空间的资源配额。 前端不能耗尽后端服务的资源,反之亦然。

定义资源配额时,命名空间中创建的所有 pod 必须在其 pod 规范中提供限制或请求。 如果它们未提供这些值,则会拒绝部署。

以下示例显示了一个设置资源配额请求和限制的 pod 规范:

requests:
  cpu: 100m
  memory: 350Mi
limits:
  cpu: 200m
  memory: 500Mi

有关资源配额的详细信息,请参阅:

自动缩放

Kubernetes 支持自动缩放,以增加分配给部署的 pod 数,或增加群集中的节点数来增加可用的计算资源总数。 自动缩放是一种自我纠正的自治反馈系统。 尽管你可以手动缩放 pod 和节点,但自动缩放可以最大程度地减少服务在承受高负载时资源枯竭的可能性。 自动缩放策略必须同时考虑到 pod 和节点。

群集自动缩放

群集自动缩放程序 (CA) 可以缩放节点数目。 假设由于资源约束而无法计划 pod,群集自动缩放程序将预配更多节点。 定义最少数量的节点可使 AKS 群集和工作负载保持正常运行,而定义最多数量的节点可以应对繁重的流量。 CA 每隔几秒钟检查一次挂起的 pod 或空节点,并相应地缩放 AKS 群集。

以下示例显示了 ARM 模板中的 CA 配置:

"autoScalerProfile": {
    "scan-interval": "10s",
    "scale-down-delay-after-add": "10m",
    "scale-down-delay-after-delete": "20s",
    "scale-down-delay-after-failure": "3m",
    "scale-down-unneeded-time": "10m",
    "scale-down-unready-time": "20m",
    "scale-down-utilization-threshold": "0.5",
    "max-graceful-termination-sec": "600",
    "balance-similar-node-groups": "false",
    "expander": "random",
    "skip-nodes-with-local-storage": "true",
    "skip-nodes-with-system-pods": "true",
    "max-empty-bulk-delete": "10",
    "max-total-unready-percentage": "45",
    "ok-total-unready-count": "3"
},

ARM 模板中的以下行设置 CA 的最小和最大节点数示例值:

"minCount": 2,
"maxCount": 5,

Pod 自动缩放

pod 横向自动缩放程序 (HPA) 根据观察到的 CPU、内存或自定义指标缩放 pod。 若要配置 pod 横向缩放,请在 Kubernetes 部署 pod 规范中指定目标指标以及最小和最大副本数。对服务进行负载测试以确定这些数字。

CA 和 HPA 可以很好地协同工作,因此请在 AKS 群集中启用这两个自动缩放程序选项。 HPA 缩放应用程序,而 CA 缩放基础结构。

以下示例为 HPA 设置资源指标:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: delivery-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: delivery
  minReplicas: 2
  maxReplicas: 5
  metrics:
    - type: Resource
      resource:
        name: cpu
        targetAverageUtilization: 60

HPA 观察实际消耗的资源或运行中 pod 的其他指标,但 CA 为尚未计划的 pod 预配节点。 因此,CA 会按照 pod 规范中的指定来观察请求的资源。使用负载测试来微调这些值。

运行状况探测

Kubernetes 对发往与服务标签选择器匹配的 pod 的流量进行负载均衡。 只有成功启动且正常的 pod 才能收到流量。 如果某个容器崩溃,Kubernetes 会删除 pod,并计划替代的 pod。

在 Kubernetes 中,一个 pod 可以公开两种类型的运行状况探测:

  • 运行情况探测向 Kubernetes 告知 pod 是否成功启动并正常运行。
  • 就绪情况探测向 Kubernetes 告知 pod 是否已准备好接受请求。

运行情况探测处理仍在运行但运行不正常且应回收的 pod。 例如,如果为 HTTP 请求提供服务的容器挂起,则该容器不会崩溃,而是停止为请求提供服务。 HTTP 运行情况探测停止响应,告知 Kubernetes 重启 pod。

有时,尽管某个 pod 已成功启动,但不一定已准备好接收流量。 例如,容器中运行的应用程序可能正在执行初始化任务。 就绪情况探测指示 pod 是否已准备好接收流量。

微服务应在其代码中公开终结点以便于进行运行状况探测,并专门针对它们执行的检查定制延迟和超时设置。 HPA 公式几乎完全关闭 pod 的“就绪”阶段,因此运行状况探测存在且准确至关重要。

监视

在微服务应用程序中,应用程序性能管理 (APM) 监视对于检测异常、诊断问题和快速了解服务之间的依赖关系至关重要。 作为 Azure Monitor 的一部分的 Application Insights 为使用 .NET Core、Node.js、Java 和其他许多应用程序语言编写的实时应用程序提供 APM 监视。

Application Insights:

  • 记录 HTTP 请求,包括延迟和结果代码。
  • 默认启用分布式跟踪。
  • 在跟踪中包含操作 ID,因此可以匹配特定操作的所有跟踪。
  • 通常在跟踪中包含额外的上下文信息。

若要根据 Kubernetes 环境将服务遥测上下文化,请将 Azure Monitor 遥测与 AKS 集成,以便从控制器、节点和容器以及容器日志和节点日志中收集指标。 如果你使用 .NET,Application Insights for Kubernetes 库可以使用映像、容器、节点、pod、标签和副本集信息来扩充 Application Insights 遥测。

下图显示了 Application Insights 为 AKS 微服务遥测跟踪生成的应用程序依赖关系映射示例:

AKS 微服务应用程序的 Application Insights 依赖关系映射的示例。

有关为 Application Insights 集成检测常用语言的选项的详细信息,请参阅 Kubernetes 的应用程序监视

注意事项

这些注意事项实施 Azure 架构良好的框架的支柱原则,即一套可用于改善工作负荷质量的指导原则。 有关详细信息,请参阅 Microsoft Azure 架构良好的框架

可伸缩性

在规划可伸缩性时,请注意以下几点。

  • 不要将自动缩放和副本数量的命令式或声明式管理相结合。 尝试修改副本数量的用户和自动缩放程序可能会导致意外行为。 启用 HPA 后,将副本数量减少至要部署的最小数量。

  • pod 自动缩放的负面影响是发生横向扩展和横向缩减事件时,会频繁地创建或逐出 pod。 若要缓解这些影响,请采取以下措施:

    • 使用就绪情况探测来让 Kubernetes 知道新 pod 已准备好接受流量。
    • 使用 pod 中断预算来限制每次可从服务中逐出的 pod 数。
  • 创建群集后无法更改 VM 大小,因此,在创建群集时,请进行初始容量规划,以便为代理节点选择适当的 VM 大小。

  • 多租户或其他高级工作负荷可能具有节点池隔离要求,这些要求需要更多和可能更小的子网。 有关创建包含独特子网的节点池的详细信息,请参阅添加包含唯一子网的节点池。 组织对其中心辐射型实现采用不同的标准。 请务必遵循组织的准则。

可管理性

在规划可管理性时,请注意以下几点。

  • 通过自动部署管道管理 AKS 群集基础结构。 此体系结构的参考实现提供了一个 GitHub Actions 工作流,在生成管道时可以参考该工作流。

  • 工作流文件仅将基础结构(而不会将工作负载)部署到已存在的虚拟网络和 Microsoft Entra 配置中。 分开部署基础结构和工作负载可以解决不同的生命周期和操作问题。

  • 如果发生区域性故障,可将工作流视为一种部署到另一个区域的机制。 生成管道,以便可以将更改了参数和输入的新群集部署到新区域中。

安全性

安全性针对蓄意攻击及滥用宝贵数据和系统提供保障措施。 有关详细信息,请参阅安全性支柱概述

在规划安全性时,请注意以下几点。

  • AKS Pod 使用 Microsoft Entra ID 中存储的工作负载标识对自身进行身份验证。 最好是使用工作负载标识,因为它不需要客户端机密。

  • 如果使用托管标识,执行进程可以快速获取 Azure 资源管理器 OAuth 2.0 令牌;不需要提供密码或连接字符串。 在 AKS 中,可以使用 Microsoft Entra 工作负载 ID 将标识分配给各个 Pod。

  • 应该为微服务应用程序中的每个服务分配唯一的工作负载标识,以便于完成最低特权 RBAC 分配。 应该只将标识分配给需要标识的服务。

  • 如果某个应用程序组件需要 Kubernetes API 访问权限,请确保将应用程序 Pod 配置为使用具有适当范围的 API 访问权限的服务帐户。 有关配置和管理 Kubernetes 服务帐户的详细信息,请参阅管理 Kubernetes 服务帐户

  • 并非所有 Azure 服务都支持使用 Microsoft Entra ID 进行数据平面身份验证。 若要为这些服务、第三方服务或 API 密钥存储凭据或应用程序机密,请使用 Azure 密钥保管库。 Azure Key Vault 提供集中式管理、访问控制、静态加密以及所有密钥和机密的审核。

  • 在 AKS 中,可将 Key Vault 中的一个或多个机密装载为一个卷。 然后,pod 可以像读取普通卷一样读取密钥保管库机密。 有关详细信息,请参阅 GitHub 上的 secrets-store-csi-driver-provider-azure 项目。

成本优化

成本优化是关于寻找减少不必要的费用和提高运营效率的方法。 有关详细信息,请参阅成本优化支柱概述

后续步骤