This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

管理 Dapr 中的组件

如何在应用程序中管理 Dapr 组件

在 Dapr 中,组件是应用程序与外部资源交互的关键。它们可以是数据库、消息队列、秘密管理系统等。开发者可以通过配置这些组件,轻松地在应用程序中集成和使用这些外部资源。

Dapr 提供了一种声明式的方法来管理组件。每个组件都通过一个 YAML 文件定义,该文件描述了组件的类型、元数据和其他配置细节。以下是一个简单的组件定义示例:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: my-pubsub
  namespace: default
spec:
  type: pubsub.redis
  version: v1
  metadata:
  - name: redisHost
    value: "localhost:6379"
  - name: redisPassword
    secretKeyRef:
      name: redis-secret
      key: password

在这个示例中,我们定义了一个名为 my-pubsub 的发布订阅组件,它使用 Redis 作为底层实现。组件的元数据部分指定了 Redis 主机和密码,其中密码是通过 secret 管理的。

要在应用程序中使用这些组件,开发者只需在应用程序代码中引用组件名称即可。Dapr 的 sidecar 会自动处理与组件的交互,使得开发者无需关心底层实现细节。

通过这种方式,Dapr 提供了一种灵活且可扩展的方式来管理应用程序中的外部资源,使得开发者可以专注于业务逻辑,而不是基础设施管理。

1 - 认证流程

组件从提交到生产就绪的认证流程

概述

Dapr 采用模块化设计,功能以组件形式提供。每个组件都有一个接口定义,所有组件都是可互换的,因此理想情况下,您可以用具有相同接口的另一个组件替换一个组件。每个用于生产的组件都需要满足一定的技术要求,以确保功能兼容性和稳健性。

一般来说,一个组件需要:

  • 符合定义的 Dapr 接口
  • 功能正确且稳健
  • 有良好的文档和维护

为了确保组件符合 Dapr 设定的标准,会在 Dapr 维护者管理的环境中对组件进行一系列测试。一旦测试持续通过,就可以确定组件的成熟度级别。

认证级别

级别如下:

Alpha

  • 组件实现了所需的接口,并按规范描述工作
  • 组件有文档
  • 组件可能存在漏洞,或在集成时暴露出漏洞
  • 组件可能无法通过所有一致性测试
  • 组件可能没有一致性测试
  • 由于后续版本中可能出现不兼容的更改,仅推荐用于非关键业务用途

所有组件都从 Alpha 阶段开始。

Beta

  • 组件必须通过所有定义的组件一致性测试以满足组件规范
  • 组件一致性测试已在 Dapr 维护者管理的环境中运行
  • 组件包含由 Dapr 维护者审核和批准的特定 components-contrib 版本的一致性测试结果记录
  • 由于后续版本中可能出现不兼容的更改,仅推荐用于非关键业务用途

Stable

  • 组件必须有组件认证测试以验证功能和弹性
  • 组件由 Dapr 维护者维护并由社区支持
  • 组件有良好的文档和测试
  • 组件在之前至少一个 Dapr 运行时的小版本发布中以 Alpha 或 Beta 形式存在
  • 维护者将根据 Dapr 支持政策解决组件安全性、核心功能和测试问题,并发布包含修补的稳定组件的补丁版本

以前的正式发布 (GA) 组件

任何先前认证为 GA 的组件,即使不符合新要求,也允许进入 Stable。

一致性测试

components-contrib 仓库中的每个组件都需要遵循 Dapr 定义的一组接口。一致性测试是在这些组件定义及其相关支持服务上运行的测试,以确保组件符合 Dapr 接口规范和行为。

一致性测试为以下构建块定义:

  • 状态存储
  • secret 存储
  • 绑定
  • pubsub

要了解更多信息,请参阅此处的自述文件。

测试要求

  • 测试应根据组件规范验证组件的功能行为和稳健性
  • 作为组件一致性测试文档的一部分,添加所有重现测试所需的详细信息

认证测试

components-contrib 仓库中的每个稳定组件必须有一个认证测试计划和自动化认证测试,以验证组件通过 Dapr 支持的所有功能。

稳定组件的测试计划应包括以下场景:

  • 客户端重新连接:如果客户端库暂时无法连接到服务,一旦服务重新上线,Dapr sidecar 不应需要重启。
  • 认证选项:验证组件可以使用所有支持的选项进行认证。
  • 验证资源配置:验证组件在初始化时是否自动配置资源(如果适用)。
  • 所有与相应构建块和组件相关的场景。

测试计划必须由 Dapr 维护者批准,并与组件代码一起发布在 README.md 文件中。

测试要求

  • 测试应根据组件规范验证组件的功能行为和稳健性,反映测试计划中的场景
  • 测试必须作为 components-contrib 仓库的持续集成的一部分成功运行

组件认证过程

为了使组件获得认证,测试在由 Dapr 项目维护的环境中运行。

新组件认证:Alpha->Beta

对于需要从 Alpha 更改为 Beta 认证的新组件,组件认证请求遵循以下步骤:

  • 请求者在 components-contrib 仓库中创建一个问题,以认证组件的当前和新认证级别
  • 请求者提交一个 PR 以将组件与定义的一致性测试套件集成(如果尚未包含)
    • 用户在创建的问题中详细说明环境设置,以便 Dapr 维护者可以在托管环境中设置服务
    • 环境设置完成后,Dapr 维护者审核 PR,如果批准则合并该 PR
  • 请求者在 docs 仓库中提交一个 PR,更新组件的认证级别

新组件认证:Beta->Stable

对于需要从 Beta 更改为 Stable 认证的新组件,组件认证请求遵循以下步骤:

  • 请求者在 components-contrib 仓库中创建一个问题,以认证组件的当前和新认证级别
  • 请求者在组件的源代码目录中提交一个 PR,将测试计划作为 README.md 文件
    • 请求者在创建的 PR 中详细说明测试环境要求,包括任何手动步骤或凭据
    • Dapr 维护者审核测试计划,提供反馈或批准,并最终合并 PR
  • 请求者提交一个 PR 用于自动化认证测试,包括在适用时配置资源的脚本
  • 在测试环境设置完成和凭据配置后,Dapr 维护者审核 PR,如果批准则合并 PR
  • 请求者在 docs 仓库中提交一个 PR,更新组件的认证级别

2 - 更新组件

更新应用程序使用的已部署组件

在更新应用程序使用的现有已部署组件时,除非启用了 HotReload 功能门控,否则 Dapr 不会自动更新组件。需要重启 Dapr sidecar 才能获取组件的最新版本。具体操作方式取决于托管环境。

Kubernetes

在 Kubernetes 中运行时,更新组件的过程包括以下两个步骤:

  1. 将新的组件 YAML 应用到所需的命名空间。
  2. 除非启用了 HotReload 功能门控,否则需要对部署执行 滚动重启操作 以获取最新组件。

自托管

除非启用了 HotReload 功能门控,更新组件的过程包括停止和重启 daprd 进程以获取最新组件的单个步骤。

热重载(预览功能)

此功能目前处于预览状态。 热重载通过 HotReload 功能门控 启用。

Dapr 可以实现“热重载”组件,从而在不需要重启 Dapr sidecar 进程或 Kubernetes pod 的情况下自动获取组件更新。这意味着创建、更新或删除组件清单将在运行时反映在 Dapr sidecar 中。

除以下类型外,所有组件均支持热重载。这些组件类型的任何创建、更新或删除都将被 sidecar 忽略,需要重启以获取更改。

进一步阅读

3 - 操作指南:将组件限定于一个或多个应用程序

限制组件访问特定的Dapr实例

Dapr组件具有命名空间(这与Kubernetes的命名空间概念不同),这意味着一个Dapr运行时实例只能访问部署在相同命名空间中的组件。

Dapr运行时,会将其配置的命名空间与加载的组件的命名空间进行匹配,并仅初始化与其命名空间匹配的组件。其他命名空间中的组件将不会被加载。

命名空间

命名空间可以用来限制组件对特定Dapr实例的访问。

在自托管模式下,开发者可以通过设置NAMESPACE环境变量来为Dapr实例指定命名空间。 如果设置了NAMESPACE环境变量,Dapr将不会加载任何在其元数据中未指定相同命名空间的组件。

例如,假设在production命名空间中有以下组件:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
  namespace: production
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: redis-master:6379

要告诉Dapr它被部署到哪个命名空间,设置环境变量:

MacOS/Linux:

export NAMESPACE=production
# 像往常一样运行Dapr

Windows:

setx NAMESPACE "production"
# 像往常一样运行Dapr

让我们考虑以下在Kubernetes中的组件:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
  namespace: production
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: redis-master:6379

在这个例子中,Redis组件仅对运行在production命名空间内的Dapr实例可访问。

应用程序对具有范围的组件的访问

开发者和操作员可能希望限制某个应用程序或一组特定应用程序对一个数据库的访问。 为实现这一点,Dapr允许您在组件YAML上指定scopes。添加到组件的应用程序范围仅限制具有特定ID的应用程序使用该组件。

以下示例展示了如何为两个启用Dapr的应用程序提供访问权限,这两个应用程序的ID分别为app1app2,访问名为statestore的Redis组件,该组件本身位于production命名空间中

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
  namespace: production
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: redis-master:6379
scopes:
- app1
- app2

社区电话演示

使用命名空间进行服务调用

阅读跨命名空间的服务调用以获取有关在服务之间调用时使用命名空间的更多信息。

使用命名空间进行pub/sub

阅读配置具有多个命名空间的Pub/Sub组件以获取有关在pub/sub中使用命名空间的更多信息。

相关链接

4 - 操作指南:在组件中引用secret

如何在组件定义中安全地引用secret

概述

在组件定义的spec.metadata部分中,可以引用secret。

要引用secret,你需要设置auth.secretStore字段来指定保存secret的secret存储的名称。

在Kubernetes中运行时,如果auth.secretStore为空,则默认使用Kubernetes secret存储。

支持的secret存储

访问此链接查看Dapr支持的所有secret存储,以及如何配置和使用它们的信息。

引用secret

虽然你可以选择使用纯文本secret(如MyPassword),如下面yaml中redisPasswordvalue所示,但这不建议用于生产环境:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    value: MyPassword

相反,建议在你的secret存储中创建secret并在组件定义中引用它。下面展示了两种情况——“secret包含嵌入的key”和“secret是一个字符串”。

“secret包含嵌入的key”适用于secret中嵌入了一个key的情况,即secret不是一个完整的连接字符串。这在以下组件定义yaml中展示。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    secretKeyRef:
      name: redis-secret
      key:  redis-password
auth:
  secretStore: <SECRET_STORE_NAME>

SECRET_STORE_NAME是配置的secret存储组件的名称。在Kubernetes中运行并使用Kubernetes secret存储时,字段auth.SecretStore默认为kubernetes,可以留空。

上述组件定义告诉Dapr从定义的secretStore中提取名为redis-secret的secret,并将secret中嵌入的redis-password key关联的值分配给组件中的redisPassword字段。此情况的一个用途是当你的代码正在构建一个连接字符串时,例如将URL、secret以及其他必要信息组合成一个字符串。

另一方面,下面的“secret是一个字符串”适用于secret中没有嵌入key的情况。相反,secret只是一个字符串。因此,在secretKeyRef部分中,secret的name和secret的key将是相同的。这种情况是当secret本身是一个完整的连接字符串,没有需要提取值的嵌入key时。通常,连接字符串由连接信息、某种允许连接的secret以及可能的其他信息组成,不需要单独的“secret”。这种情况在下面的组件定义yaml中展示。

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: servicec-inputq-azkvsecret-asbqueue
spec:
  type: bindings.azure.servicebusqueues
  version: v1
  metadata:
  - name: connectionString
    secretKeyRef:
      name: asbNsConnString
      key: asbNsConnString
  - name: queueName
    value: servicec-inputq
auth:
  secretStore: <SECRET_STORE_NAME>

上述“secret是一个字符串”情况的yaml告诉Dapr从定义的secretStore中提取名为asbNsConnstring的连接字符串,并将值分配给组件中的connectionString字段,因为从secretStore中提取的“secret”是一个纯字符串,没有嵌入的key。这要求secret的name和secret的key相同。

示例

引用Kubernetes secret

以下示例展示了如何创建一个Kubernetes secret来保存Event Hubs绑定的连接字符串。

  1. 首先,创建Kubernetes secret:

    kubectl create secret generic eventhubs-secret --from-literal=connectionString=*********
    
  2. 接下来,在你的绑定中引用secret:

    apiVersion: dapr.io/v1alpha1
    kind: Component
    metadata:
      name: eventhubs
    spec:
      type: bindings.azure.eventhubs
      version: v1
      metadata:
      - name: connectionString
        secretKeyRef:
          name: eventhubs-secret
          key: connectionString
    
  3. 最后,将组件应用到Kubernetes集群:

    kubectl apply -f ./eventhubs.yaml
    

限制对secret的访问

Dapr可以使用其配置限制对secret存储中secret的访问。阅读如何使用secret范围如何限制从secret存储中读取的secret以获取更多信息。这是使用Dapr限制对secret访问的推荐方法。

Kubernetes权限

默认命名空间

在Kubernetes中运行时,Dapr在安装期间为从Kubernetes secret存储访问secret定义了默认的Role和RoleBinding在default命名空间中。对于从default命名空间获取secret的Dapr启用的应用程序,可以如上例所示定义和引用secret。

非默认命名空间

如果你的Dapr启用的应用程序使用从非默认命名空间获取secret的组件,请将以下资源应用到该命名空间:

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: secret-reader
  namespace: <NAMESPACE>
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list"]
---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: dapr-secret-reader
  namespace: <NAMESPACE>
subjects:
- kind: ServiceAccount
  name: default
roleRef:
  kind: Role
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

这些资源授予Dapr从Role和RoleBinding中定义的命名空间的Kubernetes secret存储中获取secret的权限。

相关链接

5 - 状态存储组件

关于为 Dapr 状态管理设置不同状态存储的指导

Dapr 集成现有数据库,为应用提供 CRUD 操作、事务等状态管理功能。它还支持为每个应用配置多个独立的状态存储组件。

状态存储具有可扩展性,可以在 components-contrib 仓库中找到。

在 Dapr 中,状态存储通过 Component 文件进行描述:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.<DATABASE>
  version: v1
  metadata:
  - name: <KEY>
    value: <VALUE>
  - name: <KEY>
    value: <VALUE>
...

数据库的类型由 type 字段决定,连接字符串和其他元数据信息放在 .metadata 部分。即使元数据值可以包含明文的密钥,仍建议使用 密钥存储

请参考本指南了解如何配置状态存储组件。

支持的状态存储

请访问此参考查看 Dapr 中支持的所有状态存储。

相关主题

6 - 发布/订阅代理

关于为 Dapr 发布/订阅设置不同消息代理的指导

Dapr 支持与发布/订阅消息总线的集成,为应用程序提供创建事件驱动、松耦合架构的能力,生产者通过主题向消费者发送事件。

Dapr 允许为每个应用程序配置多个具名的发布/订阅组件。每个组件都有一个名称,用于在发布消息主题时识别。阅读 API 参考 了解如何发布和订阅主题的详细信息。

发布/订阅组件是可扩展的。支持的组件列表在这里,实现可以在 components-contrib 仓库中找到。

组件文件

发布/订阅通过 Component 文件描述:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: pubsub
  namespace: default
spec:
  type: pubsub.<NAME>
  version: v1
  metadata:
  - name: <KEY>
    value: <VALUE>
  - name: <KEY>
    value: <VALUE>
...

发布/订阅的类型由 type 字段指定,连接字符串和其他元数据等属性放在 .metadata 部分。尽管元数据值可以包含明文的 secret,建议您通过 secretKeyRef 使用 secret 存储 来管理这些 secret。

虽然所有发布/订阅组件都支持 consumerID 元数据,但如果您未提供,运行时会自动生成一个消费者 ID。所有组件元数据字段值可以使用 模板化元数据值,这些值在 Dapr sidecar 启动时解析。例如,您可以选择使用 {namespace} 作为 consumerGroup,以便在不同命名空间中使用相同的 appId 使用相同的主题,如本文所述。

访问本指南获取配置和使用发布/订阅组件的说明。

相关链接

6.1 - HowTo: 配置具有多个命名空间的 Pub/Sub 组件

使用 Dapr Pub/Sub 与多个命名空间

在某些情况下,应用程序可能会跨多个命名空间分布,并通过 PubSub 共享队列或主题。在这种情况下,需要在每个命名空间中配置 PubSub 组件。

本示例使用 PubSub 示例。Redis 安装和订阅者位于 namespace-a,而发布者 UI 位于 namespace-b。即使 Redis 安装在另一个命名空间,或者您使用托管云服务如 Azure ServiceBus、AWS SNS/SQS 或 GCP PubSub,该解决方案也同样适用。

以下是使用命名空间的示例图。



下表显示了哪些资源部署到哪些命名空间:

资源namespace-anamespace-b
Redis 主节点
Redis 副本
Dapr 的 PubSub 组件
Node 订阅者
Python 订阅者
React UI 发布者

前提条件

设置 namespace-a

创建命名空间并切换 kubectl 使用它。

kubectl create namespace namespace-a
kubectl config set-context --current --namespace=namespace-a

namespace-a 上安装 Redis(主节点和从节点),按照这些说明

现在,配置 deploy/redis.yaml,确保主机名包含 namespace-a

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: pubsub
spec:
  type: pubsub.redis
  version: v1
  metadata:
  - name: "redisHost"
    value: "redis-master.namespace-a.svc:6379"
  - name: "redisPassword"
    value: "YOUR_PASSWORD"

将资源部署到 namespace-a

kubectl apply -f deploy/redis.yaml
kubectl apply -f deploy/node-subscriber.yaml
kubectl apply -f deploy/python-subscriber.yaml

设置 namespace-b

创建命名空间并切换 kubectl 使用它。

kubectl create namespace namespace-b
kubectl config set-context --current --namespace=namespace-b

将资源部署到 namespace-b,包括 Redis 组件:

kubectl apply -f deploy/redis.yaml
kubectl apply -f deploy/react-form.yaml

现在,找到 react-form 的 IP 地址,在浏览器中打开它并向每个主题(A、B 和 C)发布消息。

kubectl get service -A

确认订阅者接收到消息。

切换回 namespace-a

kubectl config set-context --current --namespace=namespace-a

找到 POD 名称:

kubectl get pod # 复制 POD 名称并在下一个命令中使用。

显示日志:

kubectl logs node-subscriber-XYZ node-subscriber
kubectl logs python-subscriber-XYZ python-subscriber

在浏览器上发布的消息应显示在相应订阅者的日志中。Node.js 订阅者接收类型为 “A” 和 “B” 的消息,而 Python 订阅者接收类型为 “A” 和 “C” 的消息。

清理

kubectl delete -f deploy/redis.yaml  --namespace namespace-a
kubectl delete -f deploy/node-subscriber.yaml  --namespace namespace-a
kubectl delete -f deploy/python-subscriber.yaml  --namespace namespace-a
kubectl delete -f deploy/react-form.yaml  --namespace namespace-b
kubectl delete -f deploy/redis.yaml  --namespace namespace-b
kubectl config set-context --current --namespace=default
kubectl delete namespace namespace-a
kubectl delete namespace namespace-b

相关链接

7 - Secret 存储组件

关于设置不同 Secret 存储组件的指南

Dapr 集成了 Secret 存储,为应用程序和其他组件提供安全的 Secret 存储和访问,例如访问密钥和密码。每个 Secret 存储组件都有一个名称,用于访问 Secret 时使用。

与其他构建块组件类似,Secret 存储组件是可扩展的,相关代码可以在 components-contrib 仓库中找到。

在 Dapr 中,Secret 存储通过一个 Component 文件进行描述,包含以下字段:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: secretstore
spec:
  type: secretstores.<NAME>
  version: v1
  metadata:
  - name: <KEY>
    value: <VALUE>
  - name: <KEY>
    value: <VALUE>
...

Secret 存储的类型由 type 字段指定,连接字符串和其他元数据信息放在 .metadata 部分。

不同的支持的 Secret 存储会有不同的特定字段需要配置。例如,配置使用 AWS Secrets Manager 的 Secret 存储时,文件格式如下:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: awssecretmanager
spec:
  type: secretstores.aws.secretmanager
  version: v1
  metadata:
  - name: region
    value: "[aws_region]"
  - name: accessKey
    value: "[aws_access_key]"
  - name: secretKey
    value: "[aws_secret_key]"
  - name: sessionToken
    value: "[aws_session_token]"

应用配置

创建组件的 YAML 文件后,请根据您的托管环境按照以下说明应用它:

在本地运行时,创建一个包含 YAML 文件的 components 目录,并使用 --resources-path 标志提供给 dapr run 命令。

在 Kubernetes 中部署时,假设您的组件文件名为 secret-store.yaml,运行:

kubectl apply -f secret-store.yaml

支持的 Secret 存储

访问 Secret 存储参考 以获取支持的 Secret 存储的完整列表。

相关链接

8 - Bindings 组件

关于设置 Dapr bindings 组件的指导

Dapr 可以与外部资源集成,使应用程序既能被外部事件触发,也能与资源进行交互。每个 bindings 组件都有一个名称,用于与资源进行交互时使用。

与其他构建块组件一样,bindings 组件是可扩展的,相关代码可以在 components-contrib 仓库中找到。

在 Dapr 中,bindings 使用一个 Component 文件描述,包含以下字段:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
  namespace: <NAMESPACE>
spec:
  type: bindings.<NAME>
  version: v1
  metadata:
  - name: <KEY>
    value: <VALUE>
  - name: <KEY>
    value: <VALUE>
...

bindings 的类型由 type 字段指定,连接字符串和其他元数据则在 .metadata 部分定义。

不同的支持的 bindings会有不同的特定字段需要配置。例如,当为 Azure Blob Storage 配置 bindings 时,文件看起来像这样:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
spec:
  type: bindings.azure.blobstorage
  version: v1
  metadata:
  - name: storageAccount
    value: myStorageAccountName
  - name: storageAccessKey
    value: ***********
  - name: container
    value: container1
  - name: decodeBase64
    value: <bool>
  - name: getBlobRetryCount
    value: <integer>

应用配置

一旦创建了组件的 YAML 文件,请根据您的托管环境按照以下步骤进行配置:

对于自托管环境,创建一个包含 YAML 文件的 components 目录,并使用 --resources-path 标志将路径提供给 dapr run 命令。

对于 Kubernetes 部署,假设您的组件文件名为 mybinding.yaml,运行以下命令:

kubectl apply -f mybinding.yaml

支持的 bindings

访问 bindings 参考 以获取支持资源的完整列表。

相关链接

9 - 如何:注册一个可插拔组件

学习如何注册一个可插拔组件

组件注册过程

使用 gRPC 的可插拔组件通常作为容器或进程运行,需要通过Unix 域套接字(简称 UDS)与 Dapr 运行时通信。它们会通过以下步骤自动被发现并注册到运行时中:

  1. 组件监听放置在共享卷上的Unix 域套接字
  2. Dapr 运行时列出共享卷中的所有Unix 域套接字
  3. Dapr 运行时连接每个套接字,并使用 gRPC 反射从组件实现的给定构建块 API 中发现所有 proto 服务。

一个组件可以同时实现多个组件接口。

虽然 Dapr 的内置组件已经集成在运行时中,但可插拔组件在与 Dapr 一起使用之前需要进行一些设置步骤。

  1. 可插拔组件需要在 Dapr 本身启动之前启动并准备好接收请求。
  2. 用于可插拔组件通信的Unix 域套接字文件需要对 Dapr 和可插拔组件都可访问。

在独立模式下,可插拔组件可以作为进程或容器运行。在 Kubernetes 上,可插拔组件作为容器运行,并由 Dapr 的 sidecar 注入器自动注入到应用程序的 pod 中,允许通过标准的Kubernetes 容器规范进行自定义。

这也改变了在 Dapr 和可插拔组件之间共享Unix 域套接字文件的方法。

选择您的环境以开始使您的组件可被发现。

运行组件

在 Dapr 启动之前,您的组件和 Unix 套接字必须正在运行。

默认情况下,Dapr sidecar 在 /tmp/dapr-components-sockets 中查找作为Unix 域套接字文件的组件。

此文件夹中的文件名对于组件注册很重要。它们必须通过附加组件的名称和您选择的文件扩展名(通常为 .sock)来形成。例如,文件名 my-component.sock 是一个有效的 Unix 域套接字文件名,适用于名为 my-component 的组件。

由于您在与组件相同的主机上运行 Dapr,请验证此文件夹及其中的文件是否可被您的组件和 Dapr 访问和写入。如果您使用 Dapr 的 sidecar 注入器功能,则此卷会自动创建和挂载。

组件发现和多路复用

通过Unix 域套接字(UDS)可访问的可插拔组件可以托管多个不同的组件 API。在组件的初始发现过程中,Dapr 使用反射枚举 UDS 后面的所有组件 API。上例中的 my-component 可插拔组件可以包含状态存储(state)和 pub/sub(pubsub)组件 API。

通常,可插拔组件实现单个组件 API 以进行打包和部署。然而,以增加其依赖性和扩大其安全攻击面为代价,可插拔组件可以实现多个组件 API。这可以减轻部署和监控负担。隔离、容错和安全的最佳实践是为每个可插拔组件实现单个组件 API。

定义组件

使用组件规范定义您的组件。组件的 spec.type 值是通过以下两个部分与 . 连接而成的:

  1. 组件的 API(statepubsubbindings 等)
  2. 组件的名称,它是从Unix 域套接字文件名中派生的,不包括文件扩展名。

您需要为可插拔组件的Unix 域套接字公开的每个 API 定义一个组件规范。前面示例中的 Unix 域套接字 my-component.sock 公开了一个名为 my-component 的可插拔组件,具有 statepubsub API。需要两个组件规范,每个规范在其自己的 YAML 文件中,放置在 resources-path 中:一个用于 state.my-component,另一个用于 pubsub.my-component

例如,state.my-component 的组件规范可以是:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: my-production-state-store
spec:
  type: state.my-component
  version: v1
  metadata:

在上面的示例中,请注意以下几点:

  • 字段 spec.type 的内容是 state.my-component,指的是作为名为 my-component 的可插拔组件公开的状态存储。
  • 字段 metadata.name,即此处定义的状态存储的名称,与可插拔组件名称无关。

将此文件保存为 Dapr 的组件配置文件夹中的 component.yaml。就像 metadata.name 字段的内容一样,此 YAML 文件的文件名没有影响,也不依赖于可插拔组件名称。

运行 Dapr

初始化 Dapr,并确保您的组件文件放置在正确的文件夹中。

就是这样!现在您可以通过 Dapr API 调用状态存储 API。通过运行以下命令查看其运行情况。用 Dapr HTTP 端口替换 $PORT

curl -X POST -H "Content-Type: application/json" -d '[{ "key": "name", "value": "Bruce Wayne", "metadata": {}}]' http://localhost:$PORT/v1.0/state/prod-mystore

检索值,用 Dapr HTTP 端口替换 $PORT

curl http://localhost:$PORT/v1.0/state/prod-mystore/name

为您的可插拔组件构建和发布容器

确保您的组件作为容器运行,首先发布并可被您的 Kubernetes 集群访问。

在 Kubernetes 集群上部署 Dapr

按照在 Kubernetes 集群上部署 Dapr文档中提供的步骤进行操作。

在您的部署中添加可插拔组件容器

可插拔组件作为容器在与您的应用程序相同的 pod 中部署。

由于可插拔组件由Unix 域套接字支持,请使您的可插拔组件创建的套接字可被 Dapr 运行时访问。配置部署规范以:

  1. 挂载卷
  2. 提示 Dapr 挂载的 Unix 套接字卷位置
  3. 将卷附加到您的可插拔组件容器

在以下示例中,您配置的可插拔组件作为容器部署在与您的应用程序容器相同的 pod 中。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
  labels:
    app: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
      annotations:
        # 推荐自动注入可插拔组件。
        dapr.io/inject-pluggable-components: "true" 
        dapr.io/app-id: "my-app"
        dapr.io/enabled: "true"
    spec:
      containers:
      # 您的应用程序的容器规范,照常。
        - name: app
           image: YOUR_APP_IMAGE:YOUR_APP_IMAGE_VERSION

建议将 dapr.io/inject-pluggable-components 注释设置为 “true”,指示 Dapr 的 sidecar 注入器该应用程序的 pod 将有额外的容器用于可插拔组件。

或者,您可以跳过 Dapr 的 sidecar 注入功能,手动添加可插拔组件的容器并注释您的 pod,告诉 Dapr 该 pod 中哪些容器是可插拔组件,如下例所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
  labels:
    app: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
      annotations:
        dapr.io/pluggable-components: "component" ## 可插拔组件容器的名称,用 `,` 分隔,例如 "componentA,componentB"。
        dapr.io/app-id: "my-app"
        dapr.io/enabled: "true"
    spec:
      containers:
      ### --------------------- 您的应用程序容器在此处 -----------
        - name: app
           image: YOUR_APP_IMAGE:YOUR_APP_IMAGE_VERSION
      ### --------------------- 您的可插拔组件容器在此处 -----------
        - name: component
          image: YOUR_IMAGE_GOES_HERE:YOUR_IMAGE_VERSION

在应用部署之前,让我们再添加一个配置:组件规范。

定义组件

可插拔组件使用组件规范定义。组件 type 是从套接字名称(不带文件扩展名)派生的。在以下示例 YAML 中,替换:

  • your_socket_goes_here 为您的组件套接字名称(无扩展名)
  • your_component_type 为您的组件类型
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: prod-mystore
  # 在 Kubernetes 上运行并自动容器注入时,添加以下注释:
  annotations:
    dapr.io/component-container: >
      {
        "name": "my-component",
        "image": "<registry>/<image_name>:<image_tag>"
      }
spec:
  type: your_component_type.your_socket_goes_here
  version: v1
  metadata:
scopes:
  - backend

当您希望 Dapr 的 sidecar 注入器处理可插拔组件的容器和卷注入时,dapr.io/component-container 注释在 Kubernetes 上是必需的。至少,您需要 nameimage 属性,以便 Dapr 的 sidecar 注入器成功将容器添加到应用程序的 pod 中。Unix 域套接字的卷由 Dapr 的 sidecar 注入器自动创建和挂载。

范围您的组件,以确保只有目标应用程序可以连接到可插拔组件,因为它只会在其部署中运行。否则,运行时在初始化组件时会失败。

就是这样!将创建的清单应用到您的 Kubernetes 集群,并通过 Dapr API 调用状态存储 API。

使用Kubernetes pod 转发器访问 daprd 运行时。

通过运行以下命令查看其运行情况。用 Dapr HTTP 端口替换 $PORT

curl -X POST -H "Content-Type: application/json" -d '[{ "key": "name", "value": "Bruce Wayne", "metadata": {}}]' http://localhost:$PORT/v1.0/state/prod-mystore

检索值,用 Dapr HTTP 端口替换 $PORT

curl http://localhost:$PORT/v1.0/state/prod-mystore/name

下一步

使用此示例代码开始开发 .NET 可插拔组件

10 - 配置中间件组件

通过添加中间件组件自定义处理管道

Dapr 允许通过串联一系列中间件组件来定义自定义处理管道。您可以在以下两种场景中使用中间件管道:

  1. 基础模块 API - 在调用任何 Dapr HTTP API 时执行 HTTP 中间件组件。
  2. 服务间调用 - HTTP 中间件组件应用于服务间调用。

配置 API 中间件管道

启动时,Dapr sidecar 会为传入的 HTTP 调用构建一个中间件处理管道。默认情况下,管道由追踪和 CORS 中间件组成。可以通过 Dapr configuration 配置的其他中间件按定义顺序添加到管道中。该管道适用于所有 Dapr API 端点,包括 state、pubsub、service-invocation、bindings、secret、configuration、分布式锁等。

请求在路由到用户代码之前会依次经过所有定义的中间件组件,然后在返回给客户端之前以相反的顺序再次经过这些中间件,如下图所示。

图示请求和响应通过中间件的流程,如上段所述

在使用 httpPipeline 配置调用 Dapr HTTP API 时,HTTP 中间件组件会被执行。

以下配置示例定义了一个自定义管道,使用了 OAuth 2.0 中间件大写中间件组件。在这种情况下,所有请求在转发到用户代码之前都通过 OAuth 2.0 协议进行授权,并转换为大写文本。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: pipeline
  namespace: default
spec:
  httpPipeline:
    handlers:
      - name: oauth2
        type: middleware.http.oauth2
      - name: uppercase
        type: middleware.http.uppercase

与其他组件一样,中间件组件可以在支持的中间件参考dapr/components-contrib 仓库中找到。

查看所有中间件组件

配置应用中间件管道

在进行服务间调用时,您也可以使用任何中间件组件。例如,在零信任环境中添加令牌验证,转换特定应用端点的请求,或应用 OAuth 策略。

服务间调用中间件组件适用于从 Dapr sidecar 到接收应用(服务)的所有传出调用,如下图所示。

图示服务调用请求的流程。从调用者 Dapr sidecar 到被调用应用的请求经过应用中间件管道,如上段所述。

任何可以用作 HTTP 中间件的中间件组件也可以通过 appHttpPipeline 配置应用于服务间调用。下面的示例为从 Dapr sidecar(服务调用的目标)到应用的所有传出调用添加了 uppercase 中间件组件。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: pipeline
  namespace: default
spec:
  appHttpPipeline:
    handlers:
      - name: uppercase
        type: middleware.http.uppercase

相关链接