此参考体系结构演示了部署到 Azure Kubernetes 服务 (AKS) 中的微服务应用程序。 它演示的基本 AKS 配置可用作大多数部署的起点。 本文假设读者基本了解 Kubernetes。 本文侧重于有关在 AKS 中运行微服务体系结构的基础结构和 DevOps 注意事项。 有关如何设计微服务的指导,请参阅在 Azure 中构建微服务。
GitHub 中提供了此体系结构的参考实现。
体系结构
下载此体系结构的 Visio 文件。
如果希望看到基于 AKS 基准体系结构而构建的更高级微服务的示例,请参阅高级 Azure Kubernetes 服务 (AKS) 微服务体系结构
工作流
该体系结构包括以下组件。
Azure Kubernetes 服务 (AKS)。 AKS 是托管在 Azure 云中的托管 Kubernetes 群集。 Azure 管理 Kubernetes API 服务,而你只需管理代理节点。
虚拟网络。 默认情况下,AKS 创建连接代理节点的虚拟网络。 对于更高级的方案可以先创建虚拟网络,这样便可以控制子网的配置方式、本地连接和 IP 寻址等设置。 有关详细信息,请参阅在 Azure Kubernetes 服务 (AKS) 中配置高级网络。
入口。 入口服务器向群集中的服务公开 HTTP(S) 路由。 有关详细信息,请参阅下面的 API 网关部分。
Azure 负载均衡器。 创建 AKS 群集后,该群集就可使用负载均衡器。 然后,部署 NGINX 服务后,将使用面向入口控制器的新公共 IP 来配置负载均衡器。 这样,负载均衡器会将 Internet 流量路由到入口。
外部数据存储。 微服务通常是无状态的,会将状态写入 Azure SQL 数据库或 Azure Cosmos DB 等外部数据存储。
Microsoft Entra ID。 AKS 使用 Microsoft Entra 标识来创建和管理 Azure 负载均衡器等其他 Azure 资源。 对于客户端应用程序中的用户身份验证,也建议使用 Microsoft Entra ID。
Azure 容器注册表。 使用容器注册表来存储部署到群集中的专用 Docker 映像。 AKS 可使用 Microsoft Entra 标识向容器注册表进行身份验证。 AKS 不需要 Azure 容器注册表。 可以使用其他容器注册表,例如 Docker 中心。 你只需确保容器注册表达到或超过工作负载的服务级别协议 (SLA)。
Azure Pipelines。 Azure Pipelines 属于 Azure DevOps Services,并运行自动化的生成、测试和部署。 也可以使用 Jenkins 等第三方 CI/CD 解决方案。
Helm。 Helm 是 Kubernetes 的包管理器,使用它可将 Kubernetes 对象打包和概括为单个可以发布、部署、进行版本控制和更新的单元。
Azure Monitor。 Azure Monitor 收集并存储 Azure 服务的指标和日志、应用程序遥测和平台指标。 使用此数据可以监视应用程序,设置警报、仪表板,以及针对故障执行根本原因分析。 Azure Monitor 与 AKS 相集成,可以从控制器、节点和容器收集指标。
注意事项
设计
此参考体系结构侧重于微服务体系结构,不过,许多建议的做法同样适用于 AKS 上运行的其他工作负荷。
微服务
微服务是松散耦合的、可独立部署的代码单元。 微服务通常通过妥善定义的 API 进行通信,可以通过某种形式的服务发现来发现它们。 即使 Pod 四处移动,服务也应始终可供访问。 Kubernetes Service 对象是为 Kubernetes 中的微服务建模的自然方式。
API 网关
API 网关是一种通用的微服务设计模式。 API 网关位于外部客户端和微服务之间。 它充当反向代理,将来自客户端的请求路由到微服务。 它还可以执行各种横切任务,例如身份验证、SSL 终止和速率限制。 有关详细信息,请参阅:
在 Kubernetes 中,API 网关的功能主要由入口控制器处理。 入口部分介绍了注意事项。
数据存储
在微服务体系结构中,服务不应共享数据存储解决方案。 每个服务应管理自己的数据集,以避免服务之间存在隐藏的依赖关系。 分离数据有助于避免服务之间出现意外耦合 - 如果服务共享相同的底层数据架构,就会发生这种情况。 此外,当服务管理自身的数据存储时,可以使用适当的数据存储来满足特定的要求。
有关详细信息,请参阅设计微服务:数据注意事项。
避免在本地群集存储中存储持久性数据,因为这会将数据绑定到节点。 改用 Azure SQL 数据库或 Azure Cosmos DB 等外部服务。 另一种方法是使用 Azure 磁盘或 Azure 文件存储将持久性数据卷装载到解决方案。
有关详细信息,请参阅 Azure Kubernetes 服务中应用程序的存储选项。
Service 对象
Kubernetes Service 对象提供一组符合微服务要求的功能以实现服务可发现性:
IP 地址。 服务对象为一组 pod(副本集)提供静态内部 IP 地址。 创建或移动 pod 时,始终可以通过此内部 IP 地址访问服务。
负载均衡。 发送到服务 IP 地址的流量在 pod 中进行负载均衡。
服务发现。 Kubernetes DNS 服务为服务分配内部 DNS 条目。 这意味着,API 网关可以使用 DNS 名称调用后端服务。 可以使用相同的机制进行服务间的通信。 DNS 条目按命名空间进行组织,因此,如果命名空间对应于边界上下文,则服务的 DNS 名称将以自然方式映射到应用程序域。
下图演示了服务与 Pod 之间的概念关系。 到终结点 IP 地址和端口的实际映射由 Kubernetes 网络代理 kube-proxy 执行。
流入量
在 Kubernetes 中,入口控制器可能实现 API 网关模式。 这种情况下,入口和入口控制器协同工作以提供以下功能:
将客户端请求路由到适当的后端服务。 这种路由为客户端提供单一终结点,帮助将客户端与服务分开。
将多个请求聚合成单个请求,以减少客户端与后端之间的通信频率。
分担后端服务的功能,例如 SSL 终止、身份验证、IP 限制或客户端速率限制(限制)。
入口可以抽象化代理服务器的配置设置。 你还需要可提供基础入口实现的入口控制器。 Nginx、HAProxy、Traefik 和 Azure 应用程序网关等服务都有入口控制器。
入口资源可由不同的技术实现。 若要协同工作,需要将其部署为群集内的入口控制器。 它充当边缘路由器或反向代理。 反向代理服务器是潜在的瓶颈或单一故障点,因此,应至少部署两个副本以实现高可用性。
通常,配置代理服务器需要复杂的文件,如果你不是专家会感到难搞。 因此,入口控制器使之变得抽象,易于处理。 入口控制器可以访问 Kubernetes API,因此,使用它可以在路由和负载均衡方面做出明智的决策。 例如,Nginx 入口控制器可绕过 kube-proxy 网络代理。
另一方面,如果你想要对设置拥有完全控制权,则可能需要绕过这种抽象,并手动配置代理服务器。 有关详细信息,请参阅将 Nginx 或 HAProxy 部署到 Kubernetes。
注意
对于 AKS,还可以通过应用程序网关入口控制器 (AGIC) 使用 Azure 应用程序网关。 Azure 应用程序网关可以执行第 7 层路由和 SSL 终止。 同时还内置了对 Web 应用程序防火墙的支持。 如果 AKS 群集使用 CNI 网络,则应用程序网关可以部署到群集虚拟网络的子网中,或者可以部署在与 AKS 虚拟网络不同的虚拟网络中,但这两个虚拟网络必须对等互连。 AGIC 还支持 Kubenet 网络插件。 使用 Kubenet 模式时,入口控制器需要管理应用程序网关子网中的路由表,以将流量定向到 pod IP。 有关详细信息,请参阅如何设置应用程序网关与 AKS 之间的网络。
有关 Azure 中负载均衡服务的信息,请参阅 Azure 中负载均衡选项概述。
TLS/SSL 加密
在常见实现中,入口控制器用于 SSL 终止。 因此,在部署入口控制器过程中,需要创建 TLS 证书。 只将自签名证书用于开发/测试目的。 有关详细信息,请参阅创建 HTTPS 入口控制器并在 Azure Kubernetes 服务 (AKS) 中使用自己的 TLS 证书。
对于生产工作负荷,请从受信任的证书颁发机构 (CA) 获取签名证书。 有关生成和配置 Let's Encrypt 证书的信息,请参阅在 Azure Kubernetes 服务 (AKS) 中使用静态公共 IP 地址创建入口控制器。
可能还需要根据组织策略轮换这些证书。 若要了解相关信息,请参阅在 Azure Kubernetes 服务 (AKS) 中轮换证书。
命名空间
使用命名空间来组织群集中的服务。 Kubernetes 群集中的每个对象属于某个命名空间。 默认情况下,在创建新对象时,该对象将划归到 default
命名空间。 但是,良好的做法是创建更具描述性的命名空间,以帮助组织群集中的资源。
首先,命名空间有助于防止命名冲突。 如果多个团队将微服务(也许有数百个)部署到同一群集,而这些微服务都属于同一命名空间,则管理就会变得艰难。 此外,命名空间还允许:
将资源约束应用到命名空间,以避免分配到该命名空间的 pod 集总数超过该命名空间的资源配额。
在命名空间级别应用策略,包括 RBAC 和安全策略。
对于微服务体系结构,考虑将微服务组织成边界上下文,并为每个边界上下文创建命名空间。 例如,与“订单履行”边界上下文相关的所有微服务可以划归到同一命名空间。 或者,为每个开发团队创建一个命名空间。
将公用服务放入其自身的独立命名空间。 例如,可以部署 Elasticsearch 或 Prometheus 进行群集监视,或者为 Helm 部署 Tiller。
运行状况探测
Kubernetes 定义 pod 可以公开的两种类型的运行状况探测:
就绪情况探测:告知 Kubernetes Pod 是否已准备好接受请求。
运行情况探测:告知 Kubernetes 是否应删除 Pod 并启动新实例。
考虑探测的设置时,建议回顾 Kubernetes 中的服务工作原理。 服务提供与 pod 集(零个或多个)匹配的标签选择器。 Kubernetes 对发往匹配该选择器的 pod 的流量进行负载均衡。 只有成功启动且正常的 pod 才能收到流量。 如果某个容器崩溃,Kubernetes 会终止 pod,并计划替代的 pod。
有时,尽管某个 pod 已成功启动,但不一定已准备好接收流量。 例如,在执行初始化任务期间,容器中运行的应用程序会将内容载入内存或读取配置数据。 若要指示某个 pod 正常但尚未准备好接收流量,请定义就绪情况探测。
运行情况探测可以处理 pod 仍在运行但不正常,应予以回收的情况。 例如,假设某个容器正在为 HTTP 请求提供服务,但出于某种原因而挂起。 该容器未崩溃,但已停止为任何请求提供服务。 如果定义了 HTTP 运行情况探测,则探测将停止响应,并告知 Kubernetes 重启 pod。
设计探测时请注意以下事项:
如果代码的启动时间较长,则可能存在以下风险:运行情况探测在启动完成之前报告故障。 为防止发生这种探测失败,请使用
initialDelaySeconds
设置,这样可以延迟探测启动。除非重启 pod 有可能会将其还原到正常状态,否则运行情况探测没有作用。 可以使用运行情况探测来防范内存泄漏或意外死锁,但是,没有必要重启立即会再发生故障的 pod。
有时,就绪情况探测可用于检查依赖服务。 例如,如果 Pod 依赖数据库,则探测可以检查数据库连接。 但是,此方法可能造成意外的问题。 外部服务可能出于某种原因而暂时不可用。 这会导致就绪情况探测无法针对服务中的所有 pod 运行,从而导致从负载均衡中删除所有这些 pod,进而又导致上游发生连锁故障。 更好的方法是在服务中实施重试处理,使服务能够从暂时性故障中正常恢复。
资源约束
资源争用可能影响服务的可用性。 为容器定义资源约束,以避免单个容器占用过多的群集资源(内存和 CPU)。 对于非容器资源(例如线程或网络连接),请考虑使用隔舱模式来隔离资源。
使用资源配额限制允许命名空间使用的资源总量。 这样可以避免前端耗尽后端服务的资源,反之亦然。
安全性
基于角色的访问控制 (RBAC)
Kubernetes 和 Azure 都提供基于角色的访问控制 (RBAC) 机制:
Azure RBAC 控制对 Azure 中的资源的访问,还可以创建新的 Azure 资源。 可将权限分配给用户、组或服务主体。 (服务主体是应用程序使用的安全标识。)
Kubernetes RBAC 控制 Kubernetes API 的权限。 例如,可以通过 Kubernetes RBAC 授权(或拒绝)用户执行创建 Pod 和列出 Pod 的操作。 若要将 Kubernetes 权限分配给用户,请创建角色和角色绑定:
角色是在命名空间内部应用的一组权限。 权限被定义为资源(pod、部署等)上的动词(获取、更新、创建、删除)。
角色绑定将用户或组分配到角色。
此外还有一个群集角色对象,该对象类似于角色,但会应用到整个群集中的所有命名空间。 若要将用户或组分配到群集角色,请创建群集角色绑定。
AKS 集成了这两种 RBAC 机制。 创建 AKS 群集时,可将其配置为使用 Microsoft Entra ID 进行用户身份验证。 若要详细了解如何设置此项,请参阅将 icrosoft Entra ID 与 Azure Kubernetes 服务集成。
完成此配置后,想要访问 Kubernetes API(例如,通过 kubectl)的用户必须使用其 Microsoft Entra 凭据登录。
默认情况下,Microsoft Entra 用户无权访问群集。 若要授予访问权限,群集管理员需要创建引用 Microsoft Entra 用户或组的角色绑定。 如果用户对特定的操作没有权限,则该操作将会失败。
如果用户默认没有访问权限,群集管理员最初又怎么有权创建角色绑定呢? AKS 群集实际上有两种类型的凭据用于调用 Kubernetes API 服务器:群集用户和群集管理员。群集管理员凭据授予对群集的完全访问权限。 Azure CLI 命令 az aks get-credentials --admin
下载群集管理员凭据,并将其保存到 kubeconfig 文件中。 群集管理员可以使用此 kubeconfig 来创建角色和角色绑定。
最好使用 Azure RBAC 进行 Kubernetes 授权,而不要在 Kubernetes 本地管理 Kuernetes 群集角色和角色绑定对象。 这样就可以实现跨 Azure 资源、AKS 和 Kubernetes 资源的统一管理和访问控制。 这些 Azure RBAC 角色分配可以针对群集或群集中的命名空间,以实现更精细的访问控制。 Azure RBAC 支持有限的一组默认权限,你可以将这些权限与管理角色和角色绑定的本机 Kubernetes 机制相结合,以支持高级或更精细的访问模式。 启用后,将由 Azure RBAC 以独占方式验证 Microsoft Entra主体,由 Kubernetes RBAC 以独占方式验证常规 Kubernetes 用户和服务帐户。
由于群集管理员凭据的权限如此强大,因此需要使用 Azure RBAC 来限制其访问权限:
“Azure Kubernetes 服务群集管理员角色”有权下载群集管理员凭据。 应该只将群集管理员分配到此角色。
“Azure Kubernetes 服务群集用户角色”有权下载群集用户凭据。 可将非管理员用户分配到此角色。 此角色不会授予对群集中 Kubernetes 资源的任何特定权限 — 它只允许用户连接到 API 服务器。
定义 RBAC 策略(Kubernetes 和 Azure)时,请考虑组织中的角色:
- 谁可以创建或删除 AKS 群集和下载管理员凭据?
- 谁可以管理群集?
- 谁可以创建或更新命名空间中的资源?
良好的做法是使用角色和角色绑定(而不是群集角色和群集角色绑定)按命名空间限定 Kubernetes RBAC 权限的范围。
最后还有这样一个问题:AKS 群集需要拥有哪些权限才能创建和管理负载均衡器、网络或存储等 Azure 资源。 若要使用 Azure API 对自身进行身份验证,群集可以使用 Microsoft Entra 服务主体。 如果创建群集时未指定服务主体,则系统会自动创建一个服务主体。 但是,良好的安全做法是先创建服务主体,然后为其分配最少量的 RBAC 权限。 有关详细信息,请参阅 Azure Kubernetes 服务中的服务主体。
机密管理和应用程序凭据
应用程序和服务通常需要使用凭据连接到 Azure 存储或 SQL 数据库等外部服务。 此处的难题在于如何保护这些凭据的安全,避免将其透露。
对于 Azure 资源,一种做法是使用托管标识。 托管标识的概念是指,应用程序或服务在 Microsoft Entra ID 中存储一个标识,并使用此标识在 Azure 服务中进行身份验证。 在 Microsoft Entra ID 中为应用程序或服务创建一个服务主体,应用程序或服务使用 OAuth 2.0 令牌进行身份验证。 正在执行的进程代码能够以透明方式获取要使用的令牌。 这样,就不需要存储任何密码或连接字符串。 可以使用 Microsoft Entra 工作负载 ID(预览版)通过将 Microsoft Entra 标识分配到单个 pod,在 AKS 中使用托管标识。
目前,并非所有 Azure 服务都支持使用托管标识进行身份验证。 如需列表,请参阅支持 Microsoft Entra 身份验证的 Azure 服务。
即使使用托管标识,也可能需要存储某些凭据或其他应用程序机密,不管是对于不支持托管标识的 Azure 服务、第三方服务、API 密钥,还是其他服务。 下面是可安全存储机密的某些选项:
Azure Key Vault。 在 AKS 中,可将 Key Vault 中的一个或多个机密装载为一个卷。 该卷从 Key Vault 读取机密。 然后,pod 可以像读取普通卷一样读取机密。 有关详细信息,请参阅在 AKS 群集中使用适用于机密存储 CSI 驱动程序的 Azure 密钥保管库提供程序。
pod 使用工作负载标识或者使用用户分配或系统分配的托管标识来验证自己的身份。 有关其他注意事项,请参阅提供标识以访问适用于机密存储 CSI 驱动程序的 Azure 密钥保管库提供程序。
HashiCorp Vault。 Kubernetes 应用程序可使用 Microsoft Entra 托管标识向 HashiCorp Vault 进行身份验证。 请参阅 HashiCorp Vault 讲述 Microsoft Entra ID。 可将 Vault 本身部署到 Kubernetes,考虑在不同于应用程序群集的单独专用群集中运行它。
Kubernetes 机密。 另一个选项是直接使用 Kubernetes 机密。 此选项最容易配置,但存在一些难题。 机密存储在分布式密钥-值存储 etcd 中。 AKS 静态加密 etcd。 Microsoft 管理加密密钥。
使用 HashiCorp Vault 或 Azure Key Vault 等系统可以获得多种优势,例如:
- 对机密进行集中控制。
- 确保所有机密静态加密。
- 集中式密钥管理。
- 对机密进行访问控制。
- 审核
容器和业务流程协调程序安全性
以下提供了有关保护 Pod 和容器的建议做法:
威胁监视:使用 Microsoft Defender for Containers(或第三方功能)监视威胁。 如果要在 VM 上托管容器,请使用 Microsoft Defender for Servers 或第三方功能。 此外,还可将 Azure Monitor 中的容器监视解决方案日志集成到 Microsoft Sentinel 或现有 SIEM 解决方案。
漏洞监视:使用 Microsoft Defender for Cloud 或通过 Azure 市场提供的第三方解决方案来持续监视映像和运行的容器的已知漏洞。
使用 ACR 任务(Azure 容器注册表的一项功能)自动执行映像修补。 容器映像是在层中生成的。 基本层包括 OS 映像和应用程序框架映像,例如 ASP.NET Core 或 Node.js。 基本映像通常是由应用程序开发人员在上游创建的,由其他项目维护人员维护。 在上游修补这些映像时,必须更新、测试并重新部署自己的映像,以便不会留下任何已知的安全漏洞。 ACR 任务可以帮助将此过程自动化。
将映像存储在受信任的专用注册表中,例如 Azure 容器注册表或 Docker 信任的注册表。 在 Kubernetes 中使用验证许可 Webhook,以确保 pod 只能从受信任的注册表提取映像。
应用最低特权原则
- 不要以特权模式运行容器。 特权模式可让容器访问主机上的所有设备。
- 如果可能,请避免以 root 身份在容器中运行进程。 从安全角度看,容器不能提供完全的隔离,因此,最好是以非特权用户的身份运行容器进程。
DevOps
此参考体系结构提供用于预配云资源及其依赖项的 Azure 资源管理器模板。 借助 [Azure 资源管理器模板][arm-template],可以使用 Azure DevOps Services 在几分钟内预配不同的环境,例如复制生产方案。 这样可以节约成本,并且只在需要时预配负载测试环境。
考虑遵循工作负载隔离条件来构建 ARM 模板,工作负载通常定义为任意功能单元;例如可以为群集创建单独的模板,然后为依赖服务创建其他模板。 隔离工作负载后,DevOps 能够执行持续集成和持续交付 (CI/CD),因为每个工作负载都与其相应的 DevOps 团队关联并由其管理。
部署 (CI/CD) 注意事项
下面是微服务体系结构的可靠 CI/CD 过程的一些目标:
- 每个团队可以独立生成并部署自有的服务,而不影响或干扰其他团队。
- 新服务版本在部署到生产环境之前,会先部署到开发/测试/QA 环境进行验证。 在每个阶段强制实施质量控制。
- 新服务版本可以连同前一版本一起部署。
- 实施足够的访问控制策略。
- 对于容器化工作负载,可以信任部署到生产环境的容器映像。
若要了解有关挑战的详细信息,请参阅微服务体系结构的 CI/CD。
有关具体建议和最佳做法,请参阅 Kubernetes 上微服务的 CI/CD。
成本优化
使用 Azure 定价计算器估算成本。 Microsoft Azure 架构良好的框架的“成本”部分描述了其他注意事项。
此处提供了对于此体系结构中使用的某些关键服务需要考虑的事项。
Azure Kubernetes 服务 (AKS)
在 Kubernetes 群集的部署、管理和操作中,AKS 没有相关成本。 只需为 Kubernetes 群集使用的虚拟机实例、存储和网络资源付费。
若要估算所需资源的成本,请参阅容器服务计算器。
Azure 负载均衡器
你只需为配置的负载平衡和出站规则的数量付费。 入站 NAT 规则是免费的。 如果未配置规则,则标准负载均衡器不按小时收费。
有关详细信息,请参阅 Azure 负载均衡器定价。
Azure Pipelines
此参考体系结构仅使用 Azure Pipelines。 Azure 将 Azure Pipeline 作为单独的服务提供。 可以免费获得 Microsoft 托管的作业(每月 CI/CD 时长为 1,800 分钟)和 1 个自托管作业(每月不限时长),额外作业需要收费。 有关详细信息,请参阅 Azure DevOps 服务定价。
Azure Monitor
对于 Azure Monitor Log Analytics,需要为数据引入和保留付费。 有关详细信息,请参阅 Azure Monitor 定价。
部署此方案
要部署此体系结构的参考实现,请按照 GitHub 存储库中的步骤操作。
后续步骤
- 使用 Azure Kubernetes 服务的服务主体
- 适用于容器的 Microsoft Defender
- 适用于服务器的 Microsoft Defender
- Azure Monitor 中的容器监视解决方案
- Microsoft Sentinel 或现有的 SIEM 解决方案。
- Microsoft Defender for Cloud 或可通过 Azure 市场获得的第三方解决方案。
- ACR 任务
相关资源
- 若要了解更高级的微服务示例,请参阅高级 Azure Kubernetes 服务 (AKS) 微服务体系结构
- 若要了解如何监视此体系结构,请参阅监视 Azure Kubernetes 服务 (AKS) 中的微服务体系结构。
- 若要了解如何衡量此应用程序的性能,请参阅性能优化方案:分布式业务事务。
- 适用于微服务体系结构的 CI/CD
- Kubernetes 上的微服务的 CI/CD