容器和编排器旨在解决单片部署方法中常见的问题。
1. 整体部署的挑战
传统上,大多数应用程序都是作为单个单元部署的。这样的应用程序被称为单体。这种将应用程序作为单个单元部署的一般方法(即使它们由多个模块或程序集组成)称为单体架构,如图 3-1 所示。
图 3-1 . 单片架构。
尽管具有简单的优点,单片架构也面临许多挑战:
1.1 部署
此外,它们需要重新启动应用程序,如果在部署时未采用零停机技术,这可能会暂时影响可用性。
1.2 扩展
单体式应用程序完全托管在单个计算机实例上,通常需要高性能硬件。如果单体式应用程序的任何部分需要扩展,则必须将整个应用程序的另一个副本部署到另一台计算机上。使用单体式应用程序时,您无法单独扩展应用程序组件 - 要么全部扩展,要么全部不扩展。扩展不需要扩展的组件会导致资源使用效率低下且成本高昂。
1.3 环境
单体应用程序通常部署到具有预安装操作系统、运行时和库依赖项的托管环境中。此环境可能与应用程序的开发或测试环境不匹配。应用程序环境之间的不一致是单体部署的常见问题根源。
1.4 耦合
单片应用程序可能会在其功能组件之间出现高度耦合。如果没有严格的边界,系统更改通常会导致意想不到且代价高昂的副作用。新功能/修复变得棘手、耗时且成本高昂。更新需要大量测试。耦合还使得重构组件或更换替代实现变得困难。即使构建时严格区分关注点,架构侵蚀也会随着单片代码库因永无止境的"特殊情况"而恶化。
1.5 平台锁定
单片应用程序由单一技术堆栈构建而成。虽然提供了统一性,但这种承诺可能会成为创新的障碍。新功能和组件将使用应用程序的当前堆栈构建 - 即使更现代的技术可能是更好的选择。长期风险是您的技术堆栈变得过时和陈旧。将整个应用程序重新架构到新的、更现代的平台充其量是昂贵且有风险的。
2. 容器和编排器有哪些好处?
**我们在第 1 章中介绍了容器。我们重点介绍了云原生计算基金会 (CNCF) 如何将容器化列为其云原生路线图的第一步- 为企业开始云原生之旅提供指导。**在本节中,我们将讨论容器的优势。
**Docker 是最流行的容器管理平台。**它适用于 Linux 或 Windows 上的容器。容器提供独立但可重现的应用程序环境,这些环境在任何系统上都以相同的方式运行。这一特点使它们非常适合开发和托管云原生服务。容器彼此隔离。同一主机硬件上的两个容器可以拥有不同版本的软件,而不会引起冲突。
容器由简单的文本文件定义,这些文件将成为项目工件并被签入源代码控制。虽然完整的服务器和虚拟机需要手动更新,但容器很容易进行版本控制。构建在容器中运行的应用程序可以使用自动化工具作为构建管道的一部分进行开发、测试和部署。
**容器是不可变的。定义容器后,您可以以完全相同的方式重新创建和运行它。这种不变性适合基于组件的设计。**如果应用程序的某些部分的发展与其他部分不同,那么为什么要重新部署整个应用程序,而只需部署最频繁更改的部分?应用程序的不同功能和横切关注点可以分解为单独的单元。图 3-2 显示了单片应用程序如何通过委托某些功能来利用容器和微服务。应用程序本身的其余功能也已容器化。
图 3-2 . 分解单体式应用以采用微服务。
每个云原生服务都在单独的容器中构建和部署。每个服务都可以根据需要进行更新。单个服务可以托管在具有适合每个服务的资源的节点上。每个服务运行的环境都是不可变的,在开发、测试和生产环境中共享,并且易于版本控制。应用程序不同区域之间的耦合明确地以服务之间的调用或消息的形式出现,而不是整体内的编译时依赖关系。您还可以选择最适合给定功能的技术,而无需更改应用程序的其余部分。
**容器化服务需要自动化管理。手动管理大量独立部署的容器是不可行的。**例如,考虑以下任务:
- 如何在由多台机器组成的集群中配置容器实例?
- 一旦部署,容器如何相互发现和通信?
- 容器如何按需扩展或缩小?
- 如何监控每个容器的健康状况?
- 如何保护容器免受硬件和软件故障的影响?
- 如何在零停机时间内升级实时应用程序的容器?
容器编排器解决并自动化了这些和其他问题。
在云原生生态系统中,**Kubernetes 已成为事实上的容器编排器。**它是一个由云原生计算基金会 (CNCF) 管理的开源平台。Kubernetes 可自动处理整个机器集群中容器化工作负载的部署、扩展和运维问题。然而,安装和管理 Kubernetes 非常复杂。
更好的方法是利用云供应商提供的 Kubernetes 作为托管服务。Azure 云具有一个完全托管的 Kubernetes 平台,名为Azure Kubernetes 服务 (AKS)。AKS 抽象了管理 Kubernetes 的复杂性和运营开销。您将 Kubernetes 作为云服务使用;Microsoft 负责管理和支持它。AKS 还与其他 Azure 服务和开发工具紧密集成。
AKS 是一种基于集群的技术。联合虚拟机池(即节点)部署到 Azure 云。它们共同构成一个高可用性环境或集群。集群对于您的云原生应用程序而言,是一个无缝的单一实体。在底层,AKS 按照预定义的策略(均匀分配负载)在这些节点上部署您的容器化服务。
3. 扩展优势有哪些?
基于容器构建的服务可以利用 Kubernetes 等编排工具提供的扩展优势。根据设计,容器只了解自己。一旦您有多个需要协同工作的容器,就应该在更高级别组织它们。组织大量容器及其共享依赖项(例如网络配置)就是编排工具可以解决这一问题的地方!Kubernetes 在容器组上创建一个抽象层,并将它们组织成pod。 pod 在称为节点的工作机器上运行。这种有组织的结构称为集群。图 3-3 显示了 Kubernetes 集群的不同组件。
图 3-3 . Kubernetes 集群组件。
扩展容器化工作负载是容器编排器的一个关键功能。AKS 支持跨两个维度的自动扩展:容器实例和计算节点。它们共同使 AKS 能够快速高效地响应需求高峰并添加额外资源。我们将在本章后面讨论 AKS 中的扩展。
3.1 声明式与命令式
**Kubernetes 支持声明式和命令式配置。**命令式方法涉及运行各种命令,这些命令告诉 Kubernetes 每个步骤要做什么。运行此镜像。删除此 pod。公开此端口。使用声明式方法,您可以创建一个配置文件(称为清单),以描述您想要什么而不是要做什么。Kubernetes 读取清单并将您期望的最终状态转换为实际的最终状态。
**命令式命令非常适合学习和交互式实验。**但是,您需要以声明方式创建 Kubernetes 清单文件,以采用基础设施即代码方法,从而实现可靠且可重复的部署。清单文件将成为项目工件,并在 CI/CD 管道中用于自动化 Kubernetes 部署。
如果您已使用命令式命令配置集群,则可以使用 导出声明式清单kubectl get svc SERVICENAME -o yaml > service.yaml。此命令将生成类似于以下清单的清单:
yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2019-09-13T13:58:47Z"
labels:
component: apiserver
provider: kubernetes
name: kubernetes
namespace: default
resourceVersion: "153"
selfLink: /api/v1/namespaces/default/services/kubernetes
uid: 9b1fac62-d62e-11e9-8968-00155d38010d
spec:
clusterIP: 10.96.0.1
ports:
- name: https
port: 443
protocol: TCP
targetPort: 6443
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
使用声明式配置时,您可以在配置文件所在的文件夹使用 来预览提交之前所做的更改kubectl diff -f FOLDERNAME 。一旦您确定要应用更改,请运行kubectl apply -f FOLDERNAME。添加-R以递归处理文件夹层次结构。
您还可以将声明式配置与其他 Kubernetes 功能一起使用,其中之一就是部署。声明式部署有助于管理发布、更新和扩展。它们指示 Kubernetes 部署控制器如何部署新更改、扩展负载或回滚到以前的修订版本。如果集群不稳定,声明式部署将自动将集群恢复到所需状态。例如,如果某个节点崩溃,部署机制将重新部署替换节点以实现所需状态
使用声明式配置可以将基础架构表示为可以与应用程序代码一起签入和版本控制的代码。它使用构建和部署管道提供改进的变更控制和对持续部署的更好支持。
4. 哪些场景最适合容器和编排器?
4.1 以下场景非常适合使用容器和编排器。
需要高正常运行时间和可扩展性的应用程序
具有高正常运行时间和可伸缩性要求的单个应用程序是使用微服务、容器和编排器的云原生架构的理想选择。它们可以在容器中开发,在版本化环境中测试,并在零停机时间内部署到生产中。使用 Kubernetes 集群可确保此类应用还可以按需扩展并从节点故障中自动恢复。
4.2 大量申请
部署和维护大量应用程序的组织受益于容器和编排器。设置容器化环境和 Kubernetes 集群的前期工作主要是固定成本。部署、维护和更新单个应用程序的成本随应用程序数量而变化。除了少数应用程序之外,手动维护自定义应用程序的复杂性超过了使用容器和编排器实施解决方案的成本。
5. 何时应避免使用容器和编排器?
如果您无法按照十二要素应用原则构建应用程序,则应考虑避免使用容器和编排器。在这些情况下,请考虑使用基于 VM 的托管平台,或者可能是某种混合系统。有了它,您始终可以将某些功能拆分到单独的容器甚至无服务器功能中。
6. 开发资源
本节列出了一些开发资源,它们可能有助于您开始使用容器和编排器开发下一个应用程序。如果您正在寻找有关如何设计云原生微服务架构应用程序的指导,请阅读本书的配套书籍《.NET 微服务:容器化 .NET 应用程序的架构》。
6.1 本地 Kubernetes 开发
Kubernetes 部署在生产环境中具有巨大价值,但也可以在您的开发机器上本地运行。虽然您可以独立处理各个微服务,但有时您可能需要在本地运行整个系统 - 就像部署到生产环境时一样。有几种工具可以提供帮助:Minikube 和 Docker Desktop。Visual Studio 还提供了用于 Docker 开发的工具。
6.2 Minikube
什么是 Minikube?Minikube 项目称"Minikube 在 macOS、Linux 和 Windows 上实现了本地 Kubernetes 集群"。其主要目标是"成为本地 Kubernetes 应用程序开发的最佳工具,并支持所有适用的 Kubernetes 功能"。Minikube 的安装与 Docker 是分开的,但 Minikube 支持的虚拟机管理程序与 Docker Desktop 支持的虚拟机管理程序不同。Minikube 目前支持以下 Kubernetes 功能:
- DNS
- 节点端口
- ConfigMap 和 secret
- 仪表板
- 容器运行时:Docker、rkt、CRI-O 和 containerd
- 启用容器网络接口 (CNI)
- 入口(Ingress)
安装 Minikube 后,您可以通过运行命令快速开始使用它minikube start,该命令下载映像并启动本地 Kubernetes 集群。集群启动后,您可以使用标准 Kuberneteskubectl命令与其交互。
6.3 Docker 桌面
还可以直接从 Windows 上的 Docker Desktop 使用 Kubernetes。如果你使用的是 Windows 容器,这是你唯一的选择,对于非 Windows 容器来说,这也是一个不错的选择。图 3-4 显示了如何在运行 Docker Desktop 时启用本地 Kubernetes 支持。
图 3-4 . 在 Docker Desktop 中配置 Kubernetes。
Docker Desktop 是用于在本地配置和运行容器化应用的最流行的工具。使用 Docker Desktop 时,您可以针对将部署到生产环境的完全相同的 Docker 容器映像集在本地进行开发。Docker Desktop 旨在在本地"构建、测试和交付"容器化应用。它支持 Linux 和 Windows 容器。将映像推送到映像注册表(如 Azure 容器注册表或 Docker Hub)后,AKS 可以将其提取并部署到生产环境。
6.4 Visual Studio Docker 工具
Visual Studio 支持基于 Web 的应用程序的 Docker 开发。创建新的 ASP.NET Core 应用程序时,可以选择为其配置 Docker 支持,如图 3-5 所示。
图 3-5 . Visual Studio 启用 Docker 支持
选择此选项后,将Dockerfile在其根目录中创建项目,可用于在 Docker 容器中构建和托管应用程序。示例 Dockerfile 如图 3-6 所示。
bash
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["eShopWeb/eShopWeb.csproj", "eShopWeb/"]
RUN dotnet restore "eShopWeb/eShopWeb.csproj"
COPY . .
WORKDIR "/src/eShopWeb"
RUN dotnet build "eShopWeb.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "eShopWeb.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "eShopWeb.dll"]
图 3-6 . Visual Studio 生成的 Dockerfile
添加支持后,您可以在 Visual Studio 中的 Docker 容器中运行应用程序。图 3-7 显示了添加了 Docker 支持后创建的新 ASP.NET Core 项目中可用的不同运行选项。
图 3-7.Visual Studio Docker 运行选项
此外,您可以随时向现有的 ASP.NET Core 应用程序添加 Docker 支持。在 Visual Studio 解决方案资源管理器中,右键单击项目并选择"添加" > "Docker 支持",如图 3-8 所示。
图 3-8 . 向 Visual Studio 添加 Docker 支持
6.5 Visual Studio Code Docker 工具
Visual Studio Code 有许多支持 Docker 开发的扩展。
Microsoft 提供了Docker for Visual Studio Code 扩展。此扩展简化了向应用程序添加容器支持的过程。它搭建了所需的文件,构建了 Docker 映像,并使您能够在容器内调试应用程序。该扩展具有一个可视化资源管理器,可轻松对容器和映像执行启动、停止、检查、删除等操作。该扩展还支持 Docker Compose,使您可以将多个正在运行的容器作为一个单元进行管理。