项目

ABP Studio:使用 Kubernetes 工作

你可以使用 Kubernetes 面板来管理你在 Kubernetes 集群中的应用程序。该面板专为微服务项目设计,因此你不必在本地环境中运行所有微服务项目。相反,你可以将它们部署到 Kubernetes 集群中,并在本地调试一个或多个项目。当然,你也可以将此面板用于单体项目。通过点击 ABP Studio 侧边栏中的 Kubernetes 按钮即可访问。

kubernetes 面板

创建项目时会添加预设配置;请在附加选项步骤中查看 Kubernetes 配置。项目结构可能会根据你的选择而变化。例如,一个 MVC 微服务项目看起来如上图所示。你可以根据需要添加或删除图表。

先决条件

Kubernetes 面板仅在 商业版和企业版 许可中可用。你需要安装并配置以下工具才能使用 Kubernetes 面板。

  • kubectl
  • Helm
  • Docker Desktop(如果并非使用真实集群,请启用 Kubernetes 选项)
  • NGINX Ingress Controller
  • mkcert
    • 当你安装 mkcert 以允许 ABP Studio 为你生成证书时,请确保 mkcert 已安装在 受信任的证书存储区 中,方法是运行以下命令(在 Windows 上,此命令必须以管理员权限执行):

      mkcert -install
      

配置文件

你可以创建多个配置文件来管理不同的 Kubernetes 集群或同一集群内的不同命名空间。配置文件是一组可用于连接到 Kubernetes 集群的配置。如果你在附加选项步骤中创建项目时勾选了 Kubernetes 配置,则会默认提供 local 配置文件,其中包含所有项目图表。你可以在组合框中查看所有配置文件并更改当前配置文件。要编辑,请点击右侧的齿轮图标。

kubernetes-profile

更改当前配置文件不会影响 Charts 树。Charts 部分与解决方案相关,而不是配置文件。你可以在 Charts 部分添加或删除图表。

它会打开管理 Kubernetes 配置文件窗口。你可以编辑/删除现有配置文件或添加新的配置文件。

manage-kubernetes-profile

当你点击添加新配置文件按钮时,会打开新配置文件窗口。在配置文件信息选项卡中,你可以提供任意配置文件名称,该名称在所有配置文件中应是唯一的。在上下文组合框中,你将看到现有的 Kubernetes 上下文。选择其中一个。然后,提供一个在所属上下文中唯一的命名空间。创建新配置文件时,它会将 JSON 文件存储在指定的路径。对于微服务项目,你可以指定路径 abp-solution-path/etc/abp-studio/k8s-profiles,对于其他项目类型,则使用 abp-solution-path/etc/k8s-profiles 以遵循标准格式。

create-new-profile

元数据选项卡中,你可以提供有关配置文件的附加信息。我们在诸如 Build Docker Image(s)Install Chart(s) 等命令中使用此信息。例如,dotnetEnvironment 对于 Install Chart(s) 命令是必需的,用于确定环境变量。你还可以通过点击添加按钮来添加更多元数据。它会从根到子级收集所有元数据,并根据层次结构覆盖现有值。例如,如果你在配置文件和图表中定义了两个相同的元数据,它将使用图表元数据。你可以为 Kubernetes 配置文件主图表子图表 添加元数据。

create-new-profile-metadata

密钥选项卡中,你可以为配置文件提供密钥。我们在诸如 wireGuardPassword 等命令中使用此信息。与元数据选项卡类似,你可以通过点击添加按钮来添加更多密钥。它会从根到子级收集所有密钥,并根据层次结构覆盖现有值。

你可以通过点击工具栏中的 Tools -> Global Secrets 来添加全局密钥,通过 Solution Explorer 根上下文菜单中的 Solution -> Manage Secrets 添加解决方案密钥,以及通过 Kubernetes 面板中的 Add or Edit Profile -> Secrets tab 添加Kubernetes 配置文件密钥。出于安全考虑,Secrets 信息保存在本地文件系统中,而不是解决方案文件中。因此,默认情况下你无法与团队成员共享。

create-new-profile-secrets

要在配置文件信息选项卡中创建新配置文件,名称上下文命名空间就足够了。但是,你应该提供 dotnetEnvironment 元数据信息以使用 Install Chart(s) 命令。点击保存按钮以创建新配置文件。它会将配置文件添加到组合框中。同样,你可以编辑或删除现有配置文件。

当你创建新配置文件时,你还应该在 abp-solution-path/etc/helm/chart 文件夹中创建一个 values.{chart.name}-{profile.name}.yaml 文件来覆盖默认值。例如,values.bookstore-staging.yaml 用于 staging Kubernetes 配置文件中的 bookstore 图表。

图表

Helm 选项卡中,我们有解决方案中所有图表的树形视图。图表类型有三种:图表根主图表子图表

charts

图表根

它是所有主图表的根。你可以在根中拥有多个主图表。要向根添加新图表,请点击 Chart Root 上下文菜单中的 Add Chart 按钮。它会打开选择 Helm 图表窗口。从指定位置选取图表并选择主 helm 图表。将 helm 图表存储在 abp-solution-path/etc/helm/chart-name 文件夹中;否则,命令将无法工作。此外,主 chart name 和文件夹名称应相同。例如,如果主图表名称为 notebookstore,则文件夹名称也应为 notebookstore。与创建新的 kubernetes 配置文件类似,你还应该在 abp-solution-path/etc/helm/chart-name 文件夹中创建一个 values.{chart.name}-{profile.name}.yaml 文件来覆盖默认值。例如,values.notebookstore-staging.yaml 用于 staging Kubernetes 配置文件中的 notebookstore 图表。

如果你有多个主图表,你可以为所有图表执行集体命令。为此,请右键点击 Chart Root 的上下文菜单。以下选项可用于 Chart Root

chart-root

  • 命令:你有几个选项可以为所有主图表执行命令。
    • 构建 Docker 镜像:如果子图表有可用的构建 docker 镜像,它会构建所有镜像。
    • 安装图表:将所有图表安装到所选配置文件。
    • 卸载图表:从所选配置文件卸载所有图表。
    • 创建自签名 TLS 密钥:它为应用程序创建自签名证书并将其添加到 Kubernetes 集群。当你为应用程序指定用户时很有用。
  • 添加图表:它打开选择 Helm 图表窗口。从指定位置选取图表并选择主 helm 图表以向根添加新的主图表。

主图表

它是所有子图表的根。当你向根添加新的主图表时,它会自动添加与该主图表相关的子图表。右键单击主图表并从上下文菜单中选择命令。以下选项可用于 Main Chart

main-chart

  • 命令:你有几个选项可以为选定的主图表执行命令。
    • 构建 Docker 镜像:如果子图表有可用的构建 docker 镜像,它会为所选主图表构建所有 docker 镜像。
    • 安装图表:将所选图表安装到当前配置文件。
    • 卸载图表:从当前配置文件卸载所选图表。
  • 属性:它打开图表属性窗口。你可以在图表信息选项卡中查看图表信息。在元数据选项卡中,你可以为所选主图表添加元数据。它将覆盖配置文件中的元数据。在 Kubernetes Services 选项卡中,你可以将 Kubernetes 服务与主图表关联;但是,由于主图表通常不创建 kubernetes 服务,我们可以将其留空。
  • 刷新子图表:刷新所选主图表的子图表。
  • 打开方式:你可以使用 Visual Studio Code文件资源管理器 打开所选图表。
  • 移除:从解决方案中移除所选主图表。

子图表

子图表是与主图表关联的组件。当你向根添加新的主图表时,它会自动添加与该主图表相关的子图表。子图表具有特定的配置和功能,这些配置和功能有助于主图表的整体功能。右键单击子图表并从上下文菜单中选择命令。以下选项可用于 Subchart

sub-chart

  • 命令
    • 构建 Docker 镜像:为所选子图表构建 docker 镜像。仅当子图表具有 projectPathimageNameprojectType 元数据时才可见。Project Type 只接受 angulardotnet 值。它使用指定的 imageNameprojectPath 构建 docker 镜像。
  • 属性:它打开图表属性窗口。你可以在图表信息选项卡中查看图表信息。在元数据选项卡中,你可以为所选子图表添加元数据。它将覆盖配置文件以及主图表中的元数据。在 Kubernetes Services 选项卡中,你可以将 Kubernetes 服务与子图表关联;这样,当你连接到 Kubernetes 集群时,你可以在上下文菜单中看到 浏览 选项。
  • 浏览:它打开浏览器并导航到 Kubernetes 服务 URL。仅当子图表 Kubernetes Services 正则表达式模式与 Kubernetes 服务 匹配时才可见。
  • 打开方式:你可以使用 Visual Studio Code文件资源管理器 打开所选子图表。

添加新的子图表

当你向解决方案添加新的微服务模块时,你还应该为其创建一个子图表。但是,模块类型无关紧要。同样,当你想出于任何原因创建子图表时,可以按照以下步骤操作:

  1. 使用 Visual Studio Code 打开主图表。
  2. charts 文件夹中创建一个文件夹。
  3. 根据你的需要编辑文件夹中的文件。
  4. 编辑完成后,子图表模板即已完成;打开 ABP Studio 并在主图表的上下文菜单中执行 Refresh Sub Charts。你可以在 Charts 树中看到新的子图表。
  5. 如果添加的子图表具有 projectPathimageNameprojectType 元数据,你可以为子图表 Build Docker Image
  6. 如果添加的子图表具有 Kubernetes Services 正则表达式模式,当你连接到 Kubernetes 集群时,你可以 浏览 Kubernetes 服务。

连接到 Kubernetes 集群

在我们 构建 Docker 镜像安装图表 之后,我们可以连接到 Kubernetes 集群。为此,请点击 Kubernetes 选项卡中的链条图标或 Connect 按钮以与选定的 Kubernetes 集群建立连接。在初始连接期间,可能需要一段时间来准备;你可以在后台任务面板中监控进度。

connect

连接时,无法更改当前配置文件。连接后,Kubernetes 选项卡中现有的应用程序服务将变得可见。要断开连接,可以点击链条图标。

connected

当你连接到 Kubernetes 集群时,它会自动将 WireGuard VPN 安装到 Kubernetes 集群以确保安全连接。你可以在 Kubernetes Profile -> Secrets 选项卡或更高级别(例如 Solution SecretsGlobal Secrets)中指定 wireGuardPassword。如果你不提供密码,它会生成一个随机密码并将其存储在 Kubernetes Profile -> Secrets 中。但是,如果你尝试连接到已安装 WireGuard VPN 的集群,那么你应该提供相同的密码;否则,它将无法连接。要查看随机密码,你可以点击 Kubernetes Profile -> Secrets 选项卡中的眼睛图标。

wireGuardPassword

由于我们使用 WireGuard VPN 连接到 Kubernetes 集群,我们会自动将 Kubernetes 服务追加到你的 hosts 文件中。这使得你可以使用指定的 Kubernetes Service 名称无缝访问服务,包括 ClusterIP 类型的服务。例如,在此场景中,可以使用服务器名称 bookstore-local-sqlserver 通过诸如 SQL Server Management Studio (SSMS) 等工具连接到 SQL Server。SQL 服务器的默认 sa 密码设置为 myPassw@rd

ssms-login

连接到 SQL Server 后,我们可以在 对象资源管理器 面板中看到数据库。

ssms-object-explorer

当连接到 Kubernetes 集群时,应用程序会建立连接并开始向 ABP Studio 发送遥测信息。在监控面板中,你可以轻松检查应用程序的状态和其他详细信息。此外,在解决方案运行器面板中,查找带有 (external) 信息的链条图标。

connected-monitorize

与集群断开连接后,我们会清理 hosts 文件,不包括 ingress hosts。这样,你仍然可以通过浏览器访问 ingress hosts。例如,在此场景中,我们可以访问 https://bookstore-local-web

disconnect

当你使用 kubectl get svc 命令列出 Kubernetes 集群中的服务时,你应该看到 abp-wg-easyabp-wg-easy-vpn 服务。每个 WireGuard 安装都有相关服务的唯一端口号。如果你有多个针对不同 Kubernetes 配置文件或解决方案的 WireGuard 安装,当使用 kubectl get svc 命令列出它们时,你可以在 PORT(S) 字段中看到端口号。

连接到 Kubernetes 集群在同一时间仅限于一个 ABP Studio 实例。同时尝试使用另一个实例连接将无法按预期工作。

拦截服务

Kubernetes 面板的最佳功能之一是你能够拦截服务。通过这种方式,你可以在本地环境中调试和开发特定的应用程序,而无需运行所有服务。要拦截服务,请右键单击服务并从上下文菜单中选择 Enable Interception

intercept

拦截服务时,它会在后台启动拦截过程。完成后,你应该会看到服务名称旁边出现拦截图标。

intercepted

拦截服务后,所有对该服务的请求都将被重定向到本地环境。例如,在此场景中,bookstore-local-auditlogging 服务被拦截。当尝试在浏览器中访问 https://bookstore-local-web/AuditLogs 时,会发生 Bad Gateway 异常,因为 bookstore-local-auditlogging 服务未在本地环境中运行。要解决此问题,请在 IDE(例如 Visual Studio)中打开 Acme.BookStore.AuditLoggingService .NET 解决方案,将 Acme.BookStore.AuditLoggingService 设置为启动项目,然后运行它(使用 F5 进入调试模式或 CTRL+F5 运行而不调试)。

running-application

你应该使用 Kestrel 启动应用程序,而不是 IIS Express。否则,它将无法按预期工作。为此,请在 IDE 中选择 Acme.BookStore.AuditLoggingService 启动配置文件。

应用程序在你的本地机器上启动后,重新访问应用程序中的审计日志页面,你会注意到它按预期工作。ABP Studio 处理你的机器和应用程序的配置,使其能够像在 Kubernetes 集群内部一样无缝运行。

利用 ABP Studio 的拦截功能,你可以灵活地在 Kubernetes 集群中运行整个解决方案,同时使用 IDE 在本地机器上仅运行一个(或几个)服务。这种方法使你能够专注于运行、测试和调试你的服务,而无需关心系统其余部分的配置和启动细节。

你可以通过右键单击服务并从上下文菜单中选择 Disable Interception 来禁用拦截。与 Kubernetes 集群断开连接会自动禁用所有拦截。

disable-interception

在调试被拦截的应用程序时,如果你遇到 Volo.Authorization:010001 (Authorization failed! Given policy has not granted.) 异常,你应该运行 abp-solution-path/etc/helm 文件夹中的 create-tls-secret.ps1 脚本。它会为应用程序创建自签名证书并将其添加到 Kubernetes 集群。之后,你应该重启应用程序。

重新部署图表

在对项目进行一些更改后,你可以将图表重新部署到 Kubernetes 集群。为此,请右键单击服务并从上下文菜单中选择 Redeploy。它会为所选项目构建 docker 镜像并重新安装。

redeploy

指定用户

当你连接到 Kubernetes 集群时,它会使用所选配置文件中的 Kubernetes ContextNamespace 信息。之后,当你拦截服务时,它会创建一些 Kubernetes 资源并将请求重定向到本地环境。但是,如果有两个或更多开发人员在同一项目上工作,他们无法同时拦截同一服务。为了解决这个问题,你可以指定用户。为此,它使用在 Tools -> Global Metadata 或其他级别(例如 Solution MetadataKubernetes Profile Metadata)中定义的 Metadata 键值对。当你定义名为 k8ssuffix 的元数据及其所需值时,它会附加到命名空间。例如,如果你定义值为 arthurk8ssuffix 元数据,则命名空间变为 bookstore-local-arthur。之后,不同的用户可以使用相同的 Kubernetes 配置文件。

global-metadata

定义用户后,你应在图表根上执行 Create Self-Signed TLS secret 命令,以为应用程序创建自签名证书并将其添加到 Kubernetes 集群。这对于拦截服务是必需的。

当你在 Global Metadata 中定义元数据时,它对所有解决方案都可用,并且不会与你的团队成员共享。但是,如果你在 Solution MetadataKubernetes Profile Metadata 中定义元数据,则它仅对当前解决方案或 Kubernetes 配置文件可用,并且将与你的团队成员共享。

高级主题

添加自定义命令

自定义命令可以添加到 Kubernetes 面板的 HelmKubernetes 选项卡中。例如,在重新部署图表时,它涉及构建 Docker 镜像并重新安装它。但是,如果你使用的 Kubernetes 集群不是 Docker Desktop,则需要在安装过程之前将 Docker 镜像推送到注册表。这可以通过在 Kubernetes services 中加入自定义命令来实现。自定义命令可以添加到 Helm 选项卡中的 Chart RootMain ChartSubchart,以及 Kubernetes 选项卡中的 Service

为此,使用 Visual Studio Code 打开 ABP 解决方案 (.abpsln) 文件,这是一个 JSON 文件,你将在 commands 部分看到现有命令。在添加新命令之前,在 abp-solution-path/etc/helm 文件夹中创建一个 powershell 脚本。例如,我们创建一个 push-image.ps1 脚本,将 docker 镜像推送到注册表。然后,将以下命令添加到 commands 部分。

    "kubernetesRedeployWithPushImage": {
      "triggerTargets": [
        "KUBERNETES_SERVICE"
      ],
      "executionTargets": [
        "KUBERNETES_SERVICE"
      ],
      "displayName": "重新部署并推送镜像",
      "workingDirectory": "etc/helm",
      "terminalCommand": "./build-image.ps1 -ProjectPath {{chart.metadata.projectPath}} -ImageName {{chart.metadata.imageName}} -ProjectType {{chart.metadata.projectType}} &&& ./push-image.ps1 -ImageName {{chart.metadata.imageName}} &&& ./install.ps1 -ChartName {{mainChart.name}} -Namespace {{profile.namespace}} -ReleaseName {{mainChart.name}}-{{profile.name}} -DotnetEnvironment {{mainChart.metadata.dotnetEnvironment}}",
      "requireConfirmation": "true",
      "confirmationText": "你确定要重新部署并推送服务 '{{name}}' 的相关图表 '{{chart.name}}' 吗?",
      "condition": "{{chart != null && chart.metadata.projectPath != null && chart.metadata.imageName != null && chart.metadata.projectType != null}}"
    }

添加命令后,从工具栏中的 File -> Reload Solution 重新加载解决方案。重新加载后,你将在服务的上下文菜单中找到 重新部署并推送镜像 命令。

redeploy-push-image

JSON 对象具有以下属性:

  • triggerTargets:指定命令的触发目标。添加的命令将出现在这些目标中。你可以添加一个或多个触发目标,接受诸如 HELM_CHARTS_ROOTHELM_MAIN_CHARTHELM_SUB_CHARTKUBERNETES_SERVICE 等值。
  • executionTargets:指定命令的执行目标。当在根项上执行命令时,它将递归地为所有子项执行命令。可接受的值包括 HELM_CHARTS_ROOTHELM_MAIN_CHARTHELM_SUB_CHARTKUBERNETES_SERVICE
  • displayName:指定命令的显示名称。
  • workingDirectory:指定命令的工作目录。相对于解决方案路径。
  • terminalCommand:指定自定义命令的终端命令。可以使用 &&& 运算符在终端中运行多个命令。利用 Scriban 语法访问输入数据,输入数据因执行目标而异。
  • requireConfirmation:指定命令在执行前是否需要确认消息。可接受的值包括 truefalse
  • confirmationText:指定命令的确认文本。利用 Scriban 语法访问输入数据,输入数据因执行目标而异。
  • condition:指定命令的条件。如果条件返回 false,它将跳过当前项并尝试为下一项或子项执行命令。利用 Scriban 语法访问输入数据,输入数据因执行目标而异。

你可以根据执行目标在 Scriban 语法中使用以下变量:

  • HELM_CHARTS_ROOT: profile, metadata, secrets
  • HELM_MAIN_CHART: profile, chart, metadata, secret
  • HELM_SUB_CHART: profile, chart, metadata, secret
  • KUBERNETES_SERVICE: name, profile, mainChart, chart, metadata, secret

在本文档中