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

Return to the regular view of this page.

在您的环境中部署和配置 Dapr

托管选项、最佳实践,以及在 Dapr 上运行您的应用程序的其他指南

1 - 可观测性

查看和测量对组件以及网络化服务之间的消息调用

以下概述视频和演示 展示了 Dapr 中的可观测性如何工作。

1.1 - 链路追踪

了解链路追踪场景以及如何使用链路追踪为应用程序提供可观测性

1.1.1 - 分布式跟踪概述

使用跟踪获取应用程序可见性的概述

Dapr 使用 Open Telemetry (OTEL) 和 Zipkin 协议进行分布式跟踪。OTEL 是行业标准,是推荐的跟踪协议。

大多数可观测性工具都支持 OTEL,包括:

下图演示了 Dapr(使用 OTEL 和 Zipkin 协议)如何与多个可观测性工具集成。

使用 Dapr 的分布式跟踪

场景

跟踪与服务调用和发布订阅 API 一起使用。你可以在使用这些 API 的服务之间流转跟踪上下文。跟踪的使用有两种场景:

  1. Dapr 生成跟踪上下文,你将跟踪上下文传播到另一个服务。
  2. 你生成跟踪上下文,Dapr 将跟踪上下文传播到服务。

场景 1:Dapr 生成跟踪上下文头

传播顺序服务调用

Dapr 负责创建跟踪头。但是,当有两个以上服务时,你需要负责在它们之间传播跟踪头。让我们通过示例来了解这些场景:

单次服务调用调用

例如,service A -> service B

Dapr 在 service A 中生成跟踪头,然后从 service A 传播到 service B。不需要进一步传播。

多次顺序服务调用调用

例如,service A -> service B -> 传播跟踪头到 -> service C,依此类推到其他启用 Dapr 的服务。

Dapr 在请求开始时在 service A 中生成跟踪头,然后传播到 service B。你现在需要负责获取这些头并将它们传播到 service C,因为这是特定于你的应用程序的。

换句话说,如果应用程序调用 Dapr 并希望使用现有跟踪头(span)进行跟踪,它必须始终传播到 Dapr(在本示例中从 service Bservice C)。Dapr 始终将跟踪 span 传播到应用程序。

请求来自外部端点

例如,从网关服务到启用 Dapr 的服务 A

外部网关入口调用 Dapr,Dapr 生成跟踪头并调用 service AService A 然后调用 service B 和其他启用 Dapr 的服务。

你必须将头从 service A 传播到 service B。例如:Ingress -> service A -> 传播跟踪头 -> service B。这类似于情况 2

发布订阅消息

Dapr 在发布的消息主题中生成跟踪头。对于 rawPayload 消息,可以指定 traceparent 头来传播跟踪信息。这些跟踪头被传播到监听该主题的任何服务。

传播多个不同的服务调用

在以下场景中,Dapr 会为你完成部分工作,然后由你创建或传播跟踪头。

从单个服务到不同服务的多次服务调用

当你从单个服务调用多个服务时,需要传播跟踪头。例如:

service A -> service B
[ .. 一些代码逻辑 ..]
service A -> service C
[ .. 一些代码逻辑 ..]
service A -> service D
[ .. 一些代码逻辑 ..]

在这种情况下:

  1. service A 首次调用 service B 时,Dapr 在 service A 中生成跟踪头。
  2. service A 中的跟踪头被传播到 service B
  3. 这些跟踪头在 service B 的响应中作为响应头的一部分返回。
  4. 然后你需要将返回的跟踪上下文传播到下一个服务,比如 service Cservice D,因为 Dapr 不知道你想重用同一个头。

场景 2:你从非 Dapr 应用程序生成自己的跟踪上下文头

生成自己的跟踪上下文头不太常见,并且在调用 Dapr 时通常不需要。

但是,有些场景你可能会选择在服务调用中添加 W3C 跟踪头。例如,你有一个不使用 Dapr 的现有应用程序。在这种情况下,Dapr 仍然会为你传播跟踪上下文头。

如果你决定自己生成跟踪头,可以通过三种方式完成:

  1. 标准 OpenTelemetry SDK

    你可以使用行业标准 OpenTelemetry SDK 生成跟踪头,并将这些跟踪头传递给启用 Dapr 的服务。这是首选方法

  2. 供应商 SDK

    你可以使用提供生成 W3C 跟踪头方法的供应商 SDK,并将它们传递给启用 Dapr 的服务。

  3. W3C 跟踪上下文

    你可以按照 W3C 跟踪上下文规范 手工制作跟踪上下文,并将它们传递给启用 Dapr 的服务。

    阅读跟踪上下文概述以获取有关 W3C 跟踪上下文和头的更多背景信息和示例。

Baggage 支持

Dapr 支持两种不同的机制来传播 W3C Baggage 以及跟踪上下文:

  1. Context Baggage(OpenTelemetry)

    • 遵循 OpenTelemetry 约定,使用解码值
    • 在使用 OpenTelemetry 上下文传播时使用
    • 值以其原始、未编码的形式存储和传输
    • 推荐用于 OpenTelemetry 集成以及在使用应用程序上下文时
  2. Header/Metadata Baggage

    • 在设置头/元数据 baggage 时,必须对特殊字符进行 URL 编码(例如,空格使用 %20,斜杠使用 %2F
    • 值根据 W3C Baggage 规范的要求在传输中保持百分号编码
    • 在检查原始头/元数据时值保持编码
    • 只有 OpenTelemetry API 会解码这些值
    • 示例:在设置头 baggage 时使用 serverNode=DF%2028(而不是 serverNode=DF 28

出于安全目的,上下文 baggage 和头 baggage 严格分离,永远不会在域之间合并。这确保 baggage 值保持其预期的格式和安全属性。

在 Dapr 中使用 Baggage

你可以根据用例使用任一机制传播 baggage。

  1. 在你的应用程序代码中:在进行 Dapr API 调用之前在上下文中设置 baggage
  2. 调用 Dapr 时:将上下文传递给任何 Dapr API 调用
  3. 在 Dapr 内部:Dapr 运行时自动获取 baggage
  4. 传播:Dapr 自动将 baggage 传播到下游服务,为每种机制维护适当的编码

以下是这两种机制的示例:

1. 使用 Context Baggage (OpenTelemetry)

使用 OpenTelemetry SDK 时:

import 	otelbaggage "go.opentelemetry.io/otel/baggage"

// Set baggage in context (values remain unencoded)
baggage, err = otelbaggage.Parse("userId=cassie,serverNode=DF%2028")
...
ctx := otelbaggage.ContextWithBaggage(t.Context(), baggage)
)

// Pass this context to any Dapr API call
client.InvokeMethodWithContent(ctx, "serviceB", ...)

2. 使用 Header/Metadata Baggage

使用 gRPC 元数据时:

import "google.golang.org/grpc/metadata"

// Set URL-encoded baggage in context
ctx = metadata.AppendToOutgoingContext(ctx,
    "baggage", "userId=cassie,serverNode=DF%2028",
)

// Pass this context to any Dapr API call
client.InvokeMethodWithContent(ctx, "serviceB", ...)

3. 在目标服务中接收 Baggage

在目标服务中,你可以访问传播的 baggage:

// Using OpenTelemetry (values are automatically decoded)
import "go.opentelemetry.io/otel/baggage"

bag := baggage.FromContext(ctx)
userID := bag.Member("userId").Value()  // "cassie"
// Using raw gRPC metadata (values remain percent-encoded)
import "google.golang.org/grpc/metadata"

md, _ := metadata.FromIncomingContext(ctx)
if values := md.Get("baggage"); len(values) > 0 {
    // values[0] contains the percent-encoded string you set: "userId=cassie,serverNode=DF%2028"
    // Remember: You must URL encode special characters when setting baggage
    
    // To decode the values, use OpenTelemetry APIs:
    bag, err := baggage.Parse(values[0])
    ...
    userID := bag.Member("userId").Value()  // "cassie"
}

HTTP 示例(URL 编码):

curl -X POST http://localhost:3500/v1.0/invoke/serviceB/method/hello \
  -H "Content-Type: application/json" \
  -H "baggage: userID=cassie,serverNode=DF%2028" \
  -d '{"message": "Hello service B"}'

gRPC 示例(URL 编码):

ctx = grpcMetadata.AppendToOutgoingContext(ctx,
    "baggage", "userID=cassie,serverNode=DF%2028",
)

常见用例

Baggage 适用于:

  • 跨服务传播用户 ID 或关联 ID
  • 传递租户或环境信息
  • 跨服务边界维护一致的上下文
  • 调试和故障排除分布式事务

最佳实践

  1. 选择正确的机制

    • 在使用 OpenTelemetry 时使用 Context Baggage
    • 在直接使用 HTTP/gRPC 时使用 Header Baggage
  2. 安全考虑

    • 注意 baggage 会跨服务边界传播
    • 不要在 baggage 中包含敏感信息
    • 记住上下文 baggage 和头 baggage 保持分离

相关链接

1.1.2 - W3C 追踪上下文概述

在 Dapr 中使用 W3C 追踪上下文和标头的背景与场景

Dapr 使用 Open Telemetry 协议,而该协议又使用 W3C 追踪上下文进行分布式追踪,涵盖服务调用和发布订阅消息。Dapr 生成并传播追踪上下文信息,可将其发送到可观测性工具以进行可视化和查询。

背景

分布式追踪是追踪工具实现的一种方法论,用于跟踪、分析和调试跨越多个软件组件的事务。

通常,分布式追踪会跨越多个服务,因此需要能够唯一标识。追踪上下文传播会传递这一唯一标识。

过去,追踪上下文传播由各个追踪供应商单独实现。在多供应商环境中,这会导致互操作性问题,例如:

  • 不同追踪供应商收集的追踪无法关联,因为没有共享的唯一标识符。
  • 跨越不同追踪供应商边界的追踪无法传播,因为没有转发统一约定的标识符集。
  • 特定于供应商的元数据可能会被中间设备丢弃。
  • 云平台供应商、中间设备和服务提供商无法保证支持追踪上下文传播,因为没有可遵循的标准。

以前,大多数应用程序由单个追踪供应商监控,并保持在单个平台供应商的边界内,因此这些问题没有产生重大影响。

如今,越来越多的应用程序是分布式的,并利用多个中间件服务和云平台。现代应用程序的这一转变需要一个分布式追踪上下文传播标准。

W3C 追踪上下文规范定义了交换追踪上下文传播数据(称为追踪上下文)的通用约定格式。追踪上下文通过提供以下功能解决了上述问题:

  • 为单个追踪和请求提供唯一标识符,允许多个提供商的追踪数据链接在一起。
  • 约定的机制转发特定于供应商的追踪数据,并在多个追踪工具参与单个事务时避免追踪中断。
  • 中间设备、平台和硬件提供商可以支持的行业标准。

这种统一的追踪数据传播方法提高了对分布式应用程序行为的可见性,便于进行问题和性能分析。

W3C 追踪上下文和标头格式

W3C 追踪上下文

Dapr 使用标准的 W3C 追踪上下文标头。

  • 对于 HTTP 请求,Dapr 使用 traceparent 标头。
  • 对于 gRPC 请求,Dapr 使用 grpc-trace-bin 标头。

当请求到达时没有追踪 ID,Dapr 会创建一个新的。否则,它会将追踪 ID 沿调用链传递。

W3C 追踪标头

以下是 Dapr 为 HTTP 和 gRPC 生成和传播的特定追踪上下文标头。

在将追踪上下文标头从 HTTP 响应传播到 HTTP 请求时,复制这些标头:

Traceparent 标头

traceparent 标头以通用格式表示追踪系统中的传入请求,所有供应商都能理解:

traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01

了解有关 traceparent 字段详细信息

Tracestate 标头

tracestate 标头以可能特定于供应商的格式包含父级:

tracestate: congo=t61rcWkgMzE

了解有关 tracestate 字段详细信息

Baggage 支持

Dapr 支持 W3C Baggage,通过两种不同的机制传播键值对以及追踪上下文:

  1. 上下文 Baggage(OpenTelemetry)

    • 遵循 OpenTelemetry 约定,使用解码值
    • 通过应用程序上下文传播 baggage 时使用
    • 值以其原始的、未编码的形式存储
    • 使用 OpenTelemetry API 打印的示例:
      baggage: userId=cassie,serverNode=DF 28,isVIP=true
      
  2. HTTP 标头 Baggage

    • 设置标头 baggage 时必须对特殊字符进行 URL 编码(例如,空格用 %20,斜杠用 %2F
    • 值根据 W3C Baggage 规范的要求,在 HTTP 标头中保持百分比编码
    • 在 Dapr 中检查原始标头时,值保持编码状态
    • 只有像 otelbaggage.Parse() 这样的 OpenTelemetry API 会解码值
    • 示例(注意 URL 编码的空格 %20):
      curl -X POST http://localhost:3500/v1.0/invoke/serviceB/method/hello \
        -H "Content-Type: application/json" \
        -H "baggage: userId=cassie,serverNode=DF%2028,isVIP=true" \
        -d '{"message": "Hello service B"}'
      

出于安全目的,上下文 baggage 和标头 baggage 严格分离,永不跨域合并。这确保 baggage 值在每个域中保持其预期的格式和安全属性。

支持多个 baggage 标头,将根据 W3C 规范进行组合。Dapr 在服务调用之间自动传播 baggage,同时为每个域维护适当的编码。

在 gRPC API 调用中,追踪上下文通过 grpc-trace-bin 标头传递。

Baggage 支持

Dapr 支持 W3C Baggage,通过两种不同的机制传播键值对以及追踪上下文:

  1. 上下文 Baggage(OpenTelemetry)

    • 遵循 OpenTelemetry 约定,使用解码值
    • 通过 gRPC 上下文传播 baggage 时使用
    • 值以其原始的、未编码的形式存储
    • 使用 OpenTelemetry API 打印的示例:
      baggage: userId=cassie,serverNode=DF 28,isVIP=true
      
  2. gRPC 元数据 Baggage

    • 设置元数据 baggage 时必须对特殊字符进行 URL 编码(例如,空格用 %20,斜杠用 %2F
    • 值在 gRPC 元数据中保持百分比编码
    • 示例(注意 URL 编码的空格 %20):
      baggage: userId=cassie,serverNode=DF%2028,isVIP=true
      

出于安全目的,上下文 baggage 和元数据 baggage 严格分离,永不跨域合并。这确保 baggage 值在每个域中保持其预期的格式和安全属性。

支持多个 baggage 元数据条目,将根据 W3C 规范进行组合。Dapr 在服务调用之间自动传播 baggage,同时为每个域维护适当的编码。

相关链接

1.1.3 - 配置 Dapr 发送分布式追踪数据

设置 Dapr 发送分布式追踪数据

配置

Configuration 规范下的 tracing 部分包含以下属性:

spec:
  tracing:
    samplingRate: "1"
    otel: 
      endpointAddress: "myendpoint.cluster.local:4317"
      headers:
        - name: "x-api-key"
          secretKeyRef:
            name: "my-secret-store"
            key: "otel-api-key"
      timeout: "30s"
    zipkin:
      endpointAddress: "https://..."
    

下表列出了追踪的属性:

属性类型描述
samplingRatestring设置追踪的采样率以启用或禁用。
stdoutboolTrue 向追踪写入更详细的信息
otel.endpointAddressstring设置 Open Telemetry (OTEL) 目标主机名和可选端口。如果使用此选项,则不需要指定 ‘zipkin’ 部分。
otel.isSecurebool到端点地址的连接是否加密。
otel.protocolstring设置为 httpgrpc 协议。
otel.headersarray要包含在 OTLP 导出器请求中的标头。每个条目都有一个 name 和明文 valuesecretKeyRef(用于引用 Kubernetes secret)。
otel.timeoutstringOTLP 导出器请求的超时时间(例如 30s5m)。
zipkin.endpointAddressstring设置 Zipkin 服务器 URL。如果使用此选项,则不需要指定 otel 部分。

要启用追踪,请使用配置文件(在自托管模式下)或 Kubernetes 配置对象(在 Kubernetes 模式下)。例如,以下配置对象将采样率更改为 1(每个 span 都被采样),并使用 OTEL 协议将追踪发送到位于 localhost:4317 的 OTEL 服务器

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: tracing
spec:
  tracing:
    samplingRate: "1"
    otel:
      endpointAddress: "localhost:4317"
      isSecure: false
      protocol: grpc
      headers:
        - name: "x-api-key"
          value: "my-api-key"
        - name: "x-secret-header"
          secretKeyRef:
            name: "my-secret"
            key: "header-value"
      timeout: "30s"

采样率

Dapr 使用概率采样。采样率定义了追踪 span 被采样的概率,其值可以在 0 到 1 之间(含)。默认采样率为 0.0001(即每 10,000 个 span 中采样 1 个)。

samplingRate 更改为 0 会完全禁用追踪。

环境变量

OpenTelemetry (otel) 端点也可以通过环境变量进行配置。存在 OTEL_EXPORTER_OTLP_ENDPOINT 环境变量时 会为边车启用追踪。

环境变量描述
OTEL_EXPORTER_OTLP_ENDPOINT设置 Open Telemetry (OTEL) 服务器主机名和可选端口,启用追踪
OTEL_EXPORTER_OTLP_INSECURE将到端点的连接设置为未加密(true/false)
OTEL_EXPORTER_OTLP_PROTOCOL传输协议(grpchttp/protobufhttp/json
OTEL_EXPORTER_OTLP_TRACES_HEADERSOTLP 追踪导出器的逗号分隔的 key=value 标头列表
OTEL_EXPORTER_OTLP_TRACES_TIMEOUTOTLP 追踪导出器的超时时间(以毫秒为单位,例如 30000

下一步

了解如何使用以下工具之一设置追踪:

1.1.4 - OpenTelemetry Collector

如何设置可观测性工具以接收应用程序跟踪

1.1.4.1 - 使用 OpenTelemetry Collector 收集追踪数据

如何使用 Dapr 通过 OpenTelemetry Collector 推送追踪事件。

Dapr 使用 OpenTelemetry (OTLP) 协议直接写入追踪数据,这是推荐的方法。对于直接支持 OTLP 的可观测性工具,建议使用 OpenTelemetry Collector,因为它允许应用程序快速卸载数据,并包含重试、批处理和加密等功能。更多信息,请阅读 OpenTelemetry Collector 文档

Dapr 也可以使用 Zipkin 协议写入追踪数据。在支持 OTLP 协议之前,Zipkin 协议与 OpenTelemetry Collector 一起使用,将追踪数据发送到 AWS X-Ray、Google Cloud Operations Suite 和 Azure Monitor 等可观测性工具。两种协议方法都是有效的,但 OpenTelemetry 协议是推荐的选择。

使用 OpenTelemetry Collector 与多个后端集成

前提条件

设置 OTEL Collector 以推送到您的追踪后端

  1. 查看 open-telemetry-collector-generic.yaml

  2. <your-exporter-here> 部分替换为您的追踪 exporter 的正确设置。

  3. 使用以下命令应用配置:

    kubectl apply -f open-telemetry-collector-generic.yaml
    

设置 Dapr 以将追踪数据发送到 OTEL Collector

设置一个 Dapr 配置文件来启用追踪,并部署一个使用 OpenTelemetry Collector 的追踪 exporter 组件。

  1. 使用此 collector-config.yaml 文件创建您自己的配置。

  2. 使用以下命令应用配置:

    kubectl apply -f collector-config.yaml
    

使用追踪功能部署您的应用

通过在要参与分布式追踪的容器上添加 dapr.io/config 注解来应用 appconfig 配置,如下例所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  ...
spec:
  ...
  template:
    metadata:
      ...
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "MyApp"
        dapr.io/app-port: "8080"
        dapr.io/config: "appconfig"

您可以同时注册多个追踪 exporter,追踪日志会转发到所有已注册的 exporter。

就这样!无需包含任何 SDK 或检测您的应用程序代码。Dapr 会自动为您处理分布式追踪。

查看追踪数据

部署并运行一些应用程序。等待追踪数据传播到您的追踪后端,然后在那里查看它们。

相关链接

1.1.4.2 - 使用 OpenTelemetry Collector 收集追踪数据并发送到 Application Insights

如何使用 OpenTelemetry Collector 将追踪事件推送到 Azure Application Insights。

Dapr 使用 OpenTelemetry 协议 (OTLP) 与 OpenTelemetry (OTEL) Collector 集成。本指南通过一个示例演示如何使用 Dapr 通过 OpenTelemetry Collector 将追踪数据推送到 Azure Application Insights。

前置条件

设置 OTEL Collector 将数据推送到你的 Application Insights 实例

要将追踪数据推送到你的 Application Insights 实例,请在 Kubernetes 集群上安装 OpenTelemetry Collector。

  1. 下载并查看 open-telemetry-collector-appinsights.yaml 文件。

  2. <CONNECTION_STRING> 占位符替换为你的 Application Insights 连接字符串。

  3. 将 OpenTelemetry Collector 部署到运行 Dapr 应用的同一命名空间:

    kubectl apply -f open-telemetry-collector-appinsights.yaml
    

设置 Dapr 将追踪数据发送到 OpenTelemetry Collector

创建 Dapr 配置文件以启用追踪,并通过 OTLP 将追踪数据发送到 OpenTelemetry Collector。

  1. 下载并查看 collector-config-otel.yaml。更新 namespaceotel.endpointAddress 值,使其与部署 Dapr 应用和 OpenTelemetry Collector 的命名空间一致。

  2. 使用以下命令应用配置:

    kubectl apply -f collector-config-otel.yaml
    

部署启用追踪的应用

通过向要包含在分布式追踪中的 Dapr 应用添加 dapr.io/config 注解来应用 tracing 配置,如下例所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  ...
spec:
  ...
  template:
    metadata:
      ...
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "MyApp"
        dapr.io/app-port: "8080"
        dapr.io/config: "tracing"

你可以同时注册多个追踪导出器,追踪日志将转发到所有已注册的导出器。

就是这样!无需包含任何 SDK 或对应用程序代码进行插桩。Dapr 会自动为你处理分布式追踪。

查看追踪数据

部署并运行一些应用程序。几分钟后,你应该会看到追踪日志出现在你的 Application Insights 资源中。你还可以使用 Application Map 来检查服务的拓扑,如下所示:

Application map

相关链接

1.1.4.3 - 使用 Dynatrace OpenTelemetry Collector 收集追踪信息并发送到 Dynatrace

如何使用 Dynatrace OpenTelemetry Collector 将追踪事件推送到 Dynatrace。

Dapr 使用 OpenTelemetry 协议(OTLP)与 Dynatrace Collector 集成。本指南将通过一个示例演示如何使用 Dapr 通过 Dynatrace 版本的 OpenTelemetry Collector 向 Dynatrace 推送追踪信息。

前置条件

  • 在 Kubernetes 上安装 Dapr
  • 访问 Dynatrace 租户以及具有 openTelemetryTrace.ingestmetrics.ingestlogs.ingest 作用域的 API 令牌
  • Helm

设置 Dynatrace OpenTelemetry Collector 以推送到您的 Dynatrace 实例

要将追踪信息推送到您的 Dynatrace 实例,请在您的 Kubernetes 集群上安装 Dynatrace OpenTelemetry Collector。

  1. 使用您的 Dynatrace 凭证创建 Kubernetes secret:

    kubectl create secret generic dynatrace-otelcol-dt-api-credentials \
      --from-literal=DT_ENDPOINT=https://YOUR_TENANT.live.dynatrace.com/api/v2/otlp \
      --from-literal=DT_API_TOKEN=dt0s01.YOUR_TOKEN_HERE
    

    YOUR_TENANT 替换为您的 Dynatrace 租户 ID,将 YOUR_TOKEN_HERE 替换为您的 Dynatrace API 令牌。

  2. 使用 Dynatrace OpenTelemetry Collector 发行版以获得比开源版本更好的默认值和支持。下载并检查 collector-helm-values.yaml 文件。这基于 k8s enrichment demo,并包含 Kubernetes 元数据增强以获得适当的 pod/namespace/cluster 上下文。

  3. 使用 Helm 部署 Dynatrace Collector。

    helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
    helm repo update
    helm upgrade -i dynatrace-collector open-telemetry/opentelemetry-collector -f collector-helm-values.yaml
    

设置 Dapr 以将追踪信息发送到 Dynatrace Collector

创建 Dapr 配置文件以启用追踪,并通过 OTLP 将追踪信息发送到 OpenTelemetry Collector。

  1. 更新以下文件以确保 endpointAddress 指向 Kubernetes 集群中的 Dynatrace OpenTelemetry Collector 服务。如果在 default 命名空间中部署,通常是 dynatrace-collector.default.svc.cluster.local

    重要提示: 确保 endpointAddress 不包含 http:// 前缀,以避免 URL 编码问题:

     apiVersion: dapr.io/v1alpha1
     kind: Configuration
     metadata:
       name: tracing
     spec:
       tracing:
         samplingRate: "1"
         otel:
           endpointAddress: "dynatrace-collector.default.svc.cluster.local:4318" # 使用您的 collector 服务地址更新
    
  2. 应用配置:

    kubectl apply -f collector-config-otel.yaml
    

使用追踪部署应用

通过向要包含在分布式追踪中的 Dapr 应用添加 dapr.io/config 注解来应用 tracing 配置,如以下示例所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  ...
spec:
  ...
  template:
    metadata:
      ...
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "MyApp"
        dapr.io/app-port: "8080"
        dapr.io/config: "tracing"

您可以同时注册多个追踪导出器,追踪日志将转发到所有已注册的导出器。

就是这样!无需包含任何 SDK 或对应用代码进行检测。Dapr 会自动为您处理分布式追踪。

查看追踪

部署并运行一些应用。几分钟后,您应该会看到追踪信息出现在您的 Dynatrace 租户中:

  1. 在 Dynatrace UI 中导航到 Search > Distributed tracing
  2. 按服务名称筛选以查看您的 Dapr 应用及其关联的追踪 span。
Dynatrace 显示追踪数据。

相关链接

1.1.4.4 - 使用 OpenTelemetry 向 Jaeger V2 发送 traces

如何使用 OpenTelemetry 协议将 trace 事件推送到 Jaeger V2 分布式追踪平台。

Dapr 支持使用 OpenTelemetry (OTLP) 协议写入 traces,而 Jaeger V2 原生支持 OTLP,允许 Dapr 直接向 Jaeger V2 实例发送 traces。这种方法推荐用于生产环境,以利用 Jaeger V2 的分布式追踪能力。

在自托管模式下配置 Jaeger V2

本地设置

启动 Jaeger 最简单的方式是运行发布到 DockerHub 的预构建 all-in-one Jaeger 镜像并暴露 OTLP 端口:

注意: 端口 9411 通常由 Zipkin 使用。如果你正在运行 Zipkin(运行 dapr init 时默认启动),请先停止 dapr_zipkin 容器以避免端口冲突:docker stop dapr_zipkin

docker run -d --rm --name jaeger \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  -p 5778:5778 \
  -p 9411:9411 \
  cr.jaegertracing.io/jaegertracing/jaeger:2.11.0

你也可以使用以下命令查看 jaeger 容器的日志:

docker logs jaeger

配置 Dapr 追踪

你有两个选项来配置 Dapr 向 Jaeger V2 发送 traces:

选项 1:使用自定义配置文件

创建一个包含以下内容的 config.yaml 文件:

注意: 由于你使用 OpenTelemetry 协议与 Jaeger 通信,你需要填写追踪配置的 otel 部分,并将 endpointAddress 设置为 Jaeger 容器的地址。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: tracing
  namespace: default
spec:
  tracing:
    samplingRate: "1"
    stdout: true
    otel:
      endpointAddress: "localhost:4317"
      isSecure: false
      protocol: grpc 

要启动引用新 YAML 配置文件的应用程序,请使用 --config 选项。例如:

dapr run --app-id myapp --app-port 3000 node app.js --config config.yaml

选项 2:更新默认 Dapr 配置(开发环境)

或者,在你的开发环境中,导航到你的本地 Dapr 组件目录并使用上述 OTLP 配置更新默认的 config.yaml 文件。这样,所有 Dapr 应用程序将默认使用 Jaeger V2 追踪配置,无需每次指定 --config 标志。

查看 traces

要在浏览器中查看 traces,请访问 http://localhost:16686 以查看 Jaeger UI。

在 Kubernetes 上配置 Jaeger V2

以下步骤展示了如何配置 Dapr 将分布式追踪数据直接发送到使用 OpenTelemetry Operator 部署的 Jaeger V2 实例,该实例使用内存存储。

前提条件

使用 OpenTelemetry Operator 设置 Jaeger V2

Jaeger V2 可以使用 OpenTelemetry Operator 部署,以简化管理并获得原生 OTLP 支持。以下示例配置了使用内存存储的 Jaeger V2。

存储后端说明: 此示例使用内存存储(memstore)以简化操作,适用于开发或测试环境,因为它在内存中最多存储 100,000 条 traces。对于生产环境,请考虑配置持久化存储后端(如 Cassandra 或 Elasticsearch)以确保 trace 数据的持久性。

安装

注意: 为了使 API 服务器与 Operator 的 webhook 组件通信,webhook 需要 API 服务器配置为信任的 TLS 证书。你可以使用几种不同的方式来生成/配置所需的 TLS 证书,详细信息见 otel operator chart 文档

为简化操作,你可以使用 Helm 创建自动生成的自签名证书。

  1. 安装 OpenTelemetry Operator

    helm install opentelemetry-operator open-telemetry/opentelemetry-operator -n opentelemetry-operator-system --create-namespace \
     --set "manager.collectorImage.repository=ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-k8s" \
     --set admissionWebhooks.certManager.enabled=false \
     --set admissionWebhooks.autoGenerateCert.enabled=true
    

    确认 opentelemetry-operator-system 命名空间中的所有资源已就绪。

  2. 部署使用内存存储的 Jaeger V2 实例: 创建一个名为 jaeger-inmemory.yaml 的文件,包含以下配置:

    apiVersion: opentelemetry.io/v1beta1
    kind: OpenTelemetryCollector
    metadata:
      name: jaeger-inmemory-instance
      namespace: observability
    spec:
      image: jaegertracing/jaeger:latest
      ports:
      - name: jaeger
        port: 16686
      config:
        service:
          extensions: [jaeger_storage, jaeger_query]
          pipelines:
            traces:
              receivers: [otlp]
              exporters: [jaeger_storage_exporter]
        extensions:
          jaeger_query:
            storage:
              traces: memstore
          jaeger_storage:
            backends:
              memstore:
                memory:
                  max_traces: 100000
        receivers:
          otlp:
            protocols:
              grpc:
                endpoint: 0.0.0.0:4317
              http:
                endpoint: 0.0.0.0:4318
        exporters:
          jaeger_storage_exporter:
            trace_storage: memstore
    

    使用以下命令应用它:

    kubectl apply -f jaeger-inmemory.yaml -n observability
    

设置 Dapr 向 Jaeger V2 发送 traces

创建一个 Dapr 配置文件以启用追踪,并将边车 traces 直接导出到 Jaeger V2 实例。

  1. 创建一个配置文件(例如 tracing.yaml),包含以下内容,更新 namespaceotel.endpointAddress 以匹配你的 Jaeger V2 实例:

    apiVersion: dapr.io/v1alpha1
    kind: Configuration
    metadata:
      name: tracing
      namespace: order-system
    spec:
      tracing:
        samplingRate: "1"
        otel:
          endpointAddress: "jaeger-inmemory-instance-collector.observability.svc.cluster.local:4317"
          isSecure: false
          protocol: grpc
    
  2. 应用配置:

    kubectl apply -f tracing.yaml -n order-system
    

启用追踪部署应用

通过在要启用分布式追踪的应用程序部署中添加 dapr.io/config 注解来应用 tracing Dapr 配置,如以下示例所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  ...
spec:
  ...
  template:
    metadata:
      ...
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "MyApp"
        dapr.io/app-port: "8080"
        dapr.io/config: "tracing"

你可以同时注册多个追踪导出器,追踪日志将转发到所有已注册的导出器。

就是这样!无需包含 OpenTelemetry SDK 或检测应用程序代码。Dapr 会自动为你处理分布式追踪。

查看 traces

要查看 Dapr 边车 traces,请转发 Jaeger V2 服务的端口并打开 UI:

kubectl port-forward svc/jaeger-inmemory-instance-collector 16686:16686 -n observability

在浏览器中,访问 http://localhost:16686 以查看 Jaeger V2 UI。

jaeger

参考

1.1.5 - 操作指南:设置 New Relic 进行分布式追踪

设置 New Relic 进行分布式追踪

前置条件

  • 永久免费的 New Relic 账户,每月 100 GB 免费数据接入,1 个免费全权限用户,无限免费基础用户

配置 Dapr 追踪

Dapr 原生捕获可以直接发送到 New Relic 的指标和链路。最简单的导出方式是将 Dapr 配置为使用 Zipkin 追踪格式将链路发送到 New Relic 的 Trace API

为了让集成将数据发送到 New Relic 遥测数据平台,你需要一个 New Relic Insights Insert API 密钥

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
  namespace: default
spec:
  tracing:
    samplingRate: "1"
    zipkin:
      endpointAddress: "https://trace-api.newrelic.com/trace/v1?Api-Key=<NR-INSIGHTS-INSERT-API-KEY>&Data-Format=zipkin&Data-Format-Version=2"

查看追踪

New Relic 分布式追踪概览 New Relic Kubernetes Cluster Explorer App

New Relic 分布式追踪详情 New Relic Kubernetes Cluster Explorer App

(可选)New Relic Instrumentation

为了让集成将数据发送到 New Relic 遥测数据平台,你需要一个 New Relic 许可证密钥New Relic Insights Insert API 密钥

OpenTelemetry instrumentation

利用不同语言的特定 OpenTelemetry 实现,例如 New Relic Telemetry SDK 和 OpenTelemetry 对 .NET 的支持。在这种情况下,使用 OpenTelemetry Trace Exporter。参见示例

New Relic 语言代理

与 OpenTelemetry instrumentation 类似,你也可以利用 New Relic 语言代理。例如,New Relic 代理对 .NET Core 的 instrumentation是 Dockerfile 的一部分。参见示例

(可选)启用 New Relic Kubernetes 集成

如果 Dapr 和你的应用程序在 Kubernetes 环境中运行,你可以启用额外的指标和日志。

安装 New Relic Kubernetes 集成的最简单方法是使用自动化安装程序生成清单。它不仅打包了集成 DaemonSets,还包含其他 New Relic Kubernetes 配置,如 Kubernetes 事件Prometheus OpenMetricsNew Relic 日志监控

New Relic Kubernetes Cluster Explorer

New Relic Kubernetes Cluster Explorer为 Kubernetes 集成收集的整个数据和部署提供了独特的可视化。

这是观察所有数据并深入了解应用程序或微服务内部发生的任何性能问题或事件的良好起点。

New Relic Kubernetes Cluster Explorer App

自动化关联是 New Relic 可视化功能的一部分。

Pod 级别详情

New Relic K8s Pod Level Details

Logs in Context

New Relic K8s Logs In Context

New Relic 仪表板

Kubernetes 概览

New Relic Dashboard Kubernetes Overview

Dapr 系统服务

New Relic Dashboard Dapr System Services

Dapr 指标

New Relic Dashboard Dapr Metrics 1

New Relic Grafana 集成

New Relic 与 Grafana Labs合作,你可以将遥测数据平台用作 Prometheus 指标的数据源,并在现有仪表板中查看它们,无缝利用 New Relic 提供的可靠性、规模和安全性。

用于监控 Dapr 系统服务和边车的 Grafana 仪表板模板无需任何更改即可轻松使用。New Relic 提供了用于 Grafana 的 Prometheus 指标原生端点。可以轻松设置数据源:

New Relic Grafana Data Source

并且可以从 Dapr 导入完全相同的仪表板模板来可视化 Dapr 系统服务和边车。

New Relic Grafana Dashboard

New Relic 告警

从 Dapr、Kubernetes 或其上运行的任何服务收集的所有数据都可以用于在您选择的首选渠道中设置告警和通知。参见告警和 Applied Intelligence

相关链接/参考

1.1.6 - 操作指南:设置 Zipkin 进行分布式追踪

设置 Zipkin 进行分布式追踪

配置自托管模式

对于自托管模式,在运行 dapr init 时:

  1. 默认情况下,会在 $HOME/.dapr/config.yaml(Linux/Mac 上)或 %USERPROFILE%\.dapr\config.yaml(Windows 上)创建以下 YAML 文件,并且在 dapr run 调用时会默认引用该文件,除非被覆盖:
  • config.yaml
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: daprConfig
  namespace: default
spec:
  tracing:
    samplingRate: "1"
    zipkin:
      endpointAddress: "http://localhost:9411/api/v2/spans"
  1. 在运行 dapr init 时,会启动 openzipkin/zipkin docker 容器,或者可以使用以下代码启动它。

使用 Docker 启动 Zipkin:

docker run -d -p 9411:9411 openzipkin/zipkin
  1. 使用 dapr run 启动的应用程序默认引用 $HOME/.dapr/config.yaml%USERPROFILE%\.dapr\config.yaml 中的配置文件,并可以通过使用 --config 参数的 Dapr CLI 覆盖它:
dapr run --app-id mynode --app-port 3000 node app.js

查看追踪

要查看追踪,请在浏览器中打开 http://localhost:9411,您将看到 Zipkin UI。

配置 Kubernetes

以下步骤向您展示如何配置 Dapr 将分布式追踪数据发送到在 Kubernetes 集群中作为容器运行的 Zipkin,以及如何查看它们。

设置

首先,部署 Zipkin:

kubectl create deployment zipkin --image openzipkin/zipkin

为 Zipkin pod 创建 Kubernetes 服务:

kubectl expose deployment zipkin --type ClusterIP --port 9411

接下来,在本地创建以下 YAML 文件:

  • tracing.yaml 配置
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: tracing
  namespace: default
spec:
  tracing:
    samplingRate: "1"
    zipkin:
      endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"

现在,部署 Dapr 配置文件:

kubectl apply -f tracing.yaml

为了为您的 Dapr 边车启用此配置,请将以下注解添加到您的 pod 规范模板中:

annotations:
  dapr.io/config: "tracing"

就是这样!您的边车现在已配置为向 Zipkin 发送追踪数据。

查看追踪数据

要查看追踪数据,请连接到 Zipkin 服务并打开 UI:

kubectl port-forward svc/zipkin 9411:9411

在浏览器中,打开 http://localhost:9411,您将看到 Zipkin UI。

zipkin

参考

1.1.7 - 操作指南:设置 Dash0 进行分布式追踪

设置 Dash0 进行分布式追踪

Dapr 可捕获指标、链路追踪和日志,并可以通过 OpenTelemetry Collector 直接发送到 Dash0。Dash0 是一个原生 OpenTelemetry 可观测性平台,为分布式应用程序提供全面的监控能力。

配置 Dapr 追踪:使用 OpenTelemetry Collector 和 Dash0

通过使用带有 OTLP 导出器的 OpenTelemetry Collector 向 Dash0 发送数据,你可以配置 Dapr 为 Kubernetes 集群中的每个应用程序创建链路追踪,并在 Dash0 中收集它们进行分析和监控。

前置条件

  • 运行中的 Kubernetes 集群,已安装 kubectl
  • Helm v3+
  • 集群中已安装 Dapr
  • Dash0 账户(开始 14 天免费试用
  • 你的 Dash0 Auth TokenOTLP/gRPC endpoint(可在 Settings → Auth TokensSettings → Endpoints 下找到)

配置 OpenTelemetry Collector

  1. 为 Collector 创建命名空间
kubectl create namespace opentelemetry
  1. 使用你的 Dash0 Auth TokenEndpoint 创建 Secret
kubectl create secret generic dash0-secrets \
  --from-literal=dash0-authorization-token="<your_auth_token>" \
  --from-literal=dash0-endpoint="<your_otlp_grpc_endpoint>" \
  --namespace opentelemetry
  1. 添加 OpenTelemetry Helm 仓库(仅需执行一次)
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update
  1. 为 Collector 创建 values.yaml

此配置:

  • 通过环境变量从 Secret 中读取 token + endpoint
  • 启用 OTLP 接收器(gRPC + HTTP)
  • 通过 OTLP/gRPC 使用 Bearer 认证将 链路追踪、指标和日志 发送到 Dash0
mode: deployment
fullnameOverride: otel-collector
replicaCount: 1

image:
  repository: otel/opentelemetry-collector-k8s

extraEnvs:
  - name: DASH0_AUTHORIZATION_TOKEN
    valueFrom:
      secretKeyRef:
        name: dash0-secrets
        key: dash0-authorization-token
  - name: DASH0_ENDPOINT
    valueFrom:
      secretKeyRef:
        name: dash0-secrets
        key: dash0-endpoint

config:
  receivers:
    otlp:
      protocols:
        grpc: {}
        http: {}

  processors:
    batch: {}

  exporters:
    otlp/dash0:
      auth:
        authenticator: bearertokenauth/dash0
      endpoint: ${env:DASH0_ENDPOINT}

  extensions:
    bearertokenauth/dash0:
      scheme: Bearer
      token: ${env:DASH0_AUTHORIZATION_TOKEN}
    health_check: {}

  service:
    extensions:
      - bearertokenauth/dash0
      - health_check
    pipelines:
      traces:
        receivers: [otlp]
        processors: [batch]
        exporters: [otlp/dash0]
      metrics:
        receivers: [otlp]
        processors: [batch]
        exporters: [otlp/dash0]
      logs:
        receivers: [otlp]
        processors: [batch]
        exporters: [otlp/dash0]
  1. 使用 Helm 安装/升级 Collector
helm upgrade --install otel-collector open-telemetry/opentelemetry-collector \
  --namespace opentelemetry \
  -f values.yaml

配置 Dapr 向 Collector 发送遥测数据

  1. 创建配置

创建 dapr-config.yaml

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: tracing
  namespace: default
spec:
  tracing:
    samplingRate: "1"  
    otel:
      endpointAddress: "otel-collector.opentelemetry.svc.cluster.local:4317"
      isSecure: false
      protocol: grpc

应用配置:

kubectl apply -f dapr-config.yaml
  1. 为你的应用程序添加注解

在每个需要 Dapr 追踪的 Deployment/Pod 中添加:

metadata:
  annotations:
    dapr.io/config: "tracing"

验证设置

  1. 检查 OpenTelemetry Collector 是否正在运行:
kubectl get pods -n opentelemetry
  1. 检查 collector 日志以确保它正在接收和转发遥测数据:
kubectl logs -n opentelemetry deployment/otel-collector
  1. 部署一个启用了 Dapr 追踪的示例应用程序并生成一些流量,以验证链路追踪是否正在发送到 Dash0。你可以使用 Dapr Kubernetes 快速入门教程 进行测试。

查看链路追踪

完成设置且遥测数据开始流动后,你可以在 Dash0 中查看链路追踪:

  1. 导航到你的 Dash0 账户
  2. 进入 Traces 部分
  3. 你应该能看到来自 Dapr 应用程序的分布式链路追踪
  4. 使用过滤器按服务名称、操作或时间范围筛选链路追踪
Dash0 Trace Overview Dash0 Trace Details

清理

helm -n opentelemetry uninstall otel-collector
kubectl -n opentelemetry delete secret dash0-secrets
kubectl delete ns opentelemetry

相关链接

1.1.8 - 操作指南:为分布式追踪设置 Datadog

为分布式追踪设置 Datadog

Dapr 可以捕获指标和链路追踪数据,并通过 OpenTelemetry Collector 的 Datadog 导出器直接发送到 Datadog。

使用 OpenTelemetry Collector 和 Datadog 配置 Dapr 追踪

使用 OpenTelemetry Collector 的 Datadog 导出器,你可以配置 Dapr 为 Kubernetes 集群中的每个应用创建链路追踪,并在 Datadog 中收集它们。

在开始之前,先设置 OpenTelemetry Collector

  1. 将你的 Datadog API 密钥添加到 ./deploy/opentelemetry-collector-generic-datadog.yaml 文件的 datadog 导出器配置部分中:

    data:
      otel-collector-config:
        ...
        exporters:
          ...
          datadog:
            api:
              key: <YOUR_API_KEY>
    
  2. 通过运行以下命令来应用 opentelemetry-collector 配置。

    kubectl apply -f ./deploy/open-telemetry-collector-generic-datadog.yaml
    
  3. 创建一个 Dapr 配置文件,用于启用追踪并部署一个使用 OpenTelemetry Collector 的追踪导出器组件。

    kubectl apply -f ./deploy/collector-config.yaml
    
  4. 通过向希望参与分布式追踪的容器添加 dapr.io/config 注解来应用 appconfig 配置。

    annotations:
       dapr.io/config: "appconfig"
    
  5. 创建并配置应用程序。一旦运行,遥测数据将发送到 Datadog,并可在 Datadog APM 中查看。

Datadog APM showing telemetry data.

相关链接/参考

1.2 - 指标

如何查看 Dapr 指标

1.2.1 - 操作指南:使用 Prometheus 观察指标

使用 Prometheus 收集与 Dapr 运行时本身执行相关的时序数据

在本地设置 Prometheus

要在本地计算机上运行 Prometheus,您可以安装并作为进程运行,也可以将其作为 Docker 容器运行。

安装

要安装 Prometheus,请按照此处针对您的操作系统概述的步骤操作。

配置

现在您已经安装了 Prometheus,需要创建一个配置。

下面是一个 Prometheus 配置示例,将其保存到文件中,例如 /tmp/prometheus.ymlC:\Temp\prometheus.yml

global:
  scrape_interval:     15s # 默认情况下,每 15 秒抓取一次目标。

# 一个恰好包含一个要抓取的端点的抓取配置:
# 这里是 Prometheus 本身。
scrape_configs:
  - job_name: 'dapr'

    # 覆盖全局默认值,并每 5 秒从此作业抓取目标。
    scrape_interval: 5s

    static_configs:
      - targets: ['localhost:9090'] # 如果不是默认值,请替换为 Dapr 指标端口

作为进程运行

使用您的配置运行 Prometheus,以开始从指定目标收集指标。

./prometheus --config.file=/tmp/prometheus.yml --web.listen-address=:8080

我们更改了端口,使其不会与 Dapr 自己的指标端点冲突。

如果您当前没有运行 Dapr 应用程序,目标将显示为离线。为了开始收集指标,您必须使用与配置中提供的目标匹配的指标端口启动 Dapr。

Prometheus 运行后,您可以通过访问 http://localhost:8080 来访问其仪表板。

作为容器运行

要在本地计算机上将 Prometheus 作为 Docker 容器运行,首先确保已安装并运行 Docker

然后您可以使用以下命令将 Prometheus 作为 Docker 容器运行:

docker run \
    --net=host \
    -v /tmp/prometheus.yml:/etc/prometheus/prometheus.yml \
    prom/prometheus --config.file=/etc/prometheus/prometheus.yml --web.listen-address=:8080

--net=host 确保 Prometheus 实例能够连接到在主机上运行的任何 Dapr 实例。如果您还计划在容器中运行 Dapr 应用,则需要在共享的 Docker 网络上运行它们,并使用正确的目标地址更新配置。

Prometheus 运行后,您可以通过访问 http://localhost:8080 来访问其仪表板。

在 Kubernetes 上设置 Prometheus

前提条件

安装 Prometheus

  1. 首先创建可用于部署 Grafana 和 Prometheus 监控工具的命名空间
kubectl create namespace dapr-monitoring
  1. 安装 Prometheus
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install dapr-prom prometheus-community/prometheus -n dapr-monitoring

如果您是 Minikube 用户或出于开发目的想要禁用持久卷,可以使用以下命令禁用它。

helm install dapr-prom prometheus-community/prometheus -n dapr-monitoring
 --set alertmanager.persistence.enabled=false --set pushgateway.persistentVolume.enabled=false --set server.persistentVolume.enabled=false

要自动发现 Dapr 目标(服务发现),请使用:

  helm install dapr-prom prometheus-community/prometheus -f values.yaml -n dapr-monitoring --create-namespace

values.yaml 文件

alertmanager:
  persistence:
    enabled: false
pushgateway:
  persistentVolume:
    enabled: false
server:
  persistentVolume:
    enabled: false

# 向 prometheus.yml 添加额外的抓取配置
# 使用服务发现来查找 Dapr 和 Dapr sidecar 目标
extraScrapeConfigs: |-
  - job_name: dapr-sidecars
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - action: keep
        regex: "true"
        source_labels:
          - __meta_kubernetes_pod_annotation_dapr_io_enabled
      - action: keep
        regex: "true"
        source_labels:
          - __meta_kubernetes_pod_annotation_dapr_io_enable_metrics
      - action: replace
        replacement: ${1}
        source_labels:
          - __meta_kubernetes_namespace
        target_label: namespace
      - action: replace
        replacement: ${1}
        source_labels:
          - __meta_kubernetes_pod_name
        target_label: pod
      - action: replace
        regex: (.*);daprd
        replacement: ${1}-dapr
        source_labels:
          - __meta_kubernetes_pod_annotation_dapr_io_app_id
          - __meta_kubernetes_pod_container_name
        target_label: service
      - action: replace
        replacement: ${1}:9090
        source_labels:
          - __meta_kubernetes_pod_ip
        target_label: __address__

  - job_name: dapr
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - action: keep
        regex: dapr
        source_labels:
          - __meta_kubernetes_pod_label_app_kubernetes_io_name
      - action: keep
        regex: dapr
        source_labels:
          - __meta_kubernetes_pod_label_app_kubernetes_io_part_of
      - action: replace
        replacement: ${1}
        source_labels:
          - __meta_kubernetes_pod_label_app
        target_label: app
      - action: replace
        replacement: ${1}
        source_labels:
          - __meta_kubernetes_namespace
        target_label: namespace
      - action: replace
        replacement: ${1}
        source_labels:
          - __meta_kubernetes_pod_name
        target_label: pod
      - action: replace
        replacement: ${1}:9090
        source_labels:
          - __meta_kubernetes_pod_ip
        target_label: __address__
  1. 验证

确保 Prometheus 在您的集群中运行。

kubectl get pods -n dapr-monitoring

预期输出:

NAME                                                READY   STATUS    RESTARTS   AGE
dapr-prom-kube-state-metrics-9849d6cc6-t94p8        1/1     Running   0          4m58s
dapr-prom-prometheus-alertmanager-749cc46f6-9b5t8   2/2     Running   0          4m58s
dapr-prom-prometheus-node-exporter-5jh8p            1/1     Running   0          4m58s
dapr-prom-prometheus-node-exporter-88gbg            1/1     Running   0          4m58s
dapr-prom-prometheus-node-exporter-bjp9f            1/1     Running   0          4m58s
dapr-prom-prometheus-pushgateway-688665d597-h4xx2   1/1     Running   0          4m58s
dapr-prom-prometheus-server-694fd8d7c-q5d59         2/2     Running   0          4m58s

访问 Prometheus 仪表板

要查看 Prometheus 仪表板并检查服务发现:

kubectl port-forward svc/dapr-prom-prometheus-server 9090:80 -n dapr-monitoring

打开浏览器并访问 http://localhost:9090。导航到 Status > Service Discovery 以验证 Dapr 目标是否被正确发现。

Prometheus Web UI

您可以看到 job_name 及其发现的目标。

Prometheus Service Discovery

示例

参考

1.2.2 - 配置指标

启用或禁用 Dapr 指标

默认情况下,每个 Dapr 系统进程都会发出 Go 运行时/进程指标,并具有各自的 Dapr 指标

Prometheus 端点

Dapr sidecar 暴露了一个兼容 Prometheus 的指标端点,您可以对其进行抓取以更深入地了解 Dapr 的运行状态。

使用 CLI 配置指标

指标应用端点默认启用。您可以通过传递命令行参数 --enable-metrics=false 来禁用它。

默认指标端口为 9090。您可以通过向 daprd 传递命令行参数 --metrics-port 来覆盖此设置。

在 Kubernetes 中配置指标

您还可以通过在应用程序部署上设置 dapr.io/enable-metrics: "false" 注解来为特定应用程序启用/禁用指标。在禁用指标导出器的情况下,daprd 不会打开指标监听端口。

以下 Kubernetes 部署示例显示了如何显式启用指标并将端口指定为 “9090”。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
  labels:
    app: node
spec:
  replicas: 1
  selector:
    matchLabels:
      app: node
  template:
    metadata:
      labels:
        app: node
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodeapp"
        dapr.io/app-port: "3000"
        dapr.io/enable-metrics: "true"
        dapr.io/metrics-port: "9090"
    spec:
      containers:
      - name: node
        image: dapriosamples/hello-k8s-node:latest
        ports:
        - containerPort: 3000
        imagePullPolicy: Always

使用应用程序配置配置指标

您还可以通过应用程序配置启用指标。要默认禁用 Dapr sidecar 中的指标收集,请将 spec.metrics.enabled 设置为 false

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: tracing
  namespace: default
spec:
  metrics:
    enabled: false

配置错误代码指标

您可以通过将 spec.metrics.recordErrorCodes 设置为 true 来为 Dapr API 错误代码 启用其他指标。与调用者通信的 Dapr API 可能返回标准化的错误代码。记录了一个名为 error_code_total 的新指标,它允许监控由应用程序、代码和类别触发的错误代码。有关特定代码和类别,请参阅 errorcodes 包

配置示例:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: tracing
  namespace: default
spec:
  metrics:
    enabled: true
    recordErrorCodes: true

指标示例:

{
  "app_id": "publisher-app",
  "category": "state",
  "dapr_io_enabled": "true",
  "error_code": "ERR_STATE_STORE_NOT_CONFIGURED",
  "instance": "10.244.1.64:9090",
  "job": "kubernetes-service-endpoints",
  "namespace": "my-app",
  "node": "my-node",
  "service": "publisher-app-dapr"
}

使用路径匹配优化 HTTP 指标报告

在使用 HTTP 调用 Dapr 时,默认会为每个请求的方法创建指标。这可能导致大量指标,即高基数,从而影响内存使用和 CPU。

路径匹配允许您管理和控制 Dapr 中 HTTP 指标的基数。这是指标的聚合,因此您无需为每个事件设置一个指标,而是可以减少指标事件的数量并报告一个总体数字。了解如何在配置中设置基数

此配置是可选的,通过 Dapr 配置 spec.metrics.http.pathMatching 启用。定义后,它启用路径匹配,该匹配会为两个指标路径标准化指定的路径。这减少了唯一指标路径的数量,使指标更易于管理,并以受控方式减少资源消耗。

spec.metrics.http.pathMatching 与设置为 falseincreasedCardinality 标志结合使用时,非匹配路径将转换为 catch-all 存储桶以控制和限制基数,防止无限制的路径增长。相反,当 increasedCardinalitytrue(默认值)时,非匹配路径照常传递,从而允许可能更高的基数,但保留原始路径数据。

HTTP 指标中路径匹配的示例

以下示例演示了如何在 Dapr 中使用路径匹配 API 来管理 HTTP 指标。在每个示例中,指标是从 5 个对带有不同订单 ID 的 /orders 端点的 HTTP 请求中收集的。通过调整基数并利用路径匹配,您可以微调指标的粒度,以平衡细节和资源效率。

这些示例说明了指标的基数,强调高基数配置会导致许多条目,这对应于处理指标的更高内存使用。为简单起见,以下示例侧重于单个指标:dapr_http_server_request_count

使用路径匹配的低基数(推荐)

配置:

http:
  increasedCardinality: false
  pathMatching:
    - /orders/{orderID}

生成的指标:

# 匹配的路径
dapr_http_server_request_count{app_id="order-service",method="GET",path="/orders/{orderID}",status="200"} 5
# 未匹配的路径
dapr_http_server_request_count{app_id="order-service",method="GET",path="",status="200"} 1

通过配置低基数和路径匹配,您可以通过为重要端点分组指标来获得两全其美的效果,而不会影响基数。这种方法有助于避免高内存使用和潜在的安全问题。

不使用路径匹配的低基数

配置:

http:
  increasedCardinality: false

生成的指标:

dapr_http_server_request_count{app_id="order-service",method="GET", path="",status="200"} 5

在低基数模式下,作为无限制基数的主要来源的路径将被丢弃。这导致指标主要指示对给定 HTTP 方法向服务发出的请求数,但没有任何关于所调用路径的信息。

使用路径匹配的高基数

配置:

http:
  increasedCardinality: true
  pathMatching:
    - /orders/{orderID}

生成的指标:

dapr_http_server_request_count{app_id="order-service",method="GET",path="/orders/{orderID}",status="200"} 5

此示例产生与上述示例相同的 HTTP 请求,但为路径 /orders/{orderID} 配置了路径匹配。通过使用路径匹配,您可以通过根据匹配的路径对指标进行分组来实现基数降低。

不使用路径匹配的高基数

配置:

http:
  increasedCardinality: true

生成的指标:

dapr_http_server_request_count{app_id="order-service",method="GET",path="/orders/1",status="200"} 1
dapr_http_server_request_count{app_id="order-service",method="GET",path="/orders/2",status="200"} 1
dapr_http_server_request_count{app_id="order-service",method="GET",path="/orders/3",status="200"} 1
dapr_http_server_request_count{app_id="order-service",method="GET",path="/orders/4",status="200"} 1
dapr_http_server_request_count{app_id="order-service",method="GET",path="/orders/5",status="200"} 1

对于每个请求,都会使用请求路径创建一个新指标。此过程继续进行对每个新订单 ID 发出的每个请求,导致无限制的基数,因为 ID 不断增长。

HTTP 指标排除动词

excludeVerbs 选项允许您排除特定 HTTP 动词在指标中报告。这在内存节省至关重要的高性能应用程序中非常有用。

在指标中排除 HTTP 动词的示例

以下示例演示了如何在 Darp r 中排除 HTTP 动词以管理 HTTP 指标。

默认 - 包含 HTTP 动词

配置:

http:
  excludeVerbs: false

生成的指标:

dapr_http_server_request_count{app_id="order-service",method="GET",path="/orders",status="200"} 1
dapr_http_server_request_count{app_id="order-service",method="POST",path="/orders",status="200"} 1

在此示例中,HTTP 方法包含在指标中,导致对 /orders 端点的每个请求都有单独的指标。

排除 HTTP 动词

配置:

http:
  excludeVerbs: true

生成的指标:

dapr_http_server_request_count{app_id="order-service",method="",path="/orders",status="200"} 2

在此示例中,HTTP 方法从指标中排除,导致对 /orders 端点的所有请求都有单个指标。

配置自定义延迟直方图存储桶

Dapr 使用累积直方图指标将延迟值分组到存储桶中,其中每个存储桶包含:

  • 具有该延迟的请求数的计数
  • 具有较低延迟的所有请求

使用默认延迟存储桶配置

默认情况下,Dapr 将请求延迟指标分组到以下存储桶中:

1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50, 65, 80, 100, 130, 160, 200, 250, 300, 400, 500, 650, 800, 1000, 2000, 5000, 10000, 20000, 50000, 100000

以累积方式对延迟值进行分组允许根据需要使用或删除存储桶,以增加或减少数据的粒度。 例如,如果请求花费 3ms,它将计入 3ms 存储桶、4ms 存储桶、5ms 存储桶等。 同样,如果请求花费 10ms,它将计入 10ms 存储桶、13ms 存储桶、16ms 存储桶等。 在这两个请求完成后,3ms 存储桶的计数为 1,10ms 存储桶的计数为 2,因为这里包括 3ms 和 10ms 请求。

这显示如下:

123456810131620253040506580100130160…..100000
00111112222222222222…..2

默认的存储桶数量适用于大多数用例,但可以根据需要进行调整。每个请求会创建 34 个不同的指标,如果应用程序数量很大,这个值可能会大幅增长。 通过增加存储桶的数量,可以实现更准确的延迟百分位数。但是,存储桶数量越多,用于存储指标的内存就越多,可能会对您的监控系统产生负面影响。

建议将延迟存储桶的数量保持为默认值,除非您在监控系统中看到不必要的内存压力。配置存储桶的数量允许您选择以下应用程序:

  • 您希望通过增加存储桶数量来查看更多详细信息
  • 通过减少存储桶数量来使用更广泛的值

在配置存储桶数量之前,请注意您的应用程序生成的默认延迟值。

根据您的场景自定义延迟存储桶

通过修改应用程序的 Dapr 配置规范 中的 spec.metrics.latencyDistributionBuckets 字段,根据您的需求定制延迟存储桶。

例如,如果您对极低的延迟值(1-10ms)不感兴趣,可以将它们分组到一个 10ms 存储桶中。同样,您可以将高值分组到一个存储桶中(1000-5000ms),同时在您最感兴趣的中间值范围内保留更多详细信息。

以下配置规范示例用 11 个存储桶替换了默认的 34 个存储桶,在中间值范围内提供了更高级别的粒度:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: custom-metrics
spec:
    metrics:
        enabled: true
        latencyDistributionBuckets: [10, 25, 40, 50, 70, 100, 150, 200, 500, 1000, 5000]

使用正则表达式转换指标

您可以为 Dapr sidecar 暴露的每个指标设置正则表达式,以"转换"它们的值。查看所有 Dapr 指标的列表

规则的名称必须与要转换的指标的名称匹配。以下示例显示了如何为指标 dapr_runtime_service_invocation_req_sent_total 中的标签 method 应用正则表达式:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: daprConfig
spec:
  metrics:
    enabled: true
    http:
      increasedCardinality: true
    rules:
      - name: dapr_runtime_service_invocation_req_sent_total
        labels:
        - name: method
          regex:
            "orders/": "orders/.+"

应用此配置后,method 标签为 orders/a746dhsk293972nz 的记录指标将替换为 orders/

使用正则表达式减少指标基数被视为传统方法。我们鼓励所有用户改为将 spec.metrics.http.increasedCardinality 设置为 false,这样配置更简单,并提供更好的性能。

参考

1.2.3 - 操作指南:使用 Grafana 观察指标

如何在 Grafana 仪表板中查看 Dapr 指标。

可用的仪表板

grafana-system-services-dashboard.json 模板显示 Dapr 系统组件状态,包括 dapr-operator、dapr-sidecar-injector、dapr-sentry 和 dapr-placement:

系统服务仪表板截图

grafana-sidecar-dashboard.json 模板显示 Dapr 边车状态,包括边车健康状态/资源使用、HTTP 和 gRPC 的吞吐量/延迟、Actor、mTLS 等:

边车仪表板截图

grafana-actor-dashboard.json 模板显示 Dapr Sidecar 状态、Actor 调用吞吐量/延迟、timer/reminder 触发器以及轮转并发:

Actor 仪表板截图

前提条件

在 Kubernetes 上设置

安装 Grafana

  1. 添加 Grafana Helm 仓库:

    helm repo add grafana https://grafana.github.io/helm-charts
    helm repo update
    
  2. 安装 chart:

    helm install grafana grafana/grafana -n dapr-monitoring
    
  3. 获取 Grafana 登录的管理员密码:

    kubectl get secret --namespace dapr-monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
    

    你将获得一个类似于 cj3m0OfBNx8SLzUlTx91dEECgzRlYJb60D2evof1% 的密码。从密码中移除 % 字符,得到 cj3m0OfBNx8SLzUlTx91dEECgzRlYJb60D2evof1 作为管理员密码。

  4. 验证 Grafana 是否在你的集群中运行:

    kubectl get pods -n dapr-monitoring
    
    NAME                                                READY   STATUS       RESTARTS   AGE
    dapr-prom-kube-state-metrics-9849d6cc6-t94p8        1/1     Running      0          4m58s
    dapr-prom-prometheus-alertmanager-749cc46f6-9b5t8   2/2     Running      0          4m58s
    dapr-prom-prometheus-node-exporter-5jh8p            1/1     Running      0          4m58s
    dapr-prom-prometheus-node-exporter-88gbg            1/1     Running      0          4m58s
    dapr-prom-prometheus-node-exporter-bjp9f            1/1     Running      0          4m58s
    dapr-prom-prometheus-pushgateway-688665d597-h4xx2   1/1     Running      0          4m58s
    dapr-prom-prometheus-server-694fd8d7c-q5d59         2/2     Running      0          4m58s
    grafana-c49889cff-x56vj                             1/1     Running      0          5m10s
    

将 Prometheus 配置为数据源

首先需要将 Prometheus 作为数据源连接到 Grafana。

  1. 将 svc/grafana 端口转发:

    kubectl port-forward svc/grafana 8080:80 -n dapr-monitoring
    
    Forwarding from 127.0.0.1:8080 -> 3000
    Forwarding from [::1]:8080 -> 3000
    Handling connection for 8080
    Handling connection for 8080
    
  2. 在浏览器中打开 http://localhost:8080

  3. 登录 Grafana

    • 用户名 = admin
    • 密码 = 上面获取的密码
  4. 选择 ConfigurationData Sources

    Grafana 添加数据源菜单截图
  5. 添加 Prometheus 作为数据源。

    Prometheus 添加数据源截图
  6. 获取你的 Prometheus HTTP URL

    Prometheus HTTP URL 遵循格式 http://<prometheus service endpoint>.<namespace>

    首先通过运行以下命令获取 Prometheus 服务器端点:

    kubectl get svc -n dapr-monitoring
    
    NAME                                 TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)             AGE
    dapr-prom-kube-state-metrics         ClusterIP   10.0.174.177      <none>        8080/TCP            7d9h
    dapr-prom-prometheus-alertmanager    ClusterIP   10.0.255.199      <none>        80/TCP              7d9h
    dapr-prom-prometheus-node-exporter   ClusterIP   None              <none>        9100/TCP            7d9h
    dapr-prom-prometheus-pushgateway     ClusterIP   10.0.190.59       <none>        9091/TCP            7d9h
    dapr-prom-prometheus-server          ClusterIP   10.0.172.191      <none>        80/TCP              7d9h
    elasticsearch-master                 ClusterIP   10.0.36.146       <none>        9200/TCP,9300/TCP   7d10h
    elasticsearch-master-headless        ClusterIP   None              <none>        9200/TCP,9300/TCP   7d10h
    grafana                              ClusterIP   10.0.15.229       <none>        80/TCP              5d5h
    kibana-kibana                        ClusterIP   10.0.188.224      <none>        5601/TCP            7d10h
    

    在本指南中,服务器名称是 dapr-prom-prometheus-server,命名空间是 dapr-monitoring,所以 HTTP URL 将是 http://dapr-prom-prometheus-server.dapr-monitoring

  7. 填写以下设置:

    • 名称:Dapr
    • HTTP URL:http://dapr-prom-prometheus-server.dapr-monitoring
    • Default:开启
    • Skip TLS Verify:开启
      • 保存和测试配置所必需
    Prometheus 数据源配置截图
  8. 点击 Save & Test 按钮验证连接是否成功。

在 Grafana 中导入仪表板

  1. 在 Grafana 主屏幕的左上角,点击 “+” 选项,然后选择 “Import”。

    现在你可以从 发布资源中导入适用于你的 Dapr 版本的 Grafana 仪表板模板

    Grafana 仪表板上传选项截图
  2. 找到你导入的仪表板并开始使用

    Dapr 服务仪表板截图

参考

示例

1.2.4 - 操作指南:设置 New Relic 以收集和分析指标

为 Dapr 指标设置 New Relic

前置条件

  • 永久免费 New Relic 账户,每月 100 GB 免费数据接入,1 个免费全访问用户,无限免费基础用户

背景

New Relic 提供 Prometheus OpenMetrics 集成。

本文档介绍如何在集群中安装它,使用 Helm chart(推荐方式)。

安装

  1. 按照官方说明安装 Helm。

  2. 按照这些说明添加 New Relic 官方 Helm chart 仓库。

  3. 运行以下命令通过 Helm 安装 New Relic Logging Kubernetes 插件,将占位符值 YOUR_LICENSE_KEY 替换为您的 New Relic 许可证密钥

    helm install nri-prometheus newrelic/nri-prometheus --set licenseKey=YOUR_LICENSE_KEY
    

查看指标

Dapr 指标

仪表板

相关链接/参考

1.2.5 - 操作指南:设置 Azure Monitor 以搜索日志和收集指标

为 Azure Kubernetes Service (AKS) 启用带有 Azure Monitor 的 Dapr 指标和日志

前置条件

使用 Config Map 启用 Prometheus 指标采集

  1. 确保 Azure Monitor Agents (AMA) 正在运行。

    $ kubectl get pods -n kube-system
    NAME                                                  READY   STATUS    RESTARTS   AGE
    ...
    ama-logs-48kpv                                        2/2     Running   0          2d13h
    ama-logs-mx24c                                        2/2     Running   0          2d13h
    ama-logs-rs-f9bbb9898-vbt6k                           1/1     Running   0          30h
    ama-logs-sm2mz                                        2/2     Running   0          2d13h
    ama-logs-z7p4c                                        2/2     Running   0          2d13h
    ...
    
  2. 应用 Config Map 以启用 Prometheus 指标端点采集。

你可以使用 azm-config-map.yaml 来启用 Prometheus 指标端点采集。

如果你将 Dapr 安装到不同的命名空间,需要更改 monitor_kubernetes_pod_namespaces 数组值。例如:

...
  prometheus-data-collection-settings: |-
    [prometheus_data_collection_settings.cluster]
        interval = "1m"
        monitor_kubernetes_pods = true
        monitor_kubernetes_pods_namespaces = ["dapr-system", "default"]
    [prometheus_data_collection_settings.node]
        interval = "1m"
...

应用 Config Map:

kubectl apply -f ./azm-config.map.yaml

安装带有 JSON 格式日志的 Dapr

  1. 安装 Dapr 并启用 JSON 格式日志。

    helm install dapr dapr/dapr --namespace dapr-system --set global.logAsJson=true
    
  2. 在 Dapr sidecar 中启用 JSON 格式日志并添加 Prometheus 注解。

注意:Azure Monitor Agents (AMA) 仅在设置了 Prometheus 注解时才会发送指标。

在你的部署 yaml 中添加 dapr.io/log-as-json: "true" 注解。

示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pythonapp
  namespace: default
  labels:
    app: python
spec:
  replicas: 1
  selector:
    matchLabels:
      app: python
  template:
    metadata:
      labels:
        app: python
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "pythonapp"
        dapr.io/log-as-json: "true"
        prometheus.io/scrape: "true"
        prometheus.io/port: "9090"
        prometheus.io/path: "/"

...

使用 Azure Monitor 搜索指标和日志

  1. 转到 Azure 门户中的 Azure Monitor。

  2. 搜索 Dapr 日志

下面是一个示例查询,用于解析 JSON 格式的日志并从 Dapr 系统进程查询日志。

ContainerLog
| extend parsed=parse_json(LogEntry)
| project Time=todatetime(parsed['time']), app_id=parsed['app_id'], scope=parsed['scope'],level=parsed['level'], msg=parsed['msg'], type=parsed['type'], ver=parsed['ver'], instance=parsed['instance']
| where level != ""
| sort by Time
  1. 搜索 指标

此查询用于查询 Dapr 系统进程的 process_resident_memory_bytes Prometheus 指标并渲染时间图表。

InsightsMetrics
| where Namespace == "prometheus" and Name == "process_resident_memory_bytes"
| extend tags=parse_json(Tags)
| project TimeGenerated, Name, Val, app=tostring(tags['app'])
| summarize memInBytes=percentile(Val, 99) by bin(TimeGenerated, 1m), app
| where app startswith "dapr-"
| render timechart

参考

1.3 - 日志记录

如何为 Dapr 边车和你的应用程序设置日志记录

1.3.1 - 日志

了解 Dapr 日志记录

Dapr 会生成结构化日志并输出到 stdout,格式可以是纯文本或 JSON。默认情况下,所有 Dapr 进程(runtime 或 sidecar,以及所有控制平面服务)以纯文本形式将日志写入控制台(stdout)。要启用 JSON 格式的日志记录,在运行 Dapr 进程时需要添加 --log-as-json 命令标志。

日志架构

Dapr 根据以下架构生成日志:

字段描述示例
timeISO8601 时间戳2011-10-05T14:48:00.000Z
level日志级别(info/warn/debug/error)info
type日志类型log
msg日志消息hello dapr!
scope日志记录范围dapr.runtime
instance容器名称dapr-pod-xxxxx
app_idDapr App IDdapr-app
verDapr Runtime 版本1.9.0

API 日志记录可能会添加其他结构化字段,如 API 日志记录文档 中所述。

纯文本和 JSON 格式的日志

  • 纯文本日志示例
time="2022-11-01T17:08:48.303776-07:00" level=info msg="starting Dapr Runtime -- version 1.9.0 -- commit v1.9.0-g5dfcf2e" instance=dapr-pod-xxxx scope=dapr.runtime type=log ver=1.9.0
time="2022-11-01T17:08:48.303913-07:00" level=info msg="log level set to: info" instance=dapr-pod-xxxx scope=dapr.runtime type=log ver=1.9.0
  • JSON 格式日志示例
{"instance":"dapr-pod-xxxx","level":"info","msg":"starting Dapr Runtime -- version 1.9.0 -- commit v1.9.0-g5dfcf2e","scope":"dapr.runtime","time":"2022-11-01T17:09:45.788005Z","type":"log","ver":"1.9.0"}
{"instance":"dapr-pod-xxxx","level":"info","msg":"log level set to: info","scope":"dapr.runtime","time":"2022-11-01T17:09:45.788075Z","type":"log","ver":"1.9.0"}

日志格式

Dapr 支持输出纯文本(默认)或 JSON 格式的日志。

要使用 JSON 格式的日志,你需要在安装 Dapr 和部署应用时添加额外的配置选项。建议使用 JSON 格式的日志,因为大多数日志收集器和搜索引擎可以使用内置的解析器更轻松地解析 JSON。

使用 Dapr CLI 启用 JSON 日志记录

使用 Dapr CLI 运行应用程序时,传递 --log-as-json 选项以启用 JSON 格式的日志,例如:

dapr run \
  --app-id orderprocessing \
  --resources-path ./components/ \
  --log-as-json \
    -- python3 OrderProcessingService.py

在 Kubernetes 中启用 JSON 日志记录

以下步骤描述了如何为 Kubernetes 配置 JSON 格式的日志

Dapr 控制平面

Dapr 控制平面中的所有服务(例如 operatorsentry 等)都支持 --log-as-json 选项来启用 JSON 格式的日志记录。

如果你使用 Helm chart 将 Dapr 部署到 Kubernetes,可以通过传递 --set global.logAsJson=true 选项为 Dapr 系统服务启用 JSON 格式的日志,例如:

helm upgrade --install dapr \
  dapr/dapr \
  --namespace dapr-system \
  --set global.logAsJson=true

为 Dapr sidecars 启用 JSON 格式的日志

你可以通过在部署中添加 dapr.io/log-as-json: "true" 注解来为 Dapr sidecars 启用 JSON 格式的日志,例如:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pythonapp
  labels:
    app: python
spec:
  selector:
    matchLabels:
      app: python
  template:
    metadata:
      labels:
        app: python
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "pythonapp"
        # This enables JSON-formatted logging
        dapr.io/log-as-json: "true"
...

API 日志记录

API 日志记录使你能够查看应用程序对 Dapr sidecar 发起的 API 调用,以调试问题或监控应用程序的行为。你可以将 Dapr API 日志记录与 Dapr 日志事件结合使用。

有关更多信息,请参阅配置和查看 Dapr 日志配置和查看 Dapr API 日志

日志收集器

如果你在 Kubernetes 集群中运行 Dapr,Fluentd 是一个流行的容器日志收集器。你可以将 Fluentd 与 JSON 解析器插件结合使用来解析 Dapr JSON 格式的日志。这个操作指南展示了如何在集群中配置 Fluentd。

如果你使用 Azure Kubernetes Service,可以使用内置代理通过 Azure Monitor 收集日志,无需安装 Fluentd。

搜索引擎

如果你使用 Fluentd,我们建议使用 Elastic Search 和 Kibana。这个操作指南展示了如何在 Kubernetes 集群中设置 Elastic Search 和 Kibana。

如果你使用 Azure Kubernetes Service,可以使用 Azure Monitor for containers 而无需安装任何其他监控工具。另请参阅如何为容器启用 Azure Monitor

参考资料

1.3.2 - 操作指南:在 Kubernetes 中设置 Fluentd、Elasticsearch 和 Kibana

如何在 Kubernetes 中安装 Fluentd、Elasticsearch 和 Kibana 来搜索日志

前置条件

安装 Elasticsearch 和 Kibana

  1. 为监控工具创建一个 Kubernetes 命名空间

    kubectl create namespace dapr-monitoring
    
  2. 添加 Elasticsearch 的 helm 仓库

    helm repo add elastic https://helm.elastic.co
    helm repo update
    
  3. 使用 Helm 安装 Elasticsearch

    默认情况下,该 chart 会创建 3 个副本,这些副本必须分布在不同的节点上。如果你的集群节点数少于 3 个,请指定较小的副本数。例如,以下命令将副本数设置为 1:

    helm install elasticsearch elastic/elasticsearch --version 7.17.3 -n dapr-monitoring --set replicas=1
    

    否则:

    helm install elasticsearch elastic/elasticsearch --version 7.17.3 -n dapr-monitoring
    

    如果你正在使用 minikube 或只是为了开发目的想禁用持久卷,可以使用以下命令:

    helm install elasticsearch elastic/elasticsearch --version 7.17.3 -n dapr-monitoring --set persistence.enabled=false,replicas=1
    
  4. 安装 Kibana

    helm install kibana elastic/kibana --version 7.17.3 -n dapr-monitoring
    
  5. 确保 Elasticsearch 和 Kibana 在你的 Kubernetes 集群中运行

    $ kubectl get pods -n dapr-monitoring
    NAME                            READY   STATUS    RESTARTS   AGE
    elasticsearch-master-0          1/1     Running   0          6m58s
    kibana-kibana-95bc54b89-zqdrk   1/1     Running   0          4m21s
    

安装 Fluentd

  1. 安装 config map 和以 daemonset 方式运行的 Fluentd

    下载这些配置文件:

    注意:如果你的集群中已经有 Fluentd 在运行,请启用嵌套 JSON 解析器,以便它可以解析来自 Dapr 的 JSON 格式日志。

    将配置应用到你的集群:

    kubectl apply -f ./fluentd-config-map.yaml
    kubectl apply -f ./fluentd-dapr-with-rbac.yaml
    
  2. 确保 Fluentd 作为 daemonset 运行。Fluentd 实例的数量应与集群节点数相同。在下面的示例中,集群中只有一个节点:

    $ kubectl get pods -n kube-system -w
    NAME                          READY   STATUS    RESTARTS   AGE
    coredns-6955765f44-cxjxk      1/1     Running   0          4m41s
    coredns-6955765f44-jlskv      1/1     Running   0          4m41s
    etcd-m01                      1/1     Running   0          4m48s
    fluentd-sdrld                 1/1     Running   0          14s
    

安装支持 JSON 格式日志的 Dapr

  1. 安装 Dapr 并启用 JSON 格式日志

    helm repo add dapr https://dapr.github.io/helm-charts/
    helm repo update
    helm install dapr dapr/dapr --namespace dapr-system --set global.logAsJson=true
    
  2. 在 Dapr sidecar 中启用 JSON 格式日志

    dapr.io/log-as-json: "true" 注解添加到你的 deployment yaml 中。例如:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: pythonapp
      namespace: default
      labels:
        app: python
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: python
      template:
        metadata:
          labels:
            app: python
          annotations:
            dapr.io/enabled: "true"
            dapr.io/app-id: "pythonapp"
            dapr.io/log-as-json: "true"
    ...
    

搜索日志

注意:Elasticsearch 需要一些时间来索引 Fluentd 发送的日志。

  1. 从本地端口转发到 svc/kibana-kibana

    $ kubectl port-forward svc/kibana-kibana 5601 -n dapr-monitoring
    Forwarding from 127.0.0.1:5601 -> 5601
    Forwarding from [::1]:5601 -> 5601
    Handling connection for 5601
    Handling connection for 5601
    
  2. 浏览到 http://localhost:5601

  3. 展开下拉菜单并点击 Management → Stack Management

    Kibana Management 菜单选项下的 Stack Management 项

  4. 在 Stack Management 页面上,选择 Data → Index Management 并等待 dapr-* 被索引。

    Kibana Stack Management 页面上的索引管理视图

  5. 一旦 dapr-* 被索引,点击 Kibana → Index Patterns,然后点击 Create index pattern 按钮。

    Kibana 创建索引模式按钮

  6. 通过在 Index Pattern name 字段中输入 dapr* 来定义新的索引模式,然后点击 Next step 按钮继续。

    Kibana 定义索引模式页面

  7. 通过从 Time field 下拉列表中选择 @timestamp 选项,配置与新索引模式一起使用的主时间字段。点击 Create index pattern 按钮完成索引模式的创建。

    Kibana 创建索引模式的配置设置页面

  8. 应该显示新创建的索引模式。通过使用 Fields 选项卡中的搜索框,确认感兴趣的字段(如 scopetypeapp_idlevel 等)正在被索引。

    注意:如果你找不到索引字段,请稍候。搜索所有索引字段所需的时间取决于数据量和运行 Elasticsearch 的资源大小。

    创建的 Kibana 索引模式视图

  9. 要浏览索引数据,展开下拉菜单并点击 Analytics → Discover

    Kibana Analytics 菜单选项下的 Discover 项

  10. 在搜索框中输入查询字符串,例如 scope:*,然后点击 Refresh 按钮查看结果。

    注意:这可能需要很长时间。返回所有结果所需的时间取决于数据量和运行 Elasticsearch 的资源大小。

    在 Kibana Analytics Discover 页面中使用搜索框

参考

1.3.3 - 如何设置:为 Dapr 日志配置 New Relic

为 Dapr 日志配置 New Relic

前提条件

  • 永久免费的 New Relic 账户,每月 100 GB 的免费数据摄入,1 个免费的全权限用户,无限个免费基础用户

背景

New Relic 提供了一个 Fluent Bit 输出插件,可以轻松将日志转发到 New Relic Logs。该插件也以独立的 Docker 镜像形式提供,可以以 DaemonSet 的形式安装在 Kubernetes 集群中,我们称之为 Kubernetes 插件。

本文档介绍了如何在集群中安装该插件,可以使用 Helm chart(推荐),或者通过手动应用 Kubernetes 清单文件。

安装

使用 Helm chart 安装(推荐)

  1. 按照官方说明安装 Helm。

  2. 按照这些说明添加 New Relic 官方 Helm chart 仓库

  3. 运行以下命令通过 Helm 安装 New Relic Logging Kubernetes 插件,将占位符值 YOUR_LICENSE_KEY 替换为您的 New Relic 许可证密钥

  • Helm 3

    helm install newrelic-logging newrelic/newrelic-logging --set licenseKey=YOUR_LICENSE_KEY
    
  • Helm 2

    helm install newrelic/newrelic-logging --name newrelic-logging --set licenseKey=YOUR_LICENSE_KEY
    

对于欧盟用户,请在上述任何 helm install 命令中添加 --set endpoint=https://log-api.eu.newrelic.com/log/v1

默认情况下,日志跟踪设置为 /var/log/containers/*.log。要更改此设置,请在上述任何 helm install 命令中添加 –set fluentBit.path=DESIRED_PATH 来提供您首选的路径。

安装 Kubernetes 清单文件

  1. 将以下 3 个清单文件下载到当前工作目录:

    curl https://raw.githubusercontent.com/newrelic/helm-charts/master/charts/newrelic-logging/k8s/fluent-conf.yml > fluent-conf.yml
    curl https://raw.githubusercontent.com/newrelic/helm-charts/master/charts/newrelic-logging/k8s/new-relic-fluent-plugin.yml > new-relic-fluent-plugin.yml
    curl https://raw.githubusercontent.com/newrelic/helm-charts/master/charts/newrelic-logging/k8s/rbac.yml > rbac.yml
    
  2. 在下载的 new-relic-fluent-plugin.yml 文件中,将占位符值 LICENSE_KEY 替换为您的 New Relic 许可证密钥。

    对于欧盟用户,将 ENDPOINT 环境变量替换为 https://log-api.eu.newrelic.com/log/v1

  3. 添加许可证密钥后,在终端或命令行界面中运行以下命令:

    kubectl apply -f .
    
  4. [可选] 您可以通过编辑 fluent-conf.yml 文件中的 parsers.conf 部分来配置插件如何解析数据。有关更多信息,请参阅 Fluent Bit 关于 Parsers 配置的文档。

    默认情况下,日志跟踪设置为 /var/log/containers/*.log。要更改此设置,请在 new-relic-fluent-plugin.yml 文件中将默认路径替换为您首选的路径。

查看日志

Dapr Annotations

搜索

相关链接/参考

2 - Dapr 的托管选项

如何将 Dapr 部署到您的环境中。

2.1 - 在自托管模式下运行 Dapr

如何在本地环境中启动并运行 Dapr

2.1.1 - Dapr 自托管模式概述

如何在 Windows/Linux/MacOS 机器上运行 Dapr 的概述

概述

Dapr 可以配置为在本地开发机器或生产虚拟机上的自托管模式下运行。每个运行的服务都有一个 Dapr 运行时进程(或边车),配置为使用状态存储、发布订阅、绑定组件和其他构建块。

初始化

Dapr 可以使用 Docker(默认)或 slim-init 模式 进行初始化。它也可以在离线或隔离网络环境中初始化和运行。

默认的 Docker 设置提供开箱即用的功能,包括以下容器和配置:

  • 配置为充当状态管理和发布/订阅的默认组件的 Redis 容器。
  • 用于诊断和链路追踪的 Zipkin 容器。
  • 安装在 $HOME/.dapr/(Mac/Linux)或 %USERPROFILE%\.dapr\(Windows)中的默认 Dapr 配置和组件。

dapr-placement 服务负责管理 Actor 分布方案和键范围设置。此服务不会作为容器启动,仅在使用 Dapr Actor 时才需要。有关 Actor Placement 服务的更多信息,请阅读 Actor 概述

Dapr 在自托管 Docker 模式下的示意图

使用 Dapr 启动应用程序

您可以使用 dapr run CLI 命令 与您的应用程序一起启动一个 Dapr 边车进程。可以在此处找到其他参数和标志。

名称解析

Dapr 使用名称解析组件服务调用构建块中进行服务发现。默认情况下,Dapr 在自托管模式下使用 mDNS。

如果您在虚拟机上运行 Dapr 或 mDNS 不可用,则可以使用 HashiCorp Consul 组件进行名称解析。

2.1.2 - 操作指南:在 Docker 中以自托管模式运行 Dapr

如何使用 Docker 在自托管模式下部署和运行 Dapr

本文提供了在 Windows/Linux/macOS 机器或虚拟机上使用 Docker 运行 Dapr 的指导。

前置条件

初始化 Dapr 环境

要初始化 Dapr 控制平面容器并创建默认配置文件,请运行:

dapr init

将应用和边车作为进程运行

dapr run CLI 命令可用于启动 Dapr 边车以及你的应用程序:

dapr run --app-id myapp --app-port 5000 -- dotnet run

此命令将启动 daprd 边车二进制文件并运行 dotnet run,从而启动你的应用程序。

将应用作为进程运行,边车作为 Docker 容器运行

或者,如果你在 Docker 容器中运行 Dapr,并将应用程序作为主机上的进程运行,则需要配置 Docker 使用主机网络,以便 Dapr 和应用程序可以共享一个 localhost 网络接口。

如果你在 Linux 主机上运行 Docker 守护进程,可以运行以下命令来启动 Dapr:

docker run --net="host" --mount type=bind,source="$(pwd)"/components,target=/components daprio/daprd:edge ./daprd -app-id <my-app-id> -app-port <my-app-port>

然后你可以在主机上运行你的应用程序,它们应该能够通过 localhost 网络接口进行连接。

在单个 Docker 容器中运行应用和 Dapr

仅用于开发目的

不建议在同一容器内运行 Dapr 运行时和应用程序。但是,对于本地开发场景,可以这样做。

为此,你需要编写一个 Dockerfile,在其中安装 Dapr 运行时、Dapr CLI 和应用程序代码。 然后你可以使用 Dapr CLI 调用 Dapr 运行时和应用程序代码。

以下是一个实现此目的的 Dockerfile 示例:

FROM python:3.7.1
# 安装 dapr CLI
RUN wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash

# 安装 daprd
ARG DAPR_BUILD_DIR
COPY $DAPR_BUILD_DIR /opt/dapr
ENV PATH="/opt/dapr/:${PATH}"
RUN dapr init --slim

# 安装你的应用
WORKDIR /app
COPY python .
RUN pip install requests
ENTRYPOINT ["dapr"]
CMD ["run", "--app-id", "nodeapp", "--app-port", "3000", "node", "app.js"]

请记住,如果 Dapr 需要与其他组件(例如 Redis)通信,这些组件也需要对它可访问。

在 Docker 网络上运行

如果你有多个在 Docker 容器中运行的 Dapr 实例,并希望它们能够彼此通信例如用于服务调用,则需要创建一个共享的 Docker 网络,并确保这些 Dapr 容器连接到该网络。

你可以使用以下命令创建一个简单的 Docker 网络:

docker network create my-dapr-network

运行 Docker 容器时,可以使用以下命令将它们连接到网络:

docker run --net=my-dapr-network ...

每个容器将在该网络上获得一个唯一的 IP,并能够与该网络上的其他容器通信。

使用 Docker-Compose 运行

Docker Compose可用于定义多容器应用程序配置。如果你希望在不使用 Kubernetes 的情况下在本地运行多个带有 Dapr 边车的应用程序,建议使用 Docker Compose 定义(docker-compose.yml)。

Docker Compose 的语法和工具超出了本文的范围,但是建议你参考官方 Docker 文档了解更多详细信息。

要使用 Dapr 和 Docker Compose 运行应用程序,你需要在 docker-compose.yml 中定义边车模式。例如:

version: '3'
services:
  nodeapp:
    build: ./node
    ports:
      - "50001:50001" # Dapr 实例通过 gRPC 通信,因此我们需要公开 gRPC 端口
    depends_on:
      - redis
      - placement
    networks:
      - hello-dapr
  nodeapp-dapr:
    image: "daprio/daprd:edge"
    command: [
      "./daprd",
     "--app-id", "nodeapp",
     "--app-port", "3000",
     "--placement-host-address", "placement:50006", # 可以通过 docker DNS 条目访问 Dapr 的 placement 服务
     "--scheduler-host-address", "scheduler:50007", # 可以通过 docker DNS 条目访问 Dapr 的 scheduler 服务
     "--resources-path", "./components"
     ]
    volumes:
        - "./components/:/components" # 挂载我们的 components 文件夹供运行时使用。挂载位置必须与 --resources-path 参数匹配。
    depends_on:
      - nodeapp
    network_mode: "service:nodeapp" # 将 nodeapp-dapr 服务附加到 nodeapp 网络命名空间

  ... # 部署其他 daprized 服务和组件(例如 Redis)

  placement:
    image: "daprio/placement"
    command: ["./placement", "--port", "50006"]
    ports:
      - "50006:50006"

  scheduler:
    image: "daprio/scheduler"
    command: ["./scheduler", "--port", "50007", "--etcd-data-dir", "/data"]
    ports:
      - "50007:50007"
    user: root
    volumes:
    - "./dapr-etcd-data/:/data"
  
  networks:
    hello-dapr: null

对于在 Linux 主机上运行 Docker 守护进程的用户,如果需要,你也可以使用 network_mode: host 来利用主机网络。

要进一步了解如何使用 Docker Compose 运行 Dapr,请参阅Docker-Compose 示例

上述示例还包括一个调度器定义,该定义使用非持久化数据存储用于测试和开发目的。

在 Kubernetes 上运行

如果你的部署目标是 Kubernetes,请使用 Dapr 的一流集成。请参阅 Dapr on Kubernetes 文档

名称解析

Dapr 在自托管模式下默认使用 mDNS 作为服务调用的名称解析组件。如果你在虚拟机上运行 Dapr 或 mDNS 不可用,则可以使用 HashiCorp Consul 组件进行名称解析。

Docker 镜像

Dapr 为不同的组件提供了许多预构建的 Docker 镜像,你应该根据所需的二进制文件、架构和标签/版本选择相关的镜像。

镜像

Docker Hub 上提供了每个 Dapr 组件的已发布 Docker 镜像。

标签

Linux/amd64

  • latest:最新发布版本,用于开发目的。
  • edge:最新的 edge 构建(master 分支)。
  • major.minor.patch:发布版本。
  • major.minor.patch-rc.iteration:发布候选版本。

Linux/arm/v7

  • latest-arm:最新的 ARM 发布版本,用于开发目的。
  • edge-arm:最新的 ARM edge 构建(master 分支)。
  • major.minor.patch-arm:ARM 发布版本。
  • major.minor.patch-rc.iteration-arm:ARM 发布候选版本。

2.1.3 - 操作指南:使用 Podman 在自托管模式下运行 Dapr

如何使用 Podman 在自托管模式下部署和运行 Dapr

本文提供在 Windows/Linux/macOS 机器或 VM 上使用 Podman 运行 Dapr 的指导。

前置条件

初始化 Dapr 环境

要初始化 Dapr 控制平面容器并创建默认配置文件,运行:

dapr init --container-runtime podman

以进程方式同时运行应用和边车

dapr run CLI 命令 可用于启动 Dapr 边车和你的应用:

dapr run --app-id myapp --app-port 5000 -- dotnet run

此命令会同时启动 daprd 边车和你的应用。

以进程方式运行应用并以 Docker 容器方式运行边车

或者,如果你在 Docker 容器中运行 Dapr,并在主机上以进程方式运行应用,则需要配置 Podman 使用主机网络,以便 Dapr 和应用可以共享一个 localhost 网络接口。

如果你在 Linux 主机上运行 Podman,则可以运行以下命令来启动 Dapr:

podman run --network="host" --mount type=bind,source="$(pwd)"/components,target=/components daprio/daprd:edge ./daprd -app-id <my-app-id> -app-port <my-app-port>

然后你可以在主机上运行你的应用,它们应该可以通过 localhost 网络接口进行连接。

卸载 Dapr 环境

要完全卸载 Dapr,运行:

dapr uninstall --container-runtime podman --all

2.1.4 - 操作指南:在自托管模式下不使用 Docker 运行 Dapr

如何在本地机器上未安装 Docker 的情况下部署和运行自托管模式的 Dapr

前置条件

不使用容器初始化 Dapr

Dapr CLI 提供了一个使用 slim init 来初始化 Dapr 的选项,而不会默认创建依赖于 Docker 的开发环境。要在安装 Dapr CLI 后使用 slim init 初始化 Dapr,请使用以下命令:

dapr init --slim

会安装两个不同的二进制文件:

  • daprd
  • placement

placement 二进制文件是在 Dapr 自托管安装中启用 Actor 所必需的。

在 slim init 模式下,不会安装默认组件(如 Redis)用于状态管理或发布订阅。这意味着,除了服务调用之外,安装时"开箱即用"没有其他构建块功能可用。相反,你可以设置自己的环境和自定义组件。

如果配置了状态存储,基于 Actor 的服务调用是可行的,如以下章节所述。

执行服务调用

请参阅 Hello Dapr slim 示例,了解如何在 slim init 模式下执行服务调用。

启用状态管理或发布订阅

请参阅有关在不使用 Docker 的自托管模式下配置 Redis 的文档,以启用用于消息传递的本地状态存储或发布订阅代理。

启用 Actor

要启用 Actor 放置:

默认情况下,placement 二进制文件安装在:

  • 对于 Linux/MacOS:/$HOME/.dapr/bin
  • 对于 Windows:%USERPROFILE%\.dapr\bin
$ $HOME/.dapr/bin/placement

INFO[0000] starting Dapr Placement Service -- version 1.0.0-rc.1 -- commit 13ae49d  instance=Nicoletaz-L10.redmond.corp.microsoft.com scope=dapr.placement type=log ver=1.0.0-rc.1
INFO[0000] log level set to: info                        instance=Nicoletaz-L10.redmond.corp.microsoft.com scope=dapr.placement type=log ver=1.0.0-rc.1
INFO[0000] metrics server started on :9090/              instance=Nicoletaz-L10.redmond.corp.microsoft.com scope=dapr.metrics type=log ver=1.0.0-rc.1
INFO[0000] Raft server is starting on 127.0.0.1:8201...  instance=Nicoletaz-L10.redmond.corp.microsoft.com scope=dapr.placement.raft type=log ver=1.0.0-rc.1
INFO[0000] placement service started on port 50005       instance=Nicoletaz-L10.redmond.corp.microsoft.com scope=dapr.placement type=log ver=1.0.0-rc.1
INFO[0000] Healthz server is listening on :8080          instance=Nicoletaz-L10.redmond.corp.microsoft.com scope=dapr.placement type=log ver=1.0.0-rc.1
INFO[0001] cluster leadership acquired                   instance=Nicoletaz-L10.redmond.corp.microsoft.com scope=dapr.placement type=log ver=1.0.0-rc.1
INFO[0001] leader is established.                        instance=Nicoletaz-L10.redmond.corp.microsoft.com scope=dapr.placement type=log ver=1.0.0-rc.1

在 Windows 上运行独立的 placement 时,请指定端口 6050:

%USERPROFILE%/.dapr/bin/placement.exe -port 6050

time="2022-10-17T14:56:55.4055836-05:00" level=info msg="starting Dapr Placement Service -- version 1.9.0 -- commit fdce5f1f1b76012291c888113169aee845f25ef8" instance=LAPTOP-OMK50S19 scope=dapr.placement type=log ver=1.9.0
time="2022-10-17T14:56:55.4066226-05:00" level=info msg="log level set to: info" instance=LAPTOP-OMK50S19 scope=dapr.placement type=log ver=1.9.0
time="2022-10-17T14:56:55.4067306-05:00" level=info msg="metrics server started on :9090/" instance=LAPTOP-OMK50S19 scope=dapr.metrics type=log ver=1.9.0
time="2022-10-17T14:56:55.4077529-05:00" level=info msg="Raft server is starting on 127.0.0.1:8201..." instance=LAPTOP-OMK50S19 scope=dapr.placement.raft type=log ver=1.9.0
time="2022-10-17T14:56:55.4077529-05:00" level=info msg="placement service started on port 6050" instance=LAPTOP-OMK50S19 scope=dapr.placement type=log ver=1.9.0
time="2022-10-17T14:56:55.4082772-05:00" level=info msg="Healthz server is listening on :8080" instance=LAPTOP-OMK50S19 scope=dapr.placement type=log ver=1.9.0
time="2022-10-17T14:56:56.8232286-05:00" level=info msg="cluster leadership acquired" instance=LAPTOP-OMK50S19 scope=dapr.placement type=log ver=1.9.0
time="2022-10-17T14:56:56.8232286-05:00" level=info msg="leader is established." instance=LAPTOP-OMK50S19 scope=dapr.placement type=log ver=1.9.0

现在,要运行启用了 Actor 的应用程序,你可以遵循为以下内容创建的示例:

更新状态存储配置文件以匹配你的设置的 Redis 主机和密码。

通过使元数据部分类似于示例 Java Redis 组件定义,将其启用为 Actor 状态存储。

  - name: actorStateStore
    value: "true"

清理

完成后,按照在自托管环境中卸载 Dapr删除二进制文件。

后续步骤

2.1.5 - 操作指南:在离线或隔离环境中运行 Dapr

如何在隔离环境中以自托管模式部署和运行 Dapr

概述

默认情况下,Dapr 初始化会从网络下载二进制文件并拉取镜像来设置开发环境。但是,Dapr 也支持使用预先下载的产物进行离线或隔离安装,可以在 Docker 或精简环境中使用。每个 Dapr 版本的产物都被构建到可以下载的 Dapr 安装程序包中。通过在 Dapr CLI init 命令中使用此安装程序包,您可以在没有任何网络访问的环境中安装 Dapr。

设置

在隔离初始化之前,需要预先下载包含 CLI、运行时和仪表板打包在一起的 Dapr 安装程序包。这消除了在本地初始化 Dapr 时下载二进制文件和 Docker 镜像的需要。

  1. 下载特定发布版本的 Dapr 安装程序包。例如,daprbundle_linux_amd64.tar.gz、daprbundle_windows_amd64.zip。

  2. 解压它。

  3. 要安装 Dapr CLI,请将 daprbundle/dapr(Windows 为 dapr.exe)二进制文件复制到所需位置:

    • 对于 Linux/MacOS - /usr/local/bin
    • 对于 Windows,创建一个目录并将其添加到您的系统 PATH 中。例如,创建一个名为 c:\dapr 的目录,然后通过编辑系统环境变量将此目录添加到您的路径中。

    注意:如果 Dapr CLI 未移动到所需位置,您可以使用包中的本地 dapr CLI 二进制文件。上述步骤是为了将其移动到常用位置并将其添加到路径中。

初始化 Dapr 环境

Dapr 可以在隔离环境中使用或不使用 Docker 容器进行初始化。

使用 Docker 初始化 Dapr

先决条件:环境中可用 Docker)

移动到包目录并运行以下命令:

dapr init --from-dir .

对于 linux 用户,如果您使用 sudo 运行 Docker 命令,则需要使用 “sudo dapr init

如果您不是从包目录运行上述命令,请提供包目录的完整路径作为输入。例如,假设包目录路径为 $HOME/daprbundle,运行 dapr init --from-dir $HOME/daprbundle 以获得相同的行为。

输出应类似于以下内容:

  Making the jump to hyperspace...
ℹ️  Installing runtime version latest
↘  Extracting binaries and setting up components... Loaded image: daprio/dapr:$version
✅  Extracting binaries and setting up components...
✅  Extracted binaries and completed components set up.
ℹ️  daprd binary has been installed to $HOME/.dapr/bin.
ℹ️  dapr_placement container is running.
ℹ️  Use `docker ps` to check running containers.
✅  Success! Dapr is up and running. To get started, go here: https://aka.ms/dapr-getting-started

注意:要使用 dapr init 模拟在线 Dapr 初始化,您还可以按如下方式运行 Redis 和 Zipkin 容器:

1. docker run --name "dapr_zipkin" --restart always -d -p 9411:9411 openzipkin/zipkin
2. docker run --name "dapr_redis" --restart always -d -p 6379:6379 redislabs/rejson

不使用 Docker 初始化 Dapr

或者,让 CLI 不安装任何默认配置文件或不运行任何 Docker 容器,请在 init 命令中使用 --slim 标志。仅安装 Dapr 二进制文件。

dapr init --slim --from-dir .

输出应类似于以下内容:

⌛  Making the jump to hyperspace...
ℹ️  Installing runtime version latest
↙  Extracting binaries and setting up components... 
✅  Extracting binaries and setting up components...
✅  Extracted binaries and completed components set up.
ℹ️  daprd binary has been installed to $HOME.dapr/bin.
ℹ️  placement binary has been installed to $HOME/.dapr/bin.
✅  Success! Dapr is up and running. To get started, go here: https://aka.ms/dapr-getting-started

2.1.6 - 操作指南:持久化 Scheduler 任务

配置 Scheduler 使其数据库持久化,使其在重启后保持弹性

Scheduler 服务负责将任务写入其 Etcd 数据库并调度它们执行。 默认情况下,Scheduler 服务数据库将此数据写入本地卷 dapr_scheduler,意味着此数据在重启后会被持久化

此本地卷的主机文件位置通常位于 /var/lib/docker/volumes/dapr_scheduler/_data~/.local/share/containers/storage/volumes/dapr_scheduler/_data,具体取决于您的容器运行时。 请注意,如果您使用 Docker Desktop,此卷位于 Docker Desktop VM 的文件系统中,可以使用以下命令访问:

docker run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh

Scheduler 持久化卷可以通过预先存在的自定义卷或由 Dapr 创建的卷来修改。

dapr init --scheduler-volume my-scheduler-volume

2.1.7 - 在自托管环境中升级 Dapr 的步骤

按照以下步骤在自托管模式下升级 Dapr 并确保顺利升级
  1. 卸载当前的 Dapr 部署:

    dapr uninstall --all
    
  2. 通过访问此指南下载并安装最新的 CLI。

  3. 初始化 Dapr runtime:

    dapr init
    
  4. 使用以下命令确保您使用的是最新版本的 Dapr (v1.18.0):

    $ dapr --version
    
    CLI version: 1.18
    Runtime version: 1.18
    

2.1.8 - 在自托管环境中卸载 Dapr

从本地机器移除 Dapr 的步骤

以下 CLI 命令移除 Dapr 边车二进制文件和 placement 容器:

dapr uninstall

上述命令默认不会移除在 dapr init 期间安装的 Redis 或 Zipkin 容器,以防您将它们用于其他用途。若要移除 Redis、Zipkin、Actor Placement 容器,以及位于 $HOME/.dapr%USERPROFILE%\.dapr\ 的默认 Dapr 目录,请运行:

dapr uninstall --all

2.2 - 在 Kubernetes 模式下部署和运行 Dapr

如何在您的 Kubernetes 集群上启动并运行 Dapr

2.2.1 - Kubernetes 上运行 Dapr 概述

如何在 Kubernetes 集群上运行 Dapr 的概述

Dapr 可以配置为在任何受支持的 Kubernetes 版本上运行。为此,Dapr 首先部署以下 Kubernetes 服务,这些服务提供一流集成,使使用 Dapr 运行应用程序变得简单。

Kubernetes 服务描述
dapr-operator管理 组件 更新和 Dapr 的 Kubernetes 服务端点(状态存储、发布订阅等)
dapr-sidecar-injector将 Dapr 注入到已添加注解的部署 Pod 中,并添加环境变量 DAPR_HTTP_PORTDAPR_GRPC_PORT,以使用户定义的应用程序能够轻松与 Dapr 通信,而无需硬编码 Dapr 端口值。
dapr-placement仅用于 Actor。创建将 actor 实例映射到 Pod 的映射表
dapr-sentry管理服务之间的 mTLS 并充当证书颁发机构。有关更多信息,请阅读安全概述
dapr-scheduler提供由 Jobs API、Workflow API 和 Actor Reminders 使用的分布式作业调度功能

支持的版本

Dapr 对 Kubernetes 的支持与 Kubernetes 版本偏差策略保持一致。

将 Dapr 部署到 Kubernetes 集群

阅读在 Kubernetes 集群上部署 Dapr以了解如何将 Dapr 部署到您的 Kubernetes 集群。

将 Dapr 添加到 Kubernetes 部署

在 Kubernetes 集群中部署和运行启用 Dapr 的应用程序非常简单,只需在 Pod 架构中添加几个注解即可。例如,在以下示例中,您的 Kubernetes Pod 被注解为:

  • 为您的服务提供一个 Dapr 已知的 idport
  • 通过配置启用追踪
  • 启动 Dapr 边车容器
  annotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "nodeapp"
    dapr.io/app-port: "3000"
    dapr.io/config: "tracing"

有关更多信息,请查看 Dapr 注解

从私有注册表拉取容器镜像

无论用户应用程序容器镜像来自何处,Dapr 都可以与其无缝协作。只需初始化 Dapr并将 Dapr 注解添加到您的 Kubernetes 定义中,即可添加 Dapr 边车。

Dapr 控制平面和边车镜像来自 daprio Docker Hub 容器注册表,这是一个公共注册表。

有关以下方面的信息:

  • 从私有注册表拉取应用程序镜像,请参考 官方 Kubernetes 文档
  • 将 Azure Container Registry 与 Azure Kubernetes Service 结合使用,请参考 AKS 文档

教程

通过Hello Kubernetes 教程了解有关在 Kubernetes 集群上开始使用 Dapr 的更多信息。

相关链接

2.2.2 - Kubernetes 集群设置

如何创建 Kubernetes 集群

2.2.2.1 - 设置 Minikube 集群

如何设置 Minikube 集群

前置条件

启动 Minikube 集群

  1. 如果你的项目需要,设置默认虚拟机。

    minikube config set vm-driver [driver_name]
    
  2. 启动集群。如有必要,使用 --kubernetes-version 指定 Kubernetes 1.13.x 或更高版本

    minikube start --cpus=4 --memory=4096
    
  3. 启用 Minikube 仪表板和 ingress 插件。

    # 启用仪表板
    minikube addons enable dashboard
    
    # 启用 ingress
    minikube addons enable ingress
    

安装 Helm v3(可选)

如果你使用 Helm,请安装 Helm v3 客户端

故障排除

通过 kubectl get svc 无法显示负载均衡器的外部 IP 地址。

在 Minikube 中,kubectl get svc 中的 EXTERNAL-IP 对你的服务显示 <pending> 状态。在这种情况下,你可以运行 minikube service [service_name] 来打开你的服务,而无需外部 IP 地址。

$ kubectl get svc
NAME                        TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)            AGE
...
calculator-front-end        LoadBalancer   10.103.98.37     <pending>     80:30534/TCP       25h
calculator-front-end-dapr   ClusterIP      10.107.128.226   <none>        80/TCP,50001/TCP   25h
...

$ minikube service calculator-front-end
|-----------|----------------------|-------------|---------------------------|
| NAMESPACE |         NAME         | TARGET PORT |            URL            |
|-----------|----------------------|-------------|---------------------------|
| default   | calculator-front-end |             | http://192.168.64.7:30534 |
|-----------|----------------------|-------------|---------------------------|
🎉  Opening kubernetes service  default/calculator-front-end in default browser...

相关链接

2.2.2.2 - 设置 KiND 集群

如何设置 KiND 集群

前置条件

安装和配置 KiND

请参阅 KiND 文档进行安装。

如果您使用的是 Docker Desktop,请确保您已配置推荐的设置

配置和创建 KiND 集群

  1. 创建一个名为 kind-cluster-config.yaml 的文件,并粘贴以下内容:

    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    nodes:
    - role: control-plane
      kubeadmConfigPatches:
      - |
        kind: InitConfiguration
        nodeRegistration:
          kubeletExtraArgs:
            node-labels: "ingress-ready=true"
      extraPortMappings:
      - containerPort: 80
        hostPort: 8081
        protocol: TCP
      - containerPort: 443
        hostPort: 8443
        protocol: TCP
    - role: worker
    - role: worker
    

    此集群配置:

    • 请求 KiND 启动一个由控制平面和两个工作节点组成的 Kubernetes 集群。
    • 允许后续设置入口。
    • 将容器端口暴露到主机。
  2. 运行 kind create cluster 命令,提供集群配置文件:

    kind create cluster --config kind-cluster-config.yaml
    

    预期输出

    Creating cluster "kind" ...
     ✓ Ensuring node image (kindest/node:v1.21.1) 🖼
     ✓ Preparing nodes 📦 📦 📦
     ✓ Writing configuration 📜
     ✓ Starting control-plane 🕹️
     ✓ Installing CNI 🔌
     ✓ Installing StorageClass 💾
     ✓ Joining worker nodes 🚜
    Set kubectl context to "kind-kind"
    You can now use your cluster with:
    
    kubectl cluster-info --context kind-kind
    
    Thanks for using kind! 😊
    

初始化和运行 Dapr

  1. 在 Kubernetes 中初始化 Dapr。

    dapr init --kubernetes
    

    Dapr 完成初始化后,您可以在集群上使用其核心组件。

  2. 验证 Dapr 组件的状态:

    dapr status -k
    

    预期输出

      NAME                   NAMESPACE    HEALTHY  STATUS   REPLICAS  VERSION  AGE  CREATED
      dapr-sentry            dapr-system  True     Running  1         1.5.1    53s  2021-12-10 09:27.17
      dapr-operator          dapr-system  True     Running  1         1.5.1    53s  2021-12-10 09:27.17
      dapr-sidecar-injector  dapr-system  True     Running  1         1.5.1    53s  2021-12-10 09:27.17
      dapr-dashboard         dapr-system  True     Running  1         0.9.0    53s  2021-12-10 09:27.17
      dapr-placement-server  dapr-system  True     Running  1         1.5.1    52s  2021-12-10 09:27.18
    
  3. 转发端口到 Dapr 仪表板

    dapr dashboard -k -p 9999
    
  4. 导航到 http://localhost:9999 以验证设置成功。

在 Kind Kubernetes 集群上安装 metrics-server

  1. 获取 metrics-server 清单文件

    wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
    
  2. 向 components.yaml 文件添加不安全的 TLS 参数

    metadata:
       labels:
         k8s-app: metrics-server
     spec:
       containers:
       - args:
         - --cert-dir=/tmp
         - --secure-port=4443
         - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
         - --kubelet-use-node-status-port
         - --kubelet-insecure-tls   <==== 添加此行
         - --metric-resolution=15s
         image: k8s.gcr.io/metrics-server/metrics-server:v0.6.2
         imagePullPolicy: IfNotPresent
         livenessProbe:
           failureThreshold: 3
           httpGet:
             path: /livez
    
  3. 应用修改后的清单文件

    kubectl apply -f components.yaml
    

相关链接

2.2.2.3 - 设置 Azure Kubernetes Service (AKS) 集群

了解如何设置 Azure Kubernetes 集群

本指南将引导您完成安装 Azure Kubernetes Service (AKS) 集群的过程。如需更多信息,请参阅快速入门:使用 Azure CLI 部署 AKS 集群

前置条件

部署 AKS 集群

  1. 在终端中,登录到 Azure。

    az login
    
  2. 设置您的默认订阅:

    az account set -s [your_subscription_id]
    
  3. 创建资源组。

    az group create --name [your_resource_group] --location [region]
    
  4. 创建 AKS 集群。若要使用特定版本的 Kubernetes,请使用 --kubernetes-version(需要 1.13.x 或更新版本)。

    az aks create --resource-group [your_resource_group] --name [your_aks_cluster_name] --location [region] --node-count 2 --enable-app-routing --generate-ssh-keys
    
  5. 获取 AKS 集群的访问凭据。

    az aks get-credentials -n [your_aks_cluster_name] -g [your_resource_group]
    

AKS Edge Essentials

若要使用 Azure Kubernetes Service (AKS) Edge Essentials 创建单机 K8s/K3s 仅 Linux 集群,您可以参阅AKS Edge Essentials 快速入门指南

相关链接

2.2.2.4 - 设置 Google Kubernetes Engine (GKE) 集群

设置 Google Kubernetes Engine 集群

前置条件

创建新集群

通过运行以下命令创建 GKE 集群:

$ gcloud services enable container.googleapis.com && \
  gcloud container clusters create $CLUSTER_NAME \
  --zone $ZONE \
  --project $PROJECT_ID

更多选项:

私有 GKE 集群的边车注入

私有集群的边车注入需要额外步骤。

在私有 GKE 集群中,为 master 访问自动创建的防火墙规则不会打开端口 4000,而 Dapr 需要该端口进行边车注入。

查看相关的防火墙规则:

$ gcloud compute firewall-rules list --filter="name~gke-${CLUSTER_NAME}-[0-9a-z]*-master"

替换现有规则并允许 Kubernetes master 访问端口 4000:

$ gcloud compute firewall-rules update <firewall-rule-name> --allow tcp:10250,tcp:443,tcp:4000

获取 kubectl 凭据

运行以下命令获取凭据:

$ gcloud container clusters get-credentials $CLUSTER_NAME \
    --zone $ZONE \
    --project $PROJECT_ID

安装 Helm v3(可选)

如果您使用 Helm,请安装 Helm v3 客户端

故障排查

Kubernetes dashboard 权限

假设您收到类似以下的错误消息:

configmaps is forbidden: User "system:serviceaccount:kube-system:kubernetes-dashboard" cannot list configmaps in the namespace "default"

执行此命令:

kubectl create clusterrolebinding kubernetes-dashboard -n kube-system --clusterrole=cluster-admin --serviceaccount=kube-system:kubernetes-dashboard

相关链接

2.2.2.5 - 设置 Elastic Kubernetes Service (EKS) 集群

了解如何设置 EKS 集群

本指南将引导您完成安装 Elastic Kubernetes Service (EKS) 集群的过程。如需更多信息,请参阅创建 Amazon EKS 集群

前置条件

部署 EKS 集群

  1. 在终端中登录 AWS。

    aws configure
    
  2. 创建一个名为 cluster-config.yaml 的新文件并添加以下内容,将 [your_cluster_name][your_cluster_region][your_k8s_version] 替换为适当的值:

    apiVersion: eksctl.io/v1alpha5
    kind: ClusterConfig
    
    metadata:
      name: [your_cluster_name]
      region: [your_cluster_region]
      version: [your_k8s_version]
      tags:
        karpenter.sh/discovery: [your_cluster_name]
    
    iam:
      withOIDC: true
    
    managedNodeGroups:
      - name: mng-od-4vcpu-8gb
        desiredCapacity: 2
        minSize: 1
        maxSize: 5
        instanceType: c5.xlarge
        privateNetworking: true
    
    addons:
      - name: vpc-cni 
        attachPolicyARNs:
          - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
      - name: coredns
        version: latest 
      - name: kube-proxy
        version: latest
      - name: aws-ebs-csi-driver
        wellKnownPolicies: 
          ebsCSIController: true
    
  3. 通过运行以下命令创建集群:

    eksctl create cluster -f cluster-config.yaml
    
  4. 验证 kubectl 上下文:

    kubectl config current-context
    

添加 Dapr 的边车访问和默认存储类要求

  1. 更新安全组规则以允许 EKS 集群与 Dapr 边车通信,为端口 4000 创建入站规则。

    aws ec2 authorize-security-group-ingress --region [your_aws_region] \
    --group-id [your_security_group] \
    --protocol tcp \
    --port 4000 \
    --source-group [your_security_group]
    
  2. 如果您没有默认存储类,请添加一个:

kubectl patch storageclass gp2 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

安装 Dapr

通过运行以下命令在集群上安装 Dapr:

dapr init -k

您应该看到以下响应:

⌛  Making the jump to hyperspace...
ℹ️  Note: To install Dapr using Helm, see here: https://docs.dapr.io/getting-started/install-dapr-kubernetes/#install-with-helm-advanced

ℹ️  Container images will be pulled from Docker Hub
✅  Deploying the Dapr control plane with latest version to your cluster...
✅  Deploying the Dapr dashboard with latest version to your cluster...
✅  Success! Dapr has been installed to namespace dapr-system. To verify, run `dapr status -k' in your terminal. To get started, go here: https://docs.dapr.io/getting-started

服务账户的 IAM 角色 (IRSA)

您可以为 dapr_rbac Helm 子图表创建的 ServiceAccounts 附加自定义注解——这对于在 AWS EKS 上启用服务账户的 IAM 角色 (IRSA) 非常有用。 这可以通过 EKS 的 IRSA 机制为 Dapr 组件启用细粒度的安全访问控制。 更新您的 Dapr Helm 值文件以包含以下 ServiceAccounts 所需的注解。

有关 AWS 身份验证的更多信息,请参阅此处

serviceAccount:
  operator:
    annotations:
      eks.amazonaws.com/role-arn: arn:aws:iam::<ACCOUNT_ID>:role/operator-role
  injector:
    annotations: {}
  placement:
    annotations: {}
  scheduler:
    annotations: {}
  sentry:
    annotations: {}

故障排除

访问权限

如果遇到任何访问权限问题,请确保您使用的是创建集群时所用的同一 AWS 配置文件。如需要,请使用正确的配置文件更新 kubectl 配置。更多信息请参见此处

aws eks --region [your_aws_region] update-kubeconfig --name [your_eks_cluster_name] --profile [your_profile_name]

相关链接

2.2.3 - 在 Kubernetes 集群上部署 Dapr

按照以下步骤在 Kubernetes 上部署 Dapr。

Kubernetes 上设置 Dapr 时,您可以使用 Dapr CLI 或 Helm。

使用 Dapr CLI 安装

您可以使用 Dapr CLI 在 Kubernetes 集群上安装 Dapr。

前置条件

安装选项

您可以从官方 Helm chart 或私有 chart 安装 Dapr,使用自定义命名空间等。

从官方 Dapr Helm chart 安装 Dapr

-k 标志会在当前上下文的 Kubernetes 集群上初始化 Dapr。

  1. 通过检查 kubectl context (kubectl config get-contexts) 验证是否设置了正确的"目标"集群。

    • 您可以使用 kubectl config use-context <CONTEXT> 设置不同的上下文。
  2. 使用以下命令在集群上初始化 Dapr:

    dapr init -k
    

    预期输出

    ⌛  Making the jump to hyperspace...
    
    ✅  Deploying the Dapr control plane to your cluster...
    ✅  Success! Dapr has been installed to namespace dapr-system. To verify, run "dapr status -k" in your terminal. To get started, go here: https://aka.ms/dapr-getting-started
    
  3. 运行仪表板:

    dapr dashboard -k
    

    如果您在非默认命名空间中安装了 Dapr,请运行:

    dapr dashboard -k -n <your-namespace>
    

从官方 Dapr Helm chart 安装 Dapr(带开发标志)

添加 --dev 标志会在当前上下文的 Kubernetes 集群上初始化 Dapr,并额外部署 Redis 和 Zipkin。

步骤与从 Dapr Helm chart 安装类似,只需在 init 命令中添加 --dev 标志:

dapr init -k --dev

预期输出:

⌛  Making the jump to hyperspace...
ℹ️  Note: To install Dapr using Helm, see here: https://docs.dapr.io/getting-started/install-dapr-kubernetes/#install-with-helm-advanced

ℹ️  Container images will be pulled from Docker Hub
✅  Deploying the Dapr control plane with latest version to your cluster...
✅  Deploying the Dapr dashboard with latest version to your cluster...
✅  Deploying the Dapr Redis with latest version to your cluster...
✅  Deploying the Dapr Zipkin with latest version to your cluster...
ℹ️  Applying "statestore" component to Kubernetes "default" namespace.
ℹ️  Applying "pubsub" component to Kubernetes "default" namespace.
ℹ️  Applying "appconfig" zipkin configuration to Kubernetes "default" namespace.
✅  Success! Dapr has been installed to namespace dapr-system. To verify, run `dapr status -k' in your terminal. To get started, go here: https://aka.ms/dapr-getting-started

等待一小段时间(或使用 --wait 标志并指定等待时间),您可以检查 Redis 和 Zipkin 组件是否已部署到集群。

kubectl get pods --namespace default

预期输出:

NAME                              READY   STATUS    RESTARTS   AGE
dapr-dev-zipkin-bfb4b45bb-sttz7   1/1     Running   0          159m
dapr-dev-redis-master-0           1/1     Running   0          159m
dapr-dev-redis-replicas-0         1/1     Running   0          159m
dapr-dev-redis-replicas-1         1/1     Running   0          159m
dapr-dev-redis-replicas-2         1/1     Running   0          158m 

从私有 Dapr Helm chart 安装 Dapr

私有 Helm chart 安装 Dapr在以下情况下很有帮助:

  • 需要对 Dapr Helm chart 进行更细粒度的控制
  • 有自定义的 Dapr 部署
  • 从由您的组织管理和维护的可信注册表中拉取 Helm chart

设置以下参数以允许 dapr init -k 从配置的 Helm 仓库安装 Dapr 镜像。

export DAPR_HELM_REPO_URL="https://helm.custom-domain.com/dapr/dapr"
export DAPR_HELM_REPO_USERNAME="username_xxx"
export DAPR_HELM_REPO_PASSWORD="passwd_xxx"

以高可用模式安装

您可以在 dapr-system 命名空间中为每个控制平面 pod 运行三个副本,以适用于生产场景

dapr init -k --enable-ha=true

在自定义命名空间中安装

初始化 Dapr 时的默认命名空间是 dapr-system。您可以使用 -n 标志覆盖它。

dapr init -k -n mynamespace

禁用 mTLS

Dapr 默认使用 mTLS 初始化。您可以通过以下方式禁用它:

dapr init -k --enable-mtls=false

等待安装完成

您可以使用 --wait 标志等待安装完成部署。默认超时时间为 300 秒(5 分钟),但可以使用 --timeout 标志进行自定义。

dapr init -k --wait --timeout 600

使用 CLI 在 Kubernetes 上卸载 Dapr

在本地计算机上运行以下命令以卸载集群上的 Dapr:

dapr uninstall -k

使用 Helm 安装

您可以使用 Helm v3 chart 在 Kubernetes 上安装 Dapr。

重要提示: 最新的 Dapr Helm chart 不再支持 Helm v2。从 Helm v2 迁移到 Helm v3

前置条件

添加并安装 Dapr Helm chart

  1. 添加 Helm 仓库并更新:

    // 添加官方 Dapr Helm chart。
    helm repo add dapr https://dapr.github.io/helm-charts/
    // 或者添加私有 Dapr Helm chart。
    helm repo add dapr http://helm.custom-domain.com/dapr/dapr/ \
       --username=xxx --password=xxx
    helm repo update
    // 查看可用的 chart 版本
    helm search repo dapr --devel --versions
    
  2. dapr-system 命名空间中的集群上安装 Dapr chart。

    helm upgrade --install dapr dapr/dapr \
    --version=1.18 \
    --namespace dapr-system \
    --create-namespace \
    --wait
    

    要以高可用模式安装:

    helm upgrade --install dapr dapr/dapr \
    --version=1.18 \
    --namespace dapr-system \
    --create-namespace \
    --set global.ha.enabled=true \
    --wait
    

    要以高可用模式安装并独立于全局扩展选定的服务:

        helm upgrade --install dapr dapr/dapr \
     --version=1.18 \
     --namespace dapr-system \
     --create-namespace \
     --set global.ha.enabled=false \
     --set dapr_scheduler.ha=true \
     --set dapr_placement.ha=true \
     --wait
    

有关使用 Helm 安装和升级 Dapr 的更多信息,请参阅 Kubernetes 上生产就绪部署的指南

(可选)将 Dapr 仪表板作为控制平面的一部分安装

如果要安装 Dapr 仪表板,请使用此 Helm chart 并添加您选择的其他设置:

helm install dapr dapr/dapr-dashboard --namespace dapr-system

例如:

helm repo add dapr https://dapr.github.io/helm-charts/
helm repo update
kubectl create namespace dapr-system
# 安装 Dapr 仪表板
helm install dapr-dashboard dapr/dapr-dashboard --namespace dapr-system

验证安装

安装完成后,验证 dapr-operatordapr-placementdapr-sidecar-injectordapr-sentry pod 是否在 dapr-system 命名空间中运行:

kubectl get pods --namespace dapr-system
NAME                                     READY     STATUS    RESTARTS   AGE
dapr-dashboard-7bd6cbf5bf-xglsr          1/1       Running   0          40s
dapr-operator-7bd6cbf5bf-xglsr           1/1       Running   0          40s
dapr-placement-7f8f76778f-6vhl2          1/1       Running   0          40s
dapr-sidecar-injector-8555576b6f-29cqm   1/1       Running   0          40s
dapr-sentry-9435776c7f-8f7yd             1/1       Running   0          40s

在 Kubernetes 上卸载 Dapr

helm uninstall dapr --namespace dapr-system

更多信息

使用基于 Mariner 的镜像

在 Kubernetes 上拉取的默认容器镜像基于 distroless

或者,您可以使用基于 Mariner 2(最小 distroless)的 Dapr 容器镜像。Mariner,正式名称为 CBL-Mariner,是由 Microsoft 维护的免费开源 Linux 发行版和容器基础镜像。对于某些 Dapr 用户,利用基于 Mariner 的容器镜像可以帮助您满足合规性要求。

要为 Dapr 使用基于 Mariner 的镜像,您需要在 Docker 标签中添加 -mariner。例如,虽然 ghcr.io/dapr/dapr:latest 是基于 distroless 的 Docker 镜像,但 ghcr.io/dapr/dapr:latest-mariner 基于 Mariner。也可以使用特定版本的标签,例如 1.18-mariner

在 Dapr CLI 中,您可以使用 --image-variant 标志切换到使用基于 Mariner 的镜像。

dapr init -k --image-variant mariner

使用 Kubernetes 和 Helm,您可以通过设置 global.tag 选项并添加 -mariner 来使用基于 Mariner 的镜像。例如:

helm upgrade --install dapr dapr/dapr \
  --version=1.18 \
  --namespace dapr-system \
  --create-namespace \
  --set global.tag=1.18.0-mariner \
  --wait

相关链接

2.2.4 - 在 Kubernetes 集群上升级 Dapr

按照以下步骤在 Kubernetes 上升级 Dapr 并确保平滑升级。

您可以使用 Dapr CLI 或 Helm 在 Kubernetes 集群上升级 Dapr 控制平面。

使用 Dapr CLI 升级

您可以使用 Dapr CLI 来升级 Dapr。

前置条件

升级现有集群至 1.18.0

dapr upgrade -k --runtime-version=1.18.0

您可以使用 Dapr CLI 提供所有可用的 Helm chart 配置。

通过 CLI 进行升级的故障排查

在可能曾经安装过早于 1.0.0-rc.2 版本的集群上运行升级时,存在一个已知问题。

虽然这种情况很少见,但一些升级路径的边缘情况可能会在集群上留下不兼容的 CustomResourceDefinition。如果您遇到这种情况,您可能会看到类似如下的错误消息:

❌  Failed to upgrade Dapr: Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
The CustomResourceDefinition "configurations.dapr.io" is invalid: spec.preserveUnknownFields: Invalid value: true: must be false in order to use defaults in the schema

解决方案

  1. 运行以下命令将 CustomResourceDefinition 升级到兼容版本:

    kubectl replace -f https://raw.githubusercontent.com/dapr/dapr/release-1.18/charts/dapr/crds/configuration.yaml
    
  2. 继续执行 dapr upgrade --runtime-version 1.18.0 -k 命令。

使用 Helm 升级

您可以使用 Helm v3 chart 升级 Dapr。

重要提示: 最新的 Dapr Helm chart 不再支持 Helm v2。从 Helm v2 迁移到 Helm v3

前置条件

升级现有集群至 1.18.0

从 1.0.0 版本开始,使用 Helm 升级 Dapr 时,现有的证书值将自动被复用。

注意 Helm 不处理资源的升级,因此您需要手动执行该操作。资源具有向后兼容性,应仅向前安装。

  1. 将 Dapr 升级到版本 1.18.0:

    kubectl replace -f https://raw.githubusercontent.com/dapr/dapr/v1.18.0/charts/dapr/crds/components.yaml
    kubectl replace -f https://raw.githubusercontent.com/dapr/dapr/v1.18.0/charts/dapr/crds/configuration.yaml
    kubectl replace -f https://raw.githubusercontent.com/dapr/dapr/v1.18.0/charts/dapr/crds/subscription.yaml
    kubectl apply -f https://raw.githubusercontent.com/dapr/dapr/v1.18.0/charts/dapr/crds/resiliency.yaml
    kubectl apply -f https://raw.githubusercontent.com/dapr/dapr/v1.18.0/charts/dapr/crds/httpendpoints.yaml
    
    helm repo update
    
    helm upgrade dapr dapr/dapr --version 1.18.0 --namespace dapr-system --wait
    

    如果您正在使用 values 文件,请记得在运行升级命令时添加 --values 选项。

  2. 确保所有 pod 都在运行:

    kubectl get pods -n dapr-system -w
    
    NAME                                     READY   STATUS    RESTARTS   AGE
    dapr-dashboard-69f5c5c867-mqhg4          1/1     Running   0          42s
    dapr-operator-5cdd6b7f9c-9sl7g           1/1     Running   0          41s
    dapr-placement-server-0                  1/1     Running   0          41s
    dapr-sentry-84565c747b-7bh8h             1/1     Running   0          35s
    dapr-sidecar-injector-68f868668f-6xnbt   1/1     Running   0          41s
    
  3. 重启您的应用程序部署以更新 Dapr 运行时:

    kubectl rollout restart deploy/<DEPLOYMENT-NAME>
    

升级现有 Dapr 部署以启用高可用模式

通过一些额外步骤在现有 Dapr 部署中启用高可用模式。

相关链接

2.2.5 - Kubernetes 生产环境指南

以生产就绪配置在 Kubernetes 集群上部署 Dapr 的最佳实践

集群和容量要求

Dapr 对 Kubernetes 的支持遵循 Kubernetes 版本倾斜策略

使用以下资源设置作为起点。具体要求因集群规模、Pod 数量和其他因素而异。请执行单独测试以找到适合您环境的正确值。在生产环境中,建议不要为 Dapr 控制平面组件添加内存限制,以避免 OOMKilled Pod 状态。

部署CPU内存
Operator限制:1,请求:100m请求:100Mi
Sidecar Injector限制:1,请求:100m请求:30Mi
Sentry限制:1,请求:100m请求:30Mi
Placement限制:1,请求:250m请求:75Mi

Helm

使用 Helm 安装 Dapr 时,默认不设置限制/请求值。每个组件都有一个 resources 选项(例如 dapr_dashboard.resources),您可以使用它来调整 Dapr 控制平面以适应您的环境。

Helm chart readme 包含详细信息和示例。

对于本地/开发安装,您可能希望跳过配置 resources 选项。

可选组件

以下 Dapr 控制平面部署是可选的:

  • Placement:用于使用 Dapr Actors
  • Sentry:用于服务间调用的 mTLS
  • Dashboard:用于集群的操作视图

边车资源设置

使用支持的注解为 Dapr 边车设置资源分配。与资源限制相关的具体注解为:

  • dapr.io/sidecar-cpu-limit
  • dapr.io/sidecar-memory-limit
  • dapr.io/sidecar-cpu-request
  • dapr.io/sidecar-memory-request

如果未设置,Dapr 边车将在没有资源设置的情况下运行,这可能导致问题。对于生产就绪的设置,强烈建议配置这些设置。

生产就绪设置中 Dapr 边车的示例设置:

CPU内存
限制:300m,请求:100m限制:1000Mi,请求:250Mi

上述 CPU 和内存限制考虑到了 Dapr 支持大量 I/O 密集型操作。使用监控工具 获取边车(和应用)容器的基线,并根据这些基线调整这些设置。

有关在 Kubernetes 中配置资源的更多详细信息,请参阅以下 Kubernetes 指南:

为 Dapr 边车设置软内存限制

当您已设置内存限制时,为 Dapr 边车设置软内存限制。使用软内存限制时,边车垃圾回收器会在超过限制时释放内存,而不是等待内存达到运行时堆中上次内存量的两倍。等待是 Go 中使用的垃圾回收器的默认行为,可能导致 OOM 终止事件。

例如,对于 app-id 为 nodeapp 且内存限制设置为 1000Mi 的应用程序,您可以在 Pod 注解中使用以下内容:

  annotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "nodeapp"
    # 我们的 daprd 内存设置
    dapr.io/sidecar-memory-limit: "1000Mi"   # 您的内存限制
    dapr.io/env: "GOMEMLIMIT=900MiB"         # 您内存限制的 90%。还要注意后缀 "MiB" 而不是 "Mi"

在此示例中,软限制已设置为 90% 以留出 5-10% 给其他服务,正如建议的那样

GOMEMLIMIT 环境变量允许内存大小使用某些后缀:BKiBMiBGiBTiB

用于企业策略的边车服务注解

在企业环境中,集群策略可能会强制所有 Service 资源使用强制性注解,用于安全、计费或网络策略目的。Dapr Operator 为边车创建一个 Service,该服务可能需要这些自定义注解以符合您组织的策略。

您可以使用 dapr.io/sidecar-svc-annotations 注解将这些必需的注解添加到 Dapr 边车服务。

了解如何为 Dapr 边车服务配置自定义注解

高可用模式

在生产就绪配置中部署 Dapr 时,最好以控制平面的高可用(HA)配置进行部署。这会在 dapr-system 命名空间中为每个控制平面 Pod 创建三个副本,使 Dapr 控制平面能够保持三个运行实例,并在单个节点故障和其他中断中存活。

对于新的 Dapr 部署,可以通过以下方式设置 HA 模式:

对于现有的 Dapr 部署,您可以通过一些额外步骤启用 HA 模式

单个服务 HA Helm 配置

您可以通过将 global.ha.enabled 标志设置为 true 来通过 Helm 在所有服务中配置 HA 模式。默认情况下,--set global.ha.enabled=true 被完全遵守且不能被覆盖,这使得 placement 或 scheduler 服务无法同时作为单个实例运行。

注意: scheduler 和 placement 服务的 HA 不是默认设置。

要独立于 global.ha.enabled 标志将 scheduler 和 placement 扩展到三个实例,请将 global.ha.enabled 设置为 false,并将 dapr_scheduler.hadapr_placement.ha 设置为 true。例如:

helm upgrade --install dapr dapr/dapr \
 --version=1.18 \
 --namespace dapr-system \
 --create-namespace \
 --set global.ha.enabled=false \
 --set dapr_scheduler.ha=true \
 --set dapr_placement.ha=true \
 --wait

为控制平面服务设置集群关键优先级类名称

在某些情况下,节点可能面临内存和/或 CPU 压力,Dapr 控制平面 Pod 可能会被选中进行驱逐。为了防止这种情况,您可以为 Dapr 控制平面 Pod 设置关键优先级类名称。这确保 Dapr 控制平面 Pod 不会被驱逐,除非所有其他较低优先级的 Pod 都被驱逐。

保护 Dapr 控制平面组件免于驱逐尤为重要,尤其是 Scheduler 服务。当 Scheduler 被重新调度或重启时,可能会对正在进行的作业造成严重破坏,可能导致它们重复触发。为了防止这种破坏,您应该确保 Dapr 控制平面组件比您的工作负载具有更高的优先级类。

了解有关保护任务关键型 Pod 的更多信息。

Kubernetes 中有两个内置的关键优先级类:

  • system-cluster-critical
  • system-node-critical(最高优先级)

建议为 Dapr 控制平面 Pod 将 priorityClassName 设置为 system-cluster-critical。如果您有自己的应用程序自定义优先级类,请确保它们的优先级值低于分配给 Dapr 控制平面的优先级值,以维持系统稳定性并防止核心 Dapr 服务中断。

对于新的 Dapr 控制平面部署,可以通过 Helm 值 global.priorityClassName 设置 system-cluster-critical 优先级类模式。

此优先级类可以通过 Dapr CLI 和 Helm charts 设置,使用 Helm --set global.priorityClassName=system-cluster-critical 参数。

Dapr 版本 < 1.14

对于 v1.14 以下的 Dapr 版本,建议您向 Dapr 控制平面命名空间添加 ResourceQuota。这可以防止与调度 Pod 相关的问题,集群可能配置了关于哪些 Pod 可以分配高优先级类的限制。从 v1.14 开始,Helm chart 会自动添加此功能。

如果您在命名空间 dapr-system 中安装了 Dapr,可以使用以下内容创建 ResourceQuota

apiVersion: v1
kind: ResourceQuota
metadata:
  name: dapr-system-critical-quota
  namespace: dapr-system
spec:
  scopeSelector:
    matchExpressions:
      - operator : In
        scopeName: PriorityClass
        values: [system-cluster-critical]

使用 Helm 部署 Dapr

访问使用 Helm 部署 Dapr 的完整指南

参数文件

建议创建一个 values 文件,而不是在命令行上指定参数。将 values 文件检入源代码管理,以便您可以跟踪其更改。

查看可用参数和设置的完整列表

以下命令在 dapr-system 命名空间中运行每个控制平面服务的三个副本。

# 添加/更新官方 Dapr Helm 仓库。
helm repo add dapr https://dapr.github.io/helm-charts/
# 或添加/更新私有 Dapr Helm 仓库。
helm repo add dapr http://helm.custom-domain.com/dapr/dapr/ \
   --username=xxx --password=xxx
helm repo update

# 查看有哪些 chart 版本可用
helm search repo dapr --devel --versions

# 创建一个 values 文件来存储变量
touch values.yml
cat << EOF >> values.yml
global:
  ha:
    enabled: true
EOF

# 运行安装/升级
helm install dapr dapr/dapr \
  --version=<Dapr chart version> \
  --namespace dapr-system \
  --create-namespace \
  --values values.yml \
  --wait

# 验证安装
kubectl get pods --namespace dapr-system

Dapr Helm chart 会自动部署到带有标签 kubernetes.io/os=linux 的节点。您可以将 Dapr 控制平面部署到 Windows 节点。有关更多信息,请参阅部署到混合 Linux/Windows K8s 集群

使用 Helm 升级 Dapr

Dapr 支持以下步骤的零停机升级。

升级 CLI(推荐)

升级 CLI 是可选的,但推荐这样做。

  1. 下载最新版本的 CLI。
  2. 验证 Dapr CLI 在您的路径中。

升级控制平面

在 Kubernetes 集群上升级 Dapr

更新数据平面(边车)

更新运行 Dapr 的 Pod 以获取新版本的 Dapr 运行时。

  1. 为任何具有 dapr.io/enabled 注解的部署发出滚动重启命令:

    kubectl rollout restart deploy/<Application deployment name>
    
  2. 通过以下方式查看所有启用 Dapr 的部署列表:

    • Dapr Dashboard

    • 使用 Dapr CLI 运行以下命令:

      dapr list -k
      
      APP ID     APP PORT  AGE  CREATED
      nodeapp    3000      16h  2020-07-29 17:16.22
      

在现有 Dapr 部署中启用高可用性

为现有 Dapr 部署启用 HA 模式需要两个步骤:

  1. 删除现有的 placement stateful set。

    kubectl delete statefulset.apps/dapr-placement-server -n dapr-system
    

    您删除 placement stateful set 是因为在 HA 模式下,placement 服务会添加 Raft 用于领导者选举。但是,Kubernetes 只允许对 stateful set 的有限字段进行修补,从而导致 placement 服务升级失败。

    删除现有的 placement stateful set 是安全的。代理会重新连接并重新注册到新创建的 placement 服务,该服务将其表持久化在 Raft 中。

  2. 发出升级命令。

    helm upgrade dapr ./charts/dapr -n dapr-system --set global.ha.enabled=true
    

推荐的安全配置

正确配置后,Dapr 可确保安全通信,并可以通过许多内置功能使您的应用程序更安全。

验证您的生产就绪部署包括以下设置:

  1. 双向身份验证(mTLS) 已启用。Dapr 默认启用 mTLS。了解有关如何使用自己的证书的更多信息

  2. 应用程序到 Dapr API 身份验证 已启用。这是您的应用程序与 Dapr 边车之间的通信。为了保护 Dapr API 免受未经授权的应用程序访问,请启用 Dapr 的基于令牌的身份验证

  3. Dapr 到应用程序 API 身份验证 已启用。这是 Dapr 与您的应用程序之间的通信。让 Dapr 知道它正在使用令牌身份验证与授权应用程序通信

  4. 组件密钥数据在密钥存储中配置,而不是硬编码在组件 YAML 文件中。了解如何将密钥与 Dapr 组件一起使用

  5. Dapr 控制平面安装在专用命名空间上,例如 dapr-system

  6. Dapr 支持并启用为某些应用程序限定组件范围。这不是必需的做法。了解有关组件范围的更多信息

推荐的 Placement 服务配置

Placement 服务 是 Dapr 中的一个组件,负责通过 placement 表向所有 Dapr 边车传播有关 actor 地址的信息(有关更多信息可以在这里找到)。

在生产环境中运行时,建议使用以下值配置 Placement 服务:

  1. 高可用性。确保 Placement 服务高度可用(三个副本)并且可以在单个节点故障中存活。Helm chart 值:dapr_placement.ha=true
  2. 内存日志。使用内存 Raft 日志存储以实现更快的写入。权衡是在最终的 Placement 服务 Pod 故障期间更多的 placement 表传播(因此,网络流量)。Helm chart 值:dapr_placement.cluster.forceInMemoryLog=true
  3. 无元数据端点。禁用未经身份验证的 /placement/state 端点,该端点暴露 Placement 服务的 placement 表信息。Helm chart 值:dapr_placement.metadataEnabled=false
  4. 超时使用以下超时值控制 Placement 服务与边车之间网络连接的敏感性。默认值已设置,但您可以根据您的网络条件调整这些值。
    1. dapr_placement.keepAliveTime 设置 Placement 服务在 gRPC 流上向 Dapr 边车发送保活 ping 以检查连接是否仍处于活动状态的间隔。较低的值将导致在 Pod 丢失/重启情况下更短的 actor 重新平衡时间,但在正常运行期间网络流量更高。接受 1s10s 之间的值。默认为 2s
    2. dapr_placement.keepAliveTimeout 设置 Dapr 边车响应 Placement 服务的保活 ping 的超时时间,然后 Placement 服务关闭连接。较低的值将导致在 Pod 丢失/重启情况下更短的 actor 重新平衡时间,但在正常运行期间网络流量更高。接受 1s10s 之间的值。默认为 3s
    3. dapr_placement.disseminateTimeout 设置在 actor 成员资格更改(通常与 Pod 重启相关)后传播延迟的超时时间,以避免在多个 Pod 重启期间过度传播。较高的值将降低传播频率,但会延迟表传播。接受 1s3s 之间的值。默认为 2s

服务账户令牌

默认情况下,Kubernetes 在每个容器中挂载一个包含服务账户令牌的卷。应用程序可以使用此令牌,其权限根据集群和命名空间的配置等因素而异,以对 Kubernetes 控制平面执行 API 调用。

创建新 Pod(或 Deployment、StatefulSet、Job 等)时,您可以通过在 Pod spec 中设置 automountServiceAccountToken: false 来禁用自动挂载服务账户令牌。

建议您考虑使用 automountServiceAccountToken: false 部署应用程序以提高 Pod 的安全态势,除非您的应用程序依赖于拥有服务账户令牌。例如,如果您有以下情况,您可能需要服务账户令牌:

因此,Dapr 不会自动为您设置 automountServiceAccountToken: false。但是,在您的解决方案不需要服务账户的所有情况下,建议您在 Pod spec 中设置此选项。

追踪和指标配置

追踪和指标在 Dapr 中默认启用。建议您为应用程序和 Dapr 控制平面设置分布式追踪和指标。

如果您已经有自己的可观测性设置,可以禁用 Dapr 的追踪和指标。

追踪

为 Dapr 配置追踪后端

指标

对于指标,Dapr 会暴露一个在端口 9090 上监听的 Prometheus 端点,Prometheus 可以对其进行抓取。

使用 Dapr 设置 Prometheus、Grafana 和其他监控工具

注入器看门狗

Dapr Operator 服务包含一个注入器看门狗,可用于检测和修复应用程序 Pod 可能没有 Dapr 边车(daprd 容器)部署的情况。例如,它可以帮助在集群完全故障后恢复应用程序。

在 Kubernetes 模式下运行 Dapr 时,注入器看门狗默认处于禁用状态。但是,您应该考虑针对您的具体情况使用适当的值启用它。

有关注入器看门狗以及如何启用它的更多详细信息,请参阅 Dapr operator 服务文档

为边车容器配置 seccompProfile

默认情况下,Dapr 边车注入器会注入一个没有任何 seccompProfile 的边车。但是,为了使 Dapr 边车容器在带有受限配置文件的命名空间中成功运行,边车容器需要 securityContext.seccompProfile.Type 不为 nil

请参阅参数和注解概述以在边车容器上设置适当的 seccompProfile

以非 root 用户运行

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

DAPR_UNSAFE_SKIP_CONTAINER_UID_GID_CHECK="true"

最佳实践

观看此视频,深入了解使用 Kubernetes 在生产环境中运行 Dapr 的最佳实践。

相关链接

2.2.6 - 使用 Dapr Shared 每节点或每集群部署 Dapr

了解更多关于使用 Dapr Shared 作为边车替代部署的信息

Dapr 会自动注入一个边车,为您的应用程序启用 Dapr API,以获得最佳的可用性和可靠性。

Dapr Shared 支持两种替代部署策略,可以使用 Kubernetes Daemonset 进行每节点部署,或使用 Deployment 进行每集群部署,从而创建 Dapr 应用程序。

  • DaemonSet:当以 Kubernetes DaemonSet 资源运行 Dapr Shared 时,daprd 容器会在集群中的每个 Kubernetes 节点上运行。这可以减少应用程序与 Dapr 之间的网络跳数。
  • Deployment:当以 Kubernetes Deployment 运行 Dapr Shared 时,Kubernetes 调度器会决定 daprd 容器实例在集群中的哪个单个节点上运行。

为什么选择 Dapr Shared?

默认情况下,当 Dapr 安装到 Kubernetes 集群时,Dapr 控制平面会将 Dapr 作为边车注入到使用 Dapr 注解(dapr.io/enabled: "true")的应用程序中。边车提供了许多优势,包括提高的弹性,因为每个应用程序都有一个实例,并且应用程序与边车之间的所有通信都在不涉及网络的情况下进行。

虽然边车是 Dapr 的默认部署方式,但某些用例需要其他方法。假设您想要将工作负载的生命周期与 Dapr API 解耦。一个典型的例子是函数或函数即服务运行时,它们可能会自动缩减空闲工作负载以释放资源。对于这种情况,可能需要将 Dapr API 和所有 Dapr 异步功能(如订阅)分开保存。

Dapr Shared 正是为这些场景而创建的,它扩展了 Dapr 边车模型,增加了两种新的部署方法:DaemonSet(每节点)和 Deployment(每集群)。

DaemonSet(每节点)

使用 Kubernetes DaemonSet,您可以定义需要在集群中的每个节点部署一次的应用程序。这使得在同一节点上运行的应用程序能够与本地 Dapr API 通信,无论 Kubernetes Scheduler 将您的工作负载调度到何处。

Deployment(每集群)

Kubernetes Deployments 在集群中安装一次。Kubernetes Scheduler 根据可用资源决定工作负载调度到哪个节点。对于 Dapr Shared,这意味着您的工作负载和 Dapr 实例可能位于不同的节点上,这可能会引入相当大的网络延迟,但可以减少资源使用。

Dapr Shared 入门

如果您想开始使用 Dapr Shared,可以通过安装官方 Helm Chart 创建一个新的 Dapr Shared 实例:

helm install my-shared-instance oci://registry-1.docker.io/daprio/dapr-shared-chart --set shared.appId=<DAPR_APP_ID> --set shared.remoteURL=<REMOTE_URL> --set shared.remotePort=<REMOTE_PORT> --set shared.strategy=deployment

您的启用 Dapr 的应用程序现在可以通过将 Dapr SDK 指向或向 Dapr Shared 实例暴露的 my-shared-instance-dapr Kubernetes 服务发送请求来使用 Dapr Shared 实例。

上面的 my-shared-instance 是 Helm Chart 的 release 名称。

如果您使用的是 Dapr SDK,可以为应用程序设置以下环境变量以连接到 Dapr Shared 实例(在本例中,运行在 default 命名空间中):

        env:
        - name: DAPR_HTTP_ENDPOINT
          value: http://my-shared-instance-dapr.default.svc.cluster.local:3500
        - name: DAPR_GRPC_ENDPOINT
          value: http://my-shared-instance-dapr.default.svc.cluster.local:50001 

如果您不使用 SDK,可以向这些端点发送 HTTP 或 gRPC 请求。

后续步骤

2.2.7 - 操作指南:持久化 Scheduler 作业

配置 Scheduler 以持久化其数据库,使其能够抵御重启

Scheduler 服务负责将作业写入其 Etcd 数据库并调度它们执行。 默认情况下,Scheduler 服务数据库内嵌 Etcd,并将数据写入大小为 1Gb 的持久卷声明卷,使用集群的默认存储类。 这意味着在大多数 Kubernetes 部署上可靠运行调度器服务不需要额外的参数,但如果默认的 StorageClass 不可用或在生产环境中运行,则需要额外的配置

生产环境设置

ETCD 存储磁盘大小

Scheduler 的默认存储大小为 1Gb。 这个大小很可能不足以满足大多数生产部署的需求。 当超过存储大小时,Scheduler 将记录类似于以下的错误:

error running scheduler: etcdserver: mvcc: database space exceeded

了解存储大小的安全上限不是一门精确的科学,并且很大程度上取决于应用程序作业的数量、持久性和数据有效负载大小。 Job APIActor Reminders 透明地一对一映射到您的应用程序使用情况。 工作流作为 Actor Reminders 创建大量作业,但这些作业是短暂的——与每个工作流执行的生命周期相匹配。 由工作流创建的作业的数据有效负载通常为空或很小。

Scheduler 使用 Etcd 作为其后端存储数据库。 根据设计,Etcd 以 预写日志(WAL)和快照 的形式持久化历史事务和数据。 这意味着 Scheduler 的实际磁盘使用量将高于当前可观察的数据库状态,通常是多倍。

在安装时设置存储大小

如果需要增加现有 Scheduler 存储大小,请参阅下面的增加 Scheduler 存储大小 部分。 要为全新 Dapr 安装增加存储大小(在此示例中为 16Gi),可以使用以下命令:

dapr init -k --set dapr_scheduler.cluster.storageSize=16Gi --set dapr_scheduler.etcdSpaceQuota=16Gi
helm upgrade --install dapr dapr/dapr \
--version=1.18 \
--namespace dapr-system \
--create-namespace \
--set dapr_scheduler.cluster.storageSize=16Gi \
--set dapr_scheduler.etcdSpaceQuota=16Gi \
--wait

增加现有 Scheduler 存储大小

默认情况下,每个 Scheduler 将为每个 Scheduler 副本针对默认 standard 存储类创建大小为 1Gi 的持久卷和持久卷声明。 这些将类似于以下内容,在此示例中,我们在 HA 模式下运行 Scheduler。

NAMESPACE     NAME                                              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
dapr-system   dapr-scheduler-data-dir-dapr-scheduler-server-0   Bound    pvc-9f699d2e-f347-43b0-aa98-57dcf38229c5   1Gi        RWO            standard       <unset>                 3m25s
dapr-system   dapr-scheduler-data-dir-dapr-scheduler-server-1   Bound    pvc-f4c8be7b-ffbe-407b-954e-7688f2482caa   1Gi        RWO            standard       <unset>                 3m25s
dapr-system   dapr-scheduler-data-dir-dapr-scheduler-server-2   Bound    pvc-eaad5fb1-98e9-42a5-bcc8-d45dba1c4b9f   1Gi        RWO            standard       <unset>                 3m25s
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                                         STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pvc-9f699d2e-f347-43b0-aa98-57dcf38229c5   1Gi        RWO            Delete           Bound    dapr-system/dapr-scheduler-data-dir-dapr-scheduler-server-0   standard       <unset>                          4m24s
pvc-eaad5fb1-98e9-42a5-bcc8-d45dba1c4b9f   1Gi        RWO            Delete           Bound    dapr-system/dapr-scheduler-data-dir-dapr-scheduler-server-2   standard       <unset>                          4m24s
pvc-f4c8be7b-ffbe-407b-954e-7688f2482caa   1Gi        RWO            Delete           Bound    dapr-system/dapr-scheduler-data-dir-dapr-scheduler-server-1   standard       <unset>                          4m24s

要扩展 Scheduler 的存储大小,请按照以下步骤操作:

  1. 首先,确保存储类支持卷扩展,并且如果 allowVolumeExpansion 字段尚未设置为 true,请将其设置为 true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: my.driver
allowVolumeExpansion: true
...
  1. 在保留绑定的持久卷声明的同时,删除 Scheduler StatefulSet。
kubectl delete sts -n dapr-system dapr-scheduler-server --cascade=orphan
  1. 通过编辑 spec.resources.requests.storage 字段,将持久卷声明的大小增加到所需的大小。 同样在这种情况下,我们假设 Scheduler 在 HA 模式下运行,有 3 个副本。
kubectl edit pvc -n dapr-system dapr-scheduler-data-dir-dapr-scheduler-server-0 dapr-scheduler-data-dir-dapr-scheduler-server-1 dapr-scheduler-data-dir-dapr-scheduler-server-2
  1. 通过使用所需的存储大小安装 Dapr 来重新创建 Scheduler StatefulSet。

存储类

如果您的 Kubernetes 部署没有默认存储类,或者您正在配置生产集群,则需要定义存储类。

持久卷由托管的云提供商或 Kubernetes 基础设施平台提供的真实磁盘支持。 磁盘大小取决于预期要一次持久化的作业数量;但是,对于大多数生产场景,64Gb 应该绰绰有余。 一些 Kubernetes 提供商建议使用 CSI 驱动程序来提供底层磁盘。 以下是有关为主要云提供商创建持久磁盘的相关文档的有用链接列表:

一旦存储类可用,您可以使用以下命令安装 Dapr,其中 Scheduler 配置为使用存储类(将 my-storage-class 替换为存储类的名称):

dapr init -k --set dapr_scheduler.cluster.storageClassName=my-storage-class
helm upgrade --install dapr dapr/dapr \
--version=1.18 \
--namespace dapr-system \
--create-namespace \
--set dapr_scheduler.cluster.storageClassName=my-storage-class \
--wait

临时存储

在非 HA 模式下运行时,可以选择让 Scheduler 使用临时存储,这是一种能够抵御重启的内存存储。例如,所有作业数据在 Scheduler 重启后都会丢失。 这对于非生产部署或测试非常有用,在这些情况下存储不可用或不需要。

dapr init -k --set dapr_scheduler.cluster.inMemoryStorage=true
helm upgrade --install dapr dapr/dapr \
--version=1.18 \
--namespace dapr-system \
--create-namespace \
--set dapr_scheduler.cluster.inMemoryStorage=true \
--wait

2.2.8 - 部署到混合 Linux/Windows Kubernetes 集群

如何在带有 Windows 节点的 Kubernetes 集群上运行 Dapr 应用

Dapr 支持在以下 Kubernetes 集群上运行微服务:

  • Windows
  • Linux
  • 两者组合

这在将传统应用程序逐步迁移到 Dapr Kubernetes 集群时特别有用。

Kubernetes 使用一个称为**节点亲和性(node affinity)**的概念来表示你希望应用程序在 Linux 节点还是 Windows 节点上启动。当部署到同时具有 Windows 和 Linux 节点的集群时,必须为应用程序提供亲和性规则,否则 Kubernetes 调度器可能会在错误类型的节点上启动应用程序。

前置条件

在开始之前,请设置一个包含 Windows 节点的 Kubernetes 集群。许多 Kubernetes 提供商支持自动配置启用了 Windows 的 Kubernetes 集群。

  1. 按照你选择的服务商的说明设置启用了 Windows 的集群。

  2. 设置集群后,验证 Windows 和 Linux 节点都可用。

    kubectl get nodes -o wide
    
    NAME                                STATUS   ROLES   AGE     VERSION   INTERNAL-IP    EXTERNAL-IP      OS-IMAGE                         KERNEL-VERSION      CONTAINER-RUNTIME
    aks-nodepool1-11819434-vmss000000   Ready    agent   6d      v1.17.9   10.240.0.4     <none>        Ubuntu 16.04.6    LTS               4.15.0-1092-azure   docker://3.0.10+azure
    aks-nodepool1-11819434-vmss000001   Ready    agent   6d      v1.17.9   10.240.0.35    <none>        Ubuntu 16.04.6    LTS               4.15.0-1092-azure   docker://3.0.10+azure
    aks-nodepool1-11819434-vmss000002   Ready    agent   5d10h   v1.17.9   10.240.0.129   <none>        Ubuntu 16.04.6    LTS               4.15.0-1092-azure   docker://3.0.10+azure
    akswin000000                        Ready    agent   6d      v1.17.9   10.240.0.66    <none>        Windows Server 2019    Datacenter   10.0.17763.1339     docker://19.3.5
    akswin000001                        Ready    agent   6d      v1.17.9   10.240.0.97    <none>        Windows Server 2019    Datacenter   10.0.17763.1339     docker://19.3.5
    

安装 Dapr 控制平面

如果你使用 Dapr CLI 或 Helm chart 安装,只需按照常规部署流程操作:在 Kubernetes 集群上安装 Dapr

亲和性将自动设置为 kubernetes.io/os=linux。这对大多数用户来说已足够,因为 Kubernetes 至少需要一个 Linux 节点池。

安装 Dapr 应用

Windows 应用

  1. 遵循 Microsoft 文档创建一个安装了你的应用的 Docker Windows 容器

  2. 创建包含应用的 Docker 容器后,创建一个部署 YAML 文件,将节点亲和性设置为 kubernetes.io/os: windows。在下面的示例 deploy_windows.yaml 部署文件中:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: yourwinapp
      labels:
        app: applabel
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: applablel
      template:
        metadata:
          labels:
            app: applabel
          annotations:
            dapr.io/enabled: "true"
            dapr.io/id: "addapp"
            dapr.io/port: "6000"
            dapr.io/config: "appconfig"
        spec:
          containers:
          - name: add
            image: yourreponsitory/your-windows-dapr-container:your-tag
            ports:
            - containerPort: 6000
            imagePullPolicy: Always
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                  - matchExpressions:
                    - key: kubernetes.io/os
                      operator: In
                      values:
                      - windows
    
  3. 将 YAML 文件部署到你的 Kubernetes 集群。

    kubectl apply -f deploy_windows.yaml
    

Linux 应用

如果你已经有一个在 Linux 上运行的 Dapr 应用,仍然需要添加亲和性规则。

  1. 创建一个部署 YAML 文件,将节点亲和性设置为 kubernetes.io/os: linux。在下面的示例 deploy_linux.yaml 部署文件中:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: yourlinuxapp
      labels:
        app: yourlabel
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: yourlabel
      template:
        metadata:
          labels:
            app: yourlabel
          annotations:
            dapr.io/enabled: "true"
            dapr.io/id: "addapp"
            dapr.io/port: "6000"
            dapr.io/config: "appconfig"
        spec:
          containers:
          - name: add
            image: yourreponsitory/your-application:your-tag
            ports:
            - containerPort: 6000
            imagePullPolicy: Always
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                  - matchExpressions:
                    - key: kubernetes.io/os
                      operator: In
                      values:
                      - linux
    
  2. 将 YAML 部署到你的 Kubernetes 集群。

    kubectl apply -f deploy_linux.yaml
    

就是这样!

清理

要删除本指南中的部署,运行以下命令:

kubectl delete -f deploy_linux.yaml
kubectl delete -f deploy_windows.yaml
helm uninstall dapr

相关链接

2.2.9 - 在 Kubernetes Job 中运行 Dapr

在 Kubernetes Job 上下文中使用 Dapr API

Dapr 边车被设计为一个长期运行的进程。在 Kubernetes Job 的上下文中,这种行为可能会阻止您的 Job 完成。

在运行基本的 Kubernetes Job时,您需要调用 /shutdown 端点以使边车优雅停止,并将 Job 视为 Completed

当 Job 在未调用 Shutdown 的情况下结束时,您的 Job 将处于 NotReady 状态,只有 daprd 容器无休止地运行。

停止 Dapr 边车会导致其就绪探针和存活探针在您的容器中失败。

为了防止 Kubernetes 尝试重启您的 Job,请将 Job 的 restartPolicy 设置为 Never

确保在调用 shutdown HTTP API 时使用 POST HTTP 方法。例如:

apiVersion: batch/v1
kind: Job
metadata:
  name: job-with-shutdown
spec:
  template:
    metadata:
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "with-shutdown"
    spec:
      containers:
      - name: job
        image: alpine
        command: ["/bin/sh", "-c", "apk --no-cache add curl && sleep 20 && curl -X POST localhost:3500/v1.0/shutdown"]
      restartPolicy: Never

您也可以从任何 Dapr SDK 调用 Shutdown。例如,对于 Go SDK:

package main

import (
	"context"
	"log"
	"os"

	dapr "github.com/dapr/go-sdk/client"
)

func main() {
  client, err := dapr.NewClient()
  if err != nil {
    log.Panic(err)
  }
  defer client.Close()
  defer client.Shutdown()
  // Job
}

相关链接

2.2.10 - 操作指南:将 Pod 卷挂载到 Dapr 边车

配置 Dapr 边车以挂载 Pod 卷

Dapr 边车可以被配置来挂载任何附加到应用 Pod 的 Kubernetes 卷。这些卷可以被 daprd(边车)容器以 只读读写 模式访问。如果一个卷被配置为挂载但在 Pod 中不存在,Dapr 会记录警告并忽略它。

有关不同类型卷的更多信息,请查看 Kubernetes 文档

配置

你可以在部署 YAML 中设置以下注解:

注解描述
dapr.io/volume-mounts用于只读卷挂载
dapr.io/volume-mounts-rw用于读写卷挂载

这些注解是逗号分隔的 volume-name:path/in/container 对。请验证相应的卷在 Pod 规范中存在。

在官方容器镜像中,Dapr 以用户 ID(UID)65532 运行进程。请确保挂载卷内的文件夹和文件根据需要可被用户 65532 写入或读取。

虽然可以在 Dapr 边车容器内的任何文件夹中挂载卷,但为了避免冲突并确保未来的平稳运行,请将所有挂载点放在以下位置之一,或其子文件夹内:

位置描述
/mnt推荐用于包含持久化数据的卷,Dapr 边车进程可以读取和/或写入这些数据。
/tmp推荐用于包含临时数据的卷,例如临时磁盘。

示例

基本部署资源示例

在下面的部署资源示例中:

  • my-volume1 以只读模式在边车容器内的 /mnt/sample1 处可用
  • my-volume2 以只读模式在边车容器内的 /mnt/sample2 处可用
  • my-volume3 以读写模式在边车容器内的 /tmp/sample3 处可用
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: default
  labels:
    app: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "myapp"
        dapr.io/app-port: "8000"
        dapr.io/volume-mounts: "my-volume1:/mnt/sample1,my-volume2:/mnt/sample2"
        dapr.io/volume-mounts-rw: "my-volume3:/tmp/sample3"
    spec:
      volumes:
        - name: my-volume1
          hostPath:
            path: /sample
        - name: my-volume2
          persistentVolumeClaim:
            claimName: pv-sample
        - name: my-volume3
          emptyDir: {}
...

使用本地文件密钥存储的自定义密钥存储

由于任何类型的 Kubernetes 卷都可以附加到边车,你可以使用本地文件密钥存储从各种地方读取密钥。例如,如果你有一个运行在 10.201.202.203 的网络文件共享(NFS)服务器,密钥存储在 /secrets/stage/secrets.json,你可以将其用作密钥存储。

  1. 配置应用 Pod 以挂载 NFS 并将其附加到 Dapr 边车。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp
    ...
    spec:
      ...
      template:
        ...
          annotations:
            dapr.io/enabled: "true"
            dapr.io/app-id: "myapp"
            dapr.io/app-port: "8000"
            dapr.io/volume-mounts: "nfs-secrets-vol:/mnt/secrets"
        spec:
          volumes:
            - name: nfs-secrets-vol
              nfs:
                server: 10.201.202.203
                path: /secrets/stage
    ...
    
  2. 将本地文件密钥存储组件指向附加的文件。

    apiVersion: dapr.io/v1alpha1
    kind: Component
    metadata:
      name: local-secret-store
    spec:
      type: secretstores.local.file
      version: v1
      metadata:
      - name: secretsFile
        value: /mnt/secrets/secrets.json
    
  3. 使用密钥。

    GET http://localhost:<daprPort>/v1.0/secrets/local-secret-store/my-secret
    

相关链接

Dapr Kubernetes Pod 注解规范

2.3 - 在无服务器产品中运行 Dapr

了解如何在无服务器云产品中运行 Dapr 应用程序

如果您想在无需管理任何底层基础设施(如虚拟机或 Kubernetes)的情况下运行 Dapr 应用程序,可以选择无服务器云产品。这些平台与 Dapr 集成,使您可以轻松部署和管理应用程序。

产品

2.3.1 - Azure Container Apps

了解如何在 Azure Container Apps 无服务器平台上运行 Dapr 应用程序

Azure Container Apps 是一个无服务器应用程序托管服务,用户无需查看或管理任何底层虚拟机、编排器或其他云基础设施。Azure Container Apps 使您能够运行打包在多个容器中的应用程序代码,并且对所使用的运行时或编程模型没有任何偏好。

Dapr 内置于 Container Apps 中,使您能够使用 Dapr API 构建块,而无需手动部署 Dapr 运行时。您只需部署服务及其 Dapr 组件即可。

了解更多

教程

访问 Azure 文档 以尝试微服务教程,您将在其中将两个启用了 Dapr 的应用程序部署到 Azure Container Apps。

包含两个 Dapr 服务的 Container Apps 环境示意图 在 Container Apps 上试用 Dapr

3 - 管理 Dapr 配置

如何设置 Dapr 配置和管理部署

3.1 - Dapr 配置

Dapr 配置概述

Dapr 配置是设置和策略,使您能够更改单个 Dapr 应用程序的行为或 Dapr 控制平面系统服务的全局行为。

更多信息,请阅读配置概念。

应用程序配置

设置应用程序配置

您可以在自托管或 Kubernetes 模式下设置应用程序配置。

在自托管模式下,Dapr 配置是一个配置文件 - 例如,config.yaml。默认情况下,Dapr 边车会在默认的 Dapr 文件夹中查找运行时配置:

  • Linux/MacOs:$HOME/.dapr/config.yaml
  • Windows:%USERPROFILE%\.dapr\config.yaml

应用程序还可以通过使用 dapr run CLI 命令的 --config 标志来应用配置文件路径。

在 Kubernetes 模式下,Dapr 配置是一个 Configuration 资源,应用于集群。例如:

kubectl apply -f myappconfig.yaml

您可以使用 Dapr CLI 列出应用程序的 Configuration 资源。

dapr configurations -k

Dapr 边车可以通过使用 dapr.io/config 注解来应用特定配置。例如:

  annotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "nodeapp"
    dapr.io/app-port: "3000"
    dapr.io/config: "myappconfig"

注意:查看所有 Kubernetes 注解可用于在边车注入器系统服务激活时配置 Dapr 边车。

应用程序配置设置

以下菜单包含您可以设置的所有配置设置:

追踪

追踪配置可为应用程序启用追踪。

Configuration 规范下的 tracing 部分包含以下属性:

tracing:
  samplingRate: "1"
  otel: 
    endpointAddress: "otelcollector.observability.svc.cluster.local:4317"
    headers:
      - name: "x-api-key"
        secretKeyRef:
          name: "my-secret"
          key: "otel-api-key"
    timeout: "30s"
  zipkin:
    endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"

下表列出了追踪的属性:

属性类型描述
samplingRatestring设置追踪的采样率以启用或禁用。
stdoutboolTrue 向追踪写入更详细的信息
otel.endpointAddressstring设置要向其发送追踪的 Open Telemetry (OTEL) 服务器地址。根据您的 OTEL 提供商,可能需要或不需要 https:// 或 http://。
otel.isSecurebool到端点地址的连接是否加密
otel.protocolstring设置为 httpgrpc 协议
otel.headersarray要包含在 OTLP 导出器请求中的标头。每个条目都有一个 name 和纯文本 valuesecretKeyRef 以引用 Kubernetes 密钥(仅支持 Kubernetes 密钥,不支持其他密钥类型)
otel.timeoutstringOTLP 导出器请求的超时时间(例如 30s5m)。
zipkin.endpointAddressstring设置要向其发送追踪的 Zipkin 服务器地址。这应包含端点上的协议(http:// 或 https://)。
samplingRate

samplingRate 用于启用或禁用追踪。samplingRate 的有效范围介于 01 之间(含)。采样率根据值确定是否应对追踪跨度进行采样。

samplingRate : "1" 采样所有追踪。默认情况下,采样率为 (0.0001),即 10,000 条追踪中有 1 条。

要禁用采样率,请在配置中设置 samplingRate : "0"

otel

也可以通过环境变量配置 OpenTelemetry (otel) 端点。OTEL_EXPORTER_OTLP_ENDPOINT 环境变量的存在会为边车启用追踪。

环境变量描述
OTEL_EXPORTER_OTLP_ENDPOINT设置 Open Telemetry (OTEL) 服务器地址,启用追踪
OTEL_EXPORTER_OTLP_INSECURE将到端点的连接设置为未加密(true/false)
OTEL_EXPORTER_OTLP_PROTOCOL传输协议(grpchttp/protobufhttp/json
OTEL_EXPORTER_OTLP_TRACES_HEADERSOTLP 追踪导出器的逗号分隔的 key=value 标头列表
OTEL_EXPORTER_OTLP_TRACES_TIMEOUTOTLP 追踪导出器的超时时间(以毫秒为单位)(例如 30000

更多信息,请参阅可观测性分布式追踪

指标

Configuration 规范下的 metrics 部分可用于启用或禁用应用程序的指标。

metrics 部分包含以下属性:

metrics:
  enabled: true
  rules: []
  latencyDistributionBuckets: []
  http:
    increasedCardinality: true
    pathMatching:
      - /items
      - /orders/{orderID}
      - /orders/{orderID}/items/{itemID}
      - /payments/{paymentID}
      - /payments/{paymentID}/status
      - /payments/{paymentID}/refund
      - /payments/{paymentID}/details
    excludeVerbs: false
  recordErrorCodes: true

在上述示例中,路径过滤器 /orders/{orderID}/items/{itemID} 将返回与所有 orderID 和所有 itemID 匹配的_单个指标计数_,而不是为每个 itemID 返回多个指标。更多信息,请参阅 HTTP 指标路径匹配

上述示例还启用了记录错误代码指标,默认情况下该功能是禁用的。

下表列出了指标的属性:

属性类型描述
enabledboolean设置为 true 时(默认值),启用指标收集和指标端点。
rulesarray用于过滤指标的命名规则。每个规则包含一组要过滤的 labels 和要应用于指标路径的 regex 表达式。
latencyDistributionBucketsarray延迟指标直方图的延迟分布桶数组(以毫秒为单位)。
http.increasedCardinalityboolean设置为 true(默认值)时,在 Dapr HTTP 服务器中,每个请求路径都会创建一个新的指标"桶"。当有许多不同的请求端点(例如与 RESTful API 交互时)时,这可能会导致问题,包括过多的内存消耗。
为了缓解与 HTTP 服务器相关的高基数指标的高内存使用量和出口成本,您应该将 metrics.http.increasedCardinality 属性设置为 false
http.pathMatchingarray用于路径匹配的路径数组,允许用户定义匹配路径以管理基数。
http.excludeVerbsboolean设置为 true 时(默认为 false),Dapr HTTP 服务器在构建方法指标标签时会忽略每个请求的 HTTP 动词。

为了进一步帮助管理基数,路径匹配允许您根据定义的模式匹配指定路径,从而减少唯一指标路径的数量,从而控制指标基数。此功能对于具有动态 URL 的应用程序特别有用,确保指标保持有意义和可管理,而不会消耗过多的内存。

使用规则,您可以为 Dapr 边车公开的每个指标设置正则表达式。例如:

metrics:
  enabled: true
  rules:
    - name: dapr_runtime_service_invocation_req_sent_total
      labels:
      - name: method
        regex:
          "orders/": "orders/.+"

更多信息,请参阅指标文档

日志记录

Configuration 规范下的 logging 部分用于配置 Dapr Runtime 中的日志记录工作方式。

logging 部分包含以下属性:

logging:
  apiLogging:
    enabled: false
    obfuscateURLs: false
    omitHealthChecks: false

下表列出了日志记录的属性:

属性类型描述
apiLogging.enabledbooleandaprd--enable-api-logging 标志(以及相应的 dapr.io/enable-api-logging 注解)的默认值:在 Configuration 规范中设置的值将用作默认值,除非将 truefalse 值传递给每个 Dapr Runtime。默认值:false
apiLogging.obfuscateURLsboolean启用后,混淆 HTTP API 日志中的 URL 值(如果启用),记录抽象路由名称而不是被调用的完整路径,后者可能包含个人身份信息 (PII)。默认值:false
apiLogging.omitHealthChecksboolean如果为 true,则在启用 API 日志记录时,不会记录对健康检查端点(例如 /v1.0/healthz)的调用。如果这些调用在日志中产生大量噪音,这很有用。默认值:false

更多信息,请参阅日志记录文档

中间件

中间件配置设置命名 HTTP 管道中间件处理程序。Configuration 规范下的 httpPipelineappHttpPipeline 部分包含以下属性:

httpPipeline: # for incoming http calls
  handlers:
    - name: oauth2
      type: middleware.http.oauth2
    - name: uppercase
      type: middleware.http.uppercase
appHttpPipeline: # for outgoing http calls
  handlers:
    - name: oauth2
      type: middleware.http.oauth2
    - name: uppercase
      type: middleware.http.uppercase

下表列出了 HTTP 处理程序的属性:

属性类型描述
namestring中间件组件的名称
typestring中间件组件的类型

更多信息,请参阅中间件管道

名称解析组件

您可以在配置文件中设置要使用的名称解析组件。例如,要将 spec.nameResolution.component 属性设置为 "sqlite",请在 spec.nameResolution.configuration 字典中传递配置选项,如下所示。

这是一个配置资源的基本示例:

apiVersion: dapr.io/v1alpha1
kind: Configuration 
metadata:
  name: appconfig
spec:
  nameResolution:
    component: "sqlite"
    version: "v1"
    configuration:
      connectionString: "/home/user/.dapr/nr.db"

更多信息,请参阅:

工作流

workflow 部分包含用于配置工作流的属性。

属性类型描述
maxConcurrentWorkflowInvocationsint32每个 Dapr 边车的最大并发工作流执行数。默认为无限。
maxConcurrentActivityInvocationsint32每个 Dapr 边车的最大并发活动执行数。默认为无限。

限定密钥存储访问范围

有关如何将密钥范围限定到应用程序的信息和示例,请参阅限定密钥范围指南。

构建块 API 的访问控制允许列表

有关如何在构建块 API 列表上设置访问控制允许列表 (ACL) 的信息和示例,请参阅在 Dapr 边车上有选择性地启用 Dapr API指南。

服务调用 API 的访问控制允许列表

有关如何使用服务调用 API 通过 ACL 设置允许列表的信息和示例,请参阅服务调用的允许列表指南。

禁止使用某些组件类型

使用 Configuration 规范中的 components.deny 属性,您可以指定无法初始化的组件类型的拒绝列表。

例如,以下配置禁止初始化类型为 bindings.smtpsecretstores.local.file 的组件:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
spec: 
  components:
    deny:
      - bindings.smtp
      - secretstores.local.file

或者,您可以通过在组件名称末尾添加版本来指定要禁止的版本。例如,state.in-memory/v1 禁止初始化类型为 state.in-memory 和版本为 v1 的组件,但不会禁用(假设的)组件的 v2 版本。

启用预览功能

有关如何选择加入发布的预览功能的信息和示例,请参阅预览功能指南。

启用预览功能会为开发/测试添加新功能,因为它们在运行时中普遍可用 (GA) 之前仍需要更多时间。

边车配置示例

以下 YAML 显示了一个可以应用于应用程序的 Dapr 边车的配置文件示例。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  tracing:
    samplingRate: "1"
    stdout: true
    otel:
      endpointAddress: "localhost:4317"
      isSecure: false
      protocol: "grpc"
      headers:
        - name: "x-api-key"
          secretKeyRef:
            name: "my-secret"
            key: "otel-api-key"
      timeout: "30s"
  httpPipeline:
    handlers:
      - name: oauth2
        type: middleware.http.oauth2
  secrets:
    scopes:
      - storeName: localstore
        defaultAccess: allow
        deniedSecrets: ["redis-password"]
  components:
    deny:
      - bindings.smtp
      - secretstores.local.file
  workflow:
    maxConcurrentWorkflowInvocations: 100
    maxConcurrentActivityInvocations: 1000
  accessControl:
    defaultAction: deny
    trustDomain: "public"
    policies:
      - appId: app1
        defaultAction: deny
        trustDomain: 'public'
        namespace: "default"
        operations:
          - name: /op1
            httpVerb: ['POST', 'GET']
            action: deny
          - name: /op2/*
            httpVerb: ["*"]
            action: allow

控制平面配置

安装了一个名为 daprsystem 的配置文件,用于应用全局设置的 Dapr 控制平面系统服务。

这仅在将 Dapr 部署到 Kubernetes 时设置。

控制平面配置设置

Dapr 控制平面配置包含以下部分:

  • mtls 用于 mTLS(双向 TLS)

mTLS(双向 TLS)

mtls 部分包含 mTLS 的属性。

属性类型描述
enabledbool如果为 true,则为集群中的服务和应用程序之间的通信启用 mTLS。
allowedClockSkewstring检查 TLS 证书过期时允许的容差,以允许时钟偏差。遵循 Go 的 time.ParseDuration 使用的格式。默认为 15m(15 分钟)。
workloadCertTTLstring由 Dapr 颁发的 TLS 证书的有效期。遵循 Go 的 time.ParseDuration 使用的格式。默认为 24h(24 小时)。
sentryAddressstring用于连接到 Sentry 服务器的主名端口地址。
controlPlaneTrustDomainstring控制平面的信任域。这用于验证到控制平面服务的连接。
tokenValidatorsarray用于验证证书请求的其他 Sentry 令牌验证器。

更多信息,请参阅 mTLS 操作方法安全概念

控制平面配置示例

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

后续步骤

了解并发和速率限制

3.2 - 操作指南:控制应用程序的并发和速率限制

了解如何控制可以同时调用您的应用程序的请求数和事件数

在分布式计算中,通常您可能只希望允许给定数量的请求并发执行。使用 Dapr 的 app-max-concurrency,您可以控制同时调用您的应用程序的请求数和事件数。

默认的 app-max-concurrency 设置为 -1,表示不强制执行并发限制。

不同的方法

本指南重点介绍 app-max-concurrency,您也可以使用 middleware.http.ratelimit 中间件来限制每秒的请求速率。但是,了解这两种方法之间的区别很重要:

  • middleware.http.ratelimit:时间受限,限制每秒的请求数
  • app-max-concurrency:指定在任何时间点的最大并发请求(和事件)数

有关该方法的更多信息,请参阅速率限制中间件

演示

观看此视频,了解如何控制并发和速率限制。

配置 app-max-concurrency

如果不使用 Dapr,您需要在应用程序中创建某种信号量,并负责获取和释放它。

使用 Dapr,您无需对应用程序进行任何代码更改。

选择您想要配置 app-max-concurrency 的方式。

要在本地开发计算机上使用 Dapr CLI 设置并发限制,请添加 app-max-concurrency 标志:

dapr run --app-max-concurrency 1 --app-port 5000 python ./app.py

上述示例有效地将您的应用程序转换为顺序处理服务。

要在 Kubernetes 中配置并发限制,请将以下注解添加到您的 pod:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodesubscriber
  namespace: default
  labels:
    app: nodesubscriber
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nodesubscriber
  template:
    metadata:
      labels:
        app: nodesubscriber
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodesubscriber"
        dapr.io/app-port: "3000"
        dapr.io/app-max-concurrency: "1"
#...

限制

控制外部请求的并发性

对于来自 Dapr 的每个事件,包括发布订阅事件、来自其他服务的直接调用、绑定事件等,都可以保证速率限制。但是,Dapr 无法对从外部到您的应用程序的请求强制执行并发策略。

相关链接

参数和注解

后续步骤

限制 secret store 访问

3.3 - 操作指南:限制可从 secret 存储读取的密钥

通过在现有配置资源上添加限制性权限来定义 secret 范围。

除了限定哪些应用可以访问给定组件外,你还可以为应用将命名的 secret 存储组件限定到一个或多个密钥。通过定义 allowedSecrets 和/或 deniedSecrets 列表,你可以限制应用仅访问特定的密钥。

有关配置 Configuration 资源的更多信息:

配置密钥访问

Configuration 规范下的 secrets 部分包含以下属性:

secrets:
  scopes:
    - storeName: kubernetes
      defaultAccess: allow
      allowedSecrets: ["redis-password"]
    - storeName: localstore
      defaultAccess: allow
      deniedSecrets: ["redis-password"]

下表列出了 secret 范围的属性:

属性类型描述
storeNamestringsecret 存储组件的名称。storeName 在列表中必须唯一
defaultAccessstring访问修饰符。接受的值为 “allow”(默认)或 “deny”
allowedSecretslist可访问的密钥列表
deniedSecretslist不可访问的密钥列表

当存在包含至少一个元素的 allowedSecrets 列表时,应用只能访问该列表中定义的密钥。

权限优先级

allowedSecretsdeniedSecrets 列表值优先于 defaultAccess。请参阅以下示例场景中的工作方式:

场景defaultAccessallowedSecretsdeniedSecretspermission
1仅默认访问deny/allowdeny/allow
2默认拒绝且包含允许列表deny["s1"]"s1" 可被访问
3默认允许且包含拒绝列表allow["s1"]"s1" 不可被访问
4默认允许且包含允许列表allow["s1"]"s1" 可被访问
5默认拒绝且包含拒绝列表deny["s1"]deny
6默认拒绝/允许且同时包含两个列表deny/allow["s1"]["s2"]"s1" 可被访问

示例

场景 1:拒绝访问 secret 存储的所有密钥

在 Kubernetes 集群中,默认会为你的 Dapr 应用添加原生的 Kubernetes secret 存储。在某些场景中,可能需要拒绝给定应用对 Dapr 密钥的访问。要添加此配置:

  1. 定义以下 appconfig.yaml

    apiVersion: dapr.io/v1alpha1
    kind: Configuration
    metadata:
      name: appconfig
    spec:
      secrets:
        scopes:
          - storeName: kubernetes
            defaultAccess: deny
    
  2. 使用以下命令将其应用到 Kubernetes 集群:

    kubectl apply -f appconfig.yaml`.
    

对于需要拒绝访问 Kubernetes secret 存储的应用,遵循 Kubernetes 指南,将以下注解添加到应用 pod。

dapr.io/config: appconfig

定义后,应用将无法访问 Kubernetes secret 存储。

场景 2:仅允许访问 secret 存储中的某些密钥

要允许 Dapr 应用仅访问某些密钥,定义以下 config.yaml

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  secrets:
    scopes:
      - storeName: vault
        defaultAccess: deny
        allowedSecrets: ["secret1", "secret2"]

此示例为名为 vault 的 secret 存储定义了配置。对 secret 存储的默认访问为 deny。同时,根据 allowedSecrets 列表,应用可以访问某些密钥。遵循 边车配置指南 将配置应用到边车。

场景 3:拒绝访问 secret 存储中的某些敏感密钥

定义以下 config.yaml

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  secrets:
    scopes:
      - storeName: vault
        defaultAccess: allow # 这是默认值,可以省略此行
        deniedSecrets: ["secret1", "secret2"]

此配置明确拒绝访问名为 vault 的 secret 存储中的 secret1secret2,同时允许访问所有其他密钥。遵循 边车配置指南 将配置应用到边车。

后续步骤

服务调用访问控制

3.4 - 如何:为服务调用应用访问控制列表配置

限制调用应用程序可以执行的操作

使用访问控制,您可以配置策略,通过服务调用限制_调用_应用程序可以对_被调用_应用程序执行的操作。您可以在 Configuration 架构中定义访问控制策略规范来限制访问:

  • 从特定操作到被调用应用程序,以及
  • 从调用应用程序到 HTTP 动词。

访问控制策略在 Configuration 中指定,并应用于_被调用_应用程序的 Dapr 边车。对被调用应用程序的访问基于匹配的策略操作。

您可以为所有调用应用程序提供默认的全局操作。如果未指定访问控制策略,则默认行为是允许所有调用应用程序访问被调用应用程序。

查看访问策略示例。

术语

trustDomain

“信任域”(trust domain)是管理信任关系的逻辑组。每个应用程序都分配有一个信任域,可以在访问控制列表策略规范中指定。如果未定义策略规范或指定了空的信任域,则使用默认值 “public”。此信任域用于在 TLS 证书中生成应用程序的身份。

应用程序身份

Dapr 请求 sentry 服务为所有应用程序生成 SPIFFE ID。此 ID 附加在 TLS 证书中。

SPIFFE ID 的格式为:**spiffe://\<trustdomain>/ns/\<namespace\>/\<appid\>**

为了匹配策略,调用应用程序的信任域、命名空间和应用程序 ID 值从调用应用程序的 TLS 证书中的 SPIFFE ID 中提取。这些值与策略规范中指定的信任域、命名空间和应用程序 ID 值进行匹配。如果这三个值都匹配,则会进一步匹配更具体的策略。

配置属性

下表列出了访问控制、策略和操作的不同属性:

访问控制

属性类型描述
defaultActionstring当没有其他策略匹配时的全局默认操作
trustDomainstring分配给应用程序的信任域。默认为 “public”。
policiesstring用于确定调用应用程序可以对被调用应用程序执行的操作的策略

策略

属性类型描述
appstring要允许/拒绝服务调用的调用应用程序的 AppId
namespacestring需要与调用应用程序的命名空间匹配的命名空间值
trustDomainstring需要与调用应用程序的信任域匹配的信任域。默认为 “public”
defaultActionstring应用程序级别的默认操作,当找到应用程序但没有匹配特定操作时使用
operationsstring从调用应用程序允许的操作

操作

属性类型描述
namestring被调用应用程序上允许的操作的路径名称。可以在路径中使用通配符 “*” 进行匹配。可以使用通配符 “**” 在多个路径下进行匹配。
httpVerblist列出调用应用程序可以使用的特定 http 动词。可以使用通配符 “*” 匹配任何 http 动词。对于 grpc 调用未使用。
actionstring访问修饰符。接受的值为 “allow”(默认)或 “deny”

策略规则

  1. 如果未指定访问策略,则默认行为是允许所有应用程序访问被调用应用程序上的所有方法。
  2. 如果未指定全局默认操作且未定义应用程序特定策略,则空访问策略被视为未指定访问策略。默认行为是允许所有应用程序访问被调用应用程序上的所有方法。
  3. 如果未指定全局默认操作但已定义某些应用程序特定策略,则我们采用更安全的选项,即假设全局默认操作拒绝访问被调用应用程序上的所有方法。
  4. 如果定义了访问策略并且无法验证传入应用程序的身份凭证,则全局默认操作生效。
  5. 如果传入应用程序的信任域或命名空间与应用程序策略中指定的值不匹配,则应用程序策略将被忽略,全局默认操作生效。

策略优先级

与匹配的最具体策略对应的操作按以下顺序生效:

  1. HTTP 情况下的特定 HTTP 动词,或 GRPC 情况下的操作级别操作。
  2. 应用程序级别的默认操作
  3. 全局级别的默认操作

示例场景

以下是一些使用服务调用访问控制列表的示例场景。请参阅配置指南以了解应用程序边车的可用配置设置。

场景 1:

拒绝所有应用程序的访问,除了 trustDomain = publicnamespace = defaultappId = app1

使用此配置,允许 appId = app1 的所有调用方法。来自其他应用程序的所有其他调用请求都被拒绝。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: deny
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: allow
      trustDomain: 'public'
      namespace: "default"

场景 2:

拒绝所有应用程序的访问,除了 trustDomain = publicnamespace = defaultappId = app1operation = op1

使用此配置,只允许 appId = app1 的方法 op1。来自所有其他应用程序的所有其他方法请求(包括 app1 上的其他方法)都被拒绝。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: deny
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: deny
      trustDomain: 'public'
      namespace: "default"
      operations:
      - name: /op1
        httpVerb: ['*']
        action: allow

场景 3:

拒绝所有应用程序的访问,除非匹配 HTTP 的特定动词和 GRPC 的特定操作

使用此配置,仅允许以下场景访问。来自所有其他应用程序的所有其他方法请求(包括 app1app2 上的其他方法)都被拒绝。

  • trustDomain = publicnamespace = defaultappID = app1operation = op1httpVerb = POST/PUT
  • trustDomain = "myDomain"namespace = "ns1"appID = app2operation = op2 且应用程序协议为 GRPC

只允许 appId = app1 的方法 op1 上的 httpVerb POST/PUT。来自所有其他应用程序的所有其他方法请求(包括 app1 上的其他方法)都被拒绝。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: deny
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: deny
      trustDomain: 'public'
      namespace: "default"
      operations:
      - name: /op1
        httpVerb: ['POST', 'PUT']
        action: allow
    - appId: app2
      defaultAction: deny
      trustDomain: 'myDomain'
      namespace: "ns1"
      operations:
      - name: /op2
        action: allow

场景 4:

允许所有方法的访问,除了 trustDomain = publicnamespace = defaultappId = app1operation = /op1/*、所有 httpVerb

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: allow
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: allow
      trustDomain: 'public'
      namespace: "default"
      operations:
      - name: /op1/*
        httpVerb: ['*']
        action: deny

场景 5:

允许 trustDomain = publicnamespace = ns1appId = app1 的所有方法的访问,并拒绝 trustDomain = publicnamespace = ns2appId = app1 的所有方法的访问

此场景展示了如何指定具有相同应用程序 ID 但属于不同命名空间的应用程序。

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: allow
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: allow
      trustDomain: 'public'
      namespace: "ns1"
    - appId: app1
      defaultAction: deny
      trustDomain: 'public'
      namespace: "ns2"

场景 6:

允许所有方法的访问,除了 trustDomain = publicnamespace = defaultappId = app1operation = /op1/**/a、所有 httpVerb

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
spec:
  accessControl:
    defaultAction: allow
    trustDomain: "public"
    policies:
    - appId: app1
      defaultAction: allow
      trustDomain: 'public'
      namespace: "default"
      operations:
      - name: /op1/**/a
        httpVerb: ['*']
        action: deny

“hello world” 示例

在这些示例中,您将学习如何对 hello world 教程应用访问控制。

访问控制列表依赖 Dapr Sentry 服务 来生成带有用于身份验证的 SPIFFE ID 的 TLS 证书。这意味着 Sentry 服务必须在本地运行或部署到您的托管环境(例如 Kubernetes 集群)。

下面的 nodeappconfig 示例展示了如何拒绝 pythonappneworder 方法的访问,其中 Python 应用程序位于 myDomain 信任域和 default 命名空间中。Node.js 应用程序位于 public 信任域中。

nodeappconfig.yaml

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: nodeappconfig
spec:
  tracing:
    samplingRate: "1"
  accessControl:
    defaultAction: allow
    trustDomain: "public"
    policies:
    - appId: pythonapp
      defaultAction: allow
      trustDomain: 'myDomain'
      namespace: "default"
      operations:
      - name: /neworder
        httpVerb: ['POST']
        action: deny

pythonappconfig.yaml

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: pythonappconfig
spec:
  tracing:
    samplingRate: "1"
  accessControl:
    defaultAction: allow
    trustDomain: "myDomain"

自托管模式

在完成本教程时,您将:

  • 在本地运行启用了 mTLS 的 Sentry 服务
  • 设置必要的环境变量以访问证书
  • 启动 Node 应用和 Python 应用,每个应用都引用 Sentry 服务以应用 ACL

先决条件

运行 Node.js 应用

  1. 在命令提示符中,设置这些环境变量:

      ```bash
      export DAPR_TRUST_ANCHORS=`cat $HOME/.dapr/certs/ca.crt`
      export DAPR_CERT_CHAIN=`cat $HOME/.dapr/certs/issuer.crt`
      export DAPR_CERT_KEY=`cat $HOME/.dapr/certs/issuer.key`
      export NAMESPACE=default
      ```
    
      ```powershell
      $env:DAPR_TRUST_ANCHORS=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\ca.crt)
      $env:DAPR_CERT_CHAIN=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\issuer.crt)
      $env:DAPR_CERT_KEY=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\issuer.key)
      $env:NAMESPACE="default"
      ```
    
  2. 运行 daprd 以启动 Node.js 应用的 Dapr 边车,启用 mTLS,并引用本地 Sentry 服务:

    daprd --app-id nodeapp --dapr-grpc-port 50002 -dapr-http-port 3501 --log-level debug --app-port 3000 --enable-mtls --sentry-address localhost:50001 --config nodeappconfig.yaml
    
  3. 在单独的命令提示符中运行 Node.js 应用:

    node app.js
    

运行 Python 应用

  1. 在另一个命令提示符中,设置这些环境变量:

    ```bash
    export DAPR_TRUST_ANCHORS=`cat $HOME/.dapr/certs/ca.crt`
    export DAPR_CERT_CHAIN=`cat $HOME/.dapr/certs/issuer.crt`
    export DAPR_CERT_KEY=`cat $HOME/.dapr/certs/issuer.key`
    export NAMESPACE=default
    
    $env:DAPR_TRUST_ANCHORS=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\ca.crt)
    $env:DAPR_CERT_CHAIN=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\issuer.crt)
    $env:DAPR_CERT_KEY=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\issuer.key)
    $env:NAMESPACE="default"
    
  2. 运行 daprd 以启动 Python 应用的 Dapr 边车,启用 mTLS,并引用本地 Sentry 服务:

    daprd --app-id pythonapp   --dapr-grpc-port 50003 --metrics-port 9092 --log-level debug --enable-mtls --sentry-address localhost:50001 --config pythonappconfig.yaml
    
  3. 在单独的命令提示符中运行 Python 应用:

    python app.py
    

您应该看到在 Python 应用命令提示符中调用 Node.js 应用失败,这是由于 nodeappconfig 文件中的 deny 操作操作。将此操作更改为 allow 并重新运行应用程序以查看此调用成功。

Kubernetes 模式

先决条件

配置 Node.js 和 Python 应用

您可以创建并应用上述 nodeappconfig.yamlpythonappconfig.yaml 配置文件,如配置中所述。

例如,下面的 Kubernetes Deployment 展示了如何将 Python 应用部署到 Kubernetes 集群的 default 命名空间中,并使用此 pythonappconfig 配置文件。

对 Node.js 部署执行相同的操作,并查看 Python 应用的日志,以查看由于 nodeappconfig 文件中设置的 deny 操作操作而导致的调用失败。

将此操作更改为 allow 并重新部署应用程序以查看此调用成功。

Deployment YAML 示例
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pythonapp
  namespace: default
  labels:
    app: python
spec:
  replicas: 1
  selector:
    matchLabels:
      app: python
  template:
    metadata:
      labels:
        app: python
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "pythonapp"
        dapr.io/config: "pythonappconfig"
    spec:
      containers:
      - name: python
        image: dapriosamples/hello-k8s-python:edge

演示

观看此视频,了解如何为服务调用应用访问控制列表。

后续步骤

Dapr API 允许列表

3.5 - 操作指南:在 Dapr 边车上选择性地启用 Dapr API

选择哪些 Dapr 边车 API 可用于应用

在零信任网络等场景中,或通过前端将 Dapr 边车暴露给外部流量时,建议只启用应用使用的 Dapr 边车 API。这样做可以减少攻击面,并有助于将 Dapr API 限制在应用程序的实际需求范围内。

Dapr 允许您通过使用 Dapr Configuration 设置 API 允许列表或拒绝列表来控制哪些 API 可供应用程序访问。

默认行为

如果未指定 API 允许列表或拒绝列表,默认行为是允许访问所有 Dapr API。

  • 如果您仅定义了拒绝列表,则除拒绝列表中定义的 API 外,所有 Dapr API 均被允许
  • 如果您仅定义了允许列表,则仅允许允许列表中列出的 Dapr API
  • 如果您同时定义了允许列表和拒绝列表,则对于两者中都定义的 API,拒绝列表会覆盖允许列表
  • 如果两者都未定义,则允许所有 API

例如,以下配置为 HTTP 和 gRPC 启用了所有 API:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  tracing:
    samplingRate: "1"

使用允许列表

启用特定 HTTP API

以下示例启用了状态 v1.0 HTTP API 并阻止所有其他 HTTP API:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  api:
    allowed:
      - name: state
        version: v1.0
        protocol: http

启用特定 gRPC API

以下示例启用了状态 v1 gRPC API 并阻止所有其他 gRPC API:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  api:
    allowed:
      - name: state
        version: v1
        protocol: grpc

使用拒绝列表

禁用特定 HTTP API

以下示例禁用了状态 v1.0 HTTP API,允许所有其他 HTTP API:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  api:
    denied:
      - name: state
        version: v1.0
        protocol: http

禁用特定 gRPC API

以下示例禁用了状态 v1 gRPC API,允许所有其他 gRPC API:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: myappconfig
  namespace: default
spec:
  api:
    denied:
      - name: state
        version: v1
        protocol: grpc

Dapr API 列表

name 字段接受您要启用的 Dapr API 的名称。

请参阅对应不同 Dapr API 的值列表:

API 组HTTP APIgRPC API
服务调用invoke (v1.0)invoke (v1)
状态state (v1.0v1.0-alpha1)state (v1v1alpha1)
发布订阅publish (v1.0v1.0-alpha1)publish (v1v1alpha1)
输出绑定bindings (v1.0)bindings (v1)
订阅n/asubscribe (v1alpha1)
密钥secrets (v1.0)secrets (v1)
Actoractors (v1.0)actors (v1)
元数据metadata (v1.0)metadata (v1)
配置configuration (v1.0v1.0-alpha1)configuration (v1v1alpha1)
分布式锁lock (v1.0-alpha1)
unlock (v1.0-alpha1)
lock (v1alpha1)
unlock (v1alpha1)
加密crypto (v1.0-alpha1)crypto (v1alpha1)
工作流workflows (v1.0)workflows (v1)
对话conversation (v1.0-alpha1)conversation (v1alpha1)
健康检查healthz (v1.0)n/a
关闭shutdown (v1.0)shutdown (v1)

后续步骤

配置 Dapr 使用 gRPC

3.6 - 操作指南:配置 Dapr 使用 gRPC

配置 Dapr 使用 gRPC 以应对低延迟、高性能场景

Dapr 为本地调用同时实现了 HTTP 和 gRPC API。gRPC 适用于低延迟、高性能场景,并通过 proto 客户端提供语言集成支持。你可以查看自动生成客户端(Dapr SDK)的完整列表

Dapr 运行时实现了一个 proto 服务,应用程序可以通过 gRPC 与之通信。

不仅可以使用 gRPC 调用 Dapr,Dapr 也可以通过 gRPC 与应用程序通信。为此,应用程序需要托管一个 gRPC 服务器并实现 Dapr appcallback 服务

配置 Dapr 通过 gRPC 与应用程序通信

在自托管模式下运行时,使用 --app-protocol 标志告知 Dapr 使用 gRPC 与应用程序通信:

dapr run --app-protocol grpc --app-port 5005 node app.js

这会指示 Dapr 通过 gRPC 在端口 5005 上与你的应用程序通信。

在 Kubernetes 上,在部署 YAML 中设置以下注解:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: default
  labels:
    app: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "myapp"
        dapr.io/app-protocol: "grpc"
        dapr.io/app-port: "5005"
#...

后续步骤

处理大型 HTTP 头部大小

3.7 - 操作指南:处理大型 HTTP 头大小

配置更大的 HTTP 读取缓冲区大小

Dapr 对 HTTP 头读取缓冲区大小有 4KB 的默认限制。如果您发送的 HTTP 头超过默认的 4KB,可能会遇到 Too big request header 服务调用错误。

您可以通过以下方式增加 HTTP 头大小:

  • dapr.io/http-read-buffer-size 注解,或
  • 使用 CLI 时的 --dapr-http-read-buffer-size 标志。

在自托管模式下运行时,使用 --dapr-http-read-buffer-size 标志配置 Dapr 使用非默认的 http 头大小:

dapr run --dapr-http-read-buffer-size 16 node app.js

这告诉 Dapr 将最大读取缓冲区大小设置为 16 KB。

在 Kubernetes 上,在部署 YAML 中设置以下注解:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: default
  labels:
    app: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "myapp"
        dapr.io/app-port: "8000"
        dapr.io/http-read-buffer-size: "16"
#...

相关链接

Dapr Kubernetes Pod 注解规范

后续步骤

处理大型 HTTP body 请求

3.8 - 操作指南:处理更大的请求体

配置大于 4 MB 的 HTTP 请求

默认情况下,Dapr 对请求体大小有限制,设置为 4MB。你可以通过定义以下内容来更改 HTTP 和 gRPC 请求的限制:

  • dapr.io/max-body-size 注解,或
  • --max-body-size 标志。

在自托管模式下运行时,使用 --max-body-size 标志配置 Dapr 以使用非默认的请求体大小:

dapr run --max-body-size 16Mi node app.js

在 Kubernetes 上,在部署 YAML 中设置以下注解:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: default
  labels:
    app: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "myapp"
        dapr.io/app-port: "8000"
        dapr.io/max-body-size: "16Mi"
#...

这将告诉 Dapr 为 HTTP 和 gRPC 请求将最大请求体大小设置为 16 MB。

相关链接

Dapr Kubernetes pod 注解规范

下一步

安装边车证书

3.9 - 操作指南:在 Dapr 边车中安装证书

配置 Dapr 边车容器以信任证书

Dapr 边车可以配置为信任用于与外部服务通信的证书。这在需要信任自签名证书的场景中很有用,例如:

  • 使用 HTTP binding
  • 为边车配置出站代理

同时支持证书颁发机构(CA)证书和叶证书。

当边车作为容器运行时,你可以进行以下配置。

  1. 使用卷挂载将证书配置为对边车容器可用。
  2. 将边车容器中的环境变量 SSL_CERT_DIR 指向包含证书的目录。

注意: 对于 Windows 容器,请确保容器以管理员权限运行,以便它可以安装证书。

以下示例使用 Docker Compose 在边车容器中安装证书(在本地 ./certificates 目录中存在):

version: '3'
services:
  dapr-sidecar:
    image: "daprio/daprd:edge" # dapr 版本必须至少为 v1.8
    command: [
      "./daprd",
     "-app-id", "myapp",
     "-app-port", "3000",
     ]
    volumes:
        - "./components/:/components"
        - "./certificates:/certificates" # (步骤 1)将证书文件夹挂载到边车容器
    environment:
      - "SSL_CERT_DIR=/certificates" # (步骤 2)将环境变量设置为证书文件夹的路径
    # 对于 Windows 容器,取消下面的注释
    # user: ContainerAdministrator

注意: 当边车未在容器内运行时,证书必须直接安装在主机操作系统上。

在 Kubernetes 上:

  1. 使用卷挂载将证书配置为对边车容器可用。
  2. 将边车容器中的环境变量 SSL_CERT_DIR 指向包含证书的目录。

以下示例 YAML 显示了一个部署,该部署:

  • 将 Pod 卷附加到边车
  • 设置 SSL_CERT_DIR 以安装证书
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: default
  labels:
    app: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "myapp"
        dapr.io/app-port: "8000"
        dapr.io/volume-mounts: "certificates-vol:/tmp/certificates" # (步骤 1)将证书文件夹挂载到边车容器
        dapr.io/env: "SSL_CERT_DIR=/tmp/certificates" # (步骤 2)将环境变量设置为证书文件夹的路径
    spec:
      volumes:
        - name: certificates-vol
          hostPath:
            path: /certificates
#...

注意:使用 Windows 容器时,边车容器以管理员权限启动,这是安装证书所必需的。这不适用于 Linux 容器。

按照这些步骤后,将安装 SSL_CERT_DIR 指向的目录中的所有证书。

演示

观看关于安装 SSL 证书并在社区通话 64 中安全使用 HTTP binding 的演示:

相关链接

下一步

启用预览功能

3.10 - 操作指南:启用预览功能

如何指定和启用预览功能

Dapr 中的预览功能在初次发布时被视为实验性功能。这些预览功能需要你明确选择加入才能使用。你需要在 Dapr 的 Configuration 文件中指定此选择加入。

预览功能是基于每个应用程序启用的,方法是在运行应用程序实例时进行设置。

配置属性

Configuration 规范下的 features 部分包含以下属性:

属性类型描述
namestring启用/禁用的预览功能的名称
enabledbool指定是启用还是禁用该功能的布尔值

启用预览功能

预览功能在配置中指定。以下是包含多个功能的完整配置示例:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: featureconfig
spec:
  tracing:
    samplingRate: "1"
    zipkin:
      endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"
  features:
    - name: Feature1
      enabled: true
    - name: Feature2
      enabled: true

要在本地运行 Dapr 时启用预览功能,可以更新默认配置或使用 dapr run 指定单独的配置文件。

当你运行 dapr init 时会创建默认的 Dapr 配置,位于:

  • Windows: %USERPROFILE%\.dapr\config.yaml
  • Linux/macOS: ~/.dapr/config.yaml

或者,你可以通过在 dapr run 中指定 --config 标志并指向单独的 Dapr 配置文件,来更新在本地运行的所有应用程序的预览功能:

dapr run --app-id myApp --config ./previewConfig.yaml ./app

在 Kubernetes 模式下,必须通过配置组件提供配置。使用与上面相同的配置,通过 kubectl 应用它:

kubectl apply -f previewConfig.yaml

然后可以通过修改应用程序的配置,通过 dapr.io/config 元素引用该特定的配置组件,从而在任何应用程序中引用此配置组件。例如:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
  labels:
    app: node
spec:
  replicas: 1
  selector:
    matchLabels:
      app: node
  template:
    metadata:
      labels:
        app: node
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodeapp"
        dapr.io/app-port: "3000"
        dapr.io/config: "featureconfig"
    spec:
      containers:
      - name: node
        image: dapriosamples/hello-k8s-node:latest
        ports:
        - containerPort: 3000
        imagePullPolicy: Always

后续步骤

配置架构

3.11 - 操作指南:为 Dapr 边车配置来自密钥的环境变量

将 Kubernetes 密钥中的环境变量注入到 Dapr 边车中

在特殊情况下,Dapr 边车需要向其注入环境变量。此用例可能是组件、第三方库或使用环境变量来配置所述组件或自定义其行为的模块所必需的。这对于生产环境和非生产环境都很有用。

概述

在 Dapr 1.15 中,引入了新的 dapr.io/env-from-secret 注解,类似于 dapr.io/env。 使用此注解,您可以将环境变量注入到 Dapr 边车中,其值来自密钥。

注解格式

此注解的值格式如下:

  • 单键密钥:<ENV_VAR_NAME>=<SECRET_NAME>
  • 多键/值密钥:<ENV_VAR_NAME>=<SECRET_NAME>:<SECRET_KEY>

<ENV_VAR_NAME> 需要遵循 C_IDENTIFIER 格式并由 [A-Za-z_][A-Za-z0-9_]* 正则表达式捕获:

  • 必须以字母或下划线开头
  • 标识符的其余部分包含字母、数字或下划线

由于 secretKeyRef 的限制,需要设置 name 字段,因此必须同时设置 namekey在此 Kubernetes 文档的 “env.valueFrom.secretKeyRef.name” 部分了解更多信息。 在这种情况下,Dapr 将两者设置为相同的值。

配置单键密钥环境变量

在以下示例中,dapr.io/env-from-secret 注解被添加到 Deployment 中。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
spec:
  template:
    metadata:
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodeapp"
        dapr.io/app-port: "3000"
        dapr.io/env-from-secret: "AUTH_TOKEN=auth-headers-secret"
    spec:
      containers:
      - name: node
        image: dapriosamples/hello-k8s-node:latest
        ports:
        - containerPort: 3000
        imagePullPolicy: Always

值为 "AUTH_TOKEN=auth-headers-secret"dapr.io/env-from-secret 注解被注入为:

env:
- name: AUTH_TOKEN
    valueFrom:
    secretKeyRef:
        name: auth-headers-secret
        key: auth-headers-secret

这要求密钥同时具有相同值的 namekey 字段,即 “auth-headers-secret”。

示例密钥

**注意:**以下示例仅用于演示目的。不建议以明文形式存储密钥。

apiVersion: v1
kind: Secret
metadata:
  name: auth-headers-secret
type: Opaque
stringData:
  auth-headers-secret: "AUTH=mykey"

配置多键密钥环境变量

在以下示例中,dapr.io/env-from-secret 注解被添加到 Deployment 中。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
spec:
  template:
    metadata:
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodeapp"
        dapr.io/app-port: "3000"
        dapr.io/env-from-secret: "AUTH_TOKEN=auth-headers-secret:auth-header-value"
    spec:
      containers:
      - name: node
        image: dapriosamples/hello-k8s-node:latest
        ports:
        - containerPort: 3000
        imagePullPolicy: Always

值为 "AUTH_TOKEN=auth-headers-secret:auth-header-value"dapr.io/env-from-secret 注解被注入为:

env:
- name: AUTH_TOKEN
    valueFrom:
    secretKeyRef:
        name: auth-headers-secret
        key: auth-header-value

示例密钥

**注意:**以下示例仅用于演示目的。不建议以明文形式存储密钥。

apiVersion: v1
kind: Secret
metadata:
  name: auth-headers-secret
type: Opaque
stringData:
  auth-header-value: "AUTH=mykey"

3.12 - 操作指南:为 Dapr 边车服务添加自定义注解

在 Dapr 边车服务上配置自定义注解

Dapr Operator 在 Kubernetes 中运行时,会自动为 Dapr 边车创建一个 Service(名称带有 -dapr 后缀)。在某些情况下,您可能需要向此服务添加自定义注解,例如以支持特定的网络策略(如 Illumio)或指标抓取配置。

概述

dapr.io/sidecar-svc-annotations 注解让您能够指定以逗号分隔的 key=value 对列表,这些键值对将被作为注解添加到 Dapr 边车服务。

使用方式

将注解添加到您的 Deployment 或 StatefulSet Pod 模板中。

格式

值应采用逗号分隔的键值对列表: key1=value1,key2=value2

示例

以下是一个向 Dapr 边车服务添加自定义注解的 Deployment 示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-app
  namespace: default
  labels:
    app: test-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-app
  template:
    metadata:
      labels:
        app: test-app
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "test-app"
        dapr.io/sidecar-svc-annotations: "com.example.policy.app=test-app,com.example.policy.env=test,com.example.policy.team=platform"
    spec:
      containers:
      - name: test-app
        image: nginx:1.19.2

Dapr Operator 生成的 Service 将包含这些注解:

apiVersion: v1
kind: Service
metadata:
  annotations:
    com.example.policy.app: test-app
    com.example.policy.env: test
    com.example.policy.team: platform
    dapr.io/app-id: test-app
    prometheus.io/path: /
    prometheus.io/port: "9090"
    prometheus.io/probe: "true"
    prometheus.io/scrape: "true"
  labels:
    dapr.io/enabled: "true"
  name: test-app-dapr
  namespace: default
...

4 - 在 Dapr 中管理组件

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

4.1 - 认证生命周期

从提交到生产就绪的组件认证生命周期

概述

Dapr 采用模块化设计,功能以组件形式交付。每个组件都有一个接口定义。所有组件都是可互换的,因此在理想情况下,您可以用具有相同接口的另一个组件替换某个组件。生产环境中使用的每个组件都需要维护一定的技术要求,以确保功能兼容性和健壮性。

通常,组件需要满足:

  • 符合定义的 Dapr 接口
  • 功能正确且健壮
  • 文档完善且得到维护

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

认证级别

级别如下:

Alpha

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

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

Beta

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

Stable

  • 组件必须具有组件认证测试,用于验证功能和弹性
  • 组件由 Dapr 维护者维护,并由社区支持
  • 组件文档完善且经过测试
  • 组件在之前至少 1 个 Dapr runtime 次版本发布中已作为 Alpha 或 Beta 提供
  • 维护者将根据 Dapr 支持策略处理组件安全性、核心功能和测试问题,并发布包含修补后的稳定组件的补丁版本

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

任何之前认证为 GA 的组件即使不满足新要求,也允许进入 Stable 级别。

一致性测试

components-contrib 仓库中的每个组件都需要遵守 Dapr 定义的一组接口。一致性测试是在这些组件定义上运行的测试,连同其关联的后端服务,以测试组件是否符合 Dapr 接口规范和行为。

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

  • 状态存储
  • 密钥存储
  • 绑定
  • 发布订阅

要了解更多信息,请参阅此处的 readme

测试要求

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

认证测试

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

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

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

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

测试要求

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

组件认证流程

为了对组件进行认证,测试在 Dapr 项目维护的环境中运行。

新组件认证:Alpha->Beta

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

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

新组件认证:Beta->Stable

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

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

4.2 - 更新组件

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

当对应用程序使用的现有已部署组件进行更新时,除非启用了 HotReload 特性门控,否则 Dapr 不会自动更新组件。 需要重启 Dapr 边车以获取组件的最新版本。 具体操作方式取决于托管环境。

Kubernetes

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

  1. 将新的组件 YAML 应用到目标命名空间
  2. 除非启用了 HotReload 特性门控,否则在你的部署上执行 rollout restart 操作 以获取最新组件

自托管模式

除非启用了 HotReload 特性门控,否则更新组件的过程需要单个步骤:停止并重启 daprd 进程以获取最新组件。

热重载(预览功能)

此功能目前处于预览阶段。 热重载通过 HotReload 特性门控 启用。

Dapr 可以"热重载"组件,即无需重启 Dapr 边车进程或 Kubernetes pod 即可自动获取组件更新。 这意味着在运行时创建、更新或删除组件清单会反映在 Dapr 边车中。

除以下类型外,所有组件都支持热重载。 对于这些组件类型的任何创建、更新或删除操作都会被边车忽略,需要重启才能获取更改。

延伸阅读

4.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 的应用程序授予访问名为 statestore 的 Redis 组件的权限,这两个应用程序的 app ID 分别为 app1app2,而该组件本身位于 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

社区电话演示

在服务调用中使用命名空间

阅读跨命名空间的服务调用以了解更多关于在服务间调用时使用命名空间的信息。

在发布订阅中使用命名空间

阅读使用多个命名空间配置发布订阅组件以了解更多关于在发布订阅中使用命名空间的信息。

相关链接

4.4 - 操作指南:在组件中引用密钥

如何安全地从组件定义中引用密钥

概述

组件可以引用组件定义中 spec.metadata 部分的密钥。

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

在 Kubernetes 中运行时,如果 auth.secretStore 为空,则假定为 Kubernetes 密钥存储。

支持的密钥存储

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

引用密钥

虽然你可以选择使用纯文本密钥(如 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

相反,你应在密钥存储中创建密钥并在组件定义中引用它。下面显示了两种情况——“密钥包含嵌入的键"和"密钥是字符串”。

“密钥包含嵌入的键"的情况适用于密钥中嵌入有键的情况,即密钥不是完整的连接字符串。这在以下组件定义 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 是配置的密钥存储组件的名称。在 Kubernetes 中运行并使用 Kubernetes 密钥存储时,字段 auth.SecretStore 默认为 kubernetes,可以留空。

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

另一方面,下面的"密钥是字符串"的情况适用于密钥中没有嵌入键的情况。相反,密钥只是一个字符串。因此,在 secretKeyRef 部分中,密钥 name 和密钥 key 将是相同的。这种情况适用于密钥本身是一个完整的连接字符串,没有嵌入的需要提取其值的键的情况。通常,连接字符串由连接信息、某种允许连接的密钥,可能还有其他信息组成,不需要单独的"密钥”。这种情况在以下组件定义 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>

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

示例

引用 Kubernetes 密钥

以下示例向你展示如何创建 Kubernetes 密钥来保存 Event Hubs 绑定的连接字符串。

  1. 首先,创建 Kubernetes 密钥:

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

    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
    

限制对密钥的访问

Dapr 可以使用其配置限制对密钥存储中的密钥的访问。阅读操作指南:使用密钥范围操作指南:限制可以从密钥存储读取的密钥以获取更多信息。这是使用 Dapr 限制对密钥的访问的推荐方法。

Kubernetes 权限

默认命名空间

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

非默认命名空间

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

---
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 密钥存储获取密钥的权限。

相关链接

4.5 - 状态存储组件

为 Dapr 状态管理设置不同状态存储的指南

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

状态存储是可扩展的,可以在 components-contrib repo 中找到。

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 部分。 尽管元数据值可以包含明文密钥,但建议您使用 secret store

访问此指南了解如何配置状态存储组件。

支持的状态存储

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

相关主题

4.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 部分。 尽管元数据值可以明文形式包含密钥,但建议您使用 secretKeyRef 来引用密钥存储

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

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

相关链接

4.6.1 - HowTo: 配置多命名空间的发布订阅组件

在多命名空间中使用 Dapr 发布订阅

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

本示例使用 PubSub 示例。Redis 安装和订阅者位于 namespace-a 中,而发布者 UI 位于 namespace-b 中。如果 Redis 安装在另一个命名空间中,或者您使用托管云服务(如 Azure ServiceBus、AWS SNS/SQS 或 GCP PubSub),此解决方案也可以工作。

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



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

资源namespace-anamespace-b
Redis master
Redis replicas
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

相关链接

4.7 - 密钥存储组件

关于设置不同密钥存储组件的指导

Dapr 与密钥存储集成,为应用程序和其他组件提供访问密钥(如访问密钥和密码)的安全存储和访问方式。每个密钥存储组件都有一个名称,在访问密钥时使用该名称。

与其他构建块组件一样,密钥存储组件是可扩展的,可以在 components-contrib 仓库 中找到。

Dapr 中的密钥存储使用 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>
...

密钥存储的类型由 type 字段决定,连接字符串和其他元数据等内容放在 .metadata 部分中。

不同的支持的密钥存储将具有不同的需要配置的具体字段。例如,当配置使用 AWS Secrets Manager 的密钥存储时,文件将如下所示:

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-pathdapr run 命令提供该路径。

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

kubectl apply -f secret-store.yaml

支持的密钥存储

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

相关链接

4.8 - Binding 组件

设置 Dapr binding 组件的指南

Dapr 与外部资源集成,允许应用既可以被外部事件触发,也可以与这些资源进行交互。每个 binding 组件都有一个名称,在与该资源交互时使用这个名称。

与其他构建块组件一样,binding 组件是可扩展的,可以在 components-contrib repo 中找到。

Dapr 中的 binding 使用 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>
...

binding 的类型由 type 字段决定,连接字符串和其他元数据等项放在 .metadata 部分。

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

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

支持的 binding

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

相关链接

4.9 - How-To: 注册可插拔组件

了解如何注册可插拔组件

组件注册流程

基于 gRPC 的可插拔组件 通常作为容器或进程运行,需要通过 Unix Domain Socket(简称 UDS)与 Dapr 运行时通信。它们通过以下步骤在运行时中被自动发现和注册:

  1. 组件监听位于共享卷上的 Unix Domain Socket
  2. Dapr 运行时列出共享卷中的所有 Unix Domain Socket
  3. Dapr 运行时与每个 socket 建立连接,并使用 gRPC 反射从给定构建块 API 中发现该组件实现的所有 proto 服务。

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

虽然 Dapr 的内置组件随运行时一起包含,但可插拔组件需要一些设置步骤才能与 Dapr 一起使用。

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

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

这也会改变在 Dapr 和可插拔组件之间共享 Unix Domain Socket 文件的方式。

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

运行组件

在 Dapr 启动之前,您的组件和 Unix Socket 必须都在运行。

默认情况下,Dapr 边车会在 /tmp/dapr-components-sockets 中查找作为 Unix Domain Socket 文件的组件。

此文件夹中的文件名对于组件注册很重要。它们必须通过将组件的名称附加您选择的文件扩展名来构成,更常见的是 .sock。例如,文件名 my-component.sock 是名为 my-component 的组件的有效 Unix Domain Socket 文件名。

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

组件发现和多路复用

可通过 Unix Domain Socket(UDS)访问的可插拔组件可以托管多个不同的组件 API。在组件的初始发现过程中,Dapr 使用反射来枚举 UDS 后面的所有组件 API。上面示例中的 my-component 可插拔组件可以同时包含状态存储(state)和发布订阅(pubsub)组件 API。

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

定义组件

使用组件规范定义您的组件。组件的 spec.type 值是通过将以下 2 个部分用 . 连接起来构成的:

  1. 组件的 API(statepubsubbindings 等)
  2. 组件的名称,源自 Unix Domain Socket 文件名,不带文件扩展名。

您需要为可插拔组件的 Unix Domain Socket 公开的每个 API 定义一个组件规范。上一个示例中的 Unix Domain Socket 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 是此处定义的状态存储的名称,与可插拔组件名称无关。

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

运行 Dapr

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

就是这样!现在您可以通过 Dapr API 调用状态存储 API。通过运行以下命令查看实际效果。将 $PORT 替换为 Dapr HTTP 端口:

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

检索值,将 $PORT 替换为 Dapr HTTP 端口:

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

为可插拔组件构建并发布容器

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

在 Kubernetes 集群上部署 Dapr

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

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

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

由于可插拔组件由 Unix Domain Sockets 支持,因此使可插拔组件创建的 socket 可被 Dapr 运行时访问。将部署规范配置为:

  1. 挂载卷
  2. 向 Dapr 提示已挂载的 Unix socket 卷位置
  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 的边车注入器此应用程序的 pod 将具有用于可插拔组件的其他容器。

或者,您可以跳过 Dapr 的边车注入功能,手动添加可插拔组件的容器并注释您的 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 派生自 socket 名称(不带文件扩展名)。在以下示例 YAML 中,替换:

  • your_socket_goes_here 替换为您的组件 socket 名称(无扩展名)
  • 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 的边车注入器为可插拔组件处理容器和卷注入时,dapr.io/component-container 注解在 Kubernetes 上是必需的。至少,您需要为 Dapr 的边车注入器提供 nameimage 属性,以便成功将容器添加到应用程序的 pod 中。Unix Domain Socket 的卷由 Dapr 的边车注入器自动创建和挂载。

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

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

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

通过运行以下命令查看实际效果。将 $PORT 替换为 Dapr HTTP 端口:

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

检索值,将 $PORT 替换为 Dapr HTTP 端口:

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

后续步骤

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

4.10 - 配置中间件组件

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

Dapr 允许通过链式串联一系列中间件组件来定义自定义处理管道。可以在两个位置使用中间件管道:

  1. 构建块 API - 调用任何 Dapr HTTP API 时执行 HTTP 中间件组件。
  2. 服务到服务调用 - 将 HTTP 中间件组件应用于服务到服务调用。

配置 API 中间件管道

启动时,Dapr 边车会为传入的 HTTP 调用构建一个中间件处理管道。默认情况下,该管道由 追踪 和 CORS 中间件组成。可以通过 Dapr 配置 添加额外的中间件,并按定义的顺序添加到管道中。该管道应用于所有 Dapr API 端点,包括状态、发布订阅、服务调用、绑定、密钥、配置、分布式锁等。

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

Diagram showing the flow of a request and a response through the middlewares, as described in the paragraph above

使用 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 边车到接收应用程序(服务)的所有传出调用,如下图所示。

Diagram showing the flow of a service invocation request. Requests from the callee Dapr sidecar to the callee application go through the app middleware pipeline as described in the paragraph above.

任何可用作 HTTP 中间件的中间件组件都可以使用 appHttpPipeline 配置作为中间件组件应用于服务到服务调用调用。下面的示例为从 Dapr 边车(服务调用的目标)到应用此配置的应用程序的所有传出调用添加 uppercase 中间件组件。

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

相关链接

5 - 保护 Dapr 部署

关于如何保护 Dapr 应用程序的最佳实践和说明

5.1 - 设置和配置 mTLS 证书

使用自签名或用户提供的 x.509 证书加密应用程序之间的通信

Dapr 支持通过 Dapr 控制平面 Sentry 服务对 Dapr 实例之间的通信进行传输中加密,该服务是一个中央证书颁发机构(CA)。

Dapr 允许操作员和开发者引入自己的证书,或者让 Dapr 自动创建并持久化自签名的根证书和颁发者证书。

有关 mTLS 的详细信息,请阅读安全概念部分

如果未提供自定义证书,Dapr 会自动创建并持久化有效期为一年自签名证书。 在 Kubernetes 中,证书会被持久化到一个 secret 中,该 secret 位于 Dapr 系统 pod 的命名空间内,仅对它们可访问。 在自托管模式下,证书会被持久化到磁盘。

控制平面 Sentry 服务配置

mTLS 设置位于 Dapr 控制平面配置文件中。例如,当将 Dapr 控制平面部署到 Kubernetes 时,该配置文件会自动创建,然后您可以对其进行编辑。以下文件显示了配置资源中 mTLS 的可用设置,部署在 daprsystem 命名空间中:

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

此文件显示了默认的 daprsystem 配置设置。下面的示例展示了如何在 Kubernetes 和自托管模式下更改并将此配置应用于控制平面 Sentry 服务。

Kubernetes

使用配置资源设置 mTLS

在 Kubernetes 中,Dapr 会创建一个默认的控制平面配置资源,并启用 mTLS。 Sentry 服务(证书颁发机构系统 pod)在使用 Helm 和使用 dapr init --kubernetes 的 Dapr CLI 时都会安装。

您可以使用以下命令查看控制平面配置资源:

kubectl get configurations/daprsystem --namespace <DAPR_NAMESPACE> -o yaml

要更改控制平面配置资源,请运行以下命令进行编辑:

kubectl edit configurations/daprsystem --namespace <DAPR_NAMESPACE>

保存更改后,执行控制平面的滚动更新:

kubectl rollout restart deploy/dapr-sentry -n <DAPR_NAMESPACE>
kubectl rollout restart deploy/dapr-operator -n <DAPR_NAMESPACE>
kubectl rollout restart statefulsets/dapr-placement-server -n <DAPR_NAMESPACE>

注意:控制平面 Sidecar Injector 服务不需要重新部署

使用 Helm 禁用 mTLS

控制平面将继续使用 mTLS

kubectl create ns dapr-system

helm install \
  --set global.mtls.enabled=false \
  --namespace dapr-system \
  dapr \
  dapr/dapr

使用 CLI 禁用 mTLS

控制平面将继续使用 mTLS

dapr init --kubernetes --enable-mtls=false

查看日志

要查看 Sentry 服务日志,请运行以下命令:

kubectl logs --selector=app=dapr-sentry --namespace <DAPR_NAMESPACE>

自带证书

使用 Helm,您可以提供 PEM 编码的根证书、颁发者证书和私钥,这些将被填充到 Sentry 服务使用的 Kubernetes secret 中。

注意:此示例使用 OpenSSL 命令行工具,这是一个广泛分发的软件包,可以通过软件包管理器在 Linux 上轻松安装。在 Windows 上,可以使用 chocolatey 安装 OpenSSL。在 MacOS 上可以使用 brew brew install openssl 安装

创建用于生成证书的配置文件,这对于生成带有 SAN(主题备用名称)扩展字段的 v3 证书是必需的。首先将以下内容保存到名为 root.conf 的文件中:

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = VA
L = Daprville
O = dapr.io/sentry
OU = dapr.io/sentry
CN = cluster.local
[v3_req]
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = cluster.local

issuer.conf 重复此操作,将相同的内容粘贴到文件中,但在 basicConstraints 行的末尾添加 pathlen:0,如下所示:

basicConstraints = critical, CA:true, pathlen:0

运行以下命令生成根证书和密钥

# 跳过以下行以重用现有的根密钥,这是轮换过期证书所必需的
openssl ecparam -genkey -name prime256v1 | openssl ec -out root.key
openssl req -new -nodes -sha256 -key root.key -out root.csr -config root.conf -extensions v3_req
openssl x509 -req -sha256 -days 365 -in root.csr -signkey root.key -outform PEM -out root.pem -extfile root.conf -extensions v3_req

接下来运行以下命令生成颁发者证书和密钥:

# 跳过以下行以重用现有的颁发者密钥,这是轮换过期证书所必需的
openssl ecparam -genkey -name prime256v1 | openssl ec -out issuer.key
openssl req -new -sha256 -key issuer.key -out issuer.csr -config issuer.conf -extensions v3_req
openssl x509 -req -in issuer.csr -CA root.pem -CAkey root.key -CAcreateserial -outform PEM -out issuer.pem -days 365 -sha256 -extfile issuer.conf -extensions v3_req

安装 Helm 并通过配置将根证书、颁发者证书和颁发者密钥传递给 Sentry:

kubectl create ns dapr-system

helm install \
  --set-file dapr_sentry.tls.issuer.certPEM=issuer.pem \
  --set-file dapr_sentry.tls.issuer.keyPEM=issuer.key \
  --set-file dapr_sentry.tls.root.certPEM=root.pem \
  --namespace dapr-system \
  dapr \
  dapr/dapr

使用 CLI 升级根和颁发者证书(推荐)

下面的 CLI 命令可用于在 Kubernetes 集群中续订根和颁发者证书。

生成全新的证书

  1. 下面的命令生成全新的根和颁发者证书,由新生成的私用根密钥签名。

注意:Dapr Sentry 服务和其余控制平面服务必须重启才能读取新证书。可以通过向命令提供 --restart 标志来完成。

dapr mtls renew-certificate -k --valid-until <days> --restart
  1. 下面的命令生成全新的根和颁发者证书,由提供的私用根密钥签名。

注意:如果您现有的部署证书由此相同的私用根密钥签名,则 Dapr Sentry 服务无需重启即可读取这些新证书。

dapr mtls renew-certificate -k --private-key <private_key_file_path> --valid-until <days>

使用提供的自定义证书续订证书

要更新 Kubernetes 集群中提供的证书,可以使用下面的 CLI 命令。

注意 - 它不支持 valid-until 标志来指定新证书的有效期。

dapr mtls renew-certificate -k --ca-root-certificate <ca.crt> --issuer-private-key <issuer.key> --issuer-public-certificate <issuer.crt> --restart

推荐的做法是对部署执行滚动重启:

kubectl rollout restart deploy/myapp

使用 Kubectl 更新根或颁发者证书

如果根证书或颁发者证书即将过期,您可以更新它们并重启所需的系统服务。

Dapr 生成的自签名证书

  1. 通过将以下 YAML 保存到文件(例如 clear-trust-bundle.yaml)并应用此 secret 来清除现有的 Dapr Trust Bundle secret。
apiVersion: v1
kind: Secret
metadata:
  name: dapr-trust-bundle
  labels:
    app: dapr-sentry
data:
kubectl apply -f `clear-trust-bundle.yaml` -n <DAPR_NAMESPACE>
  1. 重启 Dapr Sentry 服务。这将生成新的证书包并更新 dapr-trust-bundle Kubernetes secret。
kubectl rollout restart -n <DAPR_NAMESPACE> deployment/dapr-sentry
  1. Sentry 服务重启后,重启 Dapr 控制平面的其余部分以获取新的 Dapr Trust Bundle。
kubectl rollout restart deploy/dapr-operator -n <DAPR_NAMESPACE>
kubectl rollout restart statefulsets/dapr-placement-server -n <DAPR_NAMESPACE>
kubectl rollout restart deploy/dapr-sidecar-injector -n <DAPR_NAMESPACE>
kubectl rollout restart statefulsets/dapr-scheduler-server -n <DAPR_NAMESPACE>
  1. 重启您的 Dapr 应用程序以获取最新的信任包。
kubectl rollout restart deployment/mydaprservice1 kubectl deployment/myotherdaprservice2

自定义证书(自带)

首先,使用自带证书中的步骤颁发新证书。

现在您已拥有新证书,请使用 Helm 升级证书:

helm upgrade \
  --set-file dapr_sentry.tls.issuer.certPEM=issuer.pem \
  --set-file dapr_sentry.tls.issuer.keyPEM=issuer.key \
  --set-file dapr_sentry.tls.root.certPEM=root.pem \
  --namespace dapr-system \
  dapr \
  dapr/dapr

或者,您可以更新保存它们的 Kubernetes secret:

kubectl edit secret dapr-trust-bundle -n <DAPR_NAMESPACE>

用新证书中的相应值替换 Kubernetes secret 中的 ca.crtissuer.crtissuer.key 键。 注意:值必须是 base64 编码的

如果您使用相同的私钥签名了新的证书根,Dapr Sentry 服务将自动获取新证书。您可以使用 kubectl rollout restart 零停机地重启应用程序部署。只要在原始证书过期之前重启部署,就不必一次性重启所有部署。

如果您使用不同的私钥签名了新的证书根,则必须重启 Dapr Sentry 服务,然后是 Dapr 控制平面服务的其余部分。

kubectl rollout restart deploy/dapr-sentry -n <DAPR_NAMESPACE>

Sentry 完全重启后,运行:

kubectl rollout restart deploy/dapr-operator -n <DAPR_NAMESPACE>
kubectl rollout restart statefulsets/dapr-placement-server -n <DAPR_NAMESPACE>

接下来,您必须重启所有启用 Dapr 的 pod。 推荐的做法是对部署执行滚动重启:

kubectl rollout restart deploy/myapp

由于证书不匹配,在所有部署成功重启(从而加载新的 Dapr 证书)之前,您可能会遇到潜在的停机时间。

Kubernetes 视频演示

观看此视频以了解如何在 Kubernetes 上更新 mTLS 证书

为 Dapr 控制平面 mTLS 证书过期设置监控

从 mTLS 根证书过期前 30 天开始,Dapr sentry 服务将每小时发出警告级别日志,表明根证书即将过期。

作为在 生产环境中运行 Dapr 的操作最佳实践,我们建议配置对这些特定 sentry 服务日志的监控,以便您了解即将到来的证书过期。

"Dapr root certificate expiration warning: certificate expires in 2 days and 15 hours"

证书过期后,您将看到以下消息:

"Dapr root certificate expiration warning: certificate has expired."

在 Kubernetes 中,您可以这样查看 sentry 服务日志:

kubectl logs deployment/dapr-sentry -n dapr-system

日志输出将如下所示:"

{"instance":"dapr-sentry-68cbf79bb9-gdqdv","level":"warning","msg":"Dapr root certificate expiration warning: certificate expires in 2 days and 15 hours","scope":"dapr.sentry","time":"2022-04-01T23:43:35.931825236Z","type":"log","ver":"1.6.0"}

作为提醒您即将到来的证书过期的附加工具,从 1.7.0 版本开始,CLI 现在会在您与基于 Kubernetes 的部署交互时打印证书过期状态。

示例:

dapr status -k

  NAME                   NAMESPACE    HEALTHY  STATUS   REPLICAS  VERSION   AGE  CREATED
  dapr-operator          dapr-system  True     Running  1         1.15.1    4m   2025-02-19 17:36.26
  dapr-placement-server  dapr-system  True     Running  1         1.15.1    4m   2025-02-19 17:36.27
  dapr-dashboard         dapr-system  True     Running  1         0.15.0    4m   2025-02-19 17:36.27
  dapr-sentry            dapr-system  True     Running  1         1.15.1    4m   2025-02-19 17:36.26
  dapr-scheduler-server  dapr-system  True     Running  3         1.15.1    4m   2025-02-19 17:36.27
  dapr-sidecar-injector  dapr-system  True     Running  1         1.15.1    4m   2025-02-19 17:36.26
⚠  Dapr root certificate of your Kubernetes cluster expires in 2 days. Expiry date: Mon, 04 Apr 2025 15:01:03 UTC.
 Please see docs.dapr.io for certificate renewal instructions to avoid service interruptions.

自托管

运行控制平面 Sentry 服务

要运行 Sentry 服务,您可以从源代码构建,或从这里下载发布二进制文件。

从源代码构建时,请参阅指南以了解如何构建 Dapr。

其次,为 Sentry 服务创建一个目录以创建自签名根证书:

mkdir -p $HOME/.dapr/certs

使用以下命令在本地运行 Sentry 服务:

./sentry --issuer-credentials $HOME/.dapr/certs --trust-domain cluster.local

如果成功,Sentry 服务将运行并在给定目录中创建根证书。 此命令使用默认配置值,因为未给出自定义配置文件。请参阅下面有关如何使用自定义配置启动 Sentry 服务的信息。

使用配置资源设置 mTLS

Dapr 实例配置

在自托管模式下运行 Dapr 时,默认情况下禁用 mTLS。您可以通过创建以下配置文件来启用它:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: daprsystem
  namespace: default
spec:
  mtls:
    enabled: true

除了 Dapr 配置外,您还需要为每个 Dapr sidecar 实例提供 TLS 证书。您可以通过在运行 Dapr 实例之前设置以下环境变量来做到这一点:

export DAPR_TRUST_ANCHORS=`cat $HOME/.dapr/certs/ca.crt`
export DAPR_CERT_CHAIN=`cat $HOME/.dapr/certs/issuer.crt`
export DAPR_CERT_KEY=`cat $HOME/.dapr/certs/issuer.key`
export NAMESPACE=default
$env:DAPR_TRUST_ANCHORS=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\ca.crt)
$env:DAPR_CERT_CHAIN=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\issuer.crt)
$env:DAPR_CERT_KEY=$(Get-Content -raw $env:USERPROFILE\.dapr\certs\issuer.key)
$env:NAMESPACE="default"

如果使用 Dapr CLI,请将 Dapr 指向上面的配置文件以运行启用 mTLS 的 Dapr 实例:

dapr run --app-id myapp --config ./config.yaml node myapp.js

如果直接使用 daprd,请使用以下标志启用 mTLS:

daprd --app-id myapp --enable-mtls --sentry-address localhost:50001 --config=./config.yaml

Sentry 服务配置

以下是 Sentry 的配置示例,将工作负载证书 TTL 更改为 25 秒:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: daprsystem
  namespace: default
spec:
  mtls:
    enabled: true
    workloadCertTTL: "25s"

要使用自定义配置启动 Sentry 服务,请使用以下标志:

./sentry --issuer-credentials $HOME/.dapr/certs --trust-domain cluster.local --config=./config.yaml

自带证书

要提供您自己的凭证,请创建 ECDSA PEM 编码的根和颁发者证书并将它们放置在文件系统上。 使用 --issuer-credentials 标志告诉 Sentry 服务从哪里加载证书。

下一个示例创建根和颁发者证书并使用 Sentry 服务加载它们。

注意:此示例使用 step 工具创建证书。您可以从这里安装 step 工具。Windows 二进制文件可在这里获取

创建根证书:

step certificate create cluster.local ca.crt ca.key --profile root-ca --no-password --insecure

创建颁发者证书:

step certificate create cluster.local issuer.crt issuer.key --ca ca.crt --ca-key ca.key --profile intermediate-ca --not-after 8760h --no-password --insecure

这将创建根和颁发者证书和密钥。 将 ca.crtissuer.crtissuer.key 放在所需路径中(下面的示例中为 $HOME/.dapr/certs),并启动 Sentry:

./sentry --issuer-credentials $HOME/.dapr/certs --trust-domain cluster.local

更新根或颁发者证书

如果根证书或颁发者证书即将过期,您可以更新它们并重启所需的系统服务。

要让 Dapr 生成新证书,请删除 $HOME/.dapr/certs 处的现有证书并重启 sentry 服务以生成新证书。

./sentry --issuer-credentials $HOME/.dapr/certs --trust-domain cluster.local --config=./config.yaml

要替换为您自己的证书,首先使用自带证书中的步骤生成新证书。

ca.crtissuer.crtissuer.key 复制到每个配置的系统服务的文件系统路径,并重启进程或容器。 默认情况下,系统服务将在 /var/run/dapr/credentials 中查找凭证。上面的示例使用 $HOME/.dapr/certs 作为自定义位置。

注意:如果您使用不同的私钥签名了证书根,请重启 Dapr 实例。

关于证书轮换的社区电话视频

观看此视频了解如果您的证书即将过期如何执行证书轮换。

Sentry 令牌验证器

令牌通常用于身份验证和授权目的。 令牌验证器是负责验证这些令牌的有效性和真实性的组件。 例如,在 Kubernetes 环境中,令牌验证的常见方法是通过 Kubernetes 绑定服务账户机制。 此验证器针对 Kubernetes 检查绑定的服务账户令牌,以确保其合法性。

Sentry 服务可以配置为:

  • 除了 Kubernetes 绑定服务账户验证器之外,启用额外的令牌验证器
  • 替换自托管模式下默认启用的 insecure 验证器

Sentry 令牌验证器用于将额外的非 Kubernetes 客户端加入以 Kubernetes 模式运行的 Dapr 集群,或替换自托管模式下不安全的"允许所有"验证器以启用适当的身份验证。 除非您使用的是特殊的部署场景,否则预计您不需要配置令牌验证器。

目前唯一支持的令牌验证器是 jwks 验证器。

JWKS

jwks 验证器使 Sentry 服务能够使用 JWKS 端点验证 JWT 令牌。 令牌的内容_必须_包含与 Dapr 客户端的 SPIFFE 身份匹配的 sub 声明,采用相同的 Dapr 格式 spiffe://<trust-domain>/ns/<namespace>/<app-id>。 令牌的受众必须是 Sentry 身份的 SPIFFE ID,例如 spiffe://cluster.local/ns/dapr-system/dapr-sentry。 有关签名、过期等的基本 JWT 规则也适用。

jwks 验证器可以接受远程源来获取公钥列表或静态公钥数组。

下面的配置使用远程源启用 jwks 令牌验证器。 此远程源使用 HTTPS,因此 caCertificate 字段包含远程源的信任根。

kind: Configuration
apiVersion: dapr.io/v1alpha1
metadata:
  name: sentryconfig
spec:
  mtls:
    enabled: true
    tokenValidators:
      - name: jwks
        options:
          minRefreshInterval: 2m
          requestTimeout: 1m
          source: "https://localhost:1234/"
          caCertificate: "<optional ca certificate bundle string>"

下面的配置使用静态公钥数组启用 jwks 令牌验证器。

kind: Configuration
apiVersion: dapr.io/v1alpha1
metadata:
  name: sentryconfig
spec:
  mtls:
    enabled: true
    tokenValidators:
      - name: jwks
        options:
          minRefreshInterval: 2m
          requestTimeout: 1m
          source: |
            {"keys":[ "12345.." ]}

5.2 - 使用 OAuth 配置 endpoint 授权

为你的 Web API 在应用程序 endpoint 上启用 OAuth 授权

Dapr OAuth 2.0 中间件 允许你使用 授权码授权流程 为你的 Web API 在 Dapr endpoint 上启用 OAuth 授权。 你也可以将授权令牌注入到你的 endpoint API 中,使用 客户端凭据授权流程 向你的 API 调用的外部 API 进行授权。 当中间件启用时,通过 Dapr 的任何方法调用都需要在传递给用户代码之前进行授权。

这两种流程的主要区别在于,授权码授权流程 需要用户交互并对用户进行授权,而 客户端凭据授权流程 不需要用户交互,对服务/应用程序进行授权。

在授权服务器上注册你的应用程序

不同的授权服务器提供不同的应用程序注册体验。以下是一些示例:

要配置 Dapr OAuth 中间件,你需要收集以下信息:

  • Client ID(参见此处
  • Client secret(参见此处
  • Scopes(参见此处
  • Authorization URL
  • Token URL

一些流行的授权服务器的授权/令牌 URL:

ServerAuthorization URLToken URL
Microsoft Entra IDhttps://login.microsoftonline.com/{tenant}/oauth2/authorizehttps://login.microsoftonline.com/{tenant}/oauth2/token
GitHubhttps://github.com/login/oauth/authorizehttps://github.com/login/oauth/access_token
Googlehttps://accounts.google.com/o/oauth2/v2/authhttps://accounts.google.com/o/oauth2/token https://www.googleapis.com/oauth2/v4/token
Twitterhttps://api.twitter.com/oauth/authorizehttps://api.twitter.com/oauth2/token

定义中间件组件定义

定义授权码授权组件

OAuth 中间件(授权码)由组件定义:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: oauth2
  namespace: default
spec:
  type: middleware.http.oauth2
  version: v1
  metadata:
  - name: clientId
    value: "<your client ID>"
  - name: clientSecret
    value: "<your client secret>"
  - name: scopes
    value: "<comma-separated scope names>"
  - name: authURL
    value: "<authorization URL>"
  - name: tokenURL
    value: "<token exchange URL>"
  - name: redirectURL
    value: "<redirect URL>"
  - name: authHeaderName
    value: "<header name under which the secret token is saved>"
    # forceHTTPS:
    # 此键用于在从身份提供者成功接收访问令牌后
    # 在重定向到 API 方法时设置 HTTPS 架构。
    # 默认情况下,Dapr 将在此重定向上使用 HTTP。
  - name: forceHTTPS
    value: "<set to true if you invoke an API method through Dapr from https origin>"

为授权码授权定义自定义管道

要使用 OAuth 中间件(授权码),你应该使用 Dapr 配置 创建一个自定义管道,如以下示例所示:

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

定义客户端凭据授权组件

OAuth(客户端凭据)中间件由组件定义:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: myComponent
spec:
  type: middleware.http.oauth2clientcredentials
  version: v1
  metadata:
  - name: clientId
    value: "<your client ID>"
  - name: clientSecret
    value: "<your client secret>"
  - name: scopes
    value: "<comma-separated scope names>"
  - name: tokenURL
    value: "<token issuing URL>"
  - name: headerName
    value: "<header name under which the secret token is saved>"
  - name: endpointParamsQuery
    value: "<list of additional key=value settings separated by ampersands or semicolons forwarded to the token issuing service>"
    # authStyle:
    # "0" 表示通过尝试两种方式并缓存
    # 成功的方式来自动检测提供商想要哪种认证
    # 方式。

    # "1" 在 POST 正文中作为 application/x-www-form-urlencoded 参数
    # 发送 "client_id" 和 "client_secret"。

    # "2" 使用 HTTP Basic Authorization 发送 client_id 和 client_password。
    # 这是 OAuth2 RFC 6749 第 2.3.1 节中描述的可选方式。
  - name: authStyle
    value: "<see comment>"

为客户端凭据授权定义自定义管道

要使用 OAuth 中间件(客户端凭据),你应该使用 Dapr 配置 创建一个自定义管道,如以下示例所示:

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

应用配置

要将上述配置(无论授权类型如何) 应用到你的 Dapr sidecar,请在你的 pod spec 中添加 dapr.io/config 注解:

apiVersion: apps/v1
kind: Deployment
...
spec:
  ...
  template:
    metadata:
      ...
      annotations:
        dapr.io/enabled: "true"
        ...
        dapr.io/config: "pipeline"
...

访问访问令牌

授权码授权

一旦一切就绪,每当客户端尝试通过 Dapr sidecar 调用 API 方法 (例如调用 v1.0/invoke/ endpoint), 如果未找到访问令牌,它将被重定向到授权的同意页面。 否则,访问令牌将写入 authHeaderName header 并可供应用程序代码使用。

客户端凭据授权

一旦一切就绪,每当客户端尝试通过 Dapr sidecar 调用 API 方法 (例如调用 v1.0/invoke/ endpoint), 如果未找到有效的现有令牌,它将检索一个新的访问令牌。 访问令牌将写入 headerName header 并可供应用程序代码使用。 通过这种方式,应用程序可以在调用请求该令牌的外部 API 时,在授权 header 中转发该令牌。

5.3 - 在 Dapr 中启用 API 令牌身份验证

要求每个传入的 Dapr API 请求都包含身份验证令牌,然后才允许该请求通过

默认情况下,Dapr 依赖网络边界来限制对其公共 API 的访问。如果您计划将 Dapr API 暴露到该边界之外,或者您的部署需要额外的安全级别,请考虑为 Dapr API 启用令牌身份验证。这将导致 Dapr 要求每个传入的 gRPC 和 HTTP API 请求都包含身份验证令牌,然后才允许该请求通过。

创建令牌

Dapr 使用共享令牌进行 API 身份验证。您可以自由定义要使用的 API 令牌。

虽然 Dapr 对共享令牌的格式没有任何限制,但一个好的做法是生成一个随机字节序列并将其编码为 Base64。例如,以下命令生成一个随机的 32 字节密钥并将其编码为 Base64:

openssl rand 16 | base64

在 Dapr 中配置 API 令牌身份验证

令牌身份验证的配置在 Kubernetes 或自托管 Dapr 部署中略有不同:

自托管

在自托管场景中,Dapr 会检查是否存在 DAPR_API_TOKEN 环境变量。如果在 daprd 进程启动时设置了该环境变量,Dapr 将对其公共 API 强制执行身份验证:

export DAPR_API_TOKEN=<token>

要轮换已配置的令牌,请将 DAPR_API_TOKEN 环境变量更新为新值并重启 daprd 进程。

Kubernetes

在 Kubernetes 部署中,Dapr 利用 Kubernetes 密钥存储来保存共享令牌。要配置 Dapr API 身份验证,首先创建一个新密钥:

kubectl create secret generic dapr-api-token --from-literal=token=<token>

注意,上述密钥需要在您希望启用 Dapr 令牌身份验证的每个命名空间中创建。

要指示 Dapr 使用该密钥来保护其公共 API,请在您的 Deployment 模板规范中添加注解:

annotations:
  dapr.io/enabled: "true"
  dapr.io/api-token-secret: "dapr-api-token" # Kubernetes 密钥的名称

部署后,Dapr 边车注入器将自动创建密钥引用并将实际值注入到 DAPR_API_TOKEN 环境变量中。

向客户端 API 调用添加 API 令牌

在 Dapr 中配置了令牌身份验证后,所有调用 Dapr API 的客户端都需要在每个请求中附加 dapr-api-token 令牌。

注意: Dapr SDK 会读取 DAPR_API_TOKEN 环境变量并默认为您设置,但是您仍必须确保您的应用程序有权访问该环境变量。

HTTP

对于 HTTP,Dapr 要求在 dapr-api-token 标头中提供 API 令牌。例如:

GET http://<daprAddress>/v1.0/metadata
dapr-api-token: <token>

使用 curl,您可以使用 --header(或 -H)选项传递标头。例如:

curl http://localhost:3500/v1.0/metadata \
  --header "dapr-api-token: my-token"

gRPC

使用 gRPC 协议时,Dapr 将在 gRPC 元数据中检查传入调用是否包含 API 令牌:

dapr-api-token[0].

从应用程序访问令牌

Kubernetes

在 Kubernetes 中,当您的应用程序向 Dapr API 发起出站调用(服务调用 invoke、发布订阅 publish 等)时,需要将 API 令牌作为环境变量挂载到应用程序 Pod 中,否则请求将失败并返回 Unauthorized 错误。挂载环境变量是通过在应用程序 Pod 规范中提供 Kubernetes 密钥的名称来完成的,如下例所示,其中使用名为 dapr-api-token 的 Kubernetes 密钥来保存令牌。

containers:
  - name: mycontainer
    image: myregistry/myapp
    env:
      - name: DAPR_API_TOKEN
        valueFrom:
          secretKeyRef:
            name: dapr-api-token
            key: token

自托管

在自托管模式下,您可以为应用程序将令牌设置为环境变量:

export DAPR_API_TOKEN=<my-dapr-token>

轮换令牌

自托管

要在自托管模式下轮换已配置的令牌,请将 DAPR_API_TOKEN 环境变量更新为新值并重启 daprd 进程。

Kubernetes

要在 Kubernetes 中轮换已配置的令牌,请使用新令牌更新先前在每个命名空间中创建的密钥。您可以使用 kubectl patch 命令执行此操作,但在每个命名空间中更新这些密钥的一种更简单方法是使用清单:

apiVersion: v1
kind: Secret
metadata:
  name: dapr-api-token
type: Opaque
data:
  token: <your-new-token>

然后将其应用到每个命名空间:

kubectl apply --file token-secret.yaml --namespace <namespace-name>

要告诉 Dapr 开始使用新令牌,请对每个部署触发滚动升级:

kubectl rollout restart deployment/<deployment-name> --namespace <namespace-name>

假设您的服务配置了多个副本,密钥轮换过程不会导致任何停机时间。

相关链接

5.4 - 使用令牌认证对来自 Dapr 的请求进行身份验证

要求来自 Dapr 的每个入站 API 请求都包含身份验证令牌

对于某些构建块,例如发布订阅、服务调用和输入绑定,Dapr 通过 HTTP 或 gRPC 与应用程序通信。 为了使应用程序能够对来自 Dapr 边车的传入请求进行身份验证,您可以配置 Dapr 在调用应用程序时发送 API 令牌,作为标头(在 HTTP 请求中)或元数据(在 gRPC 请求中)。

创建令牌

Dapr 使用共享令牌进行 API 身份验证。您可以自由定义要使用的 API 令牌。

虽然 Dapr 不对共享令牌施加任何格式限制,但一个良好的做法是生成一个随机字节序列并将其编码为 Base64。例如,以下命令生成一个随机的 32 字节密钥并将其编码为 Base64:

openssl rand 16 | base64

在 Dapr 中配置应用 API 令牌认证

令牌身份验证配置在 Kubernetes 或自托管 Dapr 部署中略有不同:

自托管

在自托管场景中,Dapr 会查找 APP_API_TOKEN 环境变量。如果在 daprd 进程启动时设置了该环境变量,Dapr 会在调用应用程序时包含令牌:

export APP_API_TOKEN=<token>

要轮换配置的令牌,请将 APP_API_TOKEN 环境变量更新为新值并重启 daprd 进程。

Kubernetes

在 Kubernetes 部署中,Dapr 利用 Kubernetes secrets 存储来保存共享令牌。首先,创建一个新的 secret:

kubectl create secret generic app-api-token --from-literal=token=<token>

注意,上述 secret 需要在您希望启用应用令牌身份验证的每个命名空间中创建

要指示 Dapr 在向应用程序发送请求时使用 secret 中的令牌,请在您的 Deployment 模板规范中添加一个 annotation:

annotations:
  dapr.io/enabled: "true"
  dapr.io/app-token-secret: "app-api-token" # Kubernetes secret 的名称

部署后,Dapr Sidecar Injector 会自动创建 secret 引用并将实际值注入 APP_API_TOKEN 环境变量。

轮换令牌

自托管

要在自托管环境中轮换配置的令牌,请将 APP_API_TOKEN 环境变量更新为新值并重启 daprd 进程。

Kubernetes

要在 Kubernetes 中轮换配置的令牌,请使用新令牌更新每个命名空间中先前创建的 secret。您可以使用 kubectl patch 命令执行此操作,但在每个命名空间中更新这些 secret 的更简单方法是使用清单:

apiVersion: v1
kind: Secret
metadata:
  name: app-api-token
type: Opaque
data:
  token: <your-new-token>

然后将其应用到每个命名空间:

kubectl apply --file token-secret.yaml --namespace <namespace-name>

要告知 Dapr 开始使用新令牌,请触发每个部署的滚动升级:

kubectl rollout restart deployment/<deployment-name> --namespace <namespace-name>

假设您的服务配置了多个副本,密钥轮换过程不会导致任何停机时间。

对来自 Dapr 的请求进行身份验证

一旦使用环境变量或 Kubernetes secret app-api-token 配置了应用令牌身份验证,Dapr 边车在调用应用程序时始终包含 HTTP 标头/gRPC 元数据 dapr-api-token: <token>。在应用程序端,确保您使用 dapr-api-token 值进行身份验证,该值使用您设置的 app-api-token 来对来自 Dapr 的请求进行身份验证。

HTTP

在您的代码中,在传入请求中查找 HTTP 标头 dapr-api-token

dapr-api-token: <token>

gRPC

使用 gRPC 协议时,检查传入调用中的 gRPC 元数据上的 API 令牌:

dapr-api-token[0].

从应用程序访问令牌

Kubernetes

在 Kubernetes 中,建议将 secret 作为环境变量挂载到您的 pod 中。 假设我们创建了一个名为 app-api-token 的 secret 来保存令牌:

containers:
  - name: mycontainer
    image: myregistry/myapp
    envFrom:
    - secretRef:
      name: app-api-token

自托管

在自托管模式下,您可以为应用程序将令牌设置为环境变量:

export APP_API_TOKEN=<my-app-token>

相关链接

6 - 使用弹性策略进行错误恢复

如何配置和自定义 Dapr 错误重试、超时和断路器

6.1 - 概览

配置 Dapr 重试、超时和熔断器

Dapr 提供了通过弹性规范定义和应用容错弹性策略的能力。弹性规范保存在与组件规范相同的位置,并在 Dapr 边车启动时应用。边车决定如何将弹性策略应用于您的 Dapr API 调用。

  • 在自托管模式下: 弹性规范必须命名为 resiliency.yaml
  • 在 Kubernetes 中: Dapr 会查找应用程序使用的命名弹性规范。

策略

您可以通过以下部分配置 Dapr 弹性策略:

  • 定义策略应用位置的元数据(如命名空间和作用域)
  • 指定弹性名称和行为的策略,例如:
  • 确定这些策略作用于哪些交互的目标,包括:

定义完成后,您可以使用以下命令将此配置应用到本地 Dapr 组件目录或 Kubernetes 集群:

kubectl apply -f <resiliency-spec-name>.yaml

此外,您还可以将弹性策略限定为特定应用

参见已知限制

弹性策略结构

以下是弹性策略的通用结构:

apiVersion: dapr.io/v1alpha1
kind: Resiliency
metadata:
  name: myresiliency
scopes:
  # 可选:将策略限定为特定应用
spec:
  policies:
    timeouts:
      # 超时策略定义

    retries:
      # 重试策略定义

    circuitBreakers:
      # 熔断器策略定义

  targets:
    apps:
      # 此处填写应用及其应用的策略

    actors:
      # 此处填写 actor 类型及其应用的策略

    components:
      # 此处填写组件及其应用的策略

完整示例策略

apiVersion: dapr.io/v1alpha1
kind: Resiliency
metadata:
  name: myresiliency
# 与订阅和配置规范类似,scopes 列出了可使用此弹性规范的 Dapr 应用 ID。
scopes:
  - app1
  - app2
spec:
  # policies 是定义超时、重试和熔断器策略的地方。
  # 每个策略都有一个名称,以便从弹性规范的 targets 部分引用它们。
  policies:
    # timeouts 是简单的命名持续时间。
    timeouts:
      general: 5s
      important: 60s
      largeResponse: 10s

    # retries 是重试配置的命名模板,在操作生命周期内实例化。
    retries:
      pubsubRetry:
        policy: constant
        duration: 5s
        maxRetries: 10

      retryForever:
        policy: exponential
        maxInterval: 15s
        maxRetries: -1 # 无限期重试

      important:
        policy: constant
        duration: 5s
        maxRetries: 30

      someOperation:
        policy: exponential
        maxInterval: 15s

      largeResponse:
        policy: constant
        duration: 5s
        maxRetries: 3

    # circuit breakers 会自动为每个组件和应用实例实例化。
    # 熔断器维护的计数器在 Dapr 边车运行期间一直存在。它们不会被持久化。
    circuitBreakers:
      simpleCB:
        maxRequests: 1
        timeout: 30s 
        trip: consecutiveFailures >= 5

      pubsubCB:
        maxRequests: 1
        interval: 8s
        timeout: 45s
        trip: consecutiveFailures > 8

  # targets 是命名策略应用到的对象。Dapr 支持 3 种目标类型 - 应用、组件和 actor
  targets:
    apps:
      appB:
        timeout: general
        retry: important
        # 服务的熔断器按应用实例限定作用域。
        # 当熔断器触发时,该路由会在配置的 `timeout` 期限内从负载均衡中移除。
        circuitBreaker: simpleCB

    actors:
      myActorType: # 自定义 Actor 类型名称
        timeout: general
        retry: important
        # actor 的熔断器按类型、id 或两者限定作用域。
        # 当熔断器触发时,该类型或 id 会在配置的 `timeout` 期限内从位置表中移除。
        circuitBreaker: simpleCB
        circuitBreakerScope: both ## 
        circuitBreakerCacheSize: 5000

    components:
      # 对于状态存储,策略应用于保存和检索状态。
      statestore1: # 任何组件名称 -- 这里恰好是一个状态存储
        outbound:
          timeout: general
          retry: retryForever
          # 组件的熔断器按每个组件配置/实例限定作用域。例如 myRediscomponent。
          # 当此熔断器触发时,在配置的 `timeout` 期限内将阻止与该组件的所有交互。
          circuitBreaker: simpleCB

      pubsub1: # 任何组件名称 -- 这里恰好是一个 pubsub broker
        outbound:
          retry: pubsubRetry
          circuitBreaker: pubsubCB

      pubsub2: # 任何组件名称 -- 这里恰好是另一个 pubsub broker
        outbound:
          retry: pubsubRetry
          circuitBreaker: pubsubCB
        inbound: # inbound 仅适用于从边车到应用的传递
          timeout: general
          retry: important
          circuitBreaker: pubsubCB

限制

  • 通过 gRPC 进行服务调用: 目前,通过 gRPC 进行的服务调用不支持弹性策略。

演示

观看此视频了解如何使用弹性

了解有关如何使用 Dapr 编写弹性微服务的更多信息。

后续步骤

了解有关弹性策略和目标的更多信息:

相关链接

尝试其中一个弹性快速入门:

6.2 - 弹性策略

为超时、重试和断路器配置弹性策略

policies 下定义超时、重试和断路器策略。每个策略都有一个名称,以便您可以从弹性规范中的 targets 部分引用它们。

6.2.1 - 超时弹性策略

配置超时的弹性策略

网络调用可能因多种原因失败,导致应用程序无限期等待响应。通过设置超时时长,您可以切断那些无响应的服务,释放资源以处理新请求。

超时是可选策略,可用于提前终止长时间运行的操作。设置一个现实的超时时长,反映生产环境中的实际响应时间。如果超出了超时时长:

  • 正在进行的操作将被终止(如果可能)。
  • 返回错误。

超时策略格式

spec:
  policies:
    # 超时是指定的时长。
    timeouts:
      timeoutName: timeout1
      general: 5s
      important: 60s
      largeResponse: 10s

规范元数据

| 字段 | 详情 | 示例 | | timeoutName | 超时策略的名称 | timeout1 | | general | 标记为"general"的超时时长。使用 Go 的 time.ParseDuration 格式。没有设置最大值。 | 15s2m1h30m | | important | 标记为"important"的超时时长。使用 Go 的 time.ParseDuration 格式。没有设置最大值。 | 15s2m1h30m | | largeResponse | 等待大型响应的超时时长。使用 Go 的 time.ParseDuration 格式。没有设置最大值。 | 15s2m1h30m |

如果未指定超时值,策略不会强制执行时间,默认为您根据请求客户端设置的值。

后续步骤

相关链接

试用其中一个弹性快速入门:

6.2.2 - 重试和退避弹性策略

配置重试和退避的弹性策略

6.2.2.1 - 重试弹性策略

为重试配置弹性策略

请求可能因瞬时错误而失败,例如遇到网络拥塞、重新路由到过载实例等。有时,请求也可能因已设置的其他弹性策略而失败,例如触发了定义的超时或熔断器策略。

在这些情况下,配置 retries 可以:

  • 将相同请求发送到不同的实例,或
  • 在条件清除后重试发送请求。

重试和超时协同工作,超时确保您的系统在需要时快速失败,而重试从临时故障中恢复。

Dapr 提供默认弹性策略,您可以使用用户定义的重试策略覆盖它们。

重试策略格式

示例 1

spec:
  policies:
    # Retries are named templates for retry configurations and are instantiated for life of the operation.
    retries:
      pubsubRetry:
        policy: constant
        duration: 5s
        maxRetries: 10

      retryForever:
        policy: exponential
        maxInterval: 15s
        maxRetries: -1 # Retry indefinitely

示例 2

spec:
  policies:
    retries:
      retry5xxOnly:
        policy: constant
        duration: 5s
        maxRetries: 3
        matching:
          httpStatusCodes: "429,500-599" # retry the HTTP status codes in this range. All others are not retried. 
          gRPCStatusCodes: "1-4,8-11,13,14" # retry gRPC status codes in these ranges and separate single codes.

规范元数据

以下重试选项是可配置的:

重试选项描述
policy确定退避和重试间隔策略。有效值为 constantexponential
默认为 constant
duration确定重试之间的时间间隔。仅适用于 constant 策略。
有效值为 200ms15s2m 等格式。
默认为 5s
maxInterval确定exponential 退避策略可以增长到的重试之间的最大间隔。
额外的重试总是在 maxInterval 的持续时间后发生。默认为 60s。有效值为 5s1m1m30s 等格式。
maxRetries要尝试的最大重试次数。
-1 表示无限次重试,而 0 表示不会重试请求(本质上表现为未设置重试策略)。
默认为 -1
matching.httpStatusCodes可选:逗号分隔的要重试的 HTTP 状态码或状态码范围字符串。未列出的状态码不会被重试。
有效值:100-599,参考
格式:<code> 或范围 <start>-<end>
示例:“429,501-503”
默认:空字符串 "" 或未设置字段。重试所有 HTTP 错误。
matching.gRPCStatusCodes可选:逗号分隔的要重试的 gRPC 状态码或状态码范围字符串。未列出的状态码不会被重试。
有效值:0-16,参考
格式:<code> 或范围 <start>-<end>
示例:“4,8,14”
默认:空字符串 "" 或未设置字段。重试所有 gRPC 错误。

指数退避策略

指数退避窗口使用以下公式:

BackOffDuration = PreviousBackOffDuration * (Random value from 0.5 to 1.5) * 1.5
if BackOffDuration > maxInterval {
  BackoffDuration = maxInterval
}

重试状态码

当应用程序跨越多个服务时,特别是在像 Kubernetes 这样的动态环境中,服务可能因各种原因而消失,网络调用可能会开始挂起。状态码提供了对我们操作的洞察以及它们在生产中可能失败的位置。

HTTP

下表包含您可能收到的一些 HTTP 状态码示例,以及您是否应该或不应该重试某些操作。

HTTP 状态码建议重试?描述
404 Not Found❌ 否资源不存在。
400 Bad Request❌ 否您的请求无效。
401 Unauthorized❌ 否尝试获取新凭据。
408 Request Timeout✅ 是服务器等待请求超时。
429 Too Many Requests✅ 是(如果存在,请遵守 Retry-After 头)。
500 Internal Server Error✅ 是服务器遇到意外情况。
502 Bad Gateway✅ 是网关或代理接收到无效响应。
503 Service Unavailable✅ 是服务可能会恢复。
504 Gateway Timeout✅ 是临时网络问题。

gRPC

下表包含您可能收到的一些 gRPC 状态码示例,以及您是否应该或不应该重试某些操作。

gRPC 状态码建议重试?描述
Code 1 CANCELLED❌ 否N/A
Code 3 INVALID_ARGUMENT❌ 否N/A
Code 4 DEADLINE_EXCEEDED✅ 是使用退避重试
Code 5 NOT_FOUND❌ 否N/A
Code 8 RESOURCE_EXHAUSTED✅ 是使用退避重试
Code 14 UNAVAILABLE✅ 是使用退避重试

基于状态码的重试过滤器

重试过滤器允许通过指定应应用重试的 HTTP 和 gRPC 状态码或范围,对重试策略进行细粒度控制。

spec:
  policies:
    retries:
      retry5xxOnly:
        # ...
        matching:
          httpStatusCodes: "429,500-599" # retry the HTTP status codes in this range. All others are not retried. 
          gRPCStatusCodes: "4,8-11,13,14" # retry gRPC status codes in these ranges and separate single codes.

演示

观看 Diagrid 的 Dapr v1.15 庆祝活动期间演示的演示,了解如何使用 Diagrid Conductor 设置重试状态码过滤器。

后续步骤

相关链接

尝试其中一个弹性快速入门:

6.2.2.2 - 覆盖默认重试弹性策略

了解如何为特定 API 覆盖默认重试弹性策略

Dapr 为任何不成功的请求(如故障和临时错误)提供默认重试。在弹性规范中,您可以通过使用保留的命名关键字定义策略来覆盖 Dapr 的默认重试逻辑。例如,定义一个名为 DaprBuiltInServiceRetries 的策略可以覆盖通过服务间请求在边车之间发生故障时的默认重试。策略覆盖不会应用于特定目标。

注意:虽然您可以使用更稳健的重试来覆盖默认值,但不能使用低于提供的默认值的值进行覆盖,也不能完全移除默认重试。这可以防止意外的停机。

下表描述了 Dapr 的默认重试以及用于覆盖它们的策略关键字:

功能覆盖关键字默认重试行为描述
服务调用DaprBuiltInServiceRetries每次调用重试的退避间隔为 1 秒,最多重试 3 次。边车对边车的请求(服务调用方法调用)失败并导致 gRPC 代码 UnavailableUnauthenticated
ActorsDaprBuiltInActorRetries每次调用重试的退避间隔为 1 秒,最多重试 3 次。边车对边车的请求(Actor 方法调用)失败并导致 gRPC 代码 UnavailableUnauthenticated
Actor 提醒DaprBuiltInActorReminderRetries每次调用重试采用指数退避,初始间隔为 500ms,最大间隔为 60s,持续时间为 15 分钟向状态存储持久化 Actor 提醒失败的请求
初始化重试DaprBuiltInInitializationRetries每次调用执行 3 次重试,采用指数退避,初始间隔为 500ms,持续时间为 10 秒向应用程序发出请求以检索给定规范时的故障。例如,检索订阅、组件或弹性规范失败

下面的弹性规范示例展示了如何使用保留的命名关键字 ‘DaprBuiltInServiceRetries’ 来覆盖_所有_服务调用请求的默认重试。

同时还定义了一个名为 ‘retryForever’ 的重试策略,该策略仅应用于 appB 目标。appB 使用 ‘retryForever’ 重试策略,而所有其他应用程序服务调用重试故障则使用被覆盖的 ‘DaprBuiltInServiceRetries’ 默认策略。

spec:
  policies:
    retries:
      DaprBuiltInServiceRetries: # 覆盖服务间调用的默认重试行为
        policy: constant
        duration: 5s
        maxRetries: 10

      retryForever: # 用户定义的重试策略会替换默认重试。目标仅依赖于应用的策略。 
        policy: exponential
        maxInterval: 15s
        maxRetries: -1 # 无限期重试

  targets:
    apps:
      appB: # 目标服务的 app-id
        retry: retryForever

相关链接

尝试其中一个弹性快速入门:

6.2.3 - 断路器弹性策略

为断路器配置弹性策略

当其他应用程序/服务/组件出现较高的故障率时,会使用断路器策略。断路器通过监控请求并在满足特定条件时切断到受影响服务的所有流量来减少负载。

在一定数量的请求失败后,断路器会"跳闸"或打开以防止级联故障。通过这样做,断路器为服务提供从故障中恢复的时间,而不是用事件淹没它。

断路器还可以进入"半开"状态,允许部分流量通过以查看系统是否已恢复。

一旦请求恢复成功,断路器将进入"关闭"状态,并允许流量完全恢复。

断路器策略格式

spec:
  policies:
    circuitBreakers:
      pubsubCB:
        maxRequests: 1
        interval: 8s
        timeout: 45s
        trip: consecutiveFailures > 8

规格元数据

重试选项描述
maxRequests断路器处于半开状态(从故障中恢复)时允许通过的最大请求数。默认为 1
interval断路器用于清除其内部计数的循环时间周期。如果设置为 0 秒,则永远不会清除。默认为 0s
timeout打开状态的持续时间(直接在故障之后),直到断路器切换到半开状态。默认为 60s
trip由断路器评估的 Common Expression Language (CEL) 表达式。当表达式评估为 true 时,断路器跳闸并变为打开状态。默认为 consecutiveFailures > 5。其他可能的值是 requeststotalFailures,其中 requests 表示电路打开之前成功或失败调用的数量,totalFailures 表示电路打开之前失败尝试的总数(不一定是连续的)。示例:requests > 5totalFailures >3

后续步骤

相关链接

尝试以下弹性快速入门之一:

6.2.4 - 默认弹性策略

了解有关超时、重试和熔断器的默认弹性策略的更多信息

在弹性中,您可以设置具有广泛范围的默认策略。这是通过保留关键字完成的,让 Dapr 知道何时应用该策略。有 3 种默认策略类型:

  • DefaultRetryPolicy
  • DefaultTimeoutPolicy
  • DefaultCircuitBreakerPolicy

如果定义了这些策略,它们将用于对服务、应用程序或组件的每个操作。它们还可以通过附加额外关键字来修改以更加具体。具体策略遵循以下模式,Default%sRetryPolicyDefault%sTimeoutPolicyDefault%sCircuitBreakerPolicy。其中 %s 被替换为策略的目标。

下表列出了所有可能的默认策略关键字以及它们如何转换为策略名称。

关键字目标操作示例策略名称
App服务调用。DefaultAppRetryPolicy
ActorActor 调用。DefaultActorTimeoutPolicy
Component所有组件操作。DefaultComponentCircuitBreakerPolicy
ComponentInbound所有入站组件操作。DefaultComponentInboundRetryPolicy
ComponentOutbound所有出站组件操作。DefaultComponentOutboundTimeoutPolicy
StatestoreComponentOutbound所有状态存储组件操作。DefaultStatestoreComponentOutboundCircuitBreakerPolicy
PubsubComponentOutbound所有出站发布订阅(发布)组件操作。DefaultPubsubComponentOutboundRetryPolicy
PubsubComponentInbound所有入站发布订阅(订阅)组件操作。DefaultPubsubComponentInboundTimeoutPolicy
BindingComponentOutbound所有出站绑定(调用)组件操作。DefaultBindingComponentOutboundCircuitBreakerPolicy
BindingComponentInbound所有入站绑定(读取)组件操作。DefaultBindingComponentInboundRetryPolicy
SecretstoreComponentOutbound所有密钥存储组件操作。DefaultSecretstoreComponentTimeoutPolicy
ConfigurationComponentOutbound所有配置组件操作。DefaultConfigurationComponentOutboundCircuitBreakerPolicy
LockComponentOutbound所有锁组件操作。DefaultLockComponentOutboundRetryPolicy

策略层次解析

如果正在执行的操作匹配策略类型,并且没有针对它的更具体的策略,则会应用默认策略。对于每个目标类型(app、actor 和 component),优先级最高的策略是命名策略,即专门针对该构造的策略。

如果不存在,则策略从最具体到最广泛应用。

默认策略与内置重试如何协同工作

内置重试的情况下,默认策略不会阻止内置重试策略运行。两者一起使用,但仅在特定情况下。

对于服务和 Actor 调用,内置重试专门处理连接到远程边车时的问题(在需要时)。由于这些对 Dapr 运行时的稳定性很重要,因此它们不会被禁用,除非为操作专门引用了命名策略。在某些情况下,可能会同时从内置重试和默认重试策略进行额外重试,但这可以防止过于薄弱的默认策略降低边车的可用性/成功率。

应用程序的策略解析层次,从最具体到最广泛:

  1. App 目标中的命名策略
  2. 默认 App 策略 / 内置服务重试
  3. 默认策略 / 内置服务重试

Actor 的策略解析层次,从最具体到最广泛:

  1. Actor 目标中的命名策略
  2. 默认 Actor 策略 / 内置 Actor 重试
  3. 默认策略 / 内置 Actor 重试

组件的策略解析层次,从最具体到最广泛:

  1. 组件目标中的命名策略
  2. 默认组件类型 + 组件方向策略 / 内置 Actor 提醒重试(如果适用)
  3. 默认组件方向策略 / 内置 Actor 提醒重试(如果适用)
  4. 默认组件策略 / 内置 Actor 提醒重试(如果适用)
  5. 默认策略 / 内置 Actor 提醒重试(如果适用)

作为一个示例,考虑以下解决方案,其中包含三个应用程序、三个组件和两个 Actor 类型:

应用程序:

  • AppA
  • AppB
  • AppC

组件:

  • Redis Pubsub:pubsub
  • Redis statestore:statestore
  • CosmosDB Statestore:actorstore

Actor:

  • EventActor
  • SummaryActor

以下是使用默认和命名策略并将其应用于目标的策略。

spec:
  policies:
    retries:
      # 全局重试策略
      DefaultRetryPolicy:
        policy: constant
        duration: 1s
        maxRetries: 3
      
      # 应用程序的全局重试策略
      DefaultAppRetryPolicy:
        policy: constant
        duration: 100ms
        maxRetries: 5

      # 应用程序的全局重试策略
      DefaultActorRetryPolicy:
        policy: exponential
        maxInterval: 15s
        maxRetries: 10

      # 入站组件操作的全局重试策略
      DefaultComponentInboundRetryPolicy:
        policy: constant
        duration: 5s
        maxRetries: 5

      # 状态存储的全局重试策略
      DefaultStatestoreComponentOutboundRetryPolicy:
        policy: exponential
        maxInterval: 60s
        maxRetries: -1

     # 命名策略
      fastRetries:
        policy: constant
        duration: 10ms
        maxRetries: 3

     # 命名策略
      retryForever:
        policy: exponential
        maxInterval: 10s
        maxRetries: -1

  targets:
    apps:
      appA:
        retry: fastRetries

      appB:
        retry: retryForever
    
    actors:
      EventActor:
        retry: retryForever

    components:
      actorstore:
        retry: fastRetries

下表详细分解了在尝试调用此解决方案中的各种目标时应用哪些策略。

目标使用的策略
AppAfastRetries
AppBretryForever
AppCDefaultAppRetryPolicy / DaprBuiltInActorRetries
pubsub - 发布DefaultRetryPolicy
pubsub - 订阅DefaultComponentInboundRetryPolicy
statestoreDefaultStatestoreComponentOutboundRetryPolicy
actorstorefastRetries
EventActorretryForever
SummaryActorDefaultActorRetryPolicy

后续步骤

了解如何覆盖默认重试策略。

相关链接

尝试其中一个弹性快速入门:

6.3 - 目标

将弹性策略应用于目标,包括应用、组件和 actor

目标

命名策略应用于目标。Dapr 支持三种目标类型,这些类型适用于所有 Dapr 构建块 API:

  • apps
  • components
  • actors

应用

使用 apps 目标,您可以将 retrytimeoutcircuitBreaker 策略应用于 Dapr 应用之间的服务调用。在 targets/apps 下,策略应用于每个目标服务的 app-id。当边车之间的通信发生故障时,会触发这些策略,如下图所示。

Dapr 提供了内置服务调用重试,因此任何应用的 retry 策略都是额外的。

Diagram showing service invocation resiliency

针对 app-id 为 “appB” 的目标应用应用策略的示例:

specs:
  targets:
    apps:
      appB: # 目标服务的 app-id
        timeout: general
        retry: general
        circuitBreaker: general

组件

使用 components 目标,您可以将 retrytimeoutcircuitBreaker 策略应用于组件操作。

策略可以应用于 outbound 操作(对 Dapr 边车的调用)和/或 inbound(边车调用您的应用)。

出站

outbound 操作是从边车到组件的调用,例如:

  • 持久化或检索状态。
  • 在发布订阅组件上发布消息。
  • 调用输出绑定。

某些组件可能具有内置的重试功能,并按组件配置。

Diagram showing service invocation resiliency
spec:
  targets:
    components:
      myStateStore:
        outbound:
          retry: retryForever
          circuitBreaker: simpleCB
入站

inbound 操作是从边车到您应用的调用,例如:

  • 发布订阅订阅在传递消息时。
  • 输入绑定。

某些组件可能具有内置的重试功能,并按组件配置。

Diagram showing service invocation resiliency
spec:
  targets:
    components:
      myInputBinding:
        inbound: 
          timeout: general
          retry: general
          circuitBreaker: general
发布订阅

在发布订阅 target/component 中,您可以同时指定 inboundoutbound 操作。

Diagram showing service invocation resiliency
spec:
  targets:
    components:
      myPubsub:
        outbound:
          retry: pubsubRetry
          circuitBreaker: pubsubCB
        inbound: # inbound 仅适用于从边车到应用的传递
          timeout: general
          retry: general
          circuitBreaker: general

Actor

使用 actors 目标,您可以将 retrytimeoutcircuitBreaker 策略应用于 actor 操作。

当为 actors 目标使用 circuitBreaker 策略时,您可以使用 circuitBreakerScope 指定熔断状态应如何确定范围:

  • id:单个 actor ID
  • type:给定 actor 类型的所有 actor
  • both:以上两者

您还可以使用 circuitBreakerCacheSize 属性为内存中保留的熔断器数量指定缓存大小,提供一个整数值,例如 5000

示例

spec:
  targets:
    actors:
      myActorType:
        timeout: general
        retry: general
        circuitBreaker: general
        circuitBreakerScope: both
        circuitBreakerCacheSize: 5000

后续步骤

尝试其中一个弹性快速入门:

6.4 - Health checks

如何为 Dapr 边车和应用程序设置健康检查

6.4.1 - App health checks

对应用的健康状态变化做出反应

应用健康检查功能允许探测应用程序的健康状况并对状态变化做出反应。

应用程序可能因各种原因无响应。例如,您的应用程序:

  • 可能过于忙碌而无法接受新工作;
  • 可能已崩溃;或
  • 可能处于死锁状态。

有时这种情况是暂时的,例如:

  • 如果应用只是忙碌,最终会恢复接受新工作
  • 如果应用程序因某种原因正在重启,正处于其初始化阶段

应用健康检查默认禁用。启用应用健康检查后,Dapr 运行时(sidecar)会通过 HTTP 或 gRPC 调用定期探测您的应用程序。当它检测到应用程序健康失败时,Dapr 会停止代表应用程序接受新工作,通过以下方式:

  • 取消订阅所有发布订阅订阅
  • 停止所有输入绑定
  • 短路所有服务调用请求,这些请求在 Dapr 运行时终止,不会转发到应用程序
  • 注销 Dapr Actor 类型,从而在有其他副本可用时导致 Actor 实例迁移到其他副本

这些更改是临时的,一旦 Dapr 检测到应用程序再次响应,就会恢复正常操作。

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

应用健康检查 vs 平台级健康检查

Dapr 中的应用健康检查旨在与平台级健康检查(例如在 Kubernetes 上运行时的 liveness probes)互补,而不是替代它们。

平台级健康检查(或 liveness probes)通常确保应用程序正在运行,并在失败时导致平台重启应用程序。

与平台级健康检查不同,Dapr 的应用健康检查专注于暂停向当前无法接受但预期最终能够恢复接受工作的应用程序传递工作。目标包括:

  • 不会给已经超载的应用程序带来更多负载。
  • 通过在 Dapr 知道应用程序无法处理消息时,不从队列、绑定或发布订阅代理获取消息,来做到"礼貌"的行为。

在这方面,Dapr 的应用健康检查更"温和",等待应用程序能够处理工作,而不是以"强硬"的方式终止正在运行的进程。

配置应用健康检查

应用健康检查默认禁用,但可以通过以下任一方式启用:

  • --enable-app-health-check CLI 标志;或
  • 在 Kubernetes 上运行时的 dapr.io/enable-app-health-check: true 注解。

添加此标志是使用默认选项启用应用健康检查的必要且充分条件。

完整的选项列表在下表中列出:

CLI 标志Kubernetes 部署注解描述默认值
--enable-app-health-checkdapr.io/enable-app-health-check启用健康检查的布尔值已禁用
--app-health-check-pathdapr.io/app-health-check-path当应用通道为 HTTP 时,Dapr 为健康探测调用的路径(如果应用通道使用 gRPC,则忽略此值)/healthz
--app-health-probe-intervaldapr.io/app-health-probe-interval每次健康探测之间的5
--app-health-probe-timeoutdapr.io/app-health-probe-timeout健康探测请求的超时时间(毫秒500
--app-health-thresholddapr.io/app-health-threshold在应用被认为不健康之前的连续失败最大次数3

有关所有选项及如何启用它们,请参阅 完整的 Dapr 参数和注解参考

此外,应用健康检查受应用通道使用的协议影响,该协议通过以下标志或注解配置:

CLI 标志Kubernetes 部署注解描述默认值
--app-protocoldapr.io/app-protocol应用通道使用的协议。支持的值为 httpgrpchttpsgrpcsh2c(HTTP/2 Cleartext)。http

健康检查路径

HTTP

当为 app-protocol 使用 HTTP(包括 httphttpsh2c)时,Dapr 通过向 app-health-check-path 中指定的路径(默认为 /health)进行 HTTP 调用来执行健康探测。

为了使您的应用被认为健康,响应必须具有 200-299 范围内的 HTTP 状态码。任何其他状态码都被视为失败。Dapr 只关心响应的状态码,并忽略任何响应头或响应体。

gRPC

当为应用通道使用 gRPC(app-protocol 设置为 grpcgrpcs)时,Dapr 会调用应用程序中的 /dapr.proto.runtime.v1.AppCallbackHealthCheck/HealthCheck 方法。最有可能的是,您将使用 Dapr SDK 来实现此方法的处理程序。

在响应健康探测请求时,您的应用程序可以决定执行额外的内部健康检查,以确定它是否准备好处理来自 Dapr 运行时的工作。但是,这不是必需的;这是一个取决于您的应用程序需求的选择。

间隔、超时和阈值

间隔

默认情况下,启用应用健康检查后,Dapr 每 5 秒探测一次您的应用程序。您可以使用 app-health-probe-interval 配置间隔(以秒为单位)。无论您的应用程序是否健康,这些探测都会定期进行。

超时

当 Dapr 运行时(sidecar)最初启动时,Dapr 会等待成功的健康探测后才认为应用健康。这意味着在第一次健康检查完成并成功之前,不会为您的应用程序启用发布订阅订阅、输入绑定和服务调用请求。

如果应用程序在 app-health-probe-timeout 中配置的超时时间内发送成功响应(如上所述),则健康探测请求被视为成功。默认值为 500,对应 500 毫秒(半秒)。

阈值

在 Dapr 认为应用进入不健康状态之前,它会等待 app-health-threshold 次连续失败,其默认值为 3。此默认值意味着您的应用程序必须连续 3 次健康探测失败才会被认为不健康。

如果将阈值设置为 1,任何失败都会导致 Dapr 假设您的应用不健康并停止向其传递工作。

大于 1 的阈值可以帮助排除由于外部情况导致的暂时性失败。适合您的应用程序的值取决于您的需求。

阈值仅适用于失败。单个成功响应足以让 Dapr 认为您的应用健康并恢复正常操作。

示例

使用 CLI 标志和 dapr run 命令来启用应用健康检查:

dapr run \
  --app-id my-app \
  --app-port 7001 \
  --app-protocol http \
  --enable-app-health-check \
  --app-health-check-path=/healthz \
  --app-health-probe-interval 3 \
  --app-health-probe-timeout 200 \
  --app-health-threshold 2 \
  -- \
    <command to execute>

要在 Kubernetes 中启用应用健康检查,请将相关注解添加到您的 Deployment 中:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  template:
    metadata:
      labels:
        app: my-app
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "my-app"
        dapr.io/app-port: "7001"
        dapr.io/app-protocol: "http"
        dapr.io/enable-app-health-check: "true"
        dapr.io/app-health-check-path: "/healthz"
        dapr.io/app-health-probe-interval: "3"
        dapr.io/app-health-probe-timeout: "200"
        dapr.io/app-health-threshold: "2"

演示

观看此视频以了解使用应用健康检查的概述

6.4.2 - 边车健康

Dapr 边车健康检查

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

  • 探测其整体健康状况
  • 从基础设施平台探测 Dapr 边车就绪状态
  • 在 Kubernetes 中确定就绪状态和存活状态

在本指南中,您将了解 Dapr /healthz 端点如何与应用程序托管平台(例如 Kubernetes)的健康探针以及 Dapr SDK 集成。

下图展示了 Dapr 边车启动时的步骤、healthz 端点以及应用程序通道何时初始化。

Diagram of Dapr checking oubound health connections.

出站健康端点

如上图红色边界线所示,v1.0/healthz/ 端点用于等待以下条件:

  • 所有组件已初始化;
  • Dapr HTTP 端口可用;以及
  • 应用程序通道已初始化。

这用于检查 Dapr 边车的完整初始化及其健康状况。

设置 DAPR_HEALTH_TIMEOUT 环境变量可以让您控制健康超时,例如,这在具有更高延迟的不同环境中可能很重要。

另一方面,如上图绿色边界线所示,当满足以下条件时,v1.0/healthz/outbound 端点会成功返回:

  • 所有组件已初始化;
  • Dapr HTTP 端口可用;
  • 应用程序通道尚未建立。

在 Dapr SDK 中,waitForSidecar 方法(取决于您使用的 SDK)用于使用 v1.0/healthz/outbound 端点进行此特定检查。使用此行为,Dapr 等待来自 v1.0/healthz/outbound 的成功响应,而不是等待应用程序通道可用(参见:红色边界线)与 v1.0/healthz/ 端点。这种方法使您的应用程序能够在应用程序通道初始化之前对 Dapr 边车 API 执行调用——例如,使用 secrets API 读取机密。

如果您在 SDK 上使用 waitForSidecar 方法,则会执行正确的初始化。否则,您可以在初始化期间调用 v1.0/healthz/outbound 端点,如果成功,您可以调用 Dapr 边车 API。

支持出站健康端点的 SDK

目前,v1.0/healthz/outbound 端点在以下 SDK 中受支持:

健康端点:与 Kubernetes 集成

将 Dapr 部署到 Kubernetes 等托管平台时,Dapr 健康端点会自动为您配置。

Kubernetes 使用就绪探针和存活探针来确定容器的健康状况。

存活探针

kubelet 使用存活探针来了解何时重启容器。例如,存活探针可以检测死锁(正在运行但无法继续推进的应用程序)。在这种情况下重启容器可以帮助使应用程序更加可用,尽管存在错误。

如何在 Kubernetes 中配置存活探针

在 Pod 配置文件中,存活探针添加在容器规范部分,如下所示:

    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 3
      periodSeconds: 3

在上面的示例中,periodSeconds 字段指定 kubelet 应每 3 秒执行一次存活探针。initialDelaySeconds 字段告诉 kubelet 在执行第一次探针之前应等待 3 秒。要执行探针,kubelet 向容器中运行并监听端口 8080 的服务器发送 HTTP GET 请求。如果服务器的 /healthz 路径的处理程序返回成功代码,则 kubelet 认为容器是存活和健康的。如果处理程序返回失败代码,则 kubelet 会终止容器并重新启动它。

200 到 399 之间的任何 HTTP 状态码表示成功;任何其他状态码表示失败。

就绪探针

kubelet 使用就绪探针来了解容器何时准备好开始接受流量。当 Pod 的所有容器都准备好时,该 Pod 被视为就绪。此就绪信号的一个用途是控制哪些 Pod 用作 Kubernetes 服务的后端。当 Pod 未就绪时,它会从 Kubernetes 服务负载均衡器中移除。

如何在 Kubernetes 中配置就绪探针

就绪探针的配置方式与存活探针类似。唯一的区别是您使用 readinessProbe 字段而不是 livenessProbe 字段:

    readinessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 3
      periodSeconds: 3

边车注入器

在与 Kubernetes 集成时,Dapr 边车会注入一个 Kubernetes 探针配置,告诉它使用 Dapr healthz 端点。这是由"边车注入器"系统服务完成的。与 kubelet 的集成如下图所示。

Diagram of Dapr services interacting

如何使用 Kubernetes 配置 Dapr 边车健康端点

如上所述,此配置由边车注入器服务自动完成。本节描述了在存活探针和就绪探针上设置的具体值。

Dapr 在端口 3500 上有其 HTTP 健康端点 /v1.0/healthz。这可以与 Kubernetes 一起用于就绪和存活探针。当注入 Dapr 边车时,就绪探针和存活探针在 Pod 配置文件中使用以下值进行配置:

    livenessProbe:
      httpGet:
        path: v1.0/healthz
        port: 3500
      initialDelaySeconds: 5
      periodSeconds: 10
      timeoutSeconds : 5
      failureThreshold : 3
    readinessProbe:
      httpGet:
        path: v1.0/healthz
        port: 3500
      initialDelaySeconds: 5
      periodSeconds: 10
      timeoutSeconds : 5
      failureThreshold: 3

延迟优雅关闭

Dapr 接受 dapr.io/block-shutdown-duration 注解或 --dapr-block-shutdown-duration CLI 标志,这会将完整的关闭过程延迟指定的持续时间,或直到应用程序报告不健康,以先发生者为准。

在此期间,所有订阅和输入绑定都会关闭。这对于需要在关闭过程中使用 Dapr API 的应用程序很有用。

适用的注解或 CLI 标志包括:

  • --dapr-graceful-shutdown-seconds/dapr.io/graceful-shutdown-seconds
  • --dapr-block-shutdown-duration/dapr.io/block-shutdown-duration
  • --dapr-graceful-shutdown-seconds/dapr.io/graceful-shutdown-seconds
  • --dapr-block-shutdown-duration/dapr.io/block-shutdown-duration

注解和参数指南中了解更多信息以及如何使用它们。

相关链接

7 - 支持和版本

Dapr 可用的支持和版本选项

7.1 - 版本控制策略

Dapr 的版本控制策略

简介

Dapr 通过版本控制方案,为运行时、API 和组件的未来变更而设计。本主题描述了 API、组件清单(如组件)和 Github 仓库的版本控制方案和策略。

版本控制

版本控制是为计算机软件的特定状态分配唯一版本名称或唯一版本号的过程。

  • 版本控制提供兼容性、显式的变更控制以及处理变更(特别是重大变更)的能力。
  • Dapr 努力保持向后兼容。如果需要重大变更,将提前公告
  • 弃用功能会跨越多个发布版本进行,新旧功能会并排工作。

版本控制适用于以下 Dapr 仓库:dapr、CLI、稳定语言 SDK、dashboard、components-contrib、quickstarts、helm-charts 和 documentation。

Dapr 具有以下版本控制方案:

  • Dapr HTTP API 使用 MAJOR.MINOR 进行版本控制
  • Dapr GRPC API 使用 MAJOR 进行版本控制
  • 发布版本(包括 dapr、CLI、SDK 和 Helm Chart 的 GitHub 仓库)使用 MAJOR.MINOR.PATCH
  • 文档和 Quickstarts 仓库使用 Dapr 运行时仓库的版本控制
  • Dapr Components 在 components-contrib GitHub 仓库中使用 MAJOR
  • Dapr Manifests 使用 MAJOR.MINOR。这些包括订阅和配置。

请注意,Dapr API、二进制发布版本(运行时、CLI、SDK)和组件都是相互独立的。

Dapr HTTP API

Dapr HTTP API 根据这些 REST API 指南 进行版本控制。

基于这些指南:

  • 当预期旧版本将被弃用时,API 的 MAJOR 版本会递增。任何此类弃用都将被沟通,并提供升级路径。
  • 对于任何其他更改,MINOR 版本可能会递增。例如,对发送到 API 的消息的 JSON 模式进行更改。
  • API 重大变更的定义可以查看这里
  • 实验性 API 包含"alpha"后缀以表示其 alpha 状态。例如 v1.0alpha、v2.0alpha 等。

Dapr 运行时

Dapr 发布版本使用 MAJOR.MINOR.PATCH 版本控制。例如 1.0.0。阅读支持的发布版本以了解有关发布版本控制的更多信息。

Helm Charts

helm-charts 仓库中的 Helm charts 使用 Dapr 运行时版本控制。Helm charts 用于 Kubernetes 部署

语言 SDK、CLI 和 dashboard

Dapr 语言 SDK、CLI 和 dashboard 与 Dapr 运行时独立版本控制,可以按不同的时间表发布。查看此表格以显示 SDK、CLI、dashboard 和运行时版本之间的兼容性。运行时的每个新版本都会列出相应的受支持 SDK、CLI 和 Dashboard。

SDK、CLI 和 Dashboard 的版本控制遵循 MAJOR.MINOR.PATCH 格式。当 SDK 中存在不向后兼容的更改时(例如,更改客户端方法上的参数),主版本会递增。次版本会为新功能和错误修复进行更新,而在错误或安全热修复的情况下会递增补丁版本。

SDK 中的示例和示例代码与该仓库一起进行版本控制。

组件

组件在 components-contrib 仓库中实现,遵循 MAJOR 版本控制方案。组件的版本遵守主版本(vX),补丁和非重大变更会添加到最新的主版本中。当组件接口中存在不向后兼容的更改时,版本会递增,例如,更改状态存储接口中的现有方法。

components-contrib 仓库发布版本是其内部所有组件的统一版本。也就是说,components-contrib 仓库发布版本由其中所有组件的 schema 组成。如果没有组件更改,Dapr 的新版本并不意味着 components-contrib 有新发布版本。

注意:组件具有生产使用生命周期状态:Alpha、Beta 和 Stable。这些状态与其版本控制无关。受支持组件的表格显示了它们的版本和状态。

有关组件版本控制的更多信息,请阅读组件的版本 2 及更高版本

组件 schema

组件 YAML 的版本控制有两种形式:

  • 组件清单的版本控制。apiVersion
  • 组件实现的版本。.spec.version

组件清单包含 .spec.metadata 字段中实现的 schema,.type 字段表示实现

请参阅下面示例中的注释:

apiVersion: dapr.io/v1alpha1 # <-- 这是组件清单的版本
kind: Component
metadata:
  name: pubsub
spec:
  version: v1 # <-- 这是 pubsub.redis schema 实现的版本
  type: pubsub.redis
  metadata:
  - name: redisHost
    value: redis-master:6379
  - name: redisPassword
    value: general-kenobi

组件清单版本

组件 YAML 清单使用 dapr.io/v1alpha1 进行版本控制。

组件实现版本

组件实现的版本由 .spec.version 字段确定,如上面的示例所示。.spec.version 字段在 schema 实例中是必需的,如果不存在,组件将无法加载。对于 Dapr 1.0.0 的发布版本,所有组件都标记为 v1。组件实现版本仅在不向后兼容的更改时递增。

组件弃用

组件弃用将提前两个(2)发布版本宣布。组件弃用会导致组件版本的主版本更新。2 个发布版本后,组件将从 Dapr 运行时中注销,尝试加载它将抛出致命异常。

组件弃用和移除将在发布说明中宣布。

Quickstarts 和示例

Quickstarts 仓库中的 Quickstarts 使用运行时版本控制,相应版本的表格位于示例仓库的首页。用户应仅使用与正在运行的运行时版本对应的 Quickstarts。

Samples 仓库中的示例根据示例维护者的情况逐个进行版本控制。与运行时发布版本相差甚远(落后多个版本)或超过 1 年未维护的示例将被删除。

相关链接

7.2 - 支持的运行时和 SDK 版本

运行时和 SDK 版本支持以及升级策略

简介

本主题详细介绍了 Dapr 版本的支持版本、升级策略,以及如何在所有 Dapr 仓库(运行时、CLI、SDK 等)的 1.x 及以上版本中传达弃用和重大更改。

Dapr 版本使用 MAJOR.MINOR.PATCH 版本控制。例如,1.0.0。

版本控制描述
MAJOR当运行时发生不向后兼容的更改(例如 API 更改)时更新。当发生被认为重要的功能添加/更改需要与先前版本区分时,也可能发生 MAJOR 版本发布。
MINOR作为定期发布节奏的一部分更新,包括新功能、错误和安全修复。
PATCH针对关键问题(P0)和安全热修复进行递增。

支持的版本意味着:

  • 如果版本存在关键问题(如主线中断场景或安全问题),则会发布热修复补丁。每个问题都会根据具体情况进行审查。
  • 会对支持的版本调查问题。如果版本不再受支持,您需要升级到较新的版本并确定问题是否仍然相关。

从 1.8.0 版本开始,支持三个(3)版本的 Dapr;当前版本和前两个(2)版本。通常是 MINOR 版本更新。这意味着支持的版本有一个向前移动的滚动窗口,保持与这些受支持版本的最新状态是您的运营责任。如果您使用的是较旧版本的 Dapr,您可能需要进行中间升级才能到达受支持的版本。

主要.次要版本发布之间至少有 13 周(3 个月)的时间,为用户从非支持版本升级提供至少 9 个月的滚动窗口。有关发布流程的更多详细信息,请阅读发布周期和节奏

补丁支持适用于支持的版本(当前和先前版本)。

构建变体

Dapr 的边车镜像发布到 GitHub Container RegistryDocker Registry。默认镜像包含所有组件。从 1.11 版本开始,Dapr 还提供了一种边车镜像变体,仅包含稳定组件。

  • 默认边车镜像:daprio/daprd:<version>ghcr.io/dapr/daprd:<version>(例如 ghcr.io/dapr/daprd:1.11.1
  • 稳定组件边车镜像:daprio/daprd:<version>-stablecomponentsghcr.io/dapr/daprd:<version>-stablecomponents(例如 ghcr.io/dapr/daprd:1.11.1-stablecomponents

在 Kubernetes 上,可以使用 dapr.io/sidecar-image 注解覆盖应用程序 Deployment 资源的边车镜像。有关 Dapr 的参数和注解 的更多信息。如果未指定,则使用默认的 ‘daprio/daprd:latest’ 镜像。

了解有关 Dapr 组件认证生命周期 的更多信息。

支持的版本

下表显示已经过一起测试并构成"打包"版本的 Dapr 版本。不支持任何其他版本组合。

发布日期运行时CLISDK仪表盘状态发布说明
2026 年 3 月 19 日1.17.2
1.17.0Java 1.17.0
Go 1.14.2
PHP 1.2.0
Python 1.17.0
.NET 1.17.5
JS 3.6.0
Rust 0.17.0
0.15.0支持(当前)v1.17.2 发布说明
2026 年 3 月 9 日1.17.1
1.17.0Java 1.17.0
Go 1.14.1
PHP 1.2.0
Python 1.17.0
.NET 1.17.3
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.17.1 发布说明
2026 年 2 月 26 日1.17.0
1.17.0Java 1.17.0
Go 1.14.0
PHP 1.2.0
Python 1.17.0
.NET 1.17.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.17.0 发布说明
2026 年 2 月 12 日1.16.9
1.16.5Java 1.16.0
Go 1.13.0
PHP 1.2.0
Python 1.16.0
.NET 1.16.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.16.9 发布说明
2026 年 1 月 26 日1.16.8
1.16.5Java 1.16.0
Go 1.13.0
PHP 1.2.0
Python 1.16.0
.NET 1.16.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.16.8 发布说明
2026 年 1 月 20 日1.16.7
1.16.5Java 1.16.0
Go 1.13.0
PHP 1.2.0
Python 1.16.0
.NET 1.16.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.16.7 发布说明
2026 年 1 月 20 日1.16.7
1.16.5Java 1.16.0
Go 1.13.0
PHP 1.2.0
Python 1.16.0
.NET 1.16.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.16.7 发布说明
2026 年 1 月 9 日1.16.6
1.16.5Java 1.16.0
Go 1.13.0
PHP 1.2.0
Python 1.16.0
.NET 1.16.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.16.6 发布说明
2025 年 12 月 19 日1.16.5
1.16.5Java 1.16.0
Go 1.13.0
PHP 1.2.0
Python 1.16.0
.NET 1.16.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.16.5 发布说明
2025 年 12 月 8 日1.16.4
1.16.5Java 1.16.0
Go 1.13.0
PHP 1.2.0
Python 1.16.0
.NET 1.16.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.16.4 发布说明
2025 年 11 月 21 日1.16.3
1.16.4Java 1.16.0
Go 1.13.0
PHP 1.2.0
Python 1.16.0
.NET 1.16.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.16.3 发布说明
2025 年 10 月 30 日1.16.2
1.16.3Java 1.16.0
Go 1.13.0
PHP 1.2.0
Python 1.16.0
.NET 1.16.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.16.2 发布说明
2025 年 10 月 6 日1.16.1
1.16.1Java 1.16.0
Go 1.13.0
PHP 1.2.0
Python 1.16.0
.NET 1.16.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.16.1 发布说明
2025 年 9 月 16 日1.16.0
1.16.0Java 1.16.0
Go 1.13.0
PHP 1.2.0
Python 1.16.0
.NET 1.16.0
JS 3.6.0
Rust 0.17.0
0.15.0支持v1.16.0 发布说明
2025 年 9 月 17 日1.15.12
1.15.0Java 1.14.2, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.4
JS 3.5.2
Rust 0.16.1
0.15.0支持v1.15.12 发布说明
2025 年 8 月 28 日1.15.11
1.15.0Java 1.14.2, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.4
JS 3.5.2
Rust 0.16.1
0.15.0支持v1.15.11 发布说明
2025 年 8 月 21 日1.15.10
1.15.0Java 1.14.2, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.4
JS 3.5.2
Rust 0.16.1
0.15.0支持v1.15.10 发布说明
2025 年 7 月 31 日1.15.9
1.15.0Java 1.14.2, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.4
JS 3.5.2
Rust 0.16.1
0.15.0支持v1.15.9 发布说明
2025 年 7 月 18 日1.15.8
1.15.0Java 1.14.2, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.4
JS 3.5.2
Rust 0.16.1
0.15.0支持v1.15.8 发布说明
2025 年 7 月 16 日1.15.7
1.15.0Java 1.14.1, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.4
JS 3.5.2
Rust 0.16.1
0.15.0支持v1.15.7 发布说明
2025 年 6 月 20 日1.15.6
1.15.0Java 1.14.1, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.4
JS 3.5.2
Rust 0.16.1
0.15.0支持v1.15.6 发布说明
2025 年 5 月 5 日1.15.5
1.15.0Java 1.14.1, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.4
JS 3.5.2
Rust 0.16.1
0.15.0支持v1.15.5 发布说明
2025 年 4 月 4 日1.15.4
1.15.0Java 1.14.0, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.4
JS 3.5.2
Rust 0.16.1
0.15.0支持v1.15.4 发布说明
2025 年 3 月 5 日1.15.3
1.15.0Java 1.14.0, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.4
JS 3.5.2
Rust 0.16.1
0.15.0支持v1.15.3 发布说明
2025 年 3 月 3 日1.15.2
1.15.0Java 1.14.0, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.0
JS 3.5.0
Rust 0.16
0.15.0支持v1.15.2 发布说明
2025 年 2 月 28 日1.15.1
1.15.0Java 1.14.0, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.0
JS 3.5.0
Rust 0.16
0.15.0支持v1.15.1 发布说明
2025 年 2 月 27 日1.15.0
1.15.0Java 1.14.0, 1.15.0
Go 1.12.0
PHP 1.2.0
Python 1.15.0
.NET 1.15.0
JS 3.5.0
Rust 0.16
0.15.0支持v1.15.0 发布说明
2024 年 9 月 16 日1.14.4
1.14.1Java 1.12.0
Go 1.11.0
PHP 1.2.0
Python 1.14.0
.NET 1.14.0
JS 3.3.1
0.15.0不支持v1.14.4 发布说明
2024 年 9 月 13 日1.14.3
1.14.1Java 1.12.0
Go 1.11.0
PHP 1.2.0
Python 1.14.0
.NET 1.14.0
JS 3.3.1
0.15.0⚠️ 已召回v1.14.3 发布说明
2024 年 9 月 6 日1.14.2
1.14.1Java 1.12.0
Go 1.11.0
PHP 1.2.0
Python 1.14.0
.NET 1.14.0
JS 3.3.1
0.15.0不支持v1.14.2 发布说明
2024 年 8 月 14 日1.14.1
1.14.1Java 1.12.0
Go 1.11.0
PHP 1.2.0
Python 1.14.0
.NET 1.14.0
JS 3.3.1
0.15.0不支持v1.14.1 发布说明
2024 年 8 月 14 日1.14.0
1.14.0Java 1.12.0
Go 1.11.0
PHP 1.2.0
Python 1.14.0
.NET 1.14.0
JS 3.3.1
0.15.0不支持v1.14.0 发布说明
2024 年 5 月 29 日1.13.4
1.13.0Java 1.11.0
Go 1.10.0
PHP 1.2.0
Python 1.13.0
.NET 1.13.0
JS 3.3.0
0.14.0不支持v1.13.4 发布说明
2024 年 5 月 21 日1.13.3
1.13.0Java 1.11.0
Go 1.10.0
PHP 1.2.0
Python 1.13.0
.NET 1.13.0
JS 3.3.0
0.14.0不支持v1.13.3 发布说明
2024 年 4 月 3 日1.13.2
1.13.0Java 1.11.0
Go 1.10.0
PHP 1.2.0
Python 1.13.0
.NET 1.13.0
JS 3.3.0
0.14.0不支持v1.13.2 发布说明
2024 年 3 月 26 日1.13.1
1.13.0Java 1.11.0
Go 1.10.0
PHP 1.2.0
Python 1.13.0
.NET 1.13.0
JS 3.3.0
0.14.0不支持v1.13.1 发布说明
2024 年 3 月 6 日1.13.0
1.13.0Java 1.11.0
Go 1.10.0
PHP 1.2.0
Python 1.13.0
.NET 1.13.0
JS 3.3.0
0.14.0不支持v1.13.0 发布说明
2024 年 1 月 17 日1.12.4
1.12.0Java 1.10.0
Go 1.9.1
PHP 1.2.0
Python 1.12.0
.NET 1.12.0
JS 3.2.0
0.14.0不支持v1.12.4 发布说明
2024 年 1 月 2 日1.12.3
1.12.0Java 1.10.0
Go 1.9.1
PHP 1.2.0
Python 1.12.0
.NET 1.12.0
JS 3.2.0
0.14.0不支持v1.12.3 发布说明
2023 年 11 月 18 日1.12.2
1.12.0Java 1.10.0
Go 1.9.1
PHP 1.2.0
Python 1.12.0
.NET 1.12.0
JS 3.2.0
0.14.0不支持v1.12.2 发布说明
2023 年 11 月 16 日1.12.1
1.12.0Java 1.10.0
Go 1.9.1
PHP 1.2.0
Python 1.12.0
.NET 1.12.0
JS 3.2.0
0.14.0不支持v1.12.1 发布说明
2023 年 10 月 11 日1.12.0
1.12.0Java 1.10.0
Go 1.9.0
PHP 1.1.0
Python 1.11.0
.NET 1.12.0
JS 3.1.2
0.14.0不支持v1.12.0 发布说明
2023 年 11 月 18 日1.11.6
1.11.0Java 1.9.0
Go 1.8.0
PHP 1.1.0
Python 1.10.0
.NET 1.11.0
JS 3.1.0
0.13.0不支持v1.11.6 发布说明
2023 年 11 月 3 日1.11.5
1.11.0Java 1.9.0
Go 1.8.0
PHP 1.1.0
Python 1.10.0
.NET 1.11.0
JS 3.1.0
0.13.0不支持v1.11.5 发布说明
2023 年 10 月 5 日1.11.4
1.11.0Java 1.9.0
Go 1.8.0
PHP 1.1.0
Python 1.10.0
.NET 1.11.0
JS 3.1.0
0.13.0不支持v1.11.4 发布说明
2023 年 8 月 31 日1.11.3
1.11.0Java 1.9.0
Go 1.8.0
PHP 1.1.0
Python 1.10.0
.NET 1.11.0
JS 3.1.0
0.13.0不支持v1.11.3 发布说明
2023 年 7 月 20 日1.11.2
1.11.0Java 1.9.0
Go 1.8.0
PHP 1.1.0
Python 1.10.0
.NET 1.11.0
JS 3.1.0
0.13.0不支持v1.11.2 发布说明
2023 年 6 月 22 日1.11.1
1.11.0Java 1.9.0
Go 1.8.0
PHP 1.1.0
Python 1.10.0
.NET 1.11.0
JS 3.1.0
0.13.0不支持v1.11.1 发布说明
2023 年 6 月 12 日1.11.0
1.11.0Java 1.9.0
Go 1.8.0
PHP 1.1.0
Python 1.10.0
.NET 1.11.0
JS 3.1.0
0.13.0不支持v1.11.0 发布说明
2023 年 11 月 18 日1.10.10
1.10.0Java 1.8.0
Go 1.7.0
PHP 1.1.0
Python 1.9.0
.NET 1.10.0
JS 3.0.0
0.11.0不支持
2023 年 7 月 20 日1.10.9
1.10.0Java 1.8.0
Go 1.7.0
PHP 1.1.0
Python 1.9.0
.NET 1.10.0
JS 3.0.0
0.11.0不支持
2023 年 6 月 22 日1.10.8
1.10.0Java 1.8.0
Go 1.7.0
PHP 1.1.0
Python 1.9.0
.NET 1.10.0
JS 3.0.0
0.11.0不支持
2023 年 5 月 15 日1.10.7
1.10.0Java 1.8.0
Go 1.7.0
PHP 1.1.0
Python 1.9.0
.NET 1.10.0
JS 3.0.0
0.11.0不支持
2023 年 5 月 12 日1.10.6
1.10.0Java 1.8.0
Go 1.7.0
PHP 1.1.0
Python 1.9.0
.NET 1.10.0
JS 3.0.0
0.11.0不支持
2023 年 4 月 13 日1.10.5
1.10.0Java 1.8.0
Go 1.6.0
PHP 1.1.0
Python 1.9.0
.NET 1.10.0
JS 3.0.0
0.11.0不支持
2023 年 3 月 16 日1.10.4
1.10.0Java 1.8.0
Go 1.6.0
PHP 1.1.0
Python 1.9.0
.NET 1.10.0
JS 2.5.0
0.11.0不支持
2023 年 3 月 14 日1.10.3
1.10.0Java 1.8.0
Go 1.6.0
PHP 1.1.0
Python 1.9.0
.NET 1.10.0
JS 2.5.0
0.11.0不支持
2023 年 2 月 24 日1.10.2
1.10.0Java 1.8.0
Go 1.6.0
PHP 1.1.0
Python 1.9.0
.NET 1.10.0
JS 2.5.0
0.11.0不支持
2023 年 2 月 20 日1.10.1
1.10.0Java 1.8.0
Go 1.6.0
PHP 1.1.0
Python 1.9.0
.NET 1.10.0
JS 2.5.0
0.11.0不支持
2023 年 2 月 14 日1.10.0
1.10.0Java 1.8.0
Go 1.6.0
PHP 1.1.0
Python 1.9.0
.NET 1.10.0
JS 2.5.0
0.11.0不支持
2022 年 12 月 2 日1.9.5
1.9.1Java 1.7.0
Go 1.6.0
PHP 1.1.0
Python 1.8.3
.NET 1.9.0
JS 2.4.2
0.11.0不支持
2022 年 11 月 17 日1.9.4
1.9.1Java 1.7.0
Go 1.6.0
PHP 1.1.0
Python 1.8.3
.NET 1.9.0
JS 2.4.2
0.11.0不支持
2022 年 11 月 4 日1.9.3
1.9.1Java 1.7.0
Go 1.6.0
PHP 1.1.0
Python 1.8.3
.NET 1.9.0
JS 2.4.2
0.11.0不支持
2022 年 11 月 1 日1.9.2
1.9.1Java 1.7.0
Go 1.6.0
PHP 1.1.0
Python 1.8.1
.NET 1.9.0
JS 2.4.2
0.11.0不支持
2022 年 10 月 26 日1.9.1
1.9.1Java 1.7.0
Go 1.6.0
PHP 1.1.0
Python 1.8.1
.NET 1.9.0
JS 2.4.2
0.11.0不支持
2022 年 10 月 13 日1.9.0
1.9.1Java 1.7.0
Go 1.6.0
PHP 1.1.0
Python 1.8.3
.NET 1.9.0
JS 2.4.2
0.11.0不支持
2022 年 10 月 26 日1.8.6
1.8.1Java 1.6.0
Go 1.5.0
PHP 1.1.0
Python 1.7.0
.NET 1.8.0
JS 2.3.0
0.11.0不支持
2022 年 10 月 13 日1.8.5
1.8.1Java 1.6.0
Go 1.5.0
PHP 1.1.0
Python 1.7.0
.NET 1.8.0
JS 2.3.0
0.11.0不支持
2022 年 8 月 10 日1.8.4
1.8.1Java 1.6.0
Go 1.5.0
PHP 1.1.0
Python 1.7.0
.NET 1.8.0
JS 2.3.0
0.11.0不支持
2022 年 7 月 29 日1.8.3
1.8.0Java 1.6.0
Go 1.5.0
PHP 1.1.0
Python 1.7.0
.NET 1.8.0
JS 2.3.0
0.11.0不支持
2022 年 7 月 21 日1.8.2
1.8.0Java 1.6.0
Go 1.5.0
PHP 1.1.0
Python 1.7.0
.NET 1.8.0
JS 2.3.0
0.11.0不支持
2022 年 7 月 20 日1.8.1
1.8.0Java 1.6.0
Go 1.5.0
PHP 1.1.0
Python 1.7.0
.NET 1.8.0
JS 2.3.0
0.11.0不支持
2022 年 7 月 7 日1.8.0
1.8.0Java 1.6.0
Go 1.5.0
PHP 1.1.0
Python 1.7.0
.NET 1.8.0
JS 2.3.0
0.11.0不支持
2022 年 10 月 26 日1.7.5
1.7.0Java 1.5.0
Go 1.4.0
PHP 1.1.0
Python 1.6.0
.NET 1.7.0
JS 2.2.1
0.10.0不支持
2022 年 5 月 31 日1.7.4
1.7.0Java 1.5.0
Go 1.4.0
PHP 1.1.0
Python 1.6.0
.NET 1.7.0
JS 2.2.1
0.10.0不支持
2022 年 5 月 17 日1.7.3
1.7.0Java 1.5.0
Go 1.4.0
PHP 1.1.0
Python 1.6.0
.NET 1.7.0
JS 2.2.1
0.10.0不支持
2022 年 4 月 22 日1.7.2
1.7.0Java 1.5.0
Go 1.4.0
PHP 1.1.0
Python 1.6.0
.NET 1.7.0
JS 2.1.0
0.10.0不支持
2022 年 4 月 20 日1.7.1
1.7.0Java 1.5.0
Go 1.4.0
PHP 1.1.0
Python 1.6.0
.NET 1.7.0
JS 2.1.0
0.10.0不支持
2022 年 4 月 7 日1.7.0
1.7.0Java 1.5.0
Go 1.4.0
PHP 1.1.0
Python 1.6.0
.NET 1.7.0
JS 2.1.0
0.10.0不支持
2022 年 4 月 20 日1.6.2
1.6.0Java 1.4.0
Go 1.3.1
PHP 1.1.0
Python 1.5.0
.NET 1.6.0
JS 2.0.0
0.9.0不支持
2022 年 3 月 25 日1.6.1
1.6.0Java 1.4.0
Go 1.3.1
PHP 1.1.0
Python 1.5.0
.NET 1.6.0
JS 2.0.0
0.9.0不支持
2022 年 1 月 25 日1.6.0
1.6.0Java 1.4.0
Go 1.3.1
PHP 1.1.0
Python 1.5.0
.NET 1.6.0
JS 2.0.0
0.9.0不支持

SDK 兼容性

除安全问题所需的更改外,SDK 和运行时承诺不做重大更改。所有重大更改(如有)都会在发布说明中宣布。

SDK 和运行时向前兼容性
较新的 Dapr SDK 支持 Dapr 运行时的最新版本和前两个版本(N-2)。

SDK 和运行时向后兼容性
对于新的 Dapr 运行时,支持当前的 SDK 版本和前两个版本(N-2)。

升级路径

运行时 1.0 版本发布后,可能需要通过其他版本显式升级才能达到所需的目标版本。例如,从 v1.0 升级到 v1.2 可能需要通过 v1.1。

下表显示了 Dapr 运行时的已测试升级路径。任何其他升级组合均未经过测试。

有关升级的一般指南,请参阅自托管模式Kubernetes部署。最好查看目标版本的发布说明以获取具体指南。

当前运行时版本必须通过以下版本升级目标运行时版本
1.5.0 到 1.5.2N/A1.6.0
1.6.01.6.2
1.6.21.7.5
1.7.51.8.6
1.8.61.9.6
1.9.61.10.7
1.6.0 到 1.6.2N/A1.7.5
1.7.51.8.6
1.8.61.9.6
1.9.61.10.7
1.7.0 到 1.7.5N/A1.8.6
1.8.61.9.6
1.9.61.10.7
1.8.0 到 1.8.6N/A1.9.6
1.9.0 到 1.9.6N/A1.10.8
1.10.0 到 1.10.8N/A1.11.4
1.11.0 到 1.11.4N/A1.12.4
1.12.0 到 1.12.4N/A1.13.5
1.13.0 到 1.13.5N/A1.14.0
1.14.0 到 1.14.4N/A1.14.4
1.15.0 到 1.15.12N/A1.16.9
1.16.0 到 1.16.9N/A1.17.2

在托管平台上升级

Dapr 可以支持生产环境的多个托管平台。在 1.0 版本中,两个受支持的平台是 Kubernetes 和物理机。有关 Kubernetes 升级,请参阅 Kubernetes 上的生产指南

依赖项的受支持版本

以下是最新版本的 Dapr(v1.18.0)已测试的软件列表。

依赖项支持的版本
KubernetesDapr 对 Kubernetes 的支持与 Kubernetes 版本偏差策略 一致
Open Telemetry collector (OTEL)v0.101.0
Prometheusv2.28

相关链接

7.3 - 重大变更与弃用

重大变更与弃用的处理

重大变更

重大变更定义为在升级到下一个稳定次要版本的 Dapr 工件(SDK、CLI、运行时等)后,对以下任何内容的更改导致现有的第三方应用程序或脚本出现编译错误或不良运行时行为:

  • 代码行为
  • 架构
  • 默认配置值
  • 命令行参数
  • 发布的指标
  • Kubernetes 资源模板
  • 公共可访问的 API
  • 公共可见的 SDK 接口、方法、类或属性

重大变更可以立即应用于以下情况:

  • 尚未达到 1.0.0 版本的项目
  • 预览功能
  • Alpha API
  • SDK 中的预览或 Alpha 接口、类、方法或属性
  • Alpha 或 Beta 阶段的 Dapr 组件
  • github.com/dapr/components-contrib 的接口
  • 文档和博客中的 URL
  • 例外情况,即必须修复严重错误或安全漏洞。

应用重大变更的流程

应用重大变更有一个流程:

  1. 必须在某个版本中发布弃用通知。
  2. 重大变更将在宣布弃用的版本之后的两个(2)版本中应用。
    • 例如,功能 X 在 1.0.0 版本说明中宣布弃用,随后将在 1.2.0 中移除。

弃用

弃用可应用于:

  1. API,包括 alpha API
  2. 预览功能
  3. 组件
  4. CLI
  5. 可能导致安全漏洞的功能

弃用内容会出现在版本说明中名为 “Deprecations” 的部分下,该部分指示:

  • 将来不再支持已弃用功能的时间点。例如版本 x.y.z。这至少在两个(2)版本之前。
  • 如果适用,在版本说明中记录用户必须采取的任何步骤来修改其代码、操作等。

在宣布未来的重大变更后,变更将在 2 个版本或 6 个月后生效,以较晚者为准。已弃用的功能应响应警告,但除此之外不执行任何操作。

已宣布的弃用

功能弃用公告移除版本
GET /v1.0/shutdown API(用户应改用 POST API1.2.01.4.0
Java domain builder 类已弃用(用户应改用 settersJava SDK 1.3.0Java SDK 1.5.0
服务调用将不再提供默认的 application/json 内容类型头,当未指定 content-type 时。如果您调用的应用依赖此头,则必须为服务调用显式设置内容类型头1.7.01.9.0
使用 invoke 方法的 gRPC 服务调用已被弃用。请改用代理模式服务调用。请参阅 How-To: 使用 gRPC 调用服务 以使用代理模式。1.9.01.10.0
CLI 标志 --app-ssl(在 Dapr CLI 和 daprd 中)已被弃用,取而代之的是使用值为 httpsgrpcs--app-protocoldaprd:6158 cli:12671.11.01.13.0
Hazelcast 发布订阅组件1.9.01.11.0
Twitter 绑定组件1.10.01.11.0
NATS Streaming 发布订阅组件1.11.01.13.0
工作流 API Alpha1 /v1.0-alpha1/workflows 已被弃用,取而代之的是工作流客户端1.15.01.17.0
http-max-request-size 标志/注解迁移到 max-body-size。请参阅 How-To: 处理更大的主体请求1.14.01.17.0

相关链接

7.4 - 报告安全问题

如何向 Dapr 维护者报告安全顾虑或漏洞。

Dapr 项目和维护者将安全作为我们运营和设计软件的核心关注点。从 Dapr 二进制文件到 GitHub 发布流程,我们采取了众多措施来确保用户应用程序和数据的安全。有关 Dapr 安全功能的更多信息,请访问安全页面

涵盖的仓库和问题

当我们说"Dapr 中的安全漏洞"时,这指的是 dapr GitHub 组织下任何仓库中的安全问题。

此报告流程仅适用于 Dapr 项目本身的安全问题,不适用于使用 Dapr 的应用程序或不影响安全的问题。

如果问题无法通过更改上述涵盖的仓库之一来解决,建议在相应的仓库中创建 GitHub issue 或在 Discord 中提出问题。

如果您不确定,请谨慎行事,在通过 GitHub、Discord 或其他渠道提出问题之前,先使用报告流程与我们联系。

明确不涵盖:漏洞扫描器报告

我们不接受仅仅是复制粘贴漏洞扫描工具输出的报告,除非已经做了具体工作来确认工具报告的漏洞在 Dapr 中确实存在,包括 CLI、Dapr SDK、components-contrib 仓库或 Dapr 组织下的任何其他仓库。

我们自己使用这些工具,并尝试根据它们产生的输出采取行动。然而,我们倾向于发现,当这些报告发送到我们的安全邮件列表时,它们几乎总是代表误报,因为这些工具倾向于检查库的存在,而不考虑库在上下文中如何使用。

如果我们收到的报告似乎只是来自扫描器的漏洞列表,我们保留忽略它的权利。

当工具生成的漏洞标识符不可公开可见或以某种方式为专有时,这尤其适用。我们可以查找 CVE 或其他公开可用的标识符以获取更多详细信息,但无法对专有标识符执行相同的操作。

安全联系人

有权阅读您的安全报告的人员列在 maintainers.md 中。

报告流程

  1. 用英语描述问题,最好提供一些允许重现问题的示例配置或代码。解释您为什么认为这是 Dapr 中的安全问题。
  2. 将该信息放入电子邮件中。使用描述性标题。
  3. 发送电子邮件至 Security (security@dapr.io)

响应

响应时间可能会受到周末、节假日、休息或时区差异的影响。尽管如此,维护者团队会尽快回复,理想情况下在 3 个工作日内。

如果团队确认报告的问题确实是 Dapr 项目中的安全漏洞,维护者团队中至少有两名成员会尽快讨论下一步措施,理想情况下在 24 小时内。

一旦团队确定报告确实是真正的漏洞,团队中的一员会向报告者回复,确认问题并建立披露时间表,这应该尽快完成。

分类、响应、修复和公告应在 30 天内完成。

7.5 - 预览功能

当前预览功能列表

Dapr 中的预览功能在首次发布时被视为实验性功能。

运行时预览功能需要显式选择加入才能使用。运行时选择加入是在 Dapr 应用配置中的预览设置功能中指定的。有关更多信息,请参阅如何:启用预览功能

对于 CLI,无需显式选择加入,只需使用该功能首次引入的版本即可。

当前预览功能

功能描述设置文档引入版本
可插拔组件允许创建支持 gRPC 的任何语言编写的自托管 gRPC 组件。支持以下组件 API:状态存储、发布订阅、绑定N/A可插拔组件概念v1.9
Kubernetes 多应用运行从单个配置文件配置多个 Dapr 应用程序,并通过单个命令在 Kubernetes 上运行dapr run -k -f多应用运行v1.12
加密无需管理密钥即可加密或解密数据N/A加密概念v1.11
Actor 状态 TTL允许 Actor 保存记录到设置了生存时间(TTL)的状态存储,以自动清理旧数据。在其当前实现中,带有 TTL 的 Actor 状态可能无法被客户端正确反映,阅读 Actor 状态事务 了解更多信息。ActorStateTTLActor 状态事务v1.11
组件热重载允许 Dapr 加载的组件进行"热重载"。当在 Kubernetes 中创建/更新/删除组件规范时,或在自托管模式下在文件上进行时,会重新加载组件规范。忽略对 Actor 状态存储和工作流后端的更改。HotReload热重载v1.13
订阅热重载允许声明式订阅进行"热重载"。订阅在 Kubernetes 中创建/更新/删除时或在自托管模式下的文件中进行时重新加载。重新加载时不影响正在进行的消息。HotReload热重载v1.14
工作流集群部署当工作流客户端与负载均衡器后端的同一 appID 的多个 daprd 通信时,启用工作流功能。仅在使用 Dapr 共享 时相关WorkflowsClusteredDeploymentDapr 共享v1.16
工作流持久化活动结果如果设置,可确保在多应用场景中,活动结果被持久地发送到拥有工作流,即使拥有工作流的应用程序不可用。除非运行多个 Dapr 版本,否则应启用此功能开关。默认情况下出于向后兼容性而禁用。WorkflowsRemoteActivityReminder多应用工作流v1.17

7.6 - Alpha and Beta APIs

当前 alpha 和 beta API 列表

Alpha 版 API

构建块/APIgRPCHTTP描述文档引入版本
Query StateQuery State protov1.0-alpha1/state/statestore/query状态查询 API 使您能够检索、过滤和排序存储在状态存储组件中的键/值数据。Query State APIv1.5
Distributed LockLock proto/v1.0-alpha1/lock分布式锁 API 使您能够对资源加锁。Distributed Lock APIv1.8
CryptographyCrypto protov1.0-alpha1/crypto加密 API 使您能够执行消息加密和解密的高层级加密操作。Cryptography APIv1.11
JobsJobs protov1.0-alpha1/jobsJobs API 使您能够调度和编排作业。Jobs APIv1.14
Streaming SubscriptionStreaming Subscription protoN/A订阅在应用程序代码中定义。流式订阅是动态的,意味着它们允许在运行时添加或删除订阅。Streaming Subscription APIv1.14
ConversationConversation protov1.0-alpha2/conversation使用 conversation API 在不同大语言模型之间进行对话。Conversation APIv1.15

Beta 版 API

当前没有 beta 版 API。

相关链接

了解有关 Alpha、Beta 和 Stable 生命周期阶段的更多信息。

8 - 调试与故障排除

帮助用户调试和诊断 Dapr 问题的工具、技术和常见问题

8.1 - 运行 Dapr 时的常见问题

运行 Dapr 应用程序时遇到的常见问题和故障

本指南涵盖了在安装和运行 Dapr 时可能遇到的常见问题。

安装 Dapr CLI 时 Dapr 无法连接到 Docker

在安装和初始化 Dapr CLI 时,如果运行 dapr init 后看到以下错误消息:

⌛  Making the jump to hyperspace...
❌  could not connect to docker. docker may not be installed or running

通过确保以下内容来排查错误:

  1. 正确的容器正在运行。

  2. 在 Docker Desktop 中,验证已选择 Allow the default Docker socket to be used (requires password) 选项。

我没有看到 Dapr 边车注入到我的 pod 中

边车可能无法注入到 pod 中有多种原因。 首先,检查您的 deployment 或 pod YAML 文件,并检查您是否在正确的位置具有以下注解:

annotations:
  dapr.io/enabled: "true"
  dapr.io/app-id: "nodeapp"
  dapr.io/app-port: "3000"

示例 deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp
  namespace: default
  labels:
    app: node
spec:
  replicas: 1
  selector:
    matchLabels:
      app: node
  template:
    metadata:
      labels:
        app: node
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "nodeapp"
        dapr.io/app-port: "3000"
    spec:
      containers:
      - name: node
        image: dapriosamples/hello-k8s-node
        ports:
        - containerPort: 3000
        imagePullPolicy: Always

在某些已知情况下,这可能无法正常工作:

  • 如果您的 pod 规范模板已正确注解,但您仍然没有看到边车注入,请确保 Dapr 在您的 deployment 或 pod 部署之前已部署到集群。

    如果是这种情况,重启 pod 将解决此问题。

  • 如果您在私有 GKE 集群上部署 Dapr,边车注入在无需额外步骤的情况下无法工作。请参阅设置 Google Kubernetes Engine 集群

    为了进一步诊断任何问题,请检查 Dapr 边车注入器的日志:

     kubectl logs -l app=dapr-sidecar-injector -n dapr-system
    

    注意:如果您将 Dapr 安装到不同的命名空间,请将上面的 dapr-system 替换为所需的命名空间

  • 如果您在 Amazon EKS 上部署 Dapr 并使用 Calico 等覆盖网络,您需要将 hostNetwork 参数设置为 true,这是使用此类 CNI 的 EKS 的限制。

    您可以使用 Helm values.yaml 文件设置此参数:

    helm upgrade --install dapr dapr/dapr \
    --namespace dapr-system \
    --create-namespace \
    --values values.yaml
    

    values.yaml

    dapr_sidecar_injector:
      hostNetwork: true
    

    或使用命令行:

    helm upgrade --install dapr dapr/dapr \
    --namespace dapr-system \
    --create-namespace \
    --set dapr_sidecar_injector.hostNetwork=true
    
  • 确保 kube api 服务器可以到达以下 webhook 服务:

    请与您的集群管理员联系,以设置允许从 kube api 服务器到集群中上述端口 400019443 的入站规则。

我的 pod 处于 CrashLoopBackoff 或其他由于 daprd 边车导致的失败状态

如果 Dapr 边车 (daprd) 初始化时间过长,这可能被 Kubernetes 显示为运行状况检查失败。

如果您的 pod 处于失败状态,您应该检查以下内容:

kubectl describe pod <name-of-pod>

您可能会在命令输出的末尾看到如下表格:

  Normal   Created    7m41s (x2 over 8m2s)   kubelet, aks-agentpool-12499885-vmss000000  Created container daprd
  Normal   Started    7m41s (x2 over 8m2s)   kubelet, aks-agentpool-12499885-vmss000000  Started container daprd
  Warning  Unhealthy  7m28s (x5 over 7m58s)  kubelet, aks-agentpool-12499885-vmss000000  Readiness probe failed: Get http://10.244.1.10:3500/v1.0/healthz: dial tcp 10.244.1.10:3500: connect: connection refused
  Warning  Unhealthy  7m25s (x6 over 7m55s)  kubelet, aks-agentpool-12499885-vmss000000  Liveness probe failed: Get http://10.244.1.10:3500/v1.0/healthz: dial tcp 10.244.1.10:3500: connect: connection refused
  Normal   Killing    7m25s (x2 over 7m43s)  kubelet, aks-agentpool-12499885-vmss000000  Container daprd failed liveness probe, will be restarted
  Warning  BackOff    3m2s (x18 over 6m48s)  kubelet, aks-agentpool-12499885-vmss000000  Back-off restarting failed container

消息 Container daprd failed liveness probe, will be restarted 表示 Dapr 边车未能通过其运行状况检查并将被重启。消息 Readiness probe failed: Get http://10.244.1.10:3500/v1.0/healthz: dial tcp 10.244.1.10:3500: connect: connection refusedLiveness probe failed: Get http://10.244.1.10:3500/v1.0/healthz: dial tcp 10.244.1.10:3500: connect: connection refused 显示运行状况检查失败,因为无法建立到边车的连接。

此失败的最常见原因是组件(例如状态存储)配置错误,导致初始化时间过长。当初始化耗时较长时,运行状况检查可能会在边车记录任何有用的信息之前终止边车。

要诊断根本原因:

  • 显著增加存活探针延迟 - 链接
  • 将边车的日志级别设置为 debug - 链接
  • 观察日志以获取有意义的信息 - 链接

请记得在解决问题后将存活检查延迟和日志级别配置回所需的值。

我无法保存状态或获取状态

您是否在集群中安装了 Dapr 状态存储?

要检查,请使用 kubectl 获取组件列表:

kubectl get components

如果没有状态存储组件,这意味着您需要设置一个。 访问这里了解更多详情。

如果一切设置正确,请确保您的凭据正确。 搜索 Dapr 运行时日志并查找任何状态存储错误:

kubectl logs <name-of-pod> daprd

我无法发布和接收事件

您是否在集群中安装了 Dapr 消息总线?

要检查,请使用 kubectl 获取组件列表:

kubectl get components

如果没有发布订阅组件,这意味着您需要设置一个。 访问这里了解更多详情。

如果一切设置正确,请确保您的凭据正确。 搜索 Dapr 运行时日志并查找任何发布订阅错误:

kubectl logs <name-of-pod> daprd

调用 Dapr 时收到 500 错误响应

这意味着 Dapr 运行时内部存在一些问题。 要诊断,请查看边车的日志:

kubectl logs <name-of-pod> daprd

调用 Dapr 时收到 404 Not Found 响应

这意味着您正在尝试调用一个不存在或 URL 格式错误的 Dapr API 端点。 查看这里的 Dapr API 参考,并确保您调用了正确的端点。

我没有看到来自其他服务的传入事件或调用

您是否指定了您的应用程序正在侦听的端口? 在 Kubernetes 中,确保指定了 dapr.io/app-port 注解:

annotations:
  dapr.io/enabled: "true"
  dapr.io/app-id: "nodeapp"
  dapr.io/app-port: "3000"

如果使用 Dapr Standalone 和 Dapr CLI,请确保将 --app-port 标志传递给 dapr run 命令。

我的启用 Dapr 的应用程序行为不正确

首先要做的是检查从 Dapr API 返回的 HTTP 错误代码(如果有)。 如果您仍然找不到问题,请尝试为 Dapr 运行时启用 debug 日志级别。请参阅这里了解如何执行此操作。

您可能还希望查看您自己进程的错误日志。如果在 Kubernetes 上运行,请找到包含您的应用程序的 pod,并执行以下命令:

kubectl logs <pod-name> <name-of-your-container>

如果在 Standalone 模式下运行,您应该在主控制台会话中看到来自您应用程序的 stderr 和 stdout 输出。

在本地运行 Actors 时出现超时/连接错误

每个 Dapr 实例都会将其主机地址报告给 placement 服务。然后,placement 服务将节点表及其地址分发给所有 Dapr 实例。如果该主机地址不可达,您可能会遇到套接字超时错误或其他请求失败的变体。

除非通过将名为 DAPR_HOST_IP 的环境变量设置为可访问、可 ping 的地址来指定主机名,否则 Dapr 将循环遍历网络接口并选择它找到的第一个非环回地址。

如上所述,为了告诉 Dapr 应该使用什么主机名,只需设置一个名为 DAPR_HOST_IP 的环境变量。

以下示例展示了如何将主机 IP 环境变量设置为 127.0.0.1

注意:对于 <= 0.4.0 版本,使用 HOST_IP

export DAPR_HOST_IP=127.0.0.1

当我的应用程序启动时,我的组件都没有被加载。我一直收到"Error component X cannot be found"

这通常是由于以下问题之一

  • 您可能在本地定义了 NAMESPACE 环境变量,或者将组件部署到 Kubernetes 中的不同命名空间。检查您的应用程序和组件部署到哪个命名空间。阅读将组件限定为一个或多个应用程序以获取更多信息。
  • 您可能没有为 Dapr run 命令提供 --resources-path,或者没有将组件放入您操作系统的默认组件文件夹中。阅读定义组件以获取更多信息。
  • 您可能在组件 YAML 文件中有语法问题。使用组件 YAML 示例检查您的组件 YAML。

服务调用失败,我的 Dapr 服务缺少 appId(macOS)

某些组织将实现过滤掉所有 UDP 流量的软件,这是 mDNS 所基于的。最常见的是,在 MacOS 上,Microsoft Content Filter 是罪魁祸首。

为了使 mDNS 正常运行,请确保 Microsoft Content Filter 处于非活动状态。

  • 打开终端 shell。
  • 输入 mdatp system-extension network-filter disable 并按回车键。
  • 输入您的帐户密码。

当输出为"Success"时,Microsoft Content Filter 已被禁用。

某些组织会不时重新启用过滤器。如果您反复遇到 app-id 值缺失的情况,在进行更广泛的故障排除之前,请首先检查过滤器是否已重新启用。

Admission webhook 拒绝了请求

您可能会遇到与以下类似的错误,由于 admission webhook 对服务帐户创建或修改资源有允许列表。

root:[dapr]$ kubectl run -i --tty --rm debug --image=busybox --restart=Never -- sh
Error from server: admission webhook "sidecar-injector.dapr.io" denied the request: service account 'user-xdd5l' not on the list of allowed controller accounts

要解决此错误,您应该为当前用户创建一个 clusterrolebind

kubectl create clusterrolebinding dapr-<name-of-user> --clusterrole=dapr-operator-admin --user <name-of-user>

您可以运行以下命令来获取集群中的所有用户:

kubectl config get-users

您可以在这里了解更多关于 webhook 的信息。

dapr init 期间端口不可用

在 Windows 上尝试执行 dapr init 后,您可能会遇到以下错误:

PS C:\Users\You> dapr init Making the jump to hyperspace… Container images will be pulled from Docker Hub Installing runtime version 1.14.4 Downloading binaries and setting up components… docker: Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:52379 -> 0.0.0.0:0: listen tcp4 0.0.0.0:52379: bind: An attempt was made to access a socket in a way forbidden by its access permissions.

要解决此错误,请在提升的终端中打开命令提示符并运行:

net stop winnat
dapr init
net start winnat

8.2 - 配置和查看 Dapr 日志

了解 Dapr 中的日志工作原理以及如何配置和查看日志

本节将帮助您了解 Dapr 中的日志工作原理,以及如何配置和查看日志。

概述

日志具有不同的、可配置的详细程度级别。 下面列出的级别对于系统组件和 Dapr 边车进程/容器都是相同的:

  1. error
  2. warn
  3. info
  4. debug

error 产生最少的输出,而 debug 产生最多的输出。默认级别是 info,它在正常条件下运行 Dapr 时提供平衡的信息量。

要设置输出级别,您可以使用 --log-level 命令行选项。例如:

./daprd --log-level error
./placement --log-level debug

这将启动日志级别为 error 的 Dapr 运行时二进制文件和日志级别为 debug 的 Dapr Actor Placement 服务。

独立模式下的日志

在使用 Dapr CLI 运行应用时设置日志级别,传递 log-level 参数:

dapr run --log-level warn node myapp.js

如上所述,每个 Dapr 二进制文件都接受 --log-level 参数。例如,要使用警告日志级别启动 placement 服务:

./placement --log-level warn

在独立模式下查看日志

使用 Dapr CLI 运行 Dapr 时,您的应用的日志输出和运行时的输出都将被重定向到同一会话中,以便于调试。 例如,这是运行 Dapr 时的输出:

dapr run node myapp.js
ℹ️  Starting Dapr with id Trackgreat-Lancer on port 56730
✅  You are up and running! Both Dapr and your app logs will appear here.

== APP == App listening on port 3000!
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="starting Dapr Runtime -- version 0.3.0-alpha -- commit b6f2810-dirty"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="log level set to: info"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="standalone mode configured"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="app id: Trackgreat-Lancer"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="loaded component statestore (state.redis)"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="loaded component messagebus (pubsub.redis)"
== DAPR == 2019/09/05 12:26:43 redis: connecting to localhost:6379
== DAPR == 2019/09/05 12:26:43 redis: connected to localhost:6379 (localAddr: [::1]:56734, remAddr: [::1]:6379)
== DAPR == time="2019-09-05T12:26:43-07:00" level=warn msg="failed to init input bindings: app channel not initialized"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30s"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="actors: starting connection attempt to placement service at localhost:50005"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="http server is running on port 56730"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="gRPC server is running on port 56731"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="dapr initialized. Status: Running. Init Elapsed 8.772922000000001ms"
== DAPR == time="2019-09-05T12:26:43-07:00" level=info msg="actors: established connection to placement service at localhost:50005"

Kubernetes 模式下的日志

了解如何在 Kubernetes 上调试 daprd

您可以通过在 pod 规范模板中提供以下注释来为每个边车单独设置日志级别:

annotations:
  dapr.io/log-level: "debug"

设置系统 Pod 的日志级别

使用 Helm 3.x 将 Dapr 部署到集群时,您可以为每个 Dapr 系统组件单独设置日志级别:

helm install dapr dapr/dapr --namespace dapr-system --set <COMPONENT>.logLevel=<LEVEL>

组件:

  • dapr_operator
  • dapr_placement
  • dapr_sidecar_injector

示例:

helm install dapr dapr/dapr --namespace dapr-system --set dapr_operator.logLevel=error

在 Kubernetes 上查看日志

Dapr 日志被写入 stdout 和 stderr。 本节将指导您如何查看 Dapr 系统组件以及 Dapr 边车的日志。

边车日志

在 Kubernetes 中部署时,Dapr 边车注入器会将名为 daprd 的 Dapr 容器注入到带注释的 pod 中。 要查看边车的日志,只需运行 kubectl get pods 找到相关 pod:

NAME                                        READY     STATUS    RESTARTS   AGE
addapp-74b57fb78c-67zm6                     2/2       Running   0          40h

接下来,获取 Dapr 边车容器的日志:

kubectl logs addapp-74b57fb78c-67zm6 -c daprd

time="2019-09-04T02:52:27Z" level=info msg="starting Dapr Runtime -- version 0.3.0-alpha -- commit b6f2810-dirty"
time="2019-09-04T02:52:27Z" level=info msg="log level set to: info"
time="2019-09-04T02:52:27Z" level=info msg="kubernetes mode configured"
time="2019-09-04T02:52:27Z" level=info msg="app id: addapp"
time="2019-09-04T02:52:27Z" level=info msg="application protocol: http. waiting on port 6000"
time="2019-09-04T02:52:27Z" level=info msg="application discovered on port 6000"
time="2019-09-04T02:52:27Z" level=info msg="actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30s"
time="2019-09-04T02:52:27Z" level=info msg="actors: starting connection attempt to placement service at dapr-placement.dapr-system.svc.cluster.local:80"
time="2019-09-04T02:52:27Z" level=info msg="http server is running on port 3500"
time="2019-09-04T02:52:27Z" level=info msg="gRPC server is running on port 50001"
time="2019-09-04T02:52:27Z" level=info msg="dapr initialized. Status: Running. Init Elapsed 64.234049ms"
time="2019-09-04T02:52:27Z" level=info msg="actors: established connection to placement service at dapr-placement.dapr-system.svc.cluster.local:80"

系统日志

Dapr 运行以下系统 Pod:

  • Dapr operator
  • Dapr sidecar injector
  • Dapr placement service

Operator 日志

kubectl logs -l app=dapr-operator -n dapr-system

I1207 06:01:02.891031 1 leaderelection.go:243] attempting to acquire leader lease dapr-system/operator.dapr.io...
I1207 06:01:02.913696 1 leaderelection.go:253] successfully acquired lease dapr-system/operator.dapr.io
time="2021-12-07T06:01:03.092529085Z" level=info msg="getting tls certificates" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator type=log ver=unknown
time="2021-12-07T06:01:03.092703283Z" level=info msg="tls certificates loaded successfully" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator type=log ver=unknown
time="2021-12-07T06:01:03.093062379Z" level=info msg="starting gRPC server" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator.api type=log ver=unknown
time="2021-12-07T06:01:03.093123778Z" level=info msg="Healthz server is listening on :8080" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator type=log ver=unknown
time="2021-12-07T06:01:03.497889776Z" level=info msg="starting webhooks" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator type=log ver=unknown
I1207 06:01:03.497944 1 leaderelection.go:243] attempting to acquire leader lease dapr-system/webhooks.dapr.io...
I1207 06:01:03.516641 1 leaderelection.go:253] successfully acquired lease dapr-system/webhooks.dapr.io
time="2021-12-07T06:01:03.526202227Z" level=info msg="Successfully patched webhook in CRD "subscriptions.dapr.io"" instance=dapr-operator-84bb47f895-dvbsj scope=dapr.operator type=log ver=unknown

注意:如果 Dapr 被安装到 dapr-system 以外的命名空间,只需在上述命令中将命名空间替换为所需的命名空间

边车注入器日志

kubectl logs -l app=dapr-sidecar-injector -n dapr-system

time="2021-12-07T06:01:01.554859058Z" level=info msg="log level set to: info" instance=dapr-sidecar-injector-5d88fcfcf5-2gmvv scope=dapr.injector type=log ver=unknown
time="2021-12-07T06:01:01.555114755Z" level=info msg="metrics server started on :9090/" instance=dapr-sidecar-injector-5d88fcfcf5-2gmvv scope=dapr.metrics type=log ver=unknown
time="2021-12-07T06:01:01.555233253Z" level=info msg="starting Dapr Sidecar Injector -- version 1.5.1 -- commit c6daae8e9b11b3e241a9cb84c33e5aa740d74368" instance=dapr-sidecar-injector-5d88fcfcf5-2gmvv scope=dapr.injector type=log ver=unknown
time="2021-12-07T06:01:01.557646524Z" level=info msg="Healthz server is listening on :8080" instance=dapr-sidecar-injector-5d88fcfcf5-2gmvv scope=dapr.injector type=log ver=unknown
time="2021-12-07T06:01:01.621291968Z" level=info msg="Sidecar injector is listening on :4000, patching Dapr-enabled pods" instance=dapr-sidecar-injector-5d88fcfcf5-2gmvv scope=dapr.injector type=log ver=unknown

注意:如果 Dapr 被安装到 dapr-system 以外的命名空间,只需在上述命令中将命名空间替换为所需的命名空间

查看 Placement 服务日志

kubectl logs -l app=dapr-placement-server -n dapr-system

time="2021-12-04T05:08:05.733416791Z" level=info msg="starting Dapr Placement Service -- version 1.5.0 -- commit 83fe579f5dc93bef1ce3b464d3167a225a3aff3a" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=unknown
time="2021-12-04T05:08:05.733469491Z" level=info msg="log level set to: info" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:05.733512692Z" level=info msg="metrics server started on :9090/" instance=dapr-placement-server-0 scope=dapr.metrics type=log ver=1.5.0
time="2021-12-04T05:08:05.735207095Z" level=info msg="Raft server is starting on 127.0.0.1:8201..." instance=dapr-placement-server-0 scope=dapr.placement.raft type=log ver=1.5.0
time="2021-12-04T05:08:05.735221195Z" level=info msg="mTLS enabled, getting tls certificates" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:05.735265696Z" level=info msg="tls certificates loaded successfully" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:05.735276396Z" level=info msg="placement service started on port 50005" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:05.735553696Z" level=info msg="Healthz server is listening on :8080" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:07.036850257Z" level=info msg="cluster leadership acquired" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0
time="2021-12-04T05:08:07.036909357Z" level=info msg="leader is established." instance=dapr-placement-server-0 scope=dapr.placement type=log ver=1.5.0

注意:如果 Dapr 被安装到 dapr-system 以外的命名空间,只需在上述命令中将命名空间替换为所需的命名空间

非 Kubernetes 环境

上面的示例专门针对 Kubernetes,但原理对于任何基于容器的环境都是相同的:只需获取 Dapr 边车和/或系统组件(如适用)的容器 ID 并查看其日志。

参考

8.3 - Dapr API 日志

了解 Dapr 中的 API 日志记录是如何工作的以及如何查看日志

API 日志记录使您能够查看您的应用程序向 Dapr 边车发出的 API 调用。这对于监控应用程序的行为或其他调试目的非常有用。您还可以将 Dapr API 日志记录与 Dapr 日志事件(参见 配置和查看 Dapr 日志)结合到输出中,以便一起使用日志记录功能。

概述

默认情况下,API 日志记录是禁用的。

要启用 API 日志记录,可以在启动 daprd 进程时使用 --enable-api-logging 命令行选项。例如:

./daprd --enable-api-logging

在自托管模式下配置 API 日志记录

要在使用 Dapr CLI 运行应用程序时启用 API 日志记录,请传递 --enable-api-logging 标志:

dapr run \
  --enable-api-logging \
  -- node myapp.js

在自托管模式下查看 API 日志

当使用 Dapr CLI 运行 Dapr 时,您的应用程序日志输出和 Dapr 运行时日志输出都会被重定向到同一个会话中,以便于调试。

下面的示例显示了一些 API 日志:

$ dapr run --enable-api-logging -- node myapp.js

ℹ️  Starting Dapr with id order-processor on port 56730
✅  You are up and running! Both Dapr and your app logs will appear here.
.....
INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="POST /v1.0/state/mystate" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
== APP == INFO:root:Saving Order: {'orderId': '483'}
INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="GET /v1.0/state/mystate/key123" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
== APP == INFO:root:Getting Order: {'orderId': '483'}
INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="DELETE /v1.0/state/mystate" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
== APP == INFO:root:Deleted Order: {'orderId': '483'}
INFO[0000] HTTP API Called app_id=order-processor instance=mypc method="PUT /v1.0/metadata/cliPID" scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge

在 Kubernetes 中配置 API 日志记录

您可以通过在 Pod 规范模板中添加以下注解来为边车启用 API 日志:

annotations:
  dapr.io/enable-api-logging: "true"

在 Kubernetes 上查看 API 日志

Dapr API 日志会被写入 stdout 和 stderr,您可以在 Kubernetes 上查看 API 日志。

执行以下命令以查看 Kubernetes API 日志。

kubectl logs <pod_name> daprd -n <name_space>

下面的示例显示了 Kubernetes 中 info 级别的 API 日志记录(启用了 URL 混淆)。

time="2022-03-16T18:32:02.487041454Z" level=info msg="HTTP API Called" method="POST /v1.0/invoke/{id}/method/{method:*}" app_id=invoke-caller instance=invokecaller-f4f949886-cbnmt scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
time="2022-03-16T18:32:02.698387866Z" level=info msg="HTTP API Called" method="POST /v1.0/invoke/{id}/method/{method:*}" app_id=invoke-caller instance=invokecaller-f4f949886-cbnmt scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
time="2022-03-16T18:32:02.917629403Z" level=info msg="HTTP API Called" method="POST /v1.0/invoke/{id}/method/{method:*}" app_id=invoke-caller instance=invokecaller-f4f949886-cbnmt scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
time="2022-03-16T18:32:03.137830112Z" level=info msg="HTTP API Called" method="POST /v1.0/invoke/{id}/method/{method:*}" app_id=invoke-caller instance=invokecaller-f4f949886-cbnmt scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge
time="2022-03-16T18:32:03.359097916Z" level=info msg="HTTP API Called" method="POST /v1.0/invoke/{id}/method/{method:*}" app_id=invoke-caller instance=invokecaller-f4f949886-cbnmt scope=dapr.runtime.http-info type=log useragent=Go-http-client/1.1 ver=edge

API 日志记录配置

使用 Dapr 配置规范,您可以配置 Dapr 运行时中 API 日志记录的默认行为。

默认启用 API 日志记录

使用 Dapr 配置规范,您可以通过 logging.apiLogging.enabled 选项设置 --enable-api-logging 标志(以及在 Kubernetes 上运行时对应的注解)的默认值。此值适用于引用定义该选项的配置文档或资源的所有 Dapr 运行时。

  • 如果 logging.apiLogging.enabled 设置为 false(默认值),则除非将 --enable-api-logging 设置为 true(或添加 dapr.io/enable-api-logging: true 注解),否则 Dapr 运行时的 API 日志记录将被禁用。
  • logging.apiLogging.enabledtrue 时,Dapr 运行时默认启用 API 日志记录,可以通过设置 --enable-api-logging=false 或使用 dapr.io/enable-api-logging: false 注解来禁用。

例如:

logging:
  apiLogging:
    enabled: true

在 HTTP API 日志记录中混淆 URL

默认情况下,HTTP 端点中 API 调用的日志包含被调用的完整 URL(例如,POST /v1.0/invoke/directory/method/user-123),其中可能包含个人身份信息(PII)。

为了降低 PII 意外包含在 API 日志中的风险(启用时),Dapr 可以改为记录被调用的抽象路由(例如,POST /v1.0/invoke/{id}/method/{method:*})。这有助于确保遵守 GDPR 等隐私法规。

要在 Dapr 的 HTTP API 日志中启用 URL 混淆,请将 logging.apiLogging.obfuscateURLs 设置为 true。例如:

logging:
  apiLogging:
    obfuscateURLs: true

Dapr gRPC API 发出的日志不受此配置选项的影响,因为它们仅包含被调用方法的名称,不包含参数。

从 API 日志记录中省略健康检查

当启用 API 日志记录时,对 Dapr API 服务器的所有调用都会被记录,包括对健康检查端点的调用(例如 /v1.0/healthz)。根据您的环境,这每分钟可能会生成多个日志行,并可能产生不必要的噪音。

您可以使用 Dapr 配置规范配置 Dapr 在启用 API 日志记录时不记录对健康检查端点的调用,方法是将 logging.apiLogging.omitHealthChecks 设置为 true。默认值为 false,这意味着健康检查调用会记录在 API 日志中。

例如:

logging:
  apiLogging:
    omitHealthChecks: true

8.4 - 性能分析与调试

通过性能分析会话发现并发、性能、CPU 和内存使用等方面的问题和隐患

在任何真实场景中,应用程序可能会出现资源方面的异常行为。 在大多数情况下,CPU/内存飙升并不罕见。

Dapr 允许用户通过其性能分析服务端点使用 pprof 启动按需性能分析会话,并启动检测会话以发现并发、性能、CPU 和内存使用等方面的问题和隐患。

启用性能分析

Dapr 允许您在 Kubernetes 和独立模式两种模式下启用性能分析。

独立模式

要在独立模式下启用性能分析,请将 --enable-profiling--profile-port 标志传递给 Dapr CLI: 请注意 profile-port 不是必需的,如果未提供,Dapr 将选择一个可用端口。

dapr run --enable-profiling --profile-port 7777 python myapp.py

Kubernetes

要在 Kubernetes 中启用性能分析,只需将 dapr.io/enable-profiling 注解添加到您的 Dapr 注解 pod 中:

   annotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "rust-app"
    dapr.io/enable-profiling: "true"

调试性能分析会话

启用性能分析后,我们可以启动性能分析会话来调查 Dapr 运行时发生了什么。

独立模式

对于独立模式,找到您想要分析的 Dapr 实例:

dapr list
APP ID           DAPR PORT     APP PORT  COMMAND      AGE  CREATED              PID
node-subscriber  3500          3000      node app.js  12s  2019-09-09 15:11.24  896

获取 DAPR PORT,如果已按照上述说明启用了性能分析,您现在可以开始使用 pprof 来分析 Dapr。 查看上面的 Kubernetes 示例,获取一些用于分析 Dapr 的有用命令。

有关 pprof 的更多信息可以在这里找到。

Kubernetes

首先,找到包含 Dapr 运行时的 pod。如果您还不知道 pod 名称,请输入 kubectl get pods

NAME                                        READY     STATUS    RESTARTS   AGE
divideapp-6dddf7dc74-6sq4l                  2/2       Running   0          2d23h

如果性能分析已成功启用,运行时日志应显示以下内容: time="2019-09-09T20:56:21Z" level=info msg="starting profiling server on port 7777"

在这种情况下,我们要与 pod divideapp-6dddf7dc74-6sq4l 内的 Dapr 运行时启动会话。

我们可以通过端口转发连接到 pod 来实现:

kubectl port-forward divideapp-6dddf7dc74-6sq4 7777:7777
Forwarding from 127.0.0.1:7777 -> 7777
Forwarding from [::1]:7777 -> 7777
Handling connection for 7777

既然连接已经建立,我们可以使用 pprof 来分析 Dapr 运行时。

以下示例将创建一个 cpu.pprof 文件,其中包含持续 120 秒的性能分析会话的采样:

curl "http://localhost:7777/debug/pprof/profile?seconds=120" > cpu.pprof

使用 pprof 分析文件:

pprof cpu.pprof

您还可以将结果以可视化方式保存到 PDF 中:

go tool pprof --pdf your-binary-file http://localhost:7777/debug/pprof/profile?seconds=120 > profile.pdf

对于内存相关问题,您可以分析堆:

go tool pprof --pdf your-binary-file http://localhost:7777/debug/pprof/heap > heap.pdf

heap

分析已分配的对象:

go tool pprof http://localhost:7777/debug/pprof/heap
> exit

Saved profile in /Users/myusername/pprof/pprof.daprd.alloc_objects.alloc_space.inuse_objects.inuse_space.003.pb.gz

要进行分析,请获取上面的文件路径(这是一个动态文件路径,所以请注意记录并粘贴这个路径),然后执行:

go tool pprof -alloc_objects --pdf /Users/myusername/pprof/pprof.daprd.alloc_objects.alloc_space.inuse_objects.inuse_space.003.pb.gz > alloc-objects.pdf

alloc

9 - Dapr 的性能和可扩展性统计

Dapr 构建块的基准测试和指南

9.1 - 性能结果

Dapr API 的性能基准和图表

关于性能结果,请访问 dapr/dapr 仓库中的 Dapr 性能测试套件,您可以在其中查看每个 Dapr 版本和 API 的性能图表与数据。

访问性能图表目录以查看详细的性能指标,包括不同 Dapr 版本下每个 API 的延迟、吞吐量和资源利用率。在每个文件夹中,您都会找到一个 README,其中包含若干常见用例的性能亮点,以及相应的性能图表来可视化这些数据。

9.2 - 长期性能与稳定性

本文提供了 Dapr 在 Kubernetes 上的长期性能与稳定性基准测试。

长期测试设计为运行一周时间,验证 Dapr 及其组件的稳定性,同时测量资源利用率和随时间变化的性能表现。

公共仪表板

您可以在公共 Grafana 仪表板上访问实时的长期测试结果。该仪表板近实时更新,显示长期测试的最新结果。

Dapr 长期测试仪表板

系统概览

长期环境运行在一个 3 节点的托管 Azure Kubernetes Service (AKS) 集群上,使用标准 D2s_v5 节点,配备 2 核心 8GB RAM,并启用网络加速。

测试应用程序

  • Feed generator
  • Hashtag Actor
  • Hashtag counter
  • Message Analyzer
  • Pubsub Workflow
  • Streaming Pubsub Publisher / Producer
  • Streaming Pubsub Subscriber / Consumer
  • Snapshot App
  • Validation Worker App
  • Scheduler Jobs App
  • Workflow Gen App
  • Scheduler Actor Reminders - Client
  • Scheduler Actor Reminders - Server
  • Scheduler Workflow App

重新部署

长期测试环境每 7 天重新部署一次(UTC 时间周五 08:00)。

测试基础设施

测试基础设施来源于此 GitHub 仓库

它由 Bicep IaC 模板和 Helm charts 组成,用于部署测试应用程序和 Dapr。