1 - 概览

分布式应用运行时简介

Dapr 是一个可移植的、事件驱动的运行时,它使任何开发者都能轻松构建具有弹性的无状态和有状态应用程序,这些应用程序可运行在云和边缘环境,并拥抱语言和开发者框架的多样性。

任何语言、任何框架、任何地方

随着当前云采用浪潮,Web + 数据库应用架构(如经典的三层设计)正越来越多地转向微服务应用架构,这种架构本质上是分布式的。你不应该仅仅为了创建微服务应用程序就必须成为分布式系统专家。

这正是 Dapr 发挥作用的地方。Dapr 将构建微服务应用程序的最佳实践编码为开放、独立的 API,称为构建块。Dapr 的构建块:

  • 使你能够使用你选择的语言和框架构建可移植的应用程序。
  • 完全独立
  • 在应用程序中使用多少个没有限制

使用 Dapr,你可以将现有应用程序逐步迁移到微服务架构,从而采用云原生模式,如水平扩展/收缩、弹性和独立部署。

Dapr 与平台无关,这意味着你可以在以下位置运行应用程序:

  • 本地
  • 在任何 Kubernetes 集群上
  • 在虚拟机或物理机上
  • 在 Dapr 集成的其他托管环境中。

这使你能够构建可以在云和边缘运行的微服务应用程序。

面向云和边缘的微服务构建块

Dapr 提供分布式系统构建块,供你以标准方式构建微服务应用程序并部署到任何环境。

这些构建块 API 中的每一个都是独立的,这意味着你可以在应用程序中使用其中任意数量的 API。

构建块描述
服务调用弹性的服务调用使你能够在远程服务上进行方法调用(包括重试),无论它们位于支持的托管环境中的何处。
发布订阅在服务之间发布事件和订阅主题使事件驱动架构能够简化水平可扩展性并使其对故障具有弹性。Dapr 提供至少一次消息传递保证、消息 TTL、消费者组和其他高级功能。
工作流工作流 API 可以与其他 Dapr 构建块结合使用,以定义跨越多个微服务的长时间运行的持久化进程或使用 Dapr 工作流的数据流。
状态管理通过用于存储和查询键/值对的状态管理,可以轻松地在应用程序中的无状态服务旁边编写长时间运行、高可用的有状态服务。状态存储是可插拔的,示例包括 AWS DynamoDB、Azure Cosmos DB、Azure SQL Server、GCP Firebase、PostgreSQL 或 Redis 等。
资源绑定带有触发器的资源绑定通过从任何外部源(如数据库、队列、文件系统等)接收和发送事件,进一步构建了事件驱动架构以实现可扩展性和弹性。
Actors一种有状态和无状态对象的模式,通过方法和状态封装使并发变得简单。Dapr 在其 actor 运行时中提供了许多功能,包括并发、状态,以及 actor 激活/停用的生命周期管理,以及用于唤醒 actor 的定时器和提醒。
密钥密钥管理 API 与公共云和本地密钥存储集成,以检索密钥供应用程序代码使用。
配置配置 API 使你能够从配置存储中检索和订阅应用程序配置项。
分布式锁分布式锁 API 使你的应用程序能够为任何资源获取锁,从而赋予其独占访问权限,直到应用程序释放锁或租约超时为止。
密码学密码学 API 在密钥保管库等安全基础设施之上提供抽象层。它包含允许你执行密码学操作的 API,例如加密和解密消息,而不会向你的应用程序暴露密钥。
作业作业 API 使你能够在特定时间或间隔安排作业。
对话对话 API 使你能够抽象与大型语言模型(LLM)交互的复杂性,并包括提示缓存、响应格式化、使用度量和个人身份信息(PII)混淆等功能。使用对话组件,你可以提供提示以与不同的 LLM 进行对话。

横切关注点 API

除了构建块之外,Dapr 还提供了跨你使用的所有构建块应用的横切关注点 API。

构建块描述
弹性Dapr 提供通过弹性规范定义和应用容错弹性策略的功能。支持的规范为超时、重试/退避和断路器等弹性模式定义策略。
可观测性Dapr 发出指标、日志和跟踪以调试和监视 Dapr 和用户应用程序。Dapr 支持使用 W3C 跟踪上下文标准和 Open Telemetry 发送到不同监视工具的分布式跟踪,以便在生产环境中轻松诊断和服务间调用。
安全性Dapr 支持使用 Dapr 控制平面 Sentry 服务在 Dapr 实例之间进行传输中加密通信。你可以引入自己的证书,或让 Dapr 自动创建并持久化自签名根证书和颁发者证书。

边车架构

Dapr 将其 HTTP 和 gRPC API 作为边车架构公开,可以是容器或进程,不需要应用程序代码包含任何 Dapr 运行时代码。这使得与其他运行时的集成变得容易,并提供了应用程序逻辑的分离以提高可支持性。

托管环境

Dapr 可以托管在多个环境中,包括:

  • 在 Windows/Linux/macOS 机器上自托管,用于本地开发和在生产中
  • 在 Kubernetes 或生产中的物理或虚拟机集群上

自托管本地开发

自托管模式中,Dapr 作为单独的边车进程运行,你的服务代码可以通过 HTTP 或 gRPC 调用该进程。每个运行的服务都有一个 Dapr 运行时进程(或边车),配置为使用状态存储、发布订阅、绑定组件和其他构建块。

你可以使用 Dapr CLI 在本地计算机上运行启用了 Dapr 的应用程序。在下图中,Dapr 的本地开发环境使用 CLI init 命令进行配置。尝试使用入门示例

Self-hosted 模式下 Dapr 的架构图

Kubernetes

Kubernetes 可用于:

在 Kubernetes 等容器托管环境中,Dapr 作为边车容器与应用程序容器在同一 Pod 中运行。

Dapr 的 dapr-sidecar-injectordapr-operator 控制平面服务提供一流集成,以:

  • 在与服务容器相同的 Pod 中启动 Dapr 作为边车容器
  • 提供在集群中预配的 Dapr 组件更新的通知

dapr-sentry 服务是一个证书颁发机构,它启用 Dapr 边车实例之间的相互 TLS 以进行安全数据加密,以及通过 Spiffe 提供身份。有关 Sentry 服务的更多信息,请阅读安全概览

将启用了 Dapr 的应用程序部署并运行到 Kubernetes 集群就像在部署方案中添加几个注释一样简单。访问 Dapr on Kubernetes 文档

Kubernetes 模式下 Dapr 的架构图

物理或虚拟机集群

Dapr 控制平面服务可以在生产中部署到物理或虚拟机集群的高可用性(HA)模式。在下图中,Actor Placement 和安全 Sentry 服务在三台不同的 VM 上启动,以提供 HA 控制平面。为了使用 DNS 为集群中运行的应用程序提供名称解析,Dapr 默认使用多播 DNS,但也可以选择支持 Hashicorp Consul 服务

Dapr 控制平面和 Consul 部署到高可用性模式中的 VM 的架构图

开发者语言 SDK 和框架

Dapr 提供各种 SDK 和框架,使你能够轻松使用你首选的语言开始使用 Dapr 进行开发。

Dapr SDK

为了使使用 Dapr 对不同语言更自然,它还包括特定语言的 SDK,用于:

  • Go
  • Java
  • JavaScript
  • .NET
  • PHP
  • Python

这些 SDK 通过类型化语言 API 公开 Dapr 构建块的功能,而不是调用 http/gRPC API。这使你能够使用你选择的语言编写无状态和有状态函数以及 actor 的组合。由于这些 SDK 共享 Dapr 运行时,因此你可以获得跨语言 actor 和函数支持。

开发者框架

Dapr 可以从任何开发者框架使用。以下是一些已与 Dapr 集成的框架:

Web

语言框架描述
.NETASP.NET Core提供响应来自其他服务的发布订阅事件的有状态路由控制器。也可以利用 ASP.NET Core gRPC Services
JavaSpring Boot使用 Dapr API 构建 Spring Boot 应用程序
PythonFlask使用 Dapr API 构建 Flask 应用程序
JavaScriptExpress使用 Dapr API 构建 Express 应用程序
PHP你可以使用 Apache、Nginx 或 Caddyserver 提供服务。

Dapr Agents

Dapr Agents  Overview

Dapr Agents 是一个 Python 框架,用于构建由 LLM 驱动的智能、持久的代理。它提供以代理为中心的功能,例如工具调用、内存管理、MCP 支持和代理编排,同时利用 Dapr 实现持久性、可观测性和安全性,并支持大规模。

集成和扩展

访问集成页面,了解 Dapr 对各种框架和外部产品(包括以下内容)的一流支持:

  • 公共云服务,如 Azure 和 AWS
  • Visual Studio Code
  • GitHub

为运维而设计

Dapr 是为运维和安全性而设计的。Dapr 边车、运行时、组件和配置都可以轻松安全地管理和部署,以满足你组织的需求。

通过 Dapr CLI 安装的仪表板提供了一个基于 Web 的 UI,使你能够查看运行 Dapr 应用程序的信息、查看日志等。

Dapr 支持监视工具,以深入了解 Dapr 系统服务和边车,而 Dapr 的可观测性功能则提供对应用程序的洞察,例如跟踪和指标。

2 - 构建块

通过标准 HTTP 或 gRPC API 访问的模块化最佳实践

构建块是一个可以从代码调用的 HTTP 或 gRPC API,使用一个或多个 Dapr 组件。Dapr 由一组 API 构建块组成,具有可扩展性以添加新的构建块。Dapr 的构建块:

  • 解决构建弹性微服务应用程序时的常见挑战
  • 将最佳实践和模式编码化

下图展示了构建块如何暴露由代码调用的公共 API,并使用组件来实现构建块的能力。

Dapr 提供以下构建块:

构建块端点描述
服务调用/v1.0/invoke服务调用使应用程序能够通过 http 或 gRPC 消息形式的已知端点相互通信。Dapr 提供的端点充当内置服务发现的反向代理组合,同时利用内置的分布式跟踪和错误处理。
发布订阅/v1.0/publish /v1.0/subscribe发布订阅是一种松耦合的消息传递模式,发送者(或发布者)将消息发布到主题,订阅者订阅该主题。Dapr 支持应用程序之间的发布订阅模式。
工作流/v1.0/workflow工作流 API 使您能够使用 Dapr 工作流定义跨多个微服务的长时间运行的持久化进程或数据流。工作流 API 可以与其他 Dapr API 构建块结合使用。例如,工作流可以通过服务调用调用另一个服务或检索密钥,提供灵活性和可移植性。
状态管理/v1.0/state应用程序状态是应用程序希望在单个会话之外保留的任何内容。Dapr 提供基于键/值的状态和查询 API,并带有可插拔的状态存储用于持久化。
绑定/v1.0/bindings绑定提供与外部云/本地服务或系统的双向连接。Dapr 允许您通过 Dapr 绑定 API 调用外部服务,并允许您的应用程序被连接的服务发送的事件触发。
Actor/v1.0/actorsActor 是一个隔离的、独立的计算和状态单元,具有单线程执行。Dapr 提供基于虚拟 Actor 模式的 Actor 实现,该模式提供单线程编程模型,并且 Actor 在不使用时会被垃圾回收。
密钥/v1.0/secretsDapr 提供密钥构建块 API,并与密钥存储集成(如公共云存储、本地存储和 Kubernetes)来存储密钥。服务可以调用密钥 API 来检索密钥,例如获取数据库的连接字符串。
配置/v1.0/configuration配置 API 使您能够检索和订阅支持的配置存储的应用程序配置项。这使应用程序能够检索特定的配置信息,例如在启动时或在存储中进行配置更改时。
分布式锁/v1.0-alpha1/lock分布式锁 API 使您能够对资源加锁,以便应用程序的多个实例可以无冲突地访问资源并提供一致性保证。
密码学/v1.0-alpha1/crypto密码学 API 使您能够执行加密操作,例如加密和解密消息,而无需向应用程序暴露密钥。
作业/v1.0-alpha1/jobs作业 API 使您能够调度和编排作业。示例场景包括:
  • 调度批处理作业在每个工作日运行
  • 调度各种维护脚本执行清理
  • 调度 ETL 作业在特定时间(每小时、每天)运行以获取新数据、处理新数据,并用最新信息更新数据仓库。
对话/v1.0-alpha2/conversation对话 API 使您能够提供提示以与不同的大语言模型(LLM)对话,并包含提示缓存、响应格式化、使用指标和个人身份信息(PII)脱敏等功能。

3 - 组件

由构建块和应用程序使用的模块化功能

Dapr 采用模块化设计,功能以组件的形式交付。每个组件都有一个接口定义。所有组件都可以互换,因此您可以用具有相同接口的一个组件替换为另一个组件。

您可以通过以下方式贡献实现并扩展 Dapr 的组件接口能力:

一个构建块可以使用任意组件组合。例如,Actor状态管理构建块都使用状态组件

再举一个例子,发布订阅构建块使用发布订阅组件

您可以使用 dapr components CLI 命令获取托管环境中当前可用组件的列表。

组件规范

每个组件都有一个遵循的规范(或 spec)。组件在设计时通过 YAML 文件进行配置,该文件存储在以下位置之一:

  • 解决方案中的 components/local 文件夹,或
  • 调用 dapr init 时创建的全局 .dapr 文件夹中。

这些 YAML 文件遵循通用的 Dapr 组件架构,但每个都特定于组件规范。

重要的是要理解,组件规范值,特别是规范 metadata,可能会在同一组件类型的组件之间发生变化,例如在不同的状态存储之间,并且一些设计时规范值可以在运行时向组件 API 发出请求时被覆盖。因此,强烈建议查看组件规范,特别注意用于设置与组件交互的 metadata 的请求示例负载。

下图显示了每种组件类型的一些组件示例

内置组件和可插拔组件

Dapr 包含作为运行时一部分的内置组件。这些是社区开发并捐赠的公共组件,可在每个版本中使用。

Dapr 还允许用户创建自己的私有组件,称为可插拔组件。这些组件是自托管的(进程或容器),不需要用 Go 编写,存在于 Dapr 运行时之外,并且能够"插入" Dapr 以利用构建块 API。

在可能的情况下,鼓励将内置组件捐赠给 Dapr 项目和社区。

但是,可插拔组件非常适合您想要创建自己的未包含在 Dapr 项目中的私有组件的场景。 例如:

  • 您的组件可能特定于您的公司或存在 IP 问题,因此无法包含在 Dapr 组件仓库中。
  • 您希望将组件更新与 Dapr 发布周期解耦。

有关更多信息,请阅读可插拔组件概述

热重载

启用热重载功能后,组件可以在运行时进行"热重载"。 这意味着您可以在不重启 Dapr 运行时的情况下更新组件配置。 当在 Kubernetes API 中创建、更新或删除组件资源时,或者在自托管模式下 resources 目录中的文件发生更改时,会发生组件重新加载。 更新组件时,组件首先关闭,然后使用新配置重新初始化。 在重新加载和重新初始化期间,组件在短时间内不可用。

可用的组件类型

以下是 Dapr 提供的组件类型:

名称解析

名称解析组件与服务调用构建块一起使用,与托管环境集成并提供服务到服务的发现。例如,Kubernetes 名称解析组件与 Kubernetes DNS 服务集成,自托管模式使用 mDNS,VM 集群可以使用 Consul 名称解析组件。

发布订阅代理

发布订阅代理组件是消息代理,可以作为发布和订阅构建块的一部分在服务之间传递消息。

状态存储

状态存储组件是数据存储(数据库、文件、内存),作为状态管理构建块的一部分存储键值对。

绑定

外部资源可以连接到 Dapr,以便触发应用程序上的方法或从应用程序调用,作为绑定构建块的一部分。

密钥存储

密钥是您想要防范未经授权访问的任何私人信息。密钥存储用于存储可以在应用程序中检索和使用的密钥。

配置存储

配置存储用于保存应用程序数据,应用程序实例可以在启动时读取这些数据,或者在发生更改时收到通知。这允许动态配置。

锁组件用作分布式锁,以提供对资源(如队列或数据库)的互斥访问。

加密

加密组件用于执行加密操作,包括加密和解密消息,而不会向应用程序暴露密钥。

对话

Dapr 为开发人员提供了一种抽象与大语言模型 (LLM) 交互的方法,具有内置的安全性和可靠性功能。使用对话组件向不同的 LLM 发送提示以及对话上下文。

中间件

Dapr 允许将自定义中间件插入到 HTTP 请求处理管道中。中间件可以在请求路由到用户代码之前或响应返回给客户端之前对 HTTP 请求执行其他操作(例如身份验证、加密和消息转换)。中间件组件与服务调用构建块一起使用。

4 - 弹性

配置策略并监控应用和边车健康状况

分布式应用通常由许多微服务组成,有数十个——有时数百个——实例在底层基础设施上扩缩容。随着这些分布式解决方案的规模和复杂性不断增长,系统故障的潜在风险也必然增加。由于硬件故障、意外的吞吐量或应用生命周期事件(如扩容和应用重启)等各种问题,服务实例可能会失败或变得无响应。设计和实施一个能够检测、减轻和响应故障的自愈解决方案至关重要。

弹性策略

Diagram showing the resiliency applied to Dapr APIs

Dapr 为定义和应用容错弹性策略提供了能力。您可以为以下弹性模式定义策略:

  • 超时
  • 重试/退避
  • 熔断器

当使用弹性规范调用组件时,这些策略可以应用于任何 Dapr API 调用。

应用健康检查

Diagram showing the app health feature. Running Dapr with app health enabled causes Dapr to periodically probe the app for its health

应用可能因多种原因变得无响应。例如,它们可能太忙而无法接受新工作,可能已崩溃,或处于死锁状态。有时这种情况可能是暂时的或持续的。

Dapr 提供了通过探针监控应用健康状况的能力,探针会检查应用的健康状况并对状态变化做出反应。当检测到不健康的应用时,Dapr 将停止代表该应用接受新工作。

阅读更多关于如何将应用健康检查应用于您的应用的信息。

边车健康检查

Diagram showing the app health feature. Running Dapr with app health enabled causes Dapr to periodically probe the app for its health

Dapr 提供了一种使用 HTTP /healthz 端点来确定其健康状况的方法。通过该端点,daprd 进程或边车可以:

  • 探查其健康状况
  • 确定就绪性和存活性

阅读更多关于如何将 dapr 健康检查应用于您的应用的信息。

后续步骤

5 - 应用程序和控制平面配置

更改 Dapr 应用程序边车或 Dapr 控制平面系统服务的全局行为

使用 Dapr 配置,您可以通过设置和策略来更改:

  • 单个 Dapr 应用程序的行为
  • Dapr 控制平面系统服务的全局行为

例如,在应用程序边车配置上设置采样率策略,以指示可以从另一个应用程序调用哪些方法。如果在 Dapr 控制平面配置上设置策略,可以更改部署到应用程序边车实例的所有证书的证书续订周期。

配置被定义并部署为 YAML 文件。在以下应用程序配置示例中,设置了一个链路追踪端点,用于指定指标信息的发送位置,捕获所有示例链路。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: daprConfig
  namespace: default
spec:
  tracing:
    samplingRate: "1"
    zipkin:
      endpointAddress: "http://localhost:9411/api/v2/spans"

上述 YAML 配置用于指标记录的链路追踪。您可以通过以下方式在本地自托管模式下加载它:

  • 编辑 .dapr 目录中名为 config.yaml 的默认配置文件,或
  • 使用 kubectl/helm 将其应用到 Kubernetes 集群

以下示例展示了 dapr-system 命名空间中名为 daprsystem 的 Dapr 控制平面配置。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: daprsystem
  namespace: dapr-system
spec:
  mtls:
    enabled: true
    workloadCertTTL: "24h"
    allowedClockSkew: "15m"

默认情况下,Dapr 控制平面系统服务安装了一个名为 daprsystem 的配置文件。该配置文件应用全局控制平面设置,并在将 Dapr 部署到 Kubernetes 时进行设置。

了解有关配置选项的更多信息。

后续步骤

了解有关配置的更多信息

6 - 可观测性

通过追踪、指标、日志和健康状况来观察应用

在构建应用程序时,理解系统行为是运行应用程序的重要且具有挑战性的部分,例如:

  • 观察应用程序的内部调用
  • 评估其性能
  • 在问题发生时及时感知

对于由多个微服务组成的分布式系统来说,这可能尤其具有挑战性,因为由多个调用组成的流程可能从一个微服务开始,然后在另一个微服务中继续。

应用程序的可观测性在生产环境中至关重要,在开发过程中也很有用,可以:

  • 了解瓶颈
  • 提高性能
  • 在微服务范围内执行基本调试

虽然可以从底层基础设施收集应用程序的某些数据点(内存消耗、CPU 使用率),但其他有意义的信息必须从"应用感知"层收集——该层可以展示一系列重要的调用如何在微服务之间执行。通常,你会添加一些代码来对应用程序进行检测,这只是将收集的数据(如追踪和指标)发送到可观测性工具或服务,这些工具或服务可以帮助存储、可视化和分析所有这些信息。

维护这种检测代码(不是应用程序核心逻辑的一部分)需要了解可观测性工具的 API、使用额外的 SDK 等。这种检测也可能给应用程序带来可移植性挑战,需要根据应用程序部署的位置采用不同的检测方式。例如:

  • 不同的云提供商提供不同的可观测性工具
  • 本地部署可能需要自托管解决方案

使用 Dapr 实现应用程序的可观测性

当你利用 Dapr API 构建块执行服务调用、发布订阅消息传递和其他 API 时,Dapr 在分布式追踪方面提供了优势。由于这种服务间通信流经 Dapr 运行时(或"边车"),Dapr 处于卸载应用程序级检测负担的独特位置。

分布式追踪

Dapr 可以配置为使用广泛采用的协议生成追踪数据,包括 Open Telemetry (OTEL)Zipkin。这使得它可以轻松与多种可观测性工具集成。

使用 Dapr 的分布式追踪

自动追踪上下文生成

Dapr 使用 W3C 追踪规范来处理追踪上下文,该规范作为 Open Telemetry (OTEL) 的一部分包含在内,为应用程序生成和传播上下文标头或传播用户提供的上下文标头。这意味着使用 Dapr 默认即可获得追踪功能。

Dapr 边车和控制平面的可观测性

你还可以观察 Dapr 本身,通过:

  • 生成由 Dapr 边车和 Dapr 控制平面服务发出的日志
  • 收集有关性能、吞吐量和延迟的指标
  • 使用健康端点探测来指示 Dapr 边车健康状态
Dapr 边车指标、日志和健康检查

日志记录

Dapr 生成日志以:

  • 提供边车操作的可见性
  • 帮助用户识别问题并执行调试

日志事件包含由 Dapr 系统服务产生的警告、错误、信息和调试消息。你还可以配置 Dapr 将日志发送到收集器,例如 Open Telemetry CollectorFluentdNew RelicAzure Monitor 和其他可观测性工具,以便可以搜索和分析日志以提供洞察。

指标

指标是一段时间内收集和存储的测量值和计数序列。Dapr 指标提供监控功能,用于了解 Dapr 边车和控制平面的行为。例如,Dapr 边车与用户应用程序之间的指标显示调用延迟、流量故障、请求错误率等。

Dapr 控制平面指标显示边车注入失败和控制平面服务的运行状况,包括 CPU 使用率、执行的 actor 放置数量等。

健康检查

Dapr 边车为健康检查公开了一个 HTTP 端点。使用此 API,用户代码或托管环境可以探测 Dapr 边车以确定其状态并识别边车就绪问题。

相反,可以配置 Dapr 来探测你的应用程序的健康状况,并对应用程序健康状况的变化做出反应,包括停止发布订阅订阅和短路服务调用。

后续步骤

7 - 安全

Dapr 如何在设计上考虑安全性

安全是 Dapr 的基础。本文介绍了在分布式应用中使用 Dapr 时的安全功能和能力。这些可以划分为:

  • 通过服务调用和发布订阅 API 进行安全通信。
  • 通过组件应用并通过配置强制执行的安全策略。
  • 运维安全实践。
  • 状态安全,重点关注静态数据。

本文使用一个示例应用来说明 Dapr 中提供的许多安全功能。

安全通信

Dapr 通过服务调用 API 提供端到端安全,能够对应用进行 Dapr 身份验证并设置端点访问策略。如下图所示。

<img src="/images/security-end-to-end-communication.png width=1000>

应用身份

在 Dapr 中,应用身份围绕应用 ID(App ID)的概念构建。 应用 ID 是 Dapr 中身份的单一原子单元:

  • 每个 Dapr 应用都有一个应用 ID。应用的多个副本共享同一个应用 ID。
  • Dapr 中的所有路由、服务发现、安全策略和访问控制都源自这个应用 ID。
  • Dapr 中的服务间通信使用应用 ID 而不依赖 IP 地址或主机名,从而实现跨环境的稳定和可移植寻址。

例如,当一个服务使用 Dapr 的服务调用 API 调用另一个服务时,它通过应用 ID 而不是网络位置来调用目标。 这种抽象确保安全策略、双向 TLS(mTLS)证书和访问控制在应用身份级别一致应用。

命名空间和作用域

虽然应用 ID 唯一标识应用,但命名空间提供了一层额外的作用域和隔离,特别是在多租户或大型环境中。

  • 命名空间允许操作员在逻辑分离的组中部署 Dapr 应用。
  • 两个应用可以在不同的命名空间中拥有相同的应用 ID 而不会冲突,因为安全、路由和发现是命名空间感知的。

服务调用作用域访问策略

Dapr 应用可以限定到命名空间进行部署和安全。您可以部署在不同命名空间的服务之间进行调用。阅读跨命名空间的服务调用文章了解更多详情。

Dapr 应用可以限制哪些操作可以被调用,包括允许(或拒绝)哪些应用调用它。阅读如何:为服务调用应用访问控制列表配置了解更多详情。

发布订阅主题作用域访问策略

对于发布订阅组件,您可以限制哪些主题类型和应用被允许发布和订阅特定主题。阅读限定发布/订阅主题访问了解更多详情。

使用 mTLS 加密数据

Dapr 用于加密传输中数据的安全机制之一是双向认证 TLS或 mTLS。mTLS 为应用内的网络流量提供了几个关键功能:

  • 双向认证,客户端向服务器证明其身份,反之亦然。
  • 建立双向认证后,为所有传输中通信提供加密通道

mTLS 在几乎所有场景中都很有用,特别是对于受 HIPAAPCI 等法规约束的系统。

安全的 Dapr 到 Dapr 通信

Dapr 在您的生产系统中无需额外代码或复杂配置即可启用 mTLS。同样,除非明确列出,Dapr 边车默认阻止除 localhost 外的所有 IP 地址调用它。

Dapr 包含"默认启用"的自动 mTLS,为 Dapr 边车之间的流量提供传输中加密。为实现这一点,Dapr 利用名为 Sentry 的系统服务,它充当证书颁发机构(CA)/身份提供者并签署源自 Dapr 边车的工作负载(应用)证书请求。

默认情况下,工作负载证书有效期为 24 小时,时钟偏差设置为 15 分钟。

除非您提供了现有的根证书,否则 Sentry 服务会自动创建并持久化有效期为一年自签名根证书。Dapr 管理工作负载证书轮换;如果您自带证书,Dapr 会这样做而不会对应用造成停机。

当根证书被替换时(Kubernetes 模式下的 secret 和自托管模式的文件系统),Sentry 会获取它们并重建信任链,无需重启且对 Sentry 零停机。

当新的 Dapr 边车初始化时,它会检查是否启用了 mTLS。如果启用,则会生成 ECDSA 私钥和证书签名请求,并通过 gRPC 接口发送到 Sentry。Dapr 边车与 Sentry 之间的通信使用信任链证书进行身份验证,该证书由 Dapr 边车注入器系统服务注入到每个 Dapr 实例中。

配置 mTLS

可以通过编辑通过 spec.mtls.enabled 字段部署的 Dapr 默认配置来开启/关闭 mTLS。

您可以在 Kubernetes 和自托管模式下执行此操作

自托管模式下的 mTLS

下图显示了 Sentry 系统服务如何根据操作员提供或由 Sentry 服务生成并存储在文件中的根/颁发者证书为应用颁发证书。

<img src="/images/security-mTLS-sentry-selfhosted.png width=1000>

Kubernetes 模式下的 mTLS

在 Kubernetes 集群中,保存根证书的 secret 是:

  • 限定到部署 Dapr 组件的命名空间。
  • 只能由 Dapr 控制平面系统 pod 访问。

当部署在 Kubernetes 上时,Dapr 还支持强身份,依赖于 pod 的服务帐户令牌,该令牌作为证书签名请求(CSR)的一部分发送给 Sentry。

下图显示了 Sentry 系统服务如何根据操作员提供或由 Sentry 服务生成并存储为 Kubernetes secret 的根/颁发者证书为应用颁发证书

<img src="/images/security-mTLS-sentry-kubernetes.png width=1000>

防止 Dapr 上的 IP 地址

为了防止 Dapr 边车在任何 IP 地址上被调用(特别是在 Kubernetes 等生产环境中),Dapr 将其侦听 IP 地址限制为 localhost。如果需要启用来自外部地址的访问,请使用 dapr-listen-addresses 设置。

安全的 Dapr 到应用通信

Dapr 边车通过 localhost 在应用附近运行,建议运行在与应用相同的网络边界下。虽然当今许多云原生系统认为 pod 级别(例如在 Kubernetes 上)是可信的安全边界,但 Dapr 使用令牌为应用提供 API 级身份验证。此功能保证,即使在 localhost 上:

  • 只有经过身份验证的应用才能调用 Dapr
  • 应用可以检查 Dapr 是否正在回调它

有关配置 API 令牌安全的更多详细信息,请阅读:

安全的 Dapr 到控制平面通信

除了 Dapr 边车之间的自动 mTLS 外,Dapr 还在以下之间提供强制 mTLS:

  • Dapr 边车
  • Dapr 控制平面系统服务,即:
    • Sentry 服务(证书颁发机构)
    • Placement 服务(actor 放置)
    • Kubernetes Operator 服务

当启用 mTLS 时,Sentry 将根证书和颁发者证书写入限定到安装控制平面的命名空间的 Kubernetes secret。在自托管模式下,Sentry 将证书写入可配置的文件系统路径。

在 Kubernetes 中,当 Dapr 系统服务启动时,它们会自动挂载并使用包含根证书和颁发者证书的 secret 来保护 Dapr 边车使用的 gRPC 服务器。在自托管模式下,每个系统服务可以挂载到文件系统路径以获取凭据。

当 Dapr 边车初始化时,它使用挂载的叶证书和颁发者私钥与系统 pod 进行身份验证。这些作为环境变量挂载在边车容器上。

Kubernetes 中到系统服务的 mTLS

下图显示了 Dapr 边车与 Dapr Sentry(证书颁发机构)、Placement(actor 放置)和 Kubernetes Operator 系统服务之间的安全通信。

<img src="/images/security-mTLS-dapr-system-services.png width=1000>

运维安全

Dapr 旨在让操作员管理 mTLS 证书并强制执行 OAuth 策略。

mTLS 证书部署和轮换

虽然操作员和开发人员可以将自己的证书带入 Dapr,但 Dapr 会自动创建并持久化自签名根证书和颁发者证书。阅读设置和配置 mTLS 证书了解更多详情。

使用 OAuth 的中间件端点授权

使用 Dapr OAuth 2.0 中间件,您可以为您的 API 在 Dapr 端点上启用 OAuth 授权。阅读使用 OAuth 配置端点授权了解详情。Dapr 还有其他中间件组件,您可以将它们用于 OpenID Connect 和 OPA 策略。有关更多详细信息,阅读有关支持的中间件

网络安全

您可以采用常见的网络安全技术,例如网络安全组(NSG)、非军事区(DMZ)和防火墙,为您的网络资源提供多层保护。例如,除非配置为与外部绑定目标通信,否则 Dapr 边车不会打开与互联网的连接,大多数绑定实现仅使用出站连接。您可以设计防火墙规则以仅允许通过指定端口进行出站连接。

在 Kubernetes 中以非 root 身份运行

在 Kubernetes 中运行时,Dapr 服务确保每个进程都以非 root 身份运行。这是通过检查进程的 UID 和 GID 是否为 65532 来完成的,如果不符合预期则报致命错误。如果您必须在 Kubernetes 中运行非默认的 UID 和 GID,请设置以下环境变量以跳过此检查。

DAPR_UNSAFE_SKIP_CONTAINER_UID_GID_CHECK="true"

安全策略

Dapr 有广泛的安全策略集,您可以将其应用于您的应用。您可以通过边车配置中的策略设置或组件规范来限定它们能够执行的操作。

API 访问策略

在某些场景中,例如零信任网络或通过前端将 Dapr 边车暴露给外部流量时,建议仅启用应用当前使用的 Dapr 边车 API。这减少了攻击面,并将 Dapr API 限定为应用的实际需求。您可以通过在配置中设置 API 允许列表来控制应用可访问的 API,如下图所示。

<img src="/images/security-dapr-API-scoping.png width=1000>

阅读如何:在 Dapr 边上有选择地启用 Dapr API了解更多详情。

密钥作用域访问策略

要限制 Dapr 应用对密钥的访问,您可以定义密钥作用域。将具有限制性权限的密钥作用域策略添加到应用配置中。阅读如何:使用密钥作用域了解更多详情。

组件应用作用域访问策略和密钥使用

Dapr 组件可以被命名空间化。这意味着 Dapr 边车实例只能访问部署到同一命名空间的组件。阅读如何:使用命名空间将组件限定到一个或多个应用了解更多详情。

Dapr 通过允许您指定哪些应用可以使用特定组件并拒绝其他应用来提供应用级别的组件作用域。阅读使用作用域限制应用对组件的访问了解更多详情。

Dapr 组件可以使用 Dapr 的内置密钥管理功能来管理密钥。阅读密钥存储概述如何:在组件中引用密钥了解更多详情。

绑定安全

与绑定目标的身份验证通过绑定的配置文件进行配置。通常,您应该配置最低所需的访问权限。例如,如果您仅从绑定目标读取,则应该将绑定配置为使用具有只读访问权限的帐户。

状态安全

静态状态存储加密

默认情况下,Dapr 不会转换来自应用的状态数据。这意味着:

  • Dapr 不会尝试加密/解密状态数据
  • 您的应用可以采用您选择的加密/解密方法,其中状态数据对 Dapr 保持不透明。

Dapr 组件可以使用配置的身份验证方法与底层状态存储进行身份验证。许多状态存储实现使用官方客户端库,这些库通常使用与服务器的安全通信通道。

然而,应用状态通常需要在静态时加密,以便在企业工作负载或受监管环境中提供更强的安全性。Dapr 基于 AES256 提供自动的客户端状态加密。阅读如何:加密应用状态了解更多详情。

Dapr 运行时状态

Dapr 运行时不存储任何静态数据,这意味着 Dapr 运行时对其操作不依赖任何状态存储,可以被视为无状态。

在示例应用中使用安全功能

下图显示了部署在 Kubernetes 上的示例应用中的许多安全功能。在该示例中,Dapr 控制平面、Redis 状态存储和每个服务都部署到自己的命名空间中。在 Kubernetes 上部署时,您可以使用常规 Kubernetes RBAC 来控制对管理活动的访问。

在应用中,请求由入站反向代理接收,该代理旁边运行着 Dapr 边车。从反向代理开始,Dapr 使用服务调用调用服务 A,然后服务 A 向服务 B 发布消息。服务 B 检索密钥以读取状态并将状态保存到 Redis 状态存储。

<img src="/images/security-overview-capabilities-example.png width=1000>

让我们逐一介绍每个安全功能,并描述它们如何保护此应用。

  1. API 令牌身份验证确保反向代理知道它正在与正确的 Dapr 边车实例通信。这防止将消息转发到除此 Dapr 边车之外的任何东西。
  2. 服务调用 mTLS 用于反向代理和服务 A 之间的身份验证。在服务 A 上配置的服务访问策略限制它仅从反向代理接收特定端点上的调用,而不接收其他服务的调用。
  3. 服务 B 使用发布订阅主题安全策略来指示它只能接收从服务 A 发布的消息。
  4. Redis 组件定义使用组件作用域安全策略来表示只允许服务 B 调用它。
  5. 服务 B 限制 Dapr 边车仅使用发布订阅、状态管理和密钥 API。所有其他 API 调用(例如,服务调用)都将失败。
  6. 在配置中设置的密钥安全策略限制服务 B 可以访问的密钥。在这种情况下,服务 B 只能读取连接到 Redis 状态存储组件所需的密钥,而不能读取其他密钥。
  7. 服务 B 部署到命名空间 “B”,这进一步将其与其他服务隔离。即使在其上启用了服务调用 API,它也不会因为与服务 A 在同一命名空间而被意外调用。服务 B 必须在其组件 YAML 文件中显式设置 Redis 主机命名空间才能调用 “Redis” 命名空间,否则此调用也会失败。
  8. Redis 状态存储中的数据在静态时加密,并且只能使用正确配置的 Dapr Redis 状态存储组件读取。

威胁模型

威胁建模是一个过程,通过该过程:

  • 可以识别和枚举潜在威胁,例如结构漏洞或缺乏适当的保障措施。
  • 可以确定缓解措施的优先级。

Dapr 威胁模型如下。

Dapr 威胁模型

安全审计

2023 年 9 月

2023 年 9 月,Dapr 完成了由 Ada Logics 进行的安全审计。

这次审计是一次全面的安全审计,具有以下目标:

  • 正式化 Dapr 的威胁模型
  • 进行手动代码审查
  • 根据正式化的威胁模型评估 Dapr 的模糊测试套件
  • 对 Dapr 进行 SLSA 审查

您可以在此处找到完整报告链接

审计发现了 7 个问题,其中没有一个属于高严重性或关键严重性问题。从一个第三方依赖项中的问题向 Dapr Components Contrib 分配了一个 CVE。

2023 年 6 月

2023 年 6 月,Dapr 完成了由 Ada Logics 进行的模糊测试审计。

这次审计实现了以下目标:

  • OSS-Fuzz 集成
  • 为 Dapr 新增 39 个模糊测试器
  • Dapr Runtime、Kit 和 Components-contrib 的模糊测试覆盖
  • 审计完成后所有模糊测试器持续运行

您可以在此处找到完整报告链接

审计期间发现了 3 个问题。

2021 年 2 月

2021 年 2 月,Dapr 通过了由 Cure53 进行的第二次安全审计,针对其 1.0 版本。

测试重点如下:

  • 自上次审计以来的 Dapr 运行时代码库评估
  • 访问控制列表
  • 密钥管理
  • 渗透测试
  • 验证以前高/中 issues 的修复

您可以在此处找到完整报告链接

测试期间检测并修复了一个高严重性问题。

截至 2021 年 2 月 16 日,Dapr 有 0 个关键问题,0 个高严重性问题,0 个中等问题,2 个低问题,2 个信息问题。

2020 年 6 月

2020 年 6 月,Dapr 接受了来自 Cure53(一家获得 CNCF 批准的网络安全公司)的安全审计。

测试重点如下:

  • Dapr 运行时代码库评估
  • Dapr 组件代码库评估
  • Dapr CLI 代码库评估
  • 权限提升
  • 流量欺骗
  • 密钥管理
  • RBAC
  • 验证基本假设:mTLS、作用域、API 身份验证
  • 编排硬化(Kubernetes)
  • DoS 攻击
  • 渗透测试

完整报告可以在此处找到链接

报告安全问题

访问此页面向 Dapr 维护者报告安全问题。

相关链接

运维安全

8 - Isolation

Dapr 如何提供命名空间和隔离

Dapr 命名空间在众多功能中提供隔离和多租户支持,带来更高的安全性。通常,应用程序和组件会被部署到命名空间中,以在给定环境(例如 Kubernetes)中提供隔离。

Dapr 在应用程序之间的服务调用、访问组件、在消费者组中发送发布订阅消息,以及 Actor 类型部署等场景中支持命名空间。自托管模式和 Kubernetes 模式均支持命名空间隔离。

开始之前,请创建并配置您的命名空间。

在自托管模式下,通过设置 NAMESPACE 环境变量为 Dapr 实例指定命名空间。

在 Kubernetes 上,创建并配置命名空间:

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

然后将您的应用程序部署到此命名空间中。

了解如何在 Dapr 中使用命名空间:

9 - Dapr 服务概述

了解构成 Dapr 运行时的服务

9.1 - Dapr 边车(daprd)概述

Dapr 边车进程概述

Dapr 使用边车模式,这意味着 Dapr API 在一个单独的进程中运行和暴露,该进程称为 Dapr 边车,与您的应用并行运行。Dapr 边车进程名为 daprd,根据托管环境的不同,以不同的方式启动。

Dapr 边车暴露:

当应用在其配置的端口上可访问时,Dapr 边车将达到就绪状态。在应用启动/初始化期间,应用无法访问 Dapr 组件。

边车 API 通过本地 http 或 gRPC 端点从您的应用调用。

自托管模式下使用 dapr run

当 Dapr 以自托管模式安装时,daprd 二进制文件会被下载并放置在用户主目录下(Linux/macOS 为 $HOME/.dapr/bin,Windows 为 %USERPROFILE%\.dapr\bin\)。

在自托管模式下,运行 Dapr CLI 的 run 命令 会使用提供的应用可执行文件启动 daprd 可执行文件。这是在本地开发和测试等场景中运行 Dapr 边车的推荐方式。

您可以在 Dapr run 命令参考 中找到 CLI 暴露的用于配置边车的各种参数。

Kubernetes 集群中使用 dapr-sidecar-injector

Kubernetes 上,Dapr 控制平面包含 dapr-sidecar-injector 服务,该服务监视带有 dapr.io/enabled 注解的新 Pod,并在 Pod 内注入一个包含 daprd 进程的容器。在这种情况下,边车参数可以通过注解传递,如此表中的 Kubernetes 注解 列所述。

原生边车(Kubernetes 1.28+)

默认情况下,daprd 作为常规容器与您的应用一起注入。使用 Kubernetes 原生边车KEP-753),daprd 改为作为带有 restartPolicy: Always 的初始化容器注入。有关行为和生命周期语义的详细信息,请参阅 Kubernetes 边车容器文档

通过 Helm 全局启用原生边车:

dapr_sidecar_injector:
  nativeSidecar: true

或通过注解按 Pod 启用:

annotations:
  dapr.io/enabled: "true"
  dapr.io/enable-native-sidecar: "true"

直接运行边车

在大多数情况下,您不需要显式运行 daprd,因为边车由 CLI(自托管模式)或 dapr-sidecar-injector 服务(Kubernetes)启动。对于高级用例(调试、脚本部署等),可以直接启动 daprd 进程。

有关所有可用参数的详细列表,请运行 daprd --help 或参阅此表,该表概述了 daprd 参数与 CLI 参数和 Kubernetes 注解的关联方式。

示例

  1. 通过指定唯一 ID 在应用旁边启动边车。

    注意: --app-id 是必填字段,且不能包含点。

    daprd --app-id myapp
    
  2. 指定应用正在监听的端口

    daprd --app-id myapp --app-port 5000
    
  3. 如果您使用多个自定义资源并希望指定资源定义文件的位置,请使用 --resources-path 参数:

    daprd --app-id myapp --resources-path <PATH-TO-RESOURCES-FILES>
    
  4. 如果您将组件和其他资源(例如,弹性策略、订阅或配置)组织到单独的文件夹或共享文件夹中,可以指定多个资源路径:

    daprd --app-id myapp --resources-path <PATH-1-TO-RESOURCES-FILES> --resources-path <PATH-2-TO-RESOURCES-FILES>
    
  5. 运行应用时启用 Prometheus 指标收集

    daprd --app-id myapp --enable-metrics
    
  6. 仅监听 IPv4 和 IPv6 回环地址

    daprd --app-id myapp --dapr-listen-addresses '127.0.0.1,[::1]'
    

9.2 - Dapr Operator 控制平面服务概述

Dapr Operator 服务概述

Kubernetes 模式下运行 Dapr 时,运行 Dapr Operator 服务的 Pod 管理 Dapr 组件 更新,并为 Dapr 提供 Kubernetes 服务端点。

运行 Operator 服务

Operator 服务作为 dapr init -k 的一部分部署,或通过 Dapr Helm charts 部署。有关在 Kubernetes 上运行 Dapr 的更多信息,请访问 Kubernetes 托管页面

其他配置选项

Operator 服务包含其他配置选项。

注入器看门狗

Operator 服务包含 注入器看门狗 功能,该功能定期轮询 Kubernetes 集群中运行的所有 Pod,并确认 Dapr 边车已注入到具有 dapr.io/enabled=true 注解的 Pod 中。该功能主要用于处理 注入器服务 未能成功将边车(daprd 容器)注入到 Pod 的场景。

注入器看门狗在多种情况下都很有用,包括:

  • 从完全停止的 Kubernetes 集群中恢复。当集群完全停止然后重新启动时(包括集群完全故障的情况),Pod 以随机顺序重启。如果应用程序在 Dapr 控制平面(特别是注入器服务)准备就绪之前重启,Dapr 边车可能无法注入到应用程序的 Pod 中,导致应用程序行为异常。

  • 解决边车注入器潜在的随机故障,例如注入器服务内部的瞬时故障。

如果看门狗检测到应该有边车但没有边车的 Pod,它将删除该 Pod。然后 Kubernetes 将重新创建该 Pod,再次调用 Dapr 边车注入器。

注入器看门狗功能默认禁用

您可以通过向 operator 命令传递 --watch-interval 标志来启用它,该标志可以采用以下值之一:

  • --watch-interval=0:禁用注入器看门狗(省略该标志时的默认值)。
  • --watch-interval=<interval>:启用注入器看门狗,并按指定间隔轮询所有 Pod;间隔值的字符串包含时间单位。例如:--watch-interval=10s(每 10 秒)或 --watch-interval=2m(每 2 分钟)。
  • --watch-interval=once:注入器看门狗在 Operator 服务启动时仅运行一次。

如果使用 Helm,可以使用 dapr_operator.watchInterval 选项配置注入器看门狗,该选项与命令行标志具有相同的值。

在 HA(高可用)模式下运行 Operator 服务时(配置多个副本),注入器看门狗是安全可用的。在此情况下,Kubernetes 会自动选举一个"领导者"实例,这是唯一运行注入器看门狗服务的实例。

然而,在 HA 模式下,如果将注入器看门狗配置为仅"运行一次",当 Operator 服务实例被选为领导者时,看门狗轮询会实际启动。这意味着,如果 Operator 服务的领导者崩溃并选出新的领导者,将再次触发注入器看门狗。

观看此视频,了解注入器看门狗的概览:

9.3 - Dapr Placement 控制平面服务概述

Dapr Placement 服务概述

Dapr Placement 服务用于计算和分发运行在自托管模式Kubernetes上的 Dapr actors 位置的分布式哈希表。哈希表按命名空间分组,将 actor 类型映射到 pod 或进程,以便 Dapr 应用程序可以与 actor 通信。每当 Dapr 应用程序激活 Dapr actor 时,Placement 服务会使用最新的 actor 位置更新哈希表。

自托管模式

Placement 服务 Docker 容器作为 dapr init 的一部分自动启动。如果您以 slim-init 模式 运行,也可以作为进程手动运行。

Kubernetes 模式

Placement 服务作为 dapr init -k 的一部分部署,或通过 Dapr Helm 图表部署。您可以在高可用(HA)模式下运行 Placement。了解有关在 Kubernetes 服务中设置 HA 模式的更多信息。

有关在 Kubernetes 上运行 Dapr 的更多信息,请访问 Kubernetes 托管页面

Placement 表

有一个Placement 服务的 HTTP API /placement/state 用于暴露 placement 表信息。该 API 在 sidecar 上与 healthz 相同的端口上暴露。这是一个未经身份验证的端点,默认情况下被禁用。您需要将 DAPR_PLACEMENT_METADATA_ENABLED 环境变量或 metadata-enabled 命令行参数设置为 true 来启用它。如果您使用 helm,只需将 dapr_placement.metadataEnabled 设置为 true。

用例

placement 表 API 可用于检索当前的 placement 表,其中包含在所有命名空间中注册的所有 actors。这对于调试和允许工具提取并呈现有关 actors 的信息很有帮助。

HTTP 请求

GET http://localhost:<healthzPort>/placement/state

HTTP 响应代码

代码描述
200返回 Placement 表信息
500Placement 无法返回 Placement 表信息

HTTP 响应体

Placement 表 API 响应对象

名称类型描述
tableVersionintPlacement 表版本
hostListActor 主机信息[]已注册 actor 主机信息的 json 数组。

Actor 主机信息

名称类型描述
namestringactor 的 host:port 地址。
appIdstringapp id。
actorTypesjson string array它托管的 actor 类型列表。
updatedAttimestampactor 注册/更新的时间戳。

示例

 curl localhost:8080/placement/state
{
    "hostList": [{
            "name": "198.18.0.1:49347",
            "namespace": "ns1",
            "appId": "actor1",
            "actorTypes": ["testActorType1", "testActorType3"],
            "updatedAt": 1690274322325260000
        },
        {
            "name": "198.18.0.2:49347",
            "namespace": "ns2",
            "appId": "actor2",
            "actorTypes": ["testActorType2"],
            "updatedAt": 1690274322325260000
        },
        {
            "name": "198.18.0.3:49347",
            "namespace": "ns2",
            "appId": "actor2",
            "actorTypes": ["testActorType2"],
            "updatedAt": 1690274322325260000
        }
    ],
    "tableVersion": 1
}

禁用 Placement 服务

可以使用以下设置禁用 Placement 服务:

global.actors.enabled=false

在 Kubernetes 模式下,使用此设置不会部署 Placement 服务。这不仅会禁用 actor 部署,还会禁用工作流,因为工作流使用 actors。但是,此设置仅适用于 Kubernetes 模式,而使用 --slim 初始化 Dapr 会阻止在自托管模式下部署 Placement 服务。

有关在 Kubernetes 上运行 Dapr 的更多信息,请访问 Kubernetes 托管页面

相关链接

了解有关 Placement API 的更多信息。

9.4 - Dapr Scheduler 控制平面服务概述

Dapr scheduler 服务概述

Dapr Scheduler 服务用于调度不同类型的作业,可在自托管模式Kubernetes上运行。

  • 通过 Jobs API 创建的作业
  • Actor reminder 作业(由 actor reminders 使用)
  • 由 Workflow API 创建的 actor reminder 作业(使用 actor reminders)

不存在主 Scheduler 实例的概念。 所有 Scheduler 服务副本均被视为对等节点。 所有副本都会接收待调度的作业,并在可用的 Scheduler 服务副本之间进行分配,以实现触发事件的负载均衡。

下图展示了从应用程序调用时,如何通过 Jobs API 使用 Scheduler 服务。Scheduler 服务跟踪的所有作业都存储在 Etcd 数据库中。

显示 Scheduler 控制平面服务和 Jobs API 的架构图

默认情况下,Etcd 内嵌于 Scheduler 服务中,这意味着 Scheduler 服务会运行其自己的 Etcd 实例。 有关如何配置 Scheduler 服务的更多信息,请参阅 Scheduler 服务标志

作业位置性

默认作业行为

当 Scheduler 服务触发作业时,它们会被发送回调度该作业的同一应用 ID 的单个副本,以随机负载均衡的方式进行。 这会在应用程序的副本之间提供基本的负载均衡,适用于大多数不需要严格位置性的用例。

使用 Actor Reminders 实现完全位置性

对于需要完全作业位置性(让作业在创建它们的同一主机上触发)的用户,actor reminders 提供了一种解决方案。 要为作业强制执行完全位置性:

  1. 创建一个 actor 类型,其中包含一个特定副本独有的随机 UUID
  2. 使用此 actor 类型创建一个 actor reminder

这种方法确保作业始终在创建它的同一主机上触发,而不是在副本之间随机分布。

作业触发

作业失败策略和暂存队列

当 Scheduler 服务触发作业时遇到客户端错误,默认情况下会以 1 秒间隔重试,最多重试 3 次。

对于非客户端错误,例如,在触发时无法将作业发送到可用的 Dapr 边车,它会被放置在 Scheduler 服务内的暂存队列中。作业会保留在此队列中,直到找到合适的边车实例,此时它们会自动发送到相应的 Dapr 边车实例。

自托管模式

Scheduler 服务 Docker 容器作为 dapr init 的一部分自动启动。如果您在 slim-init 模式下运行,也可以作为进程手动运行。

在自托管部署中,Scheduler 可以在高可用(HA)和非 HA 模式下运行。但是,不建议在生产环境中使用非 HA 模式。如果在非 HA 和 HA 模式之间切换,必须删除现有的数据目录,这会导致作业和 actor reminders 丢失。在进行此更改之前,请运行备份 以避免数据丢失。

Kubernetes 模式

Scheduler 服务作为 dapr init -k 的一部分或通过 Dapr Helm charts 部署。在 Kubernetes 部署中,Scheduler 始终以高可用(HA)模式运行。由于内嵌数据存储的性质,无法在不造成数据丢失的情况下扩展或缩减 Scheduler 服务副本。了解有关在 Kubernetes 服务中设置 HA 模式的更多信息。

当删除 Kubernetes 命名空间时,与该命名空间对应的所有 Job 和 Actor Reminders 也会被删除。

Docker Compose 示例

以下是在 Docker Compose 配置中为独立模式暴露 etcd 端口的方法。 在 HA 模式下运行时,只需暴露一个 scheduler 实例的端口以执行备份操作。

version: "3.5"
services:
  scheduler-0:
    image: "docker.io/daprio/scheduler:1.18.0"
    command:
    - "./scheduler"
    - "--etcd-data-dir=/var/run/dapr/scheduler"
    - "--id=scheduler-0"
    - "--etcd-initial-cluster=scheduler-0=http://scheduler-0:2380,scheduler-1=http://scheduler-1:2380,scheduler-2=http://scheduler-2:2380"
    ports:
      - 2379:2379
    volumes:
      - ./dapr_scheduler/0:/var/run/dapr/scheduler
  scheduler-1:
    image: "docker.io/daprio/scheduler:1.18.0"
    command:
    - "./scheduler"
    - "--etcd-data-dir=/var/run/dapr/scheduler"
    - "--id=scheduler-1"
    - "--etcd-initial-cluster=scheduler-0=http://scheduler-0:2380,scheduler-1=http://scheduler-1:2380,scheduler-2=http://scheduler-2:2380"
    volumes:
      - ./dapr_scheduler/1:/var/run/dapr/scheduler
  scheduler-2:
    image: "docker.io/daprio/scheduler:1.18.0"
    command:
    - "./scheduler"
    - "--etcd-data-dir=/var/run/dapr/scheduler"
    - "--id=scheduler-2"
    - "--etcd-initial-cluster=scheduler-0=http://scheduler-0:2380,scheduler-1=http://scheduler-1:2380,scheduler-2=http://scheduler-2:2380"
    volumes:
      - ./dapr_scheduler/2:/var/run/dapr/scheduler

使用 Dapr CLI 管理作业

Dapr 提供了一个 CLI 用于检查和管理所有调度的作业,无论类型如何。 CLI 是查看、备份和删除作业的推荐方式。

Scheduler 管理着几种不同类型的作业:

  • app/{app-id}/{job-name}:通过 Jobs API 创建的作业
  • actor/{actor-type}/{actor-id}/{reminder-name}:通过 Actor Reminders API 创建的 actor reminder 作业
  • activity/{app-id}/{instance-id}::{generation-name}::{activity-index}:用于 Workflow Activity reminders 内部
  • workflow/{app-id}/{instance-id}/{random-name}:用于 工作流 内部。

请参阅此处了解如何使用 CLI 专门管理 reminders

列出作业

dapr scheduler list

示例输出:

NAME                                           BEGIN     COUNT  LAST TRIGGER
actor/myactortype/actorid1/test1               -3.89s    1      2025-10-03T16:58:55Z
actor/myactortype/actorid2/test2               -3.89s    1      2025-10-03T16:58:55Z
app/test-scheduler/test1                       -3.89s    1      2025-10-03T16:58:55Z
app/test-scheduler/test2                       -3.89s    1      2025-10-03T16:58:55Z
activity/test-scheduler/xyz1::0::1             -888.8ms  0
activity/test-scheduler/xyz2::0::1             -888.8ms  0
workflow/test-scheduler/abc1/timer-0-TVIQGkvu  +50.0h    0
workflow/test-scheduler/abc2/timer-0-OM2xqG9m  +50.0h    0

要获取更多详细信息,请使用宽输出格式:

dapr scheduler list -o wide
NAMESPACE  NAME                                           BEGIN                 EXPIRATION            SCHEDULE         DUE TIME                   TTL     REPEATS  COUNT  LAST TRIGGER
default    actor/myactortype/actorid1/test1               2025-10-03T16:58:55Z                        @every 2h46m40s  2025-10-03T17:58:55+01:00          100      1      2025-10-03T16:58:55Z
default    actor/myactortype/actorid2/test2               2025-10-03T16:58:55Z                        @every 2h46m40s  2025-10-03T17:58:55+01:00          100      1      2025-10-03T16:58:55Z
default    app/test-scheduler/test1                       2025-10-03T16:58:55Z                        @every 100m      2025-10-03T17:58:55+01:00          1234     1      2025-10-03T16:58:55Z
default    app/test-scheduler/test2                       2025-10-03T16:58:55Z  2025-10-03T19:45:35Z  @every 100m      2025-10-03T17:58:55+01:00  10000s  56788    1      2025-10-03T16:58:55Z
default    activity/test-scheduler/xyz1::0::1             2025-10-03T16:58:58Z                                         0s                                          0
default    activity/test-scheduler/xyz2::0::1             2025-10-03T16:58:58Z                                         0s                                          0
default    workflow/test-scheduler/abc1/timer-0-TVIQGkvu  2025-10-05T18:58:58Z                                         2025-10-05T18:58:58Z                        0
default    workflow/test-scheduler/abc2/timer-0-OM2xqG9m  2025-10-05T18:58:58Z                                         2025-10-05T18:58:58Z                        0

获取作业详细信息

dapr scheduler get app/my-app/job1 -o yaml

删除作业

删除一个或多个特定作业:

dapr scheduler delete app/my-app/job1 actor/MyActor/123/reminder1

使用过滤器批量删除作业:

dapr scheduler delete-all all
dapr scheduler delete-all app/my-app
dapr scheduler delete-all actor/MyActorType

备份和恢复作业

在生产环境中,建议定期备份此数据,备份间隔应与您的恢复点目标保持一致。 Dapr CLI 提供了一个命令,用于将所有 Scheduler 数据导出到特定的二进制文件。 在 Kubernetes 模式下运行时,请使用 -k 标志。

dapr scheduler export -o scheduler-backup.bin
dapr scheduler export -k -o scheduler-backup.bin

要从备份文件恢复数据:

dapr scheduler import -f scheduler-backup.bin
dapr scheduler import -k -f scheduler-backup.bin

监控 Scheduler 的 etcd 指标

转发 Scheduler 实例的端口并使用以下命令查看 etcd 的指标:

curl -s http://localhost:2379/metrics

通过根据需要审查和配置 Scheduler 的 etcd 标志来微调内嵌的 etcd 以满足您的需求。

禁用 Scheduler 服务

如果您未使用任何需要 Scheduler 服务的功能(Jobs API、Actor Reminders 或 Workflows),可以通过设置 global.scheduler.enabled=false 来禁用它。 有关在 Kubernetes 上运行 Dapr 的更多信息,请访问 Kubernetes 托管页面

标志调优

Scheduler 上暴露了许多 Etcd 标志,可用于针对您的部署用例进行调优。

外部 Etcd 数据库

可以将 Scheduler 配置为使用外部 Etcd 数据库,而不是 Scheduler 服务副本内部内嵌的数据库。 由于集群或环境的管理局以及所使用的存储后端,将存储卷与 Scheduler StatefulSet 或容器解耦可能是很有意义的。 也可能完全将持久存储移出 scheduler 运行时,或者有一些现有的 Etcd 集群提供者将被重用。 外部化 Etcd 数据库也意味着 Scheduler 副本可以随意水平扩展,但请注意,在扩展事件期间,作业触发将会暂停。 Scheduler 副本计数不需要与 Etcd 节点计数约束 匹配。

要使用外部 Etcd 集群,请将 --etcd-embed 标志设置为 false,并提供 --etcd-client-endpoints 标志以及您的 Etcd 集群的端点。 如果 Etcd 集群需要身份验证,还可以选择包括 --etcd-client-username--etcd-client-password 标志。

--etcd-embed              bool         启用时,Etcd 数据库内嵌于 scheduler 服务器中。如果为 false,scheduler 使用 --etcd-client-endpoints 标志连接到外部 Etcd 集群。(默认为 true)
--etcd-client-endpoints   stringArray  要连接的 etcd 客户端端点的逗号分隔列表。仅在 --etcd-embed 为 false 时使用。
--etcd-client-username    string       etcd 客户端身份验证的用户名。仅在 --etcd-embed 为 false 时使用。
--etcd-client-password    string       etcd 客户端身份验证的密码。仅在 --etcd-embed 为 false 时使用。

Helm:

dapr_scheduler.etcdEmbed=true
dapr_scheduler.etcdClientEndpoints=[]
dapr_scheduler.etcdClientUsername=""
dapr_scheduler.etcdClientPassword=""

Etcd 领导者选举调优

为了在故障发生时提高救援节点的领导者选举速度,可以使用以下标志来加快选举过程。

--etcd-initial-election-tick-advance  是否在启动时快进初始选举 ticks 以加快选举。当它为 true 时,本地成员快进选举 ticks 以加速"初始"领导者选举触发。这有利于更大的选举 ticks 的情况。禁用此功能会减慢跨数据中心部署的初始引导过程。通过配置此标志,以缓慢的初始引导为代价来权衡。

Helm:

dapr_scheduler.etcdInitialElectionTickAdvance=true

存储调优

以下选项可用于根据您的部署需求调优内嵌的 Etcd 存储。 可以在 Etcd 文档中找到有关这些标志作用的更深入理解。

--etcd-backend-batch-interval string                            提交后端事务之前的最大时间。(默认 "50ms")
--etcd-backend-batch-limit int                                  提交后端事务之前的最大操作数。(默认 5000)
--etcd-compaction-mode string                                   etcd 的压缩模式。可以是 'periodic' 或 'revision'(默认 "periodic")
--etcd-compaction-retention string                              etcd 的压缩保留。可以表示时间或修订数,取决于 'etcd-compaction-mode' 的值(默认 "10m")
--etcd-experimental-bootstrap-defrag-threshold-megabytes uint   etcd 在引导期间考虑运行碎片整理所需释放的最小兆字节数。需要设置为非零值才能生效。(默认 100)
--etcd-max-snapshots uint                                       要保留的快照文件的最大数量(0 为无限制)。(默认 10)
--etcd-max-wals uint                                            要保留的预写日志的最大数量(0 为无限制)。(默认 10)
--etcd-snapshot-count uint                                      触发快照到磁盘的已提交事务数。(默认 10000)

Helm:

dapr_scheduler.etcdBackendBatchInterval="50ms"
dapr_scheduler.etcdBackendBatchLimit=5000
dapr_scheduler.etcdCompactionMode="periodic"
dapr_scheduler.etcdCompactionRetention="10m"
dapr_scheduler.etcdDefragThresholdMB=100
dapr_scheduler.etcdMaxSnapshots=10

相关链接

  • 了解有关 Jobs API 的更多信息。
  • [了解有关 Actor Reminders 的更多信息。]https://docs.dapr.io/zh-hans/developing-applications/building-blocks/actors/actors-features-concepts/#reminders)

9.5 - Dapr Sentry 控制平面服务概述

Dapr Sentry 服务概述

Dapr Sentry 服务管理服务之间的 mTLS 并充当证书颁发机构。它生成 mTLS 证书并将其分发到所有运行的边车。这使边车能够使用加密的 mTLS 流量进行通信。更多信息请阅读边车到边车通信概述

自托管模式

Sentry 服务 Docker 容器不会作为 dapr init 的一部分自动启动。但可以按照设置双向 TLS的说明手动执行它。

如果你运行在 slim-init 模式下,它也可以作为进程手动运行。

Kubernetes 模式

Sentry 服务作为 dapr init -k 的一部分部署,或通过 Dapr Helm charts 部署。有关在 Kubernetes 上运行 Dapr 的更多信息,请访问 Kubernetes 托管页面

延伸阅读

9.6 - Dapr Sidecar Injector 控制平面服务概述

Dapr sidecar 注入器流程概述

Kubernetes 模式 下运行 Dapr 时,会创建一个运行 Dapr Sidecar Injector 服务的 Pod,该服务会查找使用 Dapr 注解 初始化的 Pod,然后在该 Pod 中为 daprd 服务 创建另一个容器。

运行 sidecar 注入器

sidecar 注入器服务作为 dapr init -k 的一部分部署,或通过 Dapr Helm 图表部署。有关在 Kubernetes 上运行 Dapr 的更多信息,请访问 Kubernetes 托管页面

10 - Dapr 术语与定义

Dapr 文档中常见术语和缩写的定义

本页详细介绍了您在 Dapr 文档中可能遇到的所有常见术语。

术语定义更多信息
App/Application正在运行的服务/二进制文件,通常是您作为用户创建并运行的程序。
Building blockDapr 提供给用户的 API,用于帮助创建微服务和应用程序。Dapr 构建块
ComponentDapr 构建块单独或与其他组件集合一起使用的模块化功能类型。Dapr 组件
Configuration用于声明 Dapr 边车或 Dapr 控制平面所有设置的 YAML 文件。您可以在此配置控制平面 mTLS 设置,或应用程序实例的跟踪和中间件设置。Dapr 配置
DaprDistributed Application Runtime(分布式应用运行时)。Dapr 概述
Dapr Actors一个 Dapr 构建块,实现了虚拟 actor 模式,用于构建具有身份、生命周期和并发管理的有状态单线程对象。Actors 概述
Dapr Agents基于 Dapr Python SDK 构建的开发者框架,用于创建由 LLM 驱动的持久化代理应用程序。Dapr Agents
Dapr control plane属于 Dapr 安装一部分的服务集合,部署在托管平台(如 Kubernetes 集群)上。这允许启用 Dapr 的应用程序在平台上运行,并处理 actor 放置、Dapr 边车注入或证书颁发/轮换等 Dapr 功能。自托管概述
Kubernetes 概述
Dapr Workflows一个 Dapr 构建块,用于编写代码优先的工作流,具有持久执行能力,可从崩溃中恢复,支持长时间运行的进程,并支持人员交互。工作流概述
HTTPEndpointHTTPEndpoint 是一种 Dapr 资源,用于标识可通过服务调用 API 调用的非 Dapr 端点。服务调用 API
NamespacingDapr 中的命名空间提供隔离,从而提供多租户能力。了解有关命名空间的更多信息:组件服务调用发布订阅actors
Self-hosted您可以在其中运行 Dapr 应用程序的 Windows/macOS/Linux 机器。Dapr 提供了在机器上以"自托管"模式运行的功能。自托管模式
Service正在运行的应用程序或二进制文件。这可以指您的应用程序或 Dapr 应用程序。
Sidecar作为单独进程或容器与您的应用程序一起运行的程序。边车模式

11 - 常见问题与解答

通过常见问题了解更多 Dapr 概念

11.1 - Dapr 常见问题解答

关于 Dapr 的常见问题

Dapr 与服务网格(如 Istio、Linkerd 或 OSM)相比如何?

Dapr 不是服务网格。虽然服务网格专注于细粒度的网络控制,但 Dapar 专注于帮助开发者构建分布式应用程序。Dapr 和服务网格都使用边车模式,并与应用程序一起运行。它们确实有一些重叠的功能,但也提供各自独特的优势。有关更多信息,请阅读 Dapr & 服务网格 概念页面。

性能基准测试

由于 Dapr 作为应用程序的边车,其项目特别关注性能。请参阅 性能结果 获取最新的性能数据。

Actors

Dapr、Orleans 和 Service Fabric Reliable Actors 之间是什么关系?

Dapr 中的 actors 基于 Orleans 开创的虚拟 actor 概念,意味着它们在调用时激活,并在一段时间后停用。如果你熟悉 Orleans,Dapr C# actors 会让你感到熟悉。Dapr C# actors 基于 Service Fabric Reliable Actors(同样源自 Orleans),使你能够将 Service Fabric 中的 Reliable Actors 迁移到其他托管平台,例如 Kubernetes 或其他本地环境。

此外,Dapr 不仅仅是关于 actors。它为你提供了一套构建任何微服务应用程序的最佳实践构建块。请参阅 Dapr 概述

Dapr 与 actor 框架的区别

虚拟 actor 功能是 Dapr 在其运行时中提供的构建块之一。使用 Dapr,由于它具有编程语言无关的 http/gRPC API,可以从任何语言调用 actors。这允许用一种语言编写的 actors 调用用另一种语言编写的 actors。

创建新 actor 遵循本地调用,如 http://localhost:3500/v1.0/actors/<actorType>/<actorId>/…。例如,http://localhost:3500/v1.0/actors/myactor/50/method/getData 调用新创建的 id 为 50myactor 上的 getData 方法。

Dapr 运行时 SDK 具有特定语言的 actor 框架。例如,.NET SDK 拥有 C# actors。目标是让所有 Dapr 语言 SDK 都拥有 actor 框架。目前 .NET、Java、Go 和 Python SDK 都拥有 actor 框架。

如果我想使用特定的编程语言或框架,Dapr 是否有我可以使用的 SDK?

为了让 Dapr 在不同语言中的使用更加自然,它包括 Go、Java、JavaScript、.NET、Python、PHP、Rust 和 C++ 的特定语言 SDK。这些 SDK 通过类型化语言 API 而非调用 http/gRPC API 来暴露 Dapr 构建块中的功能,例如保存状态、发布事件或创建 actor。这使你能够用你选择的语言编写无状态和有状态函数及 actor 的组合。而且由于这些 SDK 共享 Dapr 运行时,你将获得跨语言的 actor 和函数支持。

Dapr 与哪些框架集成?

Dapr 可以与任何开发者框架集成。例如,在 Dapr .NET SDK 中,你可以找到 ASP.NET Core 集成,它提供了响应来自其他服务的发布订阅事件的有状态路由控制器。

Dapr 与以下框架集成:

11.2 - Dapr 与服务网格

Dapr 如何与 Linkerd、Istio 等服务网格解决方案进行比较与协作

Dapr 采用边车架构,作为独立进程与应用程序并肩运行,并包含服务调用、网络安全和分布式追踪等功能。这经常会引发一个问题:Dapr 与 LinkerdIstioOpen Service Mesh 等服务网格解决方案相比如何?

Dapr 与服务网格的对比

虽然 Dapr 与服务网格确实提供了一些重叠的能力,但Dapr 不是服务网格,这里的服务网格被定义为一种网络服务网格。与服务网格专注于网络关注点不同,Dapr 专注于提供使开发者更易于以微服务方式构建应用程序的构建块。Dapr 以开发者为中心,而服务网格以基础设施为中心。

在大多数情况下,开发者不需要知道他们正在构建的应用程序将被部署在包含服务网格的环境中,因为服务网格会拦截网络流量。服务网格主要由系统运维人员管理和部署,而 Dapr 构建块 API 旨在供开发者在代码中显式使用。

Dapr 与服务网格共享的一些常见能力包括:

  • 使用 mTLS 加密的安全服务间通信
  • 服务间指标收集
  • 服务间分布式追踪
  • 通过重试实现的弹性

重要的是,Dapr 通过名称提供服务发现和调用,这是一个以开发者为中心的关注点。这意味着通过 Dapr 的服务调用 API,开发者调用服务名称上的方法,而服务网格处理 IP 地址和 DNS 地址等网络概念。然而,Dapr 不提供流量行为方面的能力,如路由或流量分割。流量分割通常通过应用程序的入口代理来解决,不必使用服务网格。此外,Dapr 还提供其他应用程序级构建块,用于状态管理、发布订阅消息传递、actors 等。

Dapr 与服务网格之间的另一个区别是可观测性(追踪和指标)。服务网格在网络级别运行,并追踪服务之间的网络调用。Dapr 通过服务调用来实现这一点。此外,Dapr 还通过写入 Cloud Events 信封中的追踪 ID,为发布订阅调用提供可观测性(追踪和指标)。这意味着对于同时使用服务间调用和发布订阅进行通信的应用程序,Dapr 的指标和追踪比服务网格更全面。

下图展示了 Dapr 和服务网格提供的重叠功能和独特能力:

将 Dapr 与服务网格一起使用

Dapr 确实可以与服务网格一起工作。在两者一起部署的情况下,Dapr 和服务网格边车都在应用程序环境中运行。在这种情况下,建议只配置 Dapr 或只配置服务网格来执行 mTLS 加密和分布式追踪。

观看以下 Dapr 社区会议的录像,这些录像展示了将 Dapr 与不同服务网格一起运行的演示:

何时使用 Dapr 或服务网格或两者兼用

您应该使用 Dapr、服务网格,还是两者兼用?答案取决于您的需求。例如,如果您希望将 Dapr 用于一个或多个构建块(如状态管理或发布订阅),并且您正在考虑使用服务网格只是为了网络安全或可观测性,您可能会发现 Dapr 是一个很好的选择,而无需使用服务网格。

通常,在企业策略要求所有应用程序的网络流量必须加密的情况下,您会将服务网格与 Dapr 一起使用。例如,您可能只在应用程序的一部分中使用 Dapr,而应用程序中未使用 Dapr 的其他服务和进程也需要对其流量进行加密。在这种情况下,服务网格是更好的选择,最有可能的是,您应该在服务网格上使用 mTLS 和分布式追踪,并在 Dapr 上禁用这些功能。

如果您需要为 A/B 测试场景进行流量分割,您将从使用服务网格中受益,因为 Dapr 不提供这些能力。

在某些情况下,当您需要两者独有的能力时,您会发现同时利用 Dapr 和服务网格很有用;如上所述,同时使用它们没有任何限制。