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 的分布式追踪

场景

追踪用于服务调用和发布/订阅(pubsub)API。您可以在使用这些 API 的服务之间传递追踪上下文。追踪的使用有两种场景:

  1. Dapr 生成追踪上下文,您将追踪上下文传递到另一个服务。
  2. 您生成追踪上下文,Dapr 将追踪上下文传递到服务。

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

顺序服务调用的传递

Dapr 负责创建追踪头。然而,当有两个以上的服务时,您需要负责在它们之间传递追踪头。让我们通过示例来了解这些场景:

单一服务调用

例如,服务 A -> 服务 B

Dapr 在 服务 A 中生成追踪头,然后从 服务 A 传递到 服务 B。不需要进一步的传递。

多个顺序服务调用

例如,服务 A -> 服务 B -> 传递追踪头到 -> 服务 C,以及其他启用 Dapr 的服务。

Dapr 在请求开始时在 服务 A 中生成追踪头,然后传递到 服务 B。您现在需要负责获取头并将其传递到 服务 C,因为这与您的应用程序特定相关。

换句话说,如果应用程序调用 Dapr 并希望使用现有的追踪头(span)进行追踪,它必须始终传递到 Dapr(在此示例中,从 服务 B服务 C)。Dapr 始终将追踪 span 传递到应用程序。

请求来自外部端点

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

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

您必须从 服务 A 传递头到 服务 B。例如:入口 -> 服务 A -> 传递追踪头 -> 服务 B。这类似于案例 2

发布/订阅消息

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

多个不同服务调用的传递

在以下场景中,Dapr 为您完成了一些工作,您需要创建或传递追踪头。

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

当您从单个服务调用多个服务时,您需要传递追踪头。例如:

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

在这种情况下:

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

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

生成您自己的追踪上下文头较为少见,并且在调用 Dapr 时通常不需要。

然而,在某些场景中,您可能会特别选择在服务调用中添加 W3C 追踪头。例如,您有一个不使用 Dapr 的现有应用程序。在这种情况下,Dapr 仍然为您传递追踪上下文头。

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

  1. 标准 OpenTelemetry SDK

    您可以使用行业标准的 OpenTelemetry SDKs 生成追踪头,并将这些追踪头传递到启用 Dapr 的服务。这是首选方法

  2. 供应商 SDK

    您可以使用提供生成 W3C 追踪头的方法的供应商 SDK,并将其传递到启用 Dapr 的服务。

  3. W3C 追踪上下文

    您可以根据 W3C 追踪上下文规范 手工制作追踪上下文,并将其传递到启用 Dapr 的服务。

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

相关链接

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 字段的详细信息

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

相关链接

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

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

配置

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

spec:
  tracing:
    samplingRate: "1"
    otel: 
      endpointAddress: "myendpoint.cluster.local:4317"
    zipkin:
      endpointAddress: "https://..."

下表列出了追踪的属性:

属性类型描述
samplingRatestring设置追踪的采样率来启用或禁用追踪。
stdoutbool如果为真,则会将更详细的信息写入追踪。
otel.endpointAddressstring设置 Open Telemetry (OTEL) 目标主机名和可选端口。如果使用此项,则无需指定 ‘zipkin’ 部分。
otel.isSecurebool指定连接到端点地址的连接是否加密。
otel.protocolstring设置为 httpgrpc 协议。
zipkin.endpointAddressstring设置 Zipkin 服务器 URL。如果使用此项,则无需指定 otel 部分。

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

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

采样率

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

samplingRate 设置为 0 将完全禁用追踪。

环境变量

OpenTelemetry (otel) 端点也可以通过环境变量进行配置。设置 OTEL_EXPORTER_OTLP_ENDPOINT 环境变量将为 sidecar 启用追踪。

环境变量描述
OTEL_EXPORTER_OTLP_ENDPOINT设置 Open Telemetry (OTEL) 服务器主机名和可选端口,启用追踪
OTEL_EXPORTER_OTLP_INSECURE将连接设置为未加密(true/false)
OTEL_EXPORTER_OTLP_PROTOCOL传输协议(grpchttp/protobufhttp/json

下一步

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

1.1.4 - Open Telemetry Collector

如何配置您的监控工具以接收应用程序追踪数据

1.1.4.1 - 使用 OpenTelemetry Collector 收集追踪

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

Dapr 推荐使用 OpenTelemetry (OTLP) 协议来写入追踪数据。对于直接支持 OTLP 的可观测性工具,建议使用 OpenTelemetry Collector,因为它可以快速卸载数据,并提供重试、批处理和加密等功能。更多信息请参阅 Open Telemetry 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> 替换为您的追踪导出器的实际配置。

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

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

配置 Dapr 发送追踪数据到 OTEL Collector

创建一个 Dapr 配置文件以启用追踪,并部署一个使用 OpenTelemetry Collector 的追踪导出器组件。

  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"

您可以同时注册多个追踪导出器,追踪数据将被转发到所有注册的导出器。

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

查看追踪

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

相关链接

1.1.4.2 - 使用 OpenTelemetry Collector 将跟踪信息发送到应用程序洞察

如何使用 OpenTelemetry Collector 将跟踪事件推送到 Azure 应用程序洞察。

Dapr 使用 Zipkin API 集成了 OpenTelemetry (OTEL) Collector。本指南演示了如何通过 Dapr 使用 OpenTelemetry Collector 将跟踪事件推送到 Azure 应用程序洞察。

前提条件

配置 OTEL Collector 以推送数据到应用程序洞察

要将事件推送到你的应用程序洞察实例,请在 Kubernetes 集群中安装 OTEL Collector。

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

  2. 用你的应用程序洞察仪器密钥替换 <INSTRUMENTATION-KEY> 占位符。

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

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

配置 Dapr 以发送跟踪数据到 OTEL Collector

创建一个 Dapr 配置文件以启用跟踪,并部署一个使用 OpenTelemetry Collector 的跟踪导出组件。

  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"

你可以同时注册多个跟踪导出器,跟踪日志会被转发到所有注册的导出器。

就是这样!无需包含任何 SDK 或对你的应用程序代码进行额外的修改。Dapr 会自动为你处理分布式跟踪。

查看跟踪

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

应用程序地图

相关链接

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

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

Dapr 支持通过 OpenTelemetry (OTLP) 和 Zipkin 协议进行追踪信息的写入。然而,由于 Jaeger 对 Zipkin 的支持已被弃用,建议使用 OTLP。虽然 Jaeger 可以直接支持 OTLP,但在生产环境中,推荐使用 OpenTelemetry Collector 从 Dapr 收集追踪信息并发送到 Jaeger。这样可以让您的应用程序更高效地处理数据,并利用重试、批处理和加密等功能。更多信息请阅读 Open Telemetry Collector 文档

在自托管模式下配置 Jaeger

本地设置

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

docker run -d --name jaeger \
  -p 4317:4317  \
  -p 16686:16686 \
  jaegertracing/all-in-one:1.49

接下来,在本地创建以下 config.yaml 文件:

注意: 因为您使用 Open Telemetry 协议与 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

查看追踪信息

要在浏览器中查看追踪信息,请访问 http://localhost:16686 查看 Jaeger UI。

在 Kubernetes 上使用 OpenTelemetry Collector 配置 Jaeger

以下步骤展示了如何配置 Dapr 以将分布式追踪数据发送到 OpenTelemetry Collector,然后将追踪信息发送到 Jaeger。

前提条件

设置 OpenTelemetry Collector 推送到 Jaeger

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

  1. 下载并检查 open-telemetry-collector-jaeger.yaml 文件。

  2. otel-collector-conf ConfigMap 的数据部分,更新 otlp/jaeger.endpoint 值以匹配您的 Jaeger collector Kubernetes 服务对象的端点。

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

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

设置 Dapr 发送追踪信息到 OpenTelemetryCollector

创建一个 Dapr 配置文件以启用追踪,并将 sidecar 追踪信息导出到 OpenTelemetry Collector。

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

  2. 更新 namespaceotel.endpointAddress 值以与部署 Dapr 应用程序和 OpenTelemetry Collector 的命名空间对齐。

  3. 应用配置:

    kubectl apply -f collector-config.yaml
    

部署启用追踪的应用程序

通过在您希望启用分布式追踪的应用程序部署中添加 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 会自动为您处理分布式追踪。

查看追踪信息

要查看 Dapr sidecar 追踪信息,请端口转发 Jaeger 服务并打开 UI:

kubectl port-forward svc/jaeger-query 16686 -n observability

在您的浏览器中,访问 http://localhost:16686,您将看到 Jaeger 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 的 Telemetry Data Platform,您需要一个 New Relic Insights Insert API key

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 仪器化

为了将数据集成到 New Relic Telemetry Data Platform,您需要一个 New Relic license keyNew Relic Insights Insert API key

OpenTelemetry 仪器化

您可以使用不同语言的 OpenTelemetry 实现,例如 New Relic Telemetry SDK 和 .NET 的 OpenTelemetry 支持。在这种情况下,使用 OpenTelemetry Trace Exporter。示例请参见此处

New Relic 语言代理

类似于 OpenTelemetry 仪器化,您也可以使用 New Relic 语言代理。例如,.NET Core 的 New Relic 代理仪器化 是 Dockerfile 的一部分。示例请参见此处

(选择性)启用 New Relic Kubernetes 集成

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

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

New Relic Kubernetes 集群浏览器

New Relic Kubernetes 集群浏览器 提供了一个独特的可视化界面,展示了 Kubernetes 集成收集的所有数据和部署。

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

New Relic Kubernetes Cluster Explorer App

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

Pod 级别详情

New Relic K8s Pod Level Details

上下文中的日志

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 合作,您可以使用 Telemetry Data Platform 作为 Prometheus 指标的数据源,并在现有仪表板中查看它们,轻松利用 New Relic 提供的可靠性、规模和安全性。

用于监控 Dapr 系统服务和 sidecar 的 Grafana 仪表板模板 可以轻松使用,无需任何更改。New Relic 提供了一个 Prometheus 指标的本地端点 到 Grafana。可以轻松设置数据源:

New Relic Grafana Data Source

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

New Relic Grafana Dashboard

New Relic 警报

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

相关链接/参考

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

设置 Zipkin 进行分布式追踪

配置自托管模式

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

  1. 系统会默认创建一个 YAML 文件,路径为 $HOME/.dapr/config.yaml(Linux/Mac)或 %USERPROFILE%\.dapr\config.yaml(Windows)。在执行 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 中的配置文件。您可以通过 Dapr CLI 的 --config 参数来指定其他配置:
dapr run --app-id mynode --app-port 3000 node app.js

查看追踪

要查看追踪数据,请在浏览器中访问 http://localhost:9411,您将看到 Zipkin 的用户界面。

配置 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 sidecar 中启用此配置,请在 pod 规范模板中添加以下注释:

annotations:
  dapr.io/config: "tracing"

完成!您的 sidecar 现在已配置为将追踪数据发送到 Zipkin。

查看追踪数据

要查看追踪数据,请连接到 Zipkin 服务并打开用户界面:

kubectl port-forward svc/zipkin 9411:9411

在浏览器中,访问 http://localhost:9411,您将看到 Zipkin 的用户界面。

zipkin

参考资料

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

为分布式追踪设置 Datadog

Dapr 捕获的指标和追踪信息可以通过 OpenTelemetry Collector 的 Datadog 导出器直接发送到 Datadog。

使用 OpenTelemetry Collector 和 Datadog 配置 Dapr 追踪

您可以使用 OpenTelemetry Collector 的 Datadog 导出器来配置 Dapr,为 Kubernetes 集群中的每个应用程序创建追踪,并将这些追踪信息收集到 Datadog 中。

在开始之前,请先设置 OpenTelemetry Collector

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

    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 显示遥测数据。

相关链接/参考

1.2 - 监控指标

如何查看和理解Dapr的监控指标

1.2.1 - 操作指南:使用 Prometheus 监控指标

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

本地设置 Prometheus

在本地计算机上,您可以选择安装并作为进程运行 Prometheus,或者将其作为Docker 容器运行

安装

请按照此处提供的步骤,根据您的操作系统安装 Prometheus。

配置

安装完成后,您需要创建一个配置文件。

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

global:
  scrape_interval:     15s # 默认情况下,每 15 秒收集一次指标。

# 包含一个收集端点的配置:
# 这里是 Prometheus 自身。
scrape_configs:
  - job_name: 'dapr'

    # 覆盖全局默认值,每 5 秒从此 job 收集指标。
    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。您可以通过传递命令行参数--metrics-port给daprd来更改此设置。

在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.recordErrorCodestrue来为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.pathMatchingincreasedCardinality标志设置为false结合使用时,未匹配的路径会被转换为一个通用桶,以控制和限制基数,防止路径无限增长。相反,当increasedCardinalitytrue(默认值)时,未匹配的路径会像通常一样传递,允许潜在的更高基数,但保留原始路径数据。

HTTP指标中的路径匹配示例

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

这些示例说明了指标的基数,强调高基数配置会导致许多条目,这对应于处理指标的更高内存使用。为简单起见,以下示例专注于单个指标: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动词的示例

以下示例演示了如何在Dapr中排除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,因为这两个请求都包含在这里。

这显示如下:

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 sidecar 的状态,包括sidecar 的健康状况/资源使用情况、HTTP和gRPC的吞吐量/延迟、actor、mTLS等:

sidecar仪表板的截图

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. 安装图表:

    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服务端点>.<命名空间>

    首先通过运行以下命令获取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
    • 默认:开启
    • 跳过TLS验证:开启
      • 这是保存和测试配置所必需的
    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) 启用 Dapr 指标和日志的 Azure Monitor

前提条件

使用配置映射启用 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. 使用配置映射启用 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"
    ...
    

    应用配置映射:

    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 注解。

    注意:只有设置了 Prometheus 注解,Azure Monitor Agents (AMA) 才会发送指标。

    在部署的 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
    
  3. 搜索 指标

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

    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 sidecar 和您的应用程序设置日志记录

在 Dapr 中,日志记录是一个关键功能,帮助开发者监控和调试应用程序。Dapr 提供了多种日志记录选项,您可以根据需求进行灵活配置。

配置 Dapr sidecar 日志

您可以通过设置环境变量来配置 Dapr sidecar 的日志记录。可以调整日志级别、输出格式等,以适应不同的需求。常见的日志级别包括 DebugInfoWarningError

应用程序日志记录

除了 Dapr sidecar,您还可以为您的应用程序设置日志记录。通过使用 Dapr 的日志记录功能,您可以更有效地监控应用程序的行为和性能。

日志输出

Dapr 支持将日志输出到多种目标,包括控制台、文件和远程日志服务。您可以根据应用程序的部署环境选择最合适的日志输出方式。

通过合理配置日志记录,您可以更好地了解应用程序的运行状况,快速发现和解决问题。

1.3.1 - 日志

了解 Dapr 日志

Dapr 生成的结构化日志会输出到 stdout,可以选择纯文本或 JSON 格式。默认情况下,所有 Dapr 进程(包括运行时或 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 应用 IDdapr-app
verDapr 运行时版本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 sidecar 启用 JSON 格式日志

您可以通过在部署中添加 dapr.io/log-as-json: "true" 注释来为 Dapr sidecar 启用 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"
        # 启用 JSON 格式的日志
        dapr.io/log-as-json: "true"
...

API 日志

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

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

日志收集器

如果您在 Kubernetes 集群中运行 Dapr,Fluentd 是一个流行的容器日志收集器。您可以使用带有 JSON 解析器插件 的 Fluentd 来解析 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 for containers

参考资料

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

如何在 Kubernetes 中安装 Fluentd、Elastic Search 和 Kibana 以搜索日志

前提条件

安装 Elastic search 和 Kibana

  1. 创建一个用于监控工具的 Kubernetes 命名空间

    kubectl create namespace dapr-monitoring
    
  2. 添加 Elastic Search 的 Helm 仓库

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

    默认情况下,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. 确保 Elastic Search 和 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. 作为 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
    

安装 Dapr 并启用 JSON 格式日志

  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 格式日志

    在您的部署 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"
    ...
    

搜索日志

注意:Elastic Search 需要一些时间来索引 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 管理菜单选项下的 Stack Management 项

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

    Kibana Stack Management 页面上的 Index 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 等是否被索引。

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

    查看创建的 Kibana 索引模式

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

    Kibana Analytics 菜单选项下的 Discover 项

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

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

    在 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 镜像使用,并在 Kubernetes 集群中以 DaemonSet 的形式安装,我们称之为 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
    

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

默认情况下,日志跟踪路径设置为 /var/log/containers/*.log。要更改此设置,请在上述命令中添加 –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 注释

搜索

相关链接/参考

2 - Dapr 的部署方式

了解如何在不同环境中部署 Dapr。

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

如何在本地环境中启动 Dapr

2.1.1 - Dapr 自托管模式概述

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

概述

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

初始化

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

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

  • 一个 Redis 容器,配置为同时用于状态管理和发布/订阅的默认组件。
  • 一个 Zipkin 容器,用于诊断和跟踪。
  • 默认的 Dapr 配置和组件安装在 $HOME/.dapr/ (Mac/Linux) 或 %USERPROFILE%\.dapr\ (Windows)。

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

Dapr 自托管 Docker 模式的示意图

使用 Dapr 启动应用程序

您可以使用 dapr run CLI 命令 启动 Dapr sidecar 进程和您的应用程序。其他参数和标志可以在这里找到。

名称解析

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

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

2.1.2 - 如何使用 Podman 在自托管模式下运行 Dapr

使用 Podman 在自托管模式下部署和运行 Dapr 的方法

本文介绍了如何在 Windows/Linux/macOS 机器或虚拟机上使用 Podman 运行 Dapr。

准备工作

设置 Dapr 环境

要设置 Dapr 控制平面容器并创建默认配置文件,请执行以下命令:

dapr init --container-runtime podman

以进程方式运行应用程序和 sidecar

可以使用 dapr run CLI 命令 启动 Dapr sidecar 和您的应用程序:

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

此命令会启动 daprd sidecar 和您的应用程序。

以进程方式运行应用程序,sidecar 作为 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.3 - 如何使用 Docker 自托管 Dapr

在自托管模式下,如何通过 Docker 部署和运行 Dapr

本文介绍如何在 Windows/Linux/macOS 机器或虚拟机上使用 Docker 运行 Dapr。

前提条件

设置 Dapr 环境

运行以下命令以初始化 Dapr 控制平面并创建默认配置文件:

dapr init

以进程形式运行应用和 sidecar

使用 dapr run CLI 命令 启动 Dapr sidecar 和您的应用程序:

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

此命令将启动 daprd sidecar 并运行 dotnet run,从而启动您的应用程序。

应用以进程形式运行,sidecar 以 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 网络上运行

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

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

docker network create my-dapr-network

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

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

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

使用 Docker-Compose 运行

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

Docker Compose 的语法和工具超出了本文的范围,建议您参考官方 Docker 文档以获取更多详细信息。

为了使用 Dapr 和 Docker Compose 运行您的应用程序,您需要在 docker-compose.yml 中定义 sidecar 模式。例如:

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", # Dapr 的 placement 服务可以通过 docker DNS 条目访问
     "--resources-path", "./components"
     ]
    volumes:
        - "./components/:/components" # 挂载我们的组件文件夹供运行时使用。挂载位置必须与 --resources-path 参数匹配。
    depends_on:
      - nodeapp
    network_mode: "service:nodeapp" # 将 nodeapp-dapr 服务附加到 nodeapp 网络命名空间

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

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

  scheduler:
    image: "daprio/dapr"
    command: ["./scheduler", "--port", "50007"]
    ports:
      - "50007:50007"
    # 警告 - 这是一个 tmpfs 卷,您的状态不会在重启后持久化
    volumes:
    - type: tmpfs
      target: /data
      tmpfs:
        size: "10000"
  
  networks:
    hello-dapr: null

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

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

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

在 Kubernetes 上运行

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

名称解析

Dapr 默认使用 mDNS 作为自托管模式下的名称解析组件进行服务调用。如果您在虚拟机上运行 Dapr 或 mDNS 不可用的地方运行 Dapr,则可以使用 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.4 - 操作指南:在离线或隔离环境中运行Dapr

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

概述

通常情况下,Dapr初始化时会从网络下载二进制文件并拉取镜像来设置开发环境。然而,Dapr也支持使用预先下载的安装包进行离线或隔离安装,这可以通过Docker或精简模式来实现。每个Dapr版本的安装包都被构建成一个Dapr安装包,可以下载。通过使用这个安装包和Dapr CLI的init命令,你可以在没有网络访问的环境中安装Dapr。

设置

在进行隔离初始化之前,需要预先下载一个Dapr安装包,其中包含CLI、运行时和仪表板的内容。这避免了在本地初始化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以获得相同的效果。

输出应类似于以下内容:

  正在进行超空间跳跃...
ℹ️  正在安装最新的运行时版本
↘  正在提取二进制文件并设置组件... 已加载镜像:daprio/dapr:$version
✅  提取二进制文件并设置组件完成。
✅  二进制文件提取和组件设置已完成。
ℹ️  daprd二进制文件已安装到$HOME/.dapr/bin。
ℹ️  dapr_placement容器正在运行。
ℹ️  使用`docker ps`检查正在运行的容器。
✅  成功!Dapr已启动并运行。要开始使用,请访问:https://aka.ms/dapr-getting-started

注意:要模拟在线 Dapr初始化,使用dapr init,你也可以运行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 .

输出应类似于以下内容:

⌛  正在进行超空间跳跃...
ℹ️  正在安装最新的运行时版本
↙  正在提取二进制文件并设置组件... 
✅  提取二进制文件并设置组件完成。
✅  二进制文件提取和组件设置已完成。
ℹ️  daprd二进制文件已安装到$HOME/.dapr/bin。
ℹ️  placement二进制文件已安装到$HOME/.dapr/bin。
✅  成功!Dapr已启动并运行。要开始使用,请访问:https://aka.ms/dapr-getting-started

2.1.5 - 如何在没有 Docker 的环境中以自托管模式运行 Dapr

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

前提条件

初始化无容器的 Dapr

Dapr CLI 提供了一个选项,可以使用 slim init 初始化 Dapr,而无需依赖 Docker 来创建默认的开发环境。安装 Dapr CLI 后,使用以下命令进行 slim init 初始化:

dapr init --slim

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

  • daprd
  • placement

placement 二进制文件用于在 Dapr 自托管安装中启用 actor

在 slim init 模式下,不会安装用于状态管理或消息发布/订阅的默认组件(如 Redis)。这意味着,除了 服务调用 外,安装时没有其他内置功能可用。您可以根据需要设置自己的环境和自定义组件。

如果配置了状态存储,则可以进行基于 actor 的服务调用,具体说明请参见以下章节。

执行服务调用

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

启用状态管理或消息发布/订阅

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

启用 actor

要启用 actor placement:

默认情况下,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.6 - 操作指南:持久化调度器作业

配置调度器以持久化其数据库,使其在重启时具有弹性

调度器服务负责将作业写入嵌入式数据库并进行调度执行。 默认情况下,调度器服务会将数据写入本地卷dapr_scheduler,这意味着数据在重启时会被持久化

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

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

调度器的持久卷可以通过使用预先存在的自定义卷进行修改,或者由Dapr自动创建。

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

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

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

    dapr uninstall --all
    
  2. 访问本指南以下载并安装最新版本的 CLI。

  3. 初始化 Dapr 运行时:

    dapr init
    
  4. 确认您正在使用最新版本的 Dapr (v1.15.5):

    $ dapr --version
    
    CLI version: 1.15
    Runtime version: 1.15
    

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

从本地机器中移除 Dapr 的步骤

以下 CLI 命令用于移除 Dapr sidecar 二进制文件和 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 - Dapr 在 Kubernetes 上的概述

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

Dapr 可以在任何支持的 Kubernetes 版本上运行。为此,Dapr 部署了一些 Kubernetes 服务,这些服务提供了良好的集成,使得在 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 对 Kubernetes 的支持遵循 Kubernetes 版本偏差政策

将 Dapr 部署到 Kubernetes 集群

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

将 Dapr 添加到 Kubernetes 部署

要在 Kubernetes 集群中部署和运行启用 Dapr 的应用程序,只需在 pod 中添加一些注释即可。例如,在以下示例中,您的 Kubernetes pod 被标注为:

  • 为您的服务提供 Dapr 识别的 idport
  • 配置追踪功能
  • 启动 Dapr sidecar 容器
  annotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "nodeapp"
    dapr.io/app-port: "3000"
    dapr.io/config: "tracing"

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

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

Dapr 可以与任何用户应用程序容器镜像无缝配合使用,无论其来源。只需初始化 Dapr并在 Kubernetes 定义中添加 Dapr 注释 以添加 Dapr sidecar。

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

有关以下内容的信息:

教程

通过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 客户端

故障排除

负载均衡器的外部 IP 地址在 kubectl get svc 中未显示。

在 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 |
|-----------|----------------------|-------------|---------------------------|
🎉  正在默认浏览器中打开 Kubernetes 服务 default/calculator-front-end...

相关链接

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
    

    此集群配置:

    • 启动一个由控制平面和两个工作节点组成的 Kubernetes 集群。
    • 方便将来设置 Ingress。
    • 将容器端口映射到主机。
  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 服务 (AKS) 集群

学习如何配置 Azure Kubernetes 集群

本指南将引导您安装 Azure Kubernetes 服务 (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] --node-count 2 --enable-addons http_application_routing --generate-ssh-keys
    
  5. 获取 AKS 集群的访问凭据。

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

AKS Edge Essentials

要使用 Azure Kubernetes 服务 (AKS) Edge Essentials 创建单机 K8s/K3s Linux-only 集群,您可以按照 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 集群的 Sidecar 注入

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

在私有 GKE 集群中,自动创建的主访问防火墙规则未开放 Dapr 所需的 4000 端口用于 Sidecar 注入。

查看相关的防火墙规则:

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

更新现有规则以允许 Kubernetes 主节点访问 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 仪表板权限

如果您收到类似以下的错误消息:

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 - 配置弹性Kubernetes服务(EKS)集群

学习如何配置EKS集群

本指南将引导您配置一个弹性Kubernetes服务(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.yaml
    
  4. 验证kubectl上下文:

    kubectl config current-context
    

为sidecar访问和默认存储类添加Dapr要求:

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

    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

故障排除

访问权限

如果您遇到访问权限问题,请确保您使用的是创建集群时使用的相同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
    

    预期输出

    ⌛  正在初始化...
    
    ✅  正在将 Dapr 控制平面部署到集群中...
    ✅  成功!Dapr 已安装到命名空间 dapr-system。要验证,请在终端中运行 "dapr status -k"。要开始,请访问此处: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

预期输出:

⌛  正在初始化...
ℹ️  注意:要使用 Helm 安装 Dapr,请参见此处:https://docs.dapr.io/getting-started/install-dapr-kubernetes/#install-with-helm-advanced

ℹ️  容器镜像将从 Docker Hub 拉取
✅  正在将最新版本的 Dapr 控制平面部署到集群中...
✅  正在将最新版本的 Dapr 仪表板部署到集群中...
✅  正在将最新版本的 Dapr Redis 部署到集群中...
✅  正在将最新版本的 Dapr Zipkin 部署到集群中...
ℹ️  正在将 "statestore" 组件应用到 Kubernetes "default" 命名空间。
ℹ️  正在将 "pubsub" 组件应用到 Kubernetes "default" 命名空间。
ℹ️  正在将 "appconfig" zipkin 配置应用到 Kubernetes "default" 命名空间。
✅  成功!Dapr 已安装到命名空间 dapr-system。要验证,请在终端中运行 `dapr status -k`。要开始,请访问此处: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.15 \
    --namespace dapr-system \
    --create-namespace \
    --wait
    

    要在高可用模式下安装:

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

    要在高可用模式下安装并独立于全局缩放选择服务:

        helm upgrade --install dapr dapr/dapr \
     --version=1.15 \
     --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,是一个由微软维护的免费开源 Linux 发行版和容器基础镜像。对于一些 Dapr 用户,利用基于 Mariner 的容器镜像可以帮助你满足合规要求。

要使用基于 Mariner 的 Dapr 镜像,你需要在 Docker 标签中添加 -mariner。例如,ghcr.io/dapr/dapr:latest 是基于 distroless 的 Docker 镜像,而 ghcr.io/dapr/dapr:latest-mariner 是基于 Mariner 的。也有固定到特定版本的标签可用,例如 1.15-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.15 \
  --namespace dapr-system \
  --create-namespace \
  --set global.tag=1.15.5-mariner \
  --wait

相关链接

2.2.4 - 在 Kubernetes 集群上升级 Dapr

按照这些步骤在 Kubernetes 上升级 Dapr,确保顺利升级。

您可以通过 Dapr CLI 或 Helm 来升级 Kubernetes 集群上的 Dapr 控制平面。

使用 Dapr CLI 升级

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

前提条件

将现有集群升级到 1.15.5

dapr upgrade -k --runtime-version=1.15.5

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

通过 CLI 升级的故障排除

在集群上运行升级时,可能会遇到一个已知问题,即之前可能在集群上安装了 1.0.0-rc.2 之前的版本。

虽然这个问题不常见,但某些升级路径可能会在您的集群上留下不兼容的 CustomResourceDefinition。如果遇到这种情况,您可能会看到如下错误信息:

❌  升级 Dapr 失败:警告:kubectl apply 应用于由 kubectl create --save-config 或 kubectl apply 创建的资源
CustomResourceDefinition "configurations.dapr.io" 无效:spec.preserveUnknownFields: 无效值:true:必须为 false 以便在模式中使用默认值

解决方案

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

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

使用 Helm 升级

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

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

前提条件

将现有集群升级到 1.15.5

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

注意 Helm 不会自动处理资源的升级,因此您需要手动更新这些资源。资源是向后兼容的,只需向前安装即可。

  1. 将 Dapr 升级到版本 1.15.5:

    kubectl replace -f https://raw.githubusercontent.com/dapr/dapr/v1.15.5/charts/dapr/crds/components.yaml
    kubectl replace -f https://raw.githubusercontent.com/dapr/dapr/v1.15.5/charts/dapr/crds/configuration.yaml
    kubectl replace -f https://raw.githubusercontent.com/dapr/dapr/v1.15.5/charts/dapr/crds/subscription.yaml
    kubectl apply -f https://raw.githubusercontent.com/dapr/dapr/v1.15.5/charts/dapr/crds/resiliency.yaml
    kubectl apply -f https://raw.githubusercontent.com/dapr/dapr/v1.15.5/charts/dapr/crds/httpendpoints.yaml
    
    helm repo update
    
    helm upgrade dapr dapr/dapr --version 1.15.5 --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 说明 提供了详细信息和示例。

对于本地/开发安装,您可以选择不配置 resources 选项。

可选组件

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

  • Placement: 用于 Dapr actor
  • Sentry: 用于服务到服务调用的 mTLS
  • Dashboard: 用于集群的操作视图

Sidecar 资源设置

使用支持的注释设置 Dapr sidecar 的资源分配。与 资源约束 相关的特定注释是:

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

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

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

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

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

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

在 Dapr sidecar 上设置软内存限制

当您设置了内存限制时,建议在 Dapr sidecar 上设置软内存限制。使用软内存限制时,sidecar 垃圾收集器在超过限制时释放内存,而不是等待其达到运行时堆中最后一次存在的内存量的两倍。Go 的 垃圾收集器 默认会等待,这可能导致 OOM Kill 事件。

例如,对于一个内存限制设置为 1000Mi 的应用程序,其 app-id 为 nodeapp,您可以在 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

高可用模式

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

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

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

单个服务 HA Helm 配置

您可以通过将 global.ha.enabled 标志设置为 true 来跨所有服务配置 HA 模式。默认情况下,--set global.ha.enabled=true 完全被尊重且无法覆盖,因此不可能同时将 placement 或调度服务作为单个实例。

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

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

helm upgrade --install dapr dapr/dapr \
 --version=1.15 \
 --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 都被驱逐。

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

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

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

建议将 priorityClassName 设置为 system-cluster-critical 用于 Dapr 控制平面 pod。

对于新的 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

更新数据平面(sidecars)

更新运行 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 有状态集。

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

    您删除 placement 有状态集是因为在 HA 模式下,placement 服务添加了 Raft 用于领导者选举。然而,Kubernetes 仅允许有限的字段在有状态集中进行修补,随后会导致 placement 服务的升级失败。

    删除现有的 placement 有状态集是安全的。代理会重新连接并重新注册到新创建的 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 sidecar 之间的通信。为了保护 Dapr API 免受未经授权的应用程序访问,启用 Dapr 的基于令牌的认证

  3. Dapr 到应用程序 API 认证 已启用。这是 Dapr 与您的应用程序之间的通信。让 Dapr 知道它正在使用令牌认证与授权应用程序通信

  4. 组件 secret 数据配置在 secret 存储中,而不是硬编码在组件 YAML 文件中。了解如何使用 Dapr 组件的 secret

  5. Dapr 控制平面安装在专用命名空间中,例如 dapr-system

  6. Dapr 支持并启用 为某些应用程序设置组件范围。这不是必需的实践。了解更多关于组件范围

推荐的 Placement 服务配置

Placement 服务 是 Dapr 中的一个组件,负责通过 placement 表向所有 Dapr sidecar 传播 actor 地址信息(更多信息可以在 这里 找到)。

在生产环境中运行时,建议使用以下值配置 Placement 服务:

  1. 高可用性。确保 Placement 服务具有高可用性(三个副本)并能在单个节点故障中幸存。Helm chart 值:dapr_placement.ha=true
  2. 内存日志。使用内存 Raft 日志存储以加快写入速度。权衡是更多的 placement 表传播(因此,在最终的 Placement 服务 pod 故障中,网络流量会增加)。Helm chart 值:dapr_placement.cluster.forceInMemoryLog=true
  3. 无元数据端点。禁用未认证的 /placement/state 端点,该端点暴露了 Placement 服务的 placement 表信息。Helm chart 值:dapr_placement.metadataEnabled=false
  4. 超时 控制 Placement 服务与 sidecar 之间网络连接的敏感性,使用以下超时值。默认值已设置,但您可以根据网络条件调整这些值。
    1. dapr_placement.keepAliveTime 设置 Placement 服务在 gRPC 流上向 Dapr sidecar 发送 keep alive ping 的间隔,以检查连接是否仍然存活。较低的值将在 pod 丢失/重启时导致较短的 actor 重新平衡时间,但在正常操作期间会增加网络流量。接受 1s10s 之间的值。默认值为 2s
    2. dapr_placement.keepAliveTimeout 设置 Dapr sidecar 响应 Placement 服务的 keep alive 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 抓取。

设置 Prometheus、Grafana 和其他监控工具与 Dapr

注入器看门狗

Dapr Operator 服务包括一个 注入器看门狗,可用于检测和修复您的应用程序的 pod 可能在没有 Dapr sidecar(daprd 容器)的情况下部署的情况。例如,它可以帮助在集群完全故障后恢复应用程序。

在 Kubernetes 模式下运行 Dapr 时,注入器看门狗默认禁用。然而,您应该考虑根据您的具体情况启用它并设置适当的值。

请参阅 Dapr operator 服务文档 以获取有关注入器看门狗及其启用方法的更多详细信息。

为 sidecar 容器配置 seccompProfile

默认情况下,Dapr sidecar 注入器注入一个没有任何 seccompProfile 的 sidecar。然而,为了使 Dapr sidecar 容器在具有 受限 配置文件的命名空间中成功运行,sidecar 容器需要 securityContext.seccompProfile.Type 不为 nil

请参阅 参数和注释概述 以在 sidecar 容器上设置适当的 seccompProfile

最佳实践

观看此视频,深入了解在 Kubernetes 上运行 Dapr 的最佳实践。

2.2.6 - 使用 Dapr Shared 部署 Dapr 到每个节点或每个集群

了解如何使用 Dapr Shared 作为 sidecar 的替代部署方式

Dapr 会自动为您的应用程序注入一个 sidecar,以启用 Dapr API,从而实现最佳的可用性和可靠性。

Dapr Shared 提供了两种替代的部署策略:通过 Kubernetes 的 DaemonSet 实现每节点部署,或通过 Deployment 实现每集群部署。

  • DaemonSet: 当以 Kubernetes 的 DaemonSet 资源运行 Dapr Shared 时,daprd 容器会在集群中的每个 Kubernetes 节点上运行。这可以减少应用程序与 Dapr 之间的网络延迟。
  • Deployment: 当以 Kubernetes 的 Deployment 运行 Dapr Shared 时,Kubernetes 调度器会决定 daprd 容器实例在集群中的哪个节点上运行。

为什么选择 Dapr Shared?

默认情况下,当 Dapr 安装到 Kubernetes 集群中时,Dapr 控制平面会将 Dapr 作为 sidecar 注入到带有 Dapr 注释(dapr.io/enabled: "true")的应用程序中。sidecar 提供了许多优势,包括提高弹性,因为每个应用程序都有一个实例,并且应用程序与 sidecar 之间的所有通信都无需经过网络。

虽然 sidecar 是 Dapr 的默认部署方式,但某些用例需要其他方法。假设您希望将工作负载的生命周期与 Dapr API 解耦。一个典型的例子是函数或函数即服务(FaaS)运行时,它可能会自动缩减您的空闲工作负载以释放资源。在这种情况下,可能需要将 Dapr API 和所有 Dapr 异步功能(如订阅)分开。

Dapr Shared 是为这些场景而创建的,扩展了 Dapr sidecar 模型,提供了两种新的部署方法:DaemonSet(每节点)和 Deployment(每集群)。

DeamonSet(每节点)

使用 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 发布名称。

如果您使用 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 - 操作指南:持久化调度器任务

配置调度器以持久化其数据库,使其在重启时具有弹性

调度器服务负责将任务写入其嵌入的Etcd数据库并调度执行。 默认情况下,调度器服务数据库会将数据写入大小为1Gb的持久卷声明(Persistent Volume Claim),使用集群的默认存储类。 这意味着在大多数Kubernetes部署中运行调度器服务不需要额外参数,但如果没有默认的StorageClass或在生产环境中运行时,您将需要进行额外的配置

生产环境设置

ETCD存储磁盘大小

调度器的默认存储大小为1Gb。 这个大小对于大多数生产部署来说可能不够。 当存储大小超出时,调度器将记录类似以下的错误:

error running scheduler: etcdserver: mvcc: database space exceeded

确定存储大小的安全上限并不是一门精确的科学,主要取决于应用程序任务的数量、持久性和数据负载大小。 任务APIactor提醒(启用SchedulerReminders预览功能时)会根据应用程序的使用情况进行映射。 工作流(启用SchedulerReminders预览功能时)会创建大量的任务作为actor提醒,但这些任务是短暂的,与每个工作流执行的生命周期相匹配。 工作流创建的任务的数据负载通常为空或很小。

调度器使用Etcd作为其存储后端数据库。 根据设计,Etcd以预写日志(WAL)和快照的形式持久化历史事务和数据。 这意味着调度器的实际磁盘使用量将高于当前可观察的数据库状态,通常是多个倍数。

在安装时设置存储大小

如果您需要增加现有调度器的存储大小,请参见下面的增加现有调度器存储大小部分。 要增加Dapr安装的存储大小(在此示例中为16Gi),您可以使用以下命令:

dapr init -k --set dapr_scheduler.cluster.storageSize=16Gi --set dapr_scheduler.etcdSpaceQuota=16Gi
helm upgrade --install dapr dapr/dapr \
--version=1.15 \
--namespace dapr-system \
--create-namespace \
--set dapr_scheduler.cluster.storageSize=16Gi \
--set dapr_scheduler.etcdSpaceQuota=16Gi \
--wait

增加现有调度器存储大小

默认情况下,每个调度器会为每个副本创建一个大小为1Gi的持久卷和持久卷声明,使用默认的standard存储类。 这些将类似于以下内容,在此示例中我们以HA模式运行调度器。

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

要扩展调度器的存储大小,请按照以下步骤操作:

  1. 首先,确保存储类支持卷扩展,并且allowVolumeExpansion字段设置为true,如果尚未设置。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: my.driver
allowVolumeExpansion: true
...
  1. 删除调度器StatefulSet,同时保留绑定的持久卷声明。
kubectl delete sts -n dapr-system dapr-scheduler-server --cascade=orphan
  1. 通过编辑spec.resources.requests.storage字段,将持久卷声明的大小增加到所需大小。 在这种情况下,我们假设调度器以3个副本的HA模式运行。
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重新创建调度器StatefulSet。

存储类

如果您的Kubernetes部署没有默认存储类或您正在配置生产集群,则需要定义存储类。

持久卷由托管的云提供商或Kubernetes基础设施平台提供的真实磁盘支持。 磁盘大小由预计一次持久化的任务数量决定;然而,64Gb对于大多数生产场景来说应该绰绰有余。 一些Kubernetes提供商建议使用CSI驱动来配置底层磁盘。 以下是为主要云提供商创建持久磁盘的相关文档的有用链接列表:

一旦存储类可用,您可以使用以下命令安装Dapr,并将调度器配置为使用存储类(将my-storage-class替换为存储类的名称):

dapr init -k --set dapr_scheduler.cluster.storageClassName=my-storage-class
helm upgrade --install dapr dapr/dapr \
--version=1.15 \
--namespace dapr-system \
--create-namespace \
--set dapr_scheduler.cluster.storageClassName=my-storage-class \
--wait

临时存储

在非HA模式下运行时,调度器可以选择使用临时存储,即内存存储,这种存储在重启时具有弹性。例如,调度器重启后,所有任务数据都会丢失。 这在非生产部署或测试中很有用,在这些情况下存储不可用或不需要。

dapr init -k --set dapr_scheduler.cluster.inMemoryStorage=true
helm upgrade --install dapr dapr/dapr \
--version=1.15 \
--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 使用 节点亲和性 的概念来指定您的应用程序应在 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. 创建一个带有节点亲和性设置为 kubernetes.io/os: windows 的部署 YAML 文件。在下面的 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. 创建一个带有节点亲和性设置为 kubernetes.io/os: linux 的部署 YAML 文件。在下面的 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 sidecar 被设计为一个长期运行的进程。在 Kubernetes Job 的环境中,这种行为可能会阻碍作业的完成。

为了解决这个问题,Dapr sidecar 提供了一个 Shutdown 端点,用于关闭 sidecar。

在运行一个基本的 Kubernetes Job 时,你需要调用 sidecar 的 /shutdown 端点,以便优雅地停止 sidecar,并使作业被视为 Completed

如果作业在没有调用 Shutdown 的情况下完成,作业会处于 NotReady 状态,而 daprd 容器会一直运行下去。

停止 Dapr sidecar 会导致容器中的就绪性和存活性探测失败。

为了防止 Kubernetes 尝试重启你的作业,请将作业的 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 sidecar

配置 Dapr sidecar 以挂载 Pod 卷

Dapr sidecar 可以配置为挂载应用程序 Pod 上的任何 Kubernetes 卷。这些卷可以通过 daprd (sidecar) 容器以只读或读写模式访问。如果配置了一个卷进行挂载但在 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 sidecar 容器内的任何文件夹中挂载卷,但为了避免冲突并确保未来的兼容性,建议将所有挂载点放置在以下位置之一或其子文件夹中:

位置描述
/mnt推荐用于存储 Dapr sidecar 进程可读写的持久数据的卷。
/tmp推荐用于存储临时数据的卷,例如临时磁盘。

示例

基本部署资源示例

在下面的 Deployment 资源示例中:

  • my-volume1 在 sidecar 容器内以只读模式挂载到 /mnt/sample1
  • my-volume2 在 sidecar 容器内以只读模式挂载到 /mnt/sample2
  • my-volume3 在 sidecar 容器内以读写模式挂载到 /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: {}
...

使用本地文件 secret 存储自定义 secret 存储

由于任何类型的 Kubernetes 卷都可以附加到 sidecar,您可以使用本地文件 secret 存储从各种地方读取 secret。例如,如果您有一个运行在 10.201.202.203 的网络文件共享 (NFS) 服务器,secret 存储在 /secrets/stage/secrets.json,您可以将其用作 secret 存储。

  1. 配置应用程序 pod 以挂载 NFS 并将其附加到 Dapr sidecar。

    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. 将本地文件 secret 存储组件指向附加的文件。

    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. 使用 secret。

    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 容器应用

了解如何在 Azure 容器应用无服务器平台上运行您的 Dapr 应用程序

Azure 容器应用 是一种无服务器应用托管服务,用户无需管理底层的虚拟机、编排器或其他云基础设施。Azure 容器应用允许您运行打包在多个容器中的应用程序代码,并且对所使用的运行时或编程模型没有特定要求。

Dapr 已集成到容器应用中,您可以直接使用 Dapr API 的功能模块,而无需手动部署 Dapr 运行时。您只需将服务与其 Dapr 组件一起部署即可。

了解更多

教程

访问 Azure 文档 以尝试微服务教程,您将在其中将两个启用 Dapr 的应用程序部署到 Azure 容器应用。

包含两个 Dapr 服务的容器应用环境示意图 在容器应用上试用 Dapr

3 - Dapr 配置管理指南

了解如何设置 Dapr 配置并有效管理部署

3.1 - Dapr 配置

Dapr 配置概述

Dapr 配置通过一系列设置和策略,允许您调整单个 Dapr 应用程序的行为,或控制平面系统服务的整体行为。

欲了解更多信息,请阅读配置概念。

应用程序配置

设置应用程序配置

您可以在自托管模式或 Kubernetes 模式下设置应用程序配置。

在自托管模式下,Dapr 配置是一个配置文件,例如 config.yaml。默认情况下,Dapr sidecar 会在默认的 Dapr 文件夹中查找运行时配置:

  • Linux/MacOs: $HOME/.dapr/config.yaml
  • Windows: %USERPROFILE%\.dapr\config.yaml

您还可以在 dapr run CLI 命令中使用 --config 标志指定文件路径来应用配置。

在 Kubernetes 模式下,Dapr 配置是一个应用于集群的配置资源。例如:

kubectl apply -f myappconfig.yaml

您可以使用 Dapr CLI 列出应用程序的配置资源。

dapr configurations -k

Dapr sidecar 可以通过 dapr.io/config 注解来应用特定配置。例如:

  annotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "nodeapp"
    dapr.io/app-port: "3000"
    dapr.io/config: "myappconfig"

注意: 查看所有 Kubernetes 注解,以便在 sidecar 注入器系统服务激活时配置 Dapr sidecar。

应用程序配置选项

以下是您可以在 sidecar 上设置的所有配置选项。

跟踪

跟踪配置用于启用应用程序的跟踪功能。

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

tracing:
  samplingRate: "1"
  otel: 
    endpointAddress: "otelcollector.observability.svc.cluster.local:4317"
  zipkin:
    endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans"

下表列出了跟踪的属性:

属性类型描述
samplingRatestring设置跟踪的采样率以启用或禁用。
stdoutbool为跟踪写入更详细的信息
otel.endpointAddressstring设置 Open Telemetry (OTEL) 服务器地址以发送跟踪。这可能需要或不需要 https:// 或 http://,具体取决于您的 OTEL 提供商。
otel.isSecurebool连接到端点地址是否加密
otel.protocolstring设置为 httpgrpc 协议
zipkin.endpointAddressstring设置 Zipkin 服务器地址以发送跟踪。这应该在端点上包含协议 (http:// 或 https://)。
samplingRate

samplingRate 用于启用或禁用跟踪。samplingRate 的有效范围是 01(含)。采样率决定了是否根据值对跟踪跨度进行采样。

samplingRate : "1" 采样所有跟踪。默认情况下,采样率为 (0.0001),即 1 万分之一。

要禁用采样率,请在配置中设置 samplingRate : "0"

otel

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

环境变量描述
OTEL_EXPORTER_OTLP_ENDPOINT设置 Open Telemetry (OTEL) 服务器地址,启用跟踪
OTEL_EXPORTER_OTLP_INSECURE将连接到端点设置为未加密(true/false)
OTEL_EXPORTER_OTLP_PROTOCOL传输协议 (grpc, http/protobuf, http/json)

有关更多信息,请参阅 可观察性分布式跟踪

指标

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 sidecar 暴露的每个指标设置正则表达式。例如:

metrics:
  enabled: true
  rules:
    - name: dapr_runtime_service_invocation_req_sent_total
      labels:
      - name: method
        regex:
          "orders/": "orders/.+"

有关更多信息,请参阅 指标文档

日志

Configuration 规范下的 logging 部分用于配置 Dapr 运行时中的日志记录方式。

logging 部分包含以下属性:

logging:
  apiLogging:
    enabled: false
    obfuscateURLs: false
    omitHealthChecks: false

下表列出了日志记录的属性:

属性类型描述
apiLogging.enabledbooleandaprd--enable-api-logging 标志的默认值(以及相应的 dapr.io/enable-api-logging 注解):除非为每个 Dapr 运行时传递 truefalse 值,否则使用配置规范中设置的值作为默认值。默认值:false
apiLogging.obfuscateURLsboolean启用时,会在 HTTP API 日志(如果启用)中模糊化 URL 的值,记录抽象路由名称而不是被调用的完整路径,该路径可能包含个人可识别信息(PII)。默认值:false
apiLogging.omitHealthChecksboolean如果为 true,则在启用 API 日志记录时,不会记录对健康检查端点(例如 /v1.0/healthz)的调用。这在这些调用在日志中添加了大量噪音时很有用。默认值:false

有关更多信息,请参阅 日志记录文档

中间件

中间件配置设置命名的 HTTP 管道中间件处理程序。Configuration 规范下的 httpPipelineappHttpPipeline 部分包含以下属性:

httpPipeline: # 用于传入的 http 调用
  handlers:
    - name: oauth2
      type: middleware.http.oauth2
    - name: uppercase
      type: middleware.http.uppercase
appHttpPipeline: # 用于传出的 http 调用
  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"

有关更多信息,请参阅:

限制 secret 存储访问

有关如何将 secret 范围限定到应用程序的信息和示例,请参阅 范围 secret 指南。

构建块 API 的访问控制白名单

有关如何在构建块 API 列表上设置访问控制白名单(ACL)的信息和示例,请参阅 在 Dapr sidecar 上选择性启用 Dapr API 指南。

服务调用 API 的访问控制白名单

有关如何使用 ACL 设置白名单的服务调用 API 的信息和示例,请参阅 服务调用的白名单 指南。

禁止使用某些组件类型

使用 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)。

示例 sidecar 配置

以下 YAML 显示了一个可以应用于应用程序的 Dapr sidecar 的示例配置文件。

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"
  httpPipeline:
    handlers:
      - name: oauth2
        type: middleware.http.oauth2
  secrets:
    scopes:
      - storeName: localstore
        defaultAccess: allow
        deniedSecrets: ["redis-password"]
  components:
    deny:
      - bindings.smtp
      - secretstores.local.file
  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 分钟)。
workloadCertTTLstringDapr 签发的证书 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 的每个事件,包括 pub/sub 事件、来自其他服务的直接调用、bindings 事件等。然而,Dapr 无法对外部传入您应用程序的请求强制执行并发策略。

相关链接

参数和注释

下一步

限制 secret 存储访问

3.3 - 操作指南:限制从 secret 存储中读取的 secret

通过在现有配置资源中增加限制性权限来定义 secret 范围。

除了定义哪些应用程序可以访问特定组件之外,您还可以将命名的 secret 存储组件限制为应用程序的一个或多个 secret。通过定义 allowedSecrets 和/或 deniedSecrets 列表,可以限制应用程序仅访问特定的 secret。

有关配置资源的更多信息:

配置 secret 访问

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可以访问的 secret 键列表
deniedSecretslist不能访问的 secret 键列表

allowedSecrets 列表中存在至少一个元素时,应用程序只能访问列表中定义的那些 secret。

权限优先级

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 存储中所有 secret 的访问

在 Kubernetes 集群中,原生的 Kubernetes secret 存储默认会添加到您的 Dapr 应用程序中。在某些场景中,可能需要拒绝某个应用程序对 Dapr secret 的访问。要添加此配置:

  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 存储中的某些 secret

要允许 Dapr 应用程序仅访问某些 secret,请定义以下 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 列表访问某些 secret。请按照sidecar 配置指南将配置应用到 sidecar。

场景 3:拒绝访问 secret 存储中的某些敏感 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,同时允许访问所有其他 secret。请按照sidecar 配置指南将配置应用到 sidecar。

下一步

服务调用访问控制

3.4 - 操作指南:为服务调用配置应用访问控制列表

限制调用应用程序可以执行的操作

通过访问控制,您可以配置策略,限制调用应用程序在被调用应用程序上通过服务调用可以执行的操作。您可以在配置模式中定义访问控制策略规范,以限制访问:

  • 从特定操作到被调用应用程序,以及
  • 从调用应用程序到HTTP动词。

访问控制策略在配置中指定,并应用于被调用应用程序的Dapr sidecar。对被调用应用程序的访问基于匹配的策略操作。

您可以为所有调用应用程序提供一个默认的全局操作。如果未指定访问控制策略,默认行为是允许所有调用应用程序访问被调用应用程序。

查看访问策略示例。

术语

trustDomain

“信任域”是用于管理信任关系的逻辑分组。每个应用程序都被分配一个信任域,可以在访问控制列表策略规范中指定。如果未定义策略规范或指定了空的信任域,则使用默认值“public”。信任域用于在TLS证书中生成应用程序的身份。

应用程序身份

Dapr请求sentry服务为所有应用程序生成一个SPIFFE ID。此ID附加在TLS证书中。

SPIFFE ID的格式为:**spiffe://\<trustdomain>/ns/\<namespace\>/\<appid\>**

对于匹配策略,从调用应用程序的TLS证书中提取调用应用程序的信任域、命名空间和应用程序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. 全局级别的默认操作

示例场景

以下是使用访问控制列表进行服务调用的一些示例场景。请参阅配置指南以了解应用程序sidecar的可用配置设置。

场景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 sidecar,启用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 sidecar,启用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文件中的拒绝操作。将此操作更改为允许并重新运行应用程序以查看此调用成功。

Kubernetes模式

先决条件

配置Node.js和Python应用程序

您可以创建并应用上述nodeappconfig.yamlpythonappconfig.yaml配置文件,如配置中所述。

例如,下面的Kubernetes Deployment展示了Python应用程序如何在默认命名空间中使用此pythonappconfig配置文件部署到Kubernetes。

对Node.js部署执行相同操作,并查看Python应用程序的日志以查看由于nodeappconfig文件中设置的拒绝操作而导致的调用失败。

将此操作更改为允许并重新部署应用程序以查看此调用成功。

部署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 Sidecar 的 API

选择应用程序可以使用的 Dapr Sidecar API

在零信任网络环境中,或通过前端将 Dapr Sidecar 暴露给外部流量时,建议仅启用应用程序实际使用的 Dapr Sidecar API。这样可以减少潜在的攻击风险,并确保 Dapr API 仅限于应用程序的实际需求。

Dapr 允许您通过使用 Dapr 配置 设置 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

以下示例启用 state 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

以下示例启用 state 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

以下示例禁用 state 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

以下示例禁用 state 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)
健康检查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 SDKs)的完整列表

Dapr 运行时提供了一个 proto 服务,应用程序可以通过 gRPC 与其进行通信。

Dapr 不仅可以通过 gRPC 被调用,还可以通过 gRPC 与应用程序通信。为此,应用程序需要托管一个 gRPC 服务器并实现 Dapr appcallback 服务

配置 Dapr 通过 gRPC 与应用程序通信

在自托管模式下运行时,使用 --app-protocol 标志告诉 Dapr 使用 gRPC 与应用程序通信:

dapr run --app-protocol grpc --app-port 5005 node app.js

这告诉 Dapr 通过端口 5005 使用 gRPC 与您的应用程序通信。

在 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 请求体

如何配置超过 4 MB 的 HTTP 请求体

Dapr 默认限制请求体大小为 4MB。您可以通过以下方法更改此限制:

  • 使用 dapr.io/http-max-request-size 注解,或
  • 使用 --dapr-http-max-request-size 参数。

在自托管模式下运行时,使用 --dapr-http-max-request-size 参数来设置 Dapr 的请求体大小限制:

dapr run --dapr-http-max-request-size 16 node app.js

这将把 Dapr 的最大请求体大小设置为 16 MB。

在 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-max-request-size: "16"
#...

相关链接

Dapr Kubernetes pod 注解规范

下一步

安装 Sidecar 证书

3.8 - 操作指南:处理大型HTTP头部大小

配置更大的HTTP读取缓冲区大小

Dapr的HTTP头部读取缓冲区大小默认限制为4KB。如果您发送的HTTP头部超过4KB,可能会遇到请求头部过大的服务调用错误。

您可以通过以下方法增加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主体请求

3.9 - 操作指南:在Dapr sidecar中安装证书

配置Dapr sidecar容器以信任证书

Dapr sidecar可以通过配置来信任与外部服务通信所需的证书。这在需要信任自签名证书的场景中非常有用,例如:

  • 使用HTTP绑定
  • 为sidecar配置出站代理

支持信任证书颁发机构(CA)证书和叶子证书。

当sidecar作为容器运行时,可以进行以下配置。

  1. 使用卷挂载将证书配置为可用于sidecar容器。
  2. 将sidecar容器中的环境变量SSL_CERT_DIR指向包含证书的目录。

注意: 对于Windows容器,请确保容器以管理员权限运行,以便可以安装证书。

以下示例展示了如何使用Docker Compose在sidecar容器中安装证书(证书位于本地的./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)将证书文件夹挂载到sidecar容器
    environment:
      - "SSL_CERT_DIR=/certificates" # (步骤2)将环境变量设置为证书文件夹的路径
    # 对于Windows容器,取消注释下面的行
    # user: ContainerAdministrator

注意: 当sidecar不在容器内运行时,证书必须直接安装在主机操作系统上。

在Kubernetes上:

  1. 使用卷挂载将证书配置为可用于sidecar容器。
  2. 将sidecar容器中的环境变量SSL_CERT_DIR指向包含证书的目录。

以下示例YAML展示了一个部署:

  • 将pod卷附加到sidecar
  • 设置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)将证书文件夹挂载到sidecar容器
        dapr.io/env: "SSL_CERT_DIR=/tmp/certificates" # (步骤2)将环境变量设置为证书文件夹的路径
    spec:
      volumes:
        - name: certificates-vol
          hostPath:
            path: /certificates
#...

注意: 使用Windows容器时,sidecar容器以管理员权限启动,这是安装证书所需的。这不适用于Linux容器。

完成这些步骤后,SSL_CERT_DIR指向的目录中的所有证书都将被安装。

演示

观看在社区电话64中使用安装SSL证书和安全使用HTTP绑定的演示:

相关链接

下一步

启用预览功能

3.10 - 操作指南:启用预览功能

如何指定和启用预览功能

在 Dapr 中,预览功能在首次发布时被视为实验功能。这些预览功能需要您明确选择启用才能使用。您需要在 Dapr 的配置文件中进行此选择。

预览功能是通过在运行应用程序实例时设置配置来启用的。

配置属性

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

属性类型描述
name字符串启用/禁用的预览功能的名称
enabled布尔值指定功能是否启用或禁用的布尔值

启用预览功能

预览功能需要在配置中指定。以下是一个包含多个功能的完整配置示例:

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 配置是在您运行 dapr init 时创建的,位于:

  • 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 sidecar 配置 Secret 环境变量

将 Kubernetes Secret 中的环境变量注入到 Dapr sidecar

在某些情况下,Dapr sidecar 需要注入环境变量。这可能是因为某个组件、第三方库或模块需要通过环境变量进行配置或自定义行为。这在生产和非生产环境中都很有用。

概述

在 Dapr 1.15 中,引入了新的 dapr.io/env-from-secret 注解,类似于 dapr.io/env。通过这个注解,你可以将环境变量注入到 Dapr sidecar 中,其值来自于一个 secret。

注解格式

注解的格式如下:

  • 单个键的 secret: <ENV_VAR_NAME>=<SECRET_NAME>
  • 多个键/值的 secret: <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 会将两者设置为相同的值。

配置单个键的 secret 环境变量

在以下示例中,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

dapr.io/env-from-secret 注解的值为 "AUTH_TOKEN=auth-headers-secret" 被注入为:

env:
- name: AUTH_TOKEN
  valueFrom:
    secretKeyRef:
      name: auth-headers-secret
      key: auth-headers-secret

这要求 secret 的 namekey 字段具有相同的值,即 “auth-headers-secret”。

示例 secret

注意: 以下示例仅用于演示目的。不建议以明文存储 secret。

apiVersion: v1
kind: Secret
metadata:
  name: auth-headers-secret
type: Opaque
stringData:
  auth-headers-secret: "AUTH=mykey"

配置多个键的 secret 环境变量

在以下示例中,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

dapr.io/env-from-secret 注解的值为 "AUTH_TOKEN=auth-headers-secret:auth-header-value" 被注入为:

env:
- name: AUTH_TOKEN
  valueFrom:
    secretKeyRef:
      name: auth-headers-secret
      key: auth-header-value

示例 secret

注意: 以下示例仅用于演示目的。不建议以明文存储 secret。

apiVersion: v1
kind: Secret
metadata:
  name: auth-headers-secret
type: Opaque
stringData:
  auth-header-value: "AUTH=mykey"

4 - 管理 Dapr 中的组件

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

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

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

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

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

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

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

4.1 - 认证流程

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

概述

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

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

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

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

认证级别

级别如下:

Alpha

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

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

Beta

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

Stable

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

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

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

一致性测试

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

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

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

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

测试要求

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

认证测试

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

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

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

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

测试要求

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

组件认证过程

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

新组件认证:Alpha->Beta

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

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

新组件认证:Beta->Stable

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

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

4.2 - 更新组件

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

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

Kubernetes

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

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

自托管

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

热重载(预览功能)

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

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

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

进一步阅读

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的应用程序提供访问权限,这两个应用程序的ID分别为app1app2,访问名为statestore的Redis组件,该组件本身位于production命名空间中

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

社区电话演示

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

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

使用命名空间进行pub/sub

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

相关链接

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

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

概述

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

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

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

支持的secret存储

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

引用secret

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

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

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

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

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

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

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

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

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

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

示例

引用Kubernetes secret

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

  1. 首先,创建Kubernetes secret:

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

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

    kubectl apply -f ./eventhubs.yaml
    

限制对secret的访问

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

Kubernetes权限

默认命名空间

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

非默认命名空间

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

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

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

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

相关链接

4.5 - 状态存储组件

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

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

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

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

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

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

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

支持的状态存储

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

相关主题

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 部分。尽管元数据值可以包含明文的 secret,建议您通过 secretKeyRef 使用 secret 存储 来管理这些 secret。

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

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

相关链接

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

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

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

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

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



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

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

前提条件

设置 namespace-a

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

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

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

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

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

将资源部署到 namespace-a

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

设置 namespace-b

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

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

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

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

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

kubectl get service -A

确认订阅者接收到消息。

切换回 namespace-a

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

找到 POD 名称:

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

显示日志:

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

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

清理

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

相关链接

4.7 - Secret 存储组件

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

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

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

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

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

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

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

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

应用配置

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

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

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

kubectl apply -f secret-store.yaml

支持的 Secret 存储

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

相关链接

4.8 - Bindings 组件

关于设置 Dapr bindings 组件的指导

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

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

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

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

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

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

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

应用配置

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

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

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

kubectl apply -f mybinding.yaml

支持的 bindings

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

相关链接

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

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

组件注册过程

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

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

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

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

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

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

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

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

运行组件

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

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

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

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

组件发现和多路复用

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

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

定义组件

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

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

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

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

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

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

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

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

运行 Dapr

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

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

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

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

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

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

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

在 Kubernetes 集群上部署 Dapr

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

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

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

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

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

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

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

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

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

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

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

定义组件

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

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

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

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

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

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

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

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

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

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

下一步

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

4.10 - 配置中间件组件

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

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

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

配置 API 中间件管道

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

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

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

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

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

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

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

查看所有中间件组件

配置应用中间件管道

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

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

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

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

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

相关链接

5 - 保护 Dapr 部署

关于如何保护您的 Dapr 应用程序的最佳实践和说明

在使用 Dapr 部署应用程序时,确保安全性至关重要。Dapr 提供了一系列功能和最佳实践,帮助开发者保护他们的应用程序。这些功能包括身份验证、授权、数据加密以及安全的通信协议。

首先,身份验证是确保只有授权用户和服务可以访问您的 Dapr 应用程序的关键步骤。Dapr 支持多种身份验证机制,包括 OAuth 和 API 密钥。通过配置这些机制,您可以有效地控制对应用程序的访问。

其次,授权是在用户或服务通过身份验证后,确定其可以执行哪些操作。Dapr 提供了详细的权限控制,允许您定义不同角色和权限,以确保用户只能访问他们被授权的资源。

数据加密是保护敏感信息的另一重要措施。Dapr 支持在传输和存储过程中对数据进行加密。即使数据被截获,未授权用户也无法读取。

最后,Dapr 使用安全的通信协议来保护数据在网络中的传输。通过采用 HTTPS 和其他加密协议,Dapr 确保数据在传输过程中不会被窃听或篡改。

通过遵循这些最佳实践,您可以显著提高 Dapr 应用程序的安全性,保护您的数据和服务免受潜在威胁。

5.1 - 设置和配置 mTLS 证书

使用自签名或用户提供的 x.509 证书加密应用程序之间的通信

Dapr 支持通过 Dapr 控制平面的 Sentry 服务对 Dapr 实例之间的通信进行传输加密。Sentry 服务是一个中央证书颁发机构 (CA)。

Dapr 允许操作员和开发人员使用自己的证书,或者让 Dapr 自动创建并保存自签名的根证书和颁发者证书。

有关 mTLS 的详细信息,请阅读安全概念部分

如果没有提供自定义证书,Dapr 会自动创建并保存有效期为一年的自签名证书。 在 Kubernetes 中,证书会保存到 Dapr 系统 pod 所在命名空间的 secret 中,仅对它们可访问。 在自托管模式中,证书会保存到磁盘。

控制平面 Sentry 服务配置

mTLS 设置位于 Dapr 控制平面配置文件中。例如,当您将 Dapr 控制平面部署到 Kubernetes 时,此配置文件会自动创建,然后您可以编辑它。以下文件显示了在 daprsystem 命名空间中部署的配置资源中可用的 mTLS 设置:

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 CLI 使用 dapr init --kubernetes 安装。

您可以使用以下命令查看控制平面配置资源:

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 注入器服务不需要重新部署

使用 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. 清除现有的 Dapr 信任包 secret,将以下 YAML 保存到文件(例如 clear-trust-bundle.yaml)并应用此 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 信任包。
kubectl rollout restart deploy/dapr-operator -n <DAPR_NAMESPACE>
kubectl rollout restart statefulsets/dapr-placement-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-sentry            dapr-system  True     Running  1         1.7.0     17d  2022-03-15 09:29.45
  dapr-dashboard         dapr-system  True     Running  1         0.9.0     17d  2022-03-15 09:29.45
  dapr-sidecar-injector  dapr-system  True     Running  1         1.7.0     17d  2022-03-15 09:29.45
  dapr-operator          dapr-system  True     Running  1         1.7.0     17d  2022-03-15 09:29.45
  dapr-placement-server  dapr-system  True     Running  1         1.7.0     17d  2022-03-15 09:29.45
⚠  Dapr root certificate of your Kubernetes cluster expires in 2 days. Expiry date: Mon, 04 Apr 2022 15:01:03 UTC.
 请参阅 docs.dapr.io 以获取证书更新说明,以避免服务中断。

自托管

运行控制平面 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 绑定服务帐户机制。 此验证器检查绑定服务帐户令牌以确保其合法性。

Sentry 服务可以配置为:

  • 启用除 Kubernetes 绑定服务帐户验证器之外的额外令牌验证器
  • 替换自托管模式下默认启用的 insecure 验证器

Sentry 令牌验证器用于将额外的非 Kubernetes 客户端加入到以 Kubernetes 模式运行的 Dapr 集群中,或替换自托管模式下的不安全“允许所有”验证器以启用适当的身份验证。 除非您使用的是特殊的部署场景,否则不需要配置令牌验证器。

当前唯一支持的令牌验证器是 jwks 验证器。

JWKS

jwks 验证器使 Sentry 服务能够使用 JWKS 端点验证 JWT 令牌。 令牌的内容_必须_包含与 Dapr 客户端的 SPIFFE 身份匹配的 sub 声明,格式为 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 配置端点授权

为您的 Web API 启用应用程序端点的 OAuth 授权

Dapr 的 OAuth 2.0 中间件允许您在 Dapr 端点上为 Web API 启用 OAuth 授权,支持 授权码模式。您还可以将授权令牌注入到端点 API 中,这些令牌可用于通过 客户端凭证模式对 API 调用的外部 API 进行授权。启用中间件后,所有通过 Dapr 的方法调用在传递给用户代码之前都需要进行授权。

这两种模式的主要区别在于,授权码模式需要用户交互并授权用户,而客户端凭证模式不需要用户交互,授权的是服务或应用程序。

在授权服务器上注册您的应用程序

不同的授权服务器提供不同的应用程序注册体验。以下是一些示例:

要配置 Dapr OAuth 中间件,您需要收集以下信息:

  • 客户端 ID (参见 这里)
  • 客户端密钥 (参见 这里)
  • 范围 (参见 这里)
  • 授权 URL
  • 令牌 URL

一些流行的授权服务器的授权/令牌 URL:

服务器授权 URL令牌 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>"
  - 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>"
  - 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 规范中添加一个 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/ 端点),如果未找到访问令牌,客户端将被重定向到授权同意页面。否则,访问令牌将写入 authHeaderName 头中,供应用程序代码使用。

客户端凭证模式

配置完成后,每当客户端尝试通过 Dapr sidecar 调用 API 方法时(例如调用 v1.0/invoke/ 端点),如果未找到现有的有效令牌,将检索一个新的访问令牌。访问令牌将写入 headerName 头中,供应用程序代码使用。这样,应用程序可以在调用请求该令牌的外部 API 时在授权头中转发令牌。

5.3 - 在 Dapr 中启用 API 令牌认证

要求每个传入的 Dapr API 请求在通过之前包含一个认证令牌

默认情况下,Dapr 通过网络边界限制对其公共 API 的访问。如果您计划在该边界之外公开 Dapr API,或者您的部署需要额外的安全级别,请考虑为 Dapr API 启用令牌认证。这意味着 Dapr 将要求每个传入的 gRPC 和 HTTP 请求在通过之前包含认证令牌。

创建令牌

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 secret 存储来保存共享令牌。要配置 Dapr API 认证,首先创建一个新的 secret:

kubectl create secret generic dapr-api-token --from-literal=token=<token>

注意,您需要在每个希望启用 Dapr 令牌认证的命名空间中创建上述 secret。

要指示 Dapr 使用该 secret 来保护其公共 API,请在您的 Deployment 模板规范中添加一个注释:

annotations:
  dapr.io/enabled: "true"
  dapr.io/api-token-secret: "dapr-api-token" # Kubernetes secret 的名称

部署时,Dapr sidecar 注入器将自动创建一个 secret 引用并将实际值注入 DAPR_API_TOKEN 环境变量。

更新令牌

自托管

要在自托管中更新配置的令牌,请将 DAPR_API_TOKEN 环境变量更新为新值并重新启动 daprd 进程。

Kubernetes

要在 Kubernetes 中更新配置的令牌,请在每个命名空间中使用新令牌更新先前创建的 secret。您可以使用 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>

假设您的服务配置了多个副本,密钥更新过程不会导致任何停机时间。

向客户端 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 中,建议将 secret 挂载到您的 pod 作为环境变量,如下例所示,其中名为 dapr-api-token 的 Kubernetes secret 用于保存令牌。

containers:
  - name: mycontainer
    image: myregistry/myapp
    envFrom:
    - secretRef:
      name: dapr-api-token

自托管

在自托管模式下,您可以将令牌设置为应用的环境变量:

export DAPR_API_TOKEN=<my-dapr-token>

相关链接

5.4 - 使用令牌认证对Dapr请求进行身份验证

要求每个来自Dapr的API请求都包含一个认证令牌

对于一些构建块,例如pubsub、service-invocation和输入bindings,Dapr与应用程序通过HTTP或gRPC进行通信。 为了让应用程序能够验证来自Dapr sidecar的请求,您可以配置Dapr在HTTP请求的头部或gRPC请求的元数据中发送一个API令牌。

创建令牌

Dapr使用共享令牌进行API认证。您可以自由定义API令牌。

虽然Dapr对共享令牌没有强制格式,但一个好的做法是生成一个随机字节序列并将其编码为Base64。例如,这个命令生成一个随机的32字节密钥并将其编码为Base64:

openssl rand 16 | base64

在Dapr中配置应用API令牌认证

令牌认证配置在Kubernetes或selfhosted Dapr部署中略有不同:

Selfhosted

在selfhosted场景中,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模板规范中添加一个注解:

annotations:
  dapr.io/enabled: "true"
  dapr.io/app-token-secret: "app-api-token" # Kubernetes secret的名称

部署时,Dapr Sidecar Injector会自动创建一个secret引用并将实际值注入到APP_API_TOKEN环境变量中。

轮换令牌

Selfhosted

要在selfhosted中更新配置的令牌,修改APP_API_TOKEN环境变量为新值并重启daprd进程。

Kubernetes

要在Kubernetes中更新配置的令牌,修改之前创建的secret中的新令牌在每个命名空间中。您可以使用kubectl patch命令来完成此操作,但更简单的方法是使用清单更新这些:

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 sidecar在调用应用程序时总是会在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

Selfhosted

在selfhosted模式中,您可以将令牌设置为应用程序的环境变量:

export APP_API_TOKEN=<my-app-token>

相关链接

6 - 通过弹性策略实现错误恢复

了解如何配置和定制 Dapr 的错误重试、超时设置和断路保护机制

6.1 - 概述

配置 Dapr 的重试、超时和断路器

Dapr 提供了一种通过弹性规范来定义和应用容错策略的功能。弹性规范与组件规范存放在同一位置,并在 Dapr sidecar 启动时生效。sidecar 决定如何将这些策略应用于您的 Dapr API 调用。在自托管模式下,弹性规范文件必须命名为 resiliency.yaml。在 Kubernetes 中,Dapr 会找到您的应用程序使用的命名弹性规范。在弹性规范中,您可以定义常见的弹性模式策略,例如:

这些策略可以应用于目标,包括:

此外,弹性策略还可以限定到特定应用程序

演示视频

了解更多关于如何使用 Dapr 编写弹性微服务

弹性策略结构

以下是弹性策略的一般结构:

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:
      general: 5s
      important: 60s
      largeResponse: 10s

    # 重试是重试配置的命名模板,并在操作的生命周期内实例化。
    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

    # 断路器会自动为每个组件和应用实例创建。
    # 断路器维护的计数器在 Dapr sidecar 运行期间存在。它们不会被持久化。
    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 仅适用于从 sidecar 到应用程序的传递
          timeout: general
          retry: important
          circuitBreaker: pubsubCB

相关链接

观看此视频以了解如何使用弹性

下一步

了解更多关于弹性策略和目标:

6.2 - 弹性策略

配置超时、重试和断路器的弹性策略

policies 下定义超时、重试和断路器策略。每个策略都有一个名称,以便您可以在弹性规范的 targets 部分中引用它们。

注意:Dapr 为某些 API 提供默认的重试机制。请参阅此处了解如何使用用户定义的重试策略覆盖默认重试逻辑。

超时

超时是可选策略,用于提前终止长时间运行的操作。如果超过了超时时间:

  • 正在进行的操作将被终止(如果可能)。
  • 返回错误。

有效值是 Go 的 time.ParseDuration 接受的格式,例如:15s2m1h30m。超时没有设置最大值。

示例:

spec:
  policies:
    # 超时是简单的命名持续时间。
    timeouts:
      general: 5s
      important: 60s
      largeResponse: 10s

如果未指定超时值,则策略不会强制执行时间限制,默认使用请求客户端设置的任何值。

重试

通过 retries,您可以为失败的操作定义重试策略,包括由于触发定义的超时或断路器策略而失败的请求。

以下重试选项是可配置的:

重试选项描述
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>
示例:“1,501-503”
默认:空字符串 "" 或字段未设置。重试所有 gRPC 错误。

指数退避窗口使用以下公式:

BackOffDuration = PreviousBackOffDuration * (随机值从 0.5 到 1.5) * 1.5
if BackOffDuration > maxInterval {
  BackoffDuration = maxInterval
}

示例:

spec:
  policies:
    # 重试是重试配置的命名模板,并在操作的生命周期内实例化。
    retries:
      pubsubRetry:
        policy: constant
        duration: 5s
        maxRetries: 10

      retryForever:
        policy: exponential
        maxInterval: 15s
        maxRetries: -1 # 无限重试

示例 2:

spec:
  policies:
    retries:
      retry5xxOnly:
        policy: constant
        duration: 5s
        maxRetries: 3
        matching:
          httpStatusCodes: "429,500-599" # 重试此范围内的 HTTP 状态代码。所有其他不重试。
          gRPCStatusCodes: "1-4,8-11,13,14" # 重试这些范围内的 gRPC 状态代码并分隔单个代码。

断路器

断路器(CB)策略用于当其他应用程序/服务/组件经历较高的失败率时。CB 监控请求,并在满足某个条件时关闭所有流向受影响服务的流量(“打开”状态)。通过这样做,CB 给服务时间从其故障中恢复,而不是用事件淹没它。CB 还可以允许部分流量通过,以查看系统是否已恢复(“半开”状态)。一旦请求恢复成功,CB 进入“关闭”状态并允许流量完全恢复。

重试选项描述
maxRequests在 CB 半开(从故障中恢复)时允许通过的最大请求数。默认为 1
intervalCB 用于清除其内部计数的周期性时间段。如果设置为 0 秒,则永不清除。默认为 0s
timeout开放状态(直接在故障后)到 CB 切换到半开的时间段。默认为 60s
trip由 CB 评估的 通用表达式语言(CEL) 语句。当语句评估为 true 时,CB 触发并变为打开。默认为 consecutiveFailures > 5。其他可能的值是 requeststotalFailures,其中 requests 表示电路打开之前的成功或失败调用次数,totalFailures 表示电路打开之前的总失败尝试次数(不一定是连续的)。示例:requests > 5totalFailures >3

示例:

spec:
  policies:
    circuitBreakers:
      pubsubCB:
        maxRequests: 1
        interval: 8s
        timeout: 45s
        trip: consecutiveFailures > 8

覆盖默认重试

Dapr 为任何不成功的请求(如失败和瞬态错误)提供默认重试。在弹性规范中,您可以通过定义具有保留名称关键字的策略来覆盖 Dapr 的默认重试逻辑。例如,定义名为 DaprBuiltInServiceRetries 的策略,覆盖通过服务到服务请求的 sidecar 之间的失败的默认重试。策略覆盖不适用于特定目标。

注意:尽管您可以使用更强大的重试覆盖默认值,但您不能使用比提供的默认值更低的值覆盖,或完全删除默认重试。这可以防止意外停机。

下面是描述 Dapr 默认重试和覆盖它们的策略关键字的表格:

功能覆盖关键字默认重试行为描述
服务调用DaprBuiltInServiceRetries每次调用重试以 1 秒的退避间隔执行,最多达到 3 次的阈值。sidecar 到 sidecar 请求(服务调用方法调用)失败并导致 gRPC 代码 UnavailableUnauthenticated
actorDaprBuiltInActorRetries每次调用重试以 1 秒的退避间隔执行,最多达到 3 次的阈值。sidecar 到 sidecar 请求(actor 方法调用)失败并导致 gRPC 代码 UnavailableUnauthenticated
actor 提醒DaprBuiltInActorReminderRetries每次调用重试以指数退避执行,初始间隔为 500ms,最多 60s,持续 15 分钟请求失败将 actor 提醒持久化到状态存储
初始化重试DaprBuiltInInitializationRetries每次调用重试 3 次,指数退避,初始间隔为 500ms,持续 10s向应用程序发出请求以检索给定规范时的失败。例如,无法检索订阅、组件或弹性规范

下面的弹性规范示例显示了使用保留名称关键字 ‘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

设置默认策略

在弹性中,您可以设置默认策略,这些策略具有广泛的范围。这是通过保留关键字完成的,这些关键字让 Dapr 知道何时应用策略。有 3 种默认策略类型:

  • DefaultRetryPolicy
  • DefaultTimeoutPolicy
  • DefaultCircuitBreakerPolicy

如果定义了这些策略,它们将用于服务、应用程序或组件的每个操作。它们还可以通过附加其他关键字进行更具体的修改。特定策略遵循以下模式,Default%sRetryPolicyDefault%sTimeoutPolicyDefault%sCircuitBreakerPolicy。其中 %s 被策略的目标替换。

下面是所有可能的默认策略关键字及其如何转换为策略名称的表格。

关键字目标操作示例策略名称
App服务调用。DefaultAppRetryPolicy
Actoractor 调用。DefaultActorTimeoutPolicy
Component所有组件操作。DefaultComponentCircuitBreakerPolicy
ComponentInbound所有入站组件操作。DefaultComponentInboundRetryPolicy
ComponentOutbound所有出站组件操作。DefaultComponentOutboundTimeoutPolicy
StatestoreComponentOutbound所有状态存储组件操作。DefaultStatestoreComponentOutboundCircuitBreakerPolicy
PubsubComponentOutbound所有出站 pubsub(发布)组件操作。DefaultPubsubComponentOutboundRetryPolicy
PubsubComponentInbound所有入站 pubsub(订阅)组件操作。DefaultPubsubComponentInboundTimeoutPolicy
BindingComponentOutbound所有出站绑定(调用)组件操作。DefaultBindingComponentOutboundCircuitBreakerPolicy
BindingComponentInbound所有入站绑定(读取)组件操作。DefaultBindingComponentInboundRetryPolicy
SecretstoreComponentOutbound所有 secretstore 组件操作。DefaultSecretstoreComponentTimeoutPolicy
ConfigurationComponentOutbound所有配置组件操作。DefaultConfigurationComponentOutboundCircuitBreakerPolicy
LockComponentOutbound所有锁组件操作。DefaultLockComponentOutboundRetryPolicy

策略层次结构解析

如果正在执行的操作与策略类型匹配,并且没有更具体的策略针对它,则应用默认策略。对于每个目标类型(应用程序、actor 和组件),优先级最高的策略是命名策略,即专门针对该构造的策略。

如果不存在,则策略从最具体到最广泛应用。

默认策略和内置重试如何协同工作

在 [内置重试](https://v1-16.docs.dapr.io/zh-hans/operations/resiliency/policies/#Override Default Retries) 的情况下,默认策略不会阻止内置重试策略运行。两者一起使用,但仅在特定情况下。

对于服务和 actor 调用,内置重试专门处理连接到远程 sidecar 的问题(如有必要)。由于这些对于 Dapr 运行时的稳定性至关重要,因此它们不会被禁用除非为操作专门引用了命名策略。在某些情况下,可能会有来自内置重试和默认重试策略的额外重试,但这可以防止过于弱的默认策略降低 sidecar 的可用性/成功率。

应用程序的策略解析层次结构,从最具体到最广泛:

  1. 应用程序目标中的命名策略
  2. 默认应用程序策略 / 内置服务重试
  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
  • CosmosDB 状态存储: actorstore

actor:

  • EventActor
  • SummaryActor

下面是使用默认和命名策略的策略,并将其应用于目标。

spec:
  policies:
    retries:
      # 全局重试策略
      DefaultRetryPolicy:
        policy: constant
        duration: 1s
        maxRetries: 3
      
      # 应用程序的全局重试策略
      DefaultAppRetryPolicy:
        policy: constant
        duration: 100ms
        maxRetries: 5

      # actor 的全局重试策略
      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。当sidecar之间的通信出现故障时,这些策略将被调用,如下图所示。

Dapr提供了内置的服务调用重试,因此任何应用的retry策略都是额外的。

显示服务调用弹性的图示

应用于目标应用程序app-id为"appB"的策略示例:

specs:
  targets:
    apps:
      appB: # 目标服务的app-id
        timeout: general
        retry: general
        circuitBreaker: general

组件

使用components目标,您可以将retrytimeoutcircuitBreaker策略应用于组件操作。

策略可以应用于outbound操作(从Dapr sidecar到组件的调用)和/或inbound(从sidecar到您的应用程序的调用)。

出站

outbound操作是从sidecar到组件的调用,例如:

  • 持久化或检索状态。
  • 在pubsub组件上发布消息。
  • 调用输出绑定。

某些组件可能具有内置的重试功能,并且可以在每个组件的基础上进行配置。

显示服务调用弹性的图示
spec:
  targets:
    components:
      myStateStore:
        outbound:
          retry: retryForever
          circuitBreaker: simpleCB
入站

inbound操作是从sidecar到您的应用程序的调用,例如:

  • pubsub订阅在传递消息时。
  • 输入绑定。

某些组件可能具有内置的重试功能,并且可以在每个组件的基础上进行配置。

显示服务调用弹性的图示
spec:
  targets:
    components:
      myInputBinding:
        inbound: 
          timeout: general
          retry: general
          circuitBreaker: general
PubSub

在pubsub target/component中,您可以同时指定inboundoutbound操作。

显示服务调用弹性的图示
spec:
  targets:
    components:
      myPubsub:
        outbound:
          retry: pubsubRetry
          circuitBreaker: pubsubCB
        inbound: # 入站仅适用于从sidecar到应用程序的传递
          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 - 健康检查

如何为Dapr sidecar及您的应用程序进行健康检查设置

6.4.1 - 应用健康检查

响应应用健康状态的变化

应用健康检查功能可以检测应用程序的健康状况,并对状态变化做出反应。

应用程序可能由于多种原因变得无响应。例如,您的应用程序:

  • 可能太忙而无法接受新工作;
  • 可能已崩溃;或
  • 可能处于死锁状态。

有时这种情况可能是暂时的,例如:

  • 如果应用程序只是忙碌,最终会恢复接受新工作
  • 如果应用程序因某种原因正在重启并处于初始化阶段

应用健康检查默认情况下是禁用的。一旦启用,Dapr 运行时(sidecar)会通过 HTTP 或 gRPC 调用定期轮询您的应用程序。当检测到应用程序的健康状况出现问题时,Dapr 会通过以下方式暂停接受新工作:

  • 取消所有 pub/sub 订阅
  • 停止所有输入绑定
  • 短路所有服务调用请求,这些请求在 Dapr 运行时终止,不会转发到应用程序

这些变化是暂时的,一旦 Dapr 检测到应用程序恢复响应,它将恢复正常操作。

显示应用健康功能的图示。启用应用健康的 Dapr 运行时会定期探测应用程序的健康状况。

应用健康检查与平台级健康检查

Dapr 的应用健康检查旨在补充而不是替代任何平台级健康检查,例如在 Kubernetes 上运行时的存活探针

平台级健康检查(或存活探针)通常确保应用程序正在运行,并在出现故障时导致平台重启应用程序。

与平台级健康检查不同,Dapr 的应用健康检查专注于暂停当前无法接受工作的应用程序,但预计最终能够恢复接受工作。目标包括:

  • 不给已经超载的应用程序带来更多负担。
  • 当 Dapr 知道应用程序无法处理消息时,不从队列、绑定或 pub/sub 代理中获取消息。

在这方面,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 明文)。http

健康检查路径

HTTP

当使用 HTTP(包括 httphttpsh2c)作为 app-protocol 时,Dapr 通过对 app-health-check-path 指定的路径进行 HTTP 调用来执行健康探测,默认路径为 /health

为了使您的应用被视为健康,响应必须具有 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 会等待成功的健康探测,然后才认为应用程序是健康的。这意味着在第一次健康检查完成并成功之前,pub/sub 订阅、输入绑定和服务调用请求不会为您的应用程序启用。

如果应用程序在 app-health-probe-timeout 中配置的超时内发送成功响应(如上所述),则健康探测请求被视为成功。默认值为 500,对应于 500 毫秒(半秒)。

阈值

在 Dapr 认为应用程序进入不健康状态之前,它将等待 app-health-threshold 次连续失败,默认值为 3。此默认值意味着您的应用程序必须连续失败健康探测 3 次才能被视为不健康。

如果您将阈值设置为 1,任何失败都会导致 Dapr 假设您的应用程序不健康,并停止向其传递工作。

大于 1 的阈值可以帮助排除由于外部情况导致的瞬态故障。适合您的应用程序的正确值取决于您的要求。

阈值仅适用于失败。单个成功响应足以让 Dapr 认为您的应用程序是健康的,并恢复正常操作。

示例

使用 dapr run 命令的 CLI 标志启用应用健康检查:

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 - Sidecar 健康检查

Dapr sidecar 健康检查

Dapr 提供了一种方法,通过 HTTP /healthz 端点 来确定其健康状态。通过这个端点,daprd 进程或 sidecar 可以:

  • 检查整体健康状况
  • 在初始化期间确认 Dapr sidecar 的就绪状态
  • 在 Kubernetes 中确定就绪和存活状态

在本指南中,您将了解 Dapr /healthz 端点如何与应用托管平台(如 Kubernetes)以及 Dapr SDK 的健康检查功能集成。

下图展示了 Dapr sidecar 启动时,healthz 端点和应用通道初始化的步骤。

Dapr 检查出站健康连接的图示。

出站健康端点

如上图中的红色边界线所示,v1.0/healthz/ 端点用于等待以下情况:

  • 所有组件已初始化;
  • Dapr HTTP 端口可用;并且,
  • 应用通道已初始化。

这用于确认 Dapr sidecar 的完整初始化及其健康状况。

您可以通过设置 DAPR_HEALTH_TIMEOUT 环境变量来控制健康检查的超时时间,这在高延迟环境中可能很重要。

另一方面,如上图中的绿色边界线所示,当 v1.0/healthz/outbound 端点返回成功时:

  • 所有组件已初始化;
  • Dapr HTTP 端口可用;但,
  • 应用通道尚未建立。

在 Dapr SDK 中,waitForSidecar/wait_until_ready 方法(取决于您使用的 SDK)用于通过 v1.0/healthz/outbound 端点进行此特定检查。使用这种方法,您的应用程序可以在应用通道初始化之前调用 Dapr sidecar API,例如,通过 secret API 读取 secret。

如果您在 SDK 上使用 waitForSidecar/wait_until_ready 方法,则会执行正确的初始化。否则,您可以在初始化期间调用 v1.0/healthz/outbound 端点,如果成功,您可以调用 Dapr sidecar 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 被用作 Kubernetes 服务的后端。当 pod 未就绪时,它会从 Kubernetes 服务负载均衡器中移除。

如何在 Kubernetes 中配置就绪探针

就绪探针的配置与存活探针类似。唯一的区别是使用 readinessProbe 字段而不是 livenessProbe 字段:

    readinessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 3
      periodSeconds: 3

Sidecar 注入器

在与 Kubernetes 集成时,Dapr sidecar 被注入了一个 Kubernetes 探针配置,告诉它使用 Dapr healthz 端点。这是由 “Sidecar 注入器” 系统服务完成的。与 kubelet 的集成如下面的图示所示。

Dapr 服务交互的图示

Dapr sidecar 健康端点如何与 Kubernetes 配置

如上所述,此配置由 Sidecar 注入器服务自动完成。本节描述了在存活和就绪探针上设置的具体值。

Dapr 在端口 3500 上有其 HTTP 健康端点 /v1.0/healthz。这可以与 Kubernetes 一起用于就绪和存活探针。当 Dapr sidecar 被注入时,存活和就绪探针在 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

注释和参数指南 中了解更多关于这些及其使用方法。

相关链接

7 - 支持和版本控制

Dapr 的技术支持和版本控制方案

7.1 - 版本控制政策

Dapr 的版本控制政策

介绍

Dapr 通过版本控制方案为未来的运行时、API 和组件的变化做好了设计。本主题描述了 API、组件和 Github 仓库的版本控制方案和策略。

版本控制

版本控制是为计算机软件的每个独特状态分配唯一版本名称或版本号的过程。

  • 版本控制提供兼容性、明确的变更控制,并处理变更,尤其是重大变更。
  • Dapr 力求保持向后兼容性。如果需要重大变更,将会提前宣布
  • 废弃的功能将在多个版本中逐步淘汰,新旧功能将并行工作。

版本控制涉及以下 Dapr 仓库:dapr、CLI、稳定语言 SDK、dashboard、components-contrib、quickstarts、helm-charts 和文档。

Dapr 具有以下版本控制方案:

  • Dapr HTTP API 采用 MAJOR.MINOR 版本控制
  • Dapr GRPC API 采用 MAJOR 版本控制
  • 发布版本(包括 GitHub 仓库中的 dapr、CLI、SDK 和 Helm Chart)采用 MAJOR.MINOR.PATCH 版本控制
  • 文档和 Quickstarts 仓库与 Dapr 运行时仓库版本控制一致。
  • Dapr 组件 在 components-contrib GitHub 仓库中采用 MAJOR 版本控制。
  • Dapr 清单 采用 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),因为补丁和非破坏性更改会添加到最新的主版本中。当组件接口中存在非向后兼容的更改时,例如更改 State Store 接口中的现有方法,版本会递增。

components-contrib 仓库发布是所有内部组件的统一版本。也就是说,components-contrib 仓库发布的版本由其内部所有组件的模式组成。如果没有组件更改,Dapr 的新版本并不意味着 components-contrib 有新的发布。

注意:组件具有生产使用生命周期状态:Alpha、Beta 和 Stable。这些状态与其版本控制无关。支持的组件表显示了它们的版本和状态。

有关组件版本控制的更多信息,请阅读组件的版本 2 及以后

组件模式

组件 YAML 的版本控制有两种形式:

  • 组件清单的版本控制。apiVersion
  • 组件实现的版本。.spec.version

组件清单在 .spec.metadata 字段中包含实现的模式,.type 字段表示实现

请参阅下面示例中的注释:

apiVersion: dapr.io/v1alpha1 # <-- 这是组件清单的版本
kind: Component
metadata:
  name: pubsub
spec:
  version: v1 # <-- 这是 pubsub.redis 模式实现的版本
  type: pubsub.redis
  metadata:
  - name: redisHost
    value: redis-master:6379
  - name: redisPassword
    value: general-kenobi

组件清单版本

组件 YAML 清单的版本为 dapr.io/v1alpha1

组件实现版本

组件实现的版本由示例中的 .spec.version 字段确定。.spec.version 字段在模式实例中是必需的,如果不存在,该组件将无法加载。在 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版本开始,Dapr支持三个版本:当前版本和之前的两个版本。通常这些是MINOR版本更新。这意味着支持版本的动态窗口会向前移动,您有责任保持这些支持版本的最新状态。如果您使用较旧版本的Dapr,可能需要进行中间升级以达到支持的版本。

在major.minor版本发布之间至少有13周(3个月)的时间,给用户至少9个月的时间从不支持的版本进行升级。有关发布过程的更多详细信息,请阅读发布周期和节奏

补丁支持适用于当前和之前的支持版本。

构建变体

Dapr的sidecar镜像被发布到GitHub容器注册表Docker注册表。默认镜像包含所有组件。从1.11版本开始,Dapr还提供了仅包含稳定组件的sidecar镜像变体。

  • 默认sidecar镜像:daprio/daprd:<version>ghcr.io/dapr/daprd:<version>(例如ghcr.io/dapr/daprd:1.11.1
  • 稳定组件的sidecar镜像:daprio/daprd:<version>-stablecomponentsghcr.io/dapr/daprd:<version>-stablecomponents(例如ghcr.io/dapr/daprd:1.11.1-stablecomponents

在Kubernetes上,可以通过dapr.io/sidecar-image注释覆盖应用程序部署资源的sidecar镜像。有关更多信息,请参阅Dapr的参数和注释。如果未指定,则使用默认的’daprio/daprd:latest’镜像。

了解更多关于Dapr组件的认证生命周期

支持的版本

下表显示了已一起测试并形成“打包”发布的Dapr版本。任何其他版本组合都不受支持。

发布日期运行时CLISDKs仪表板状态发布说明
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运行时的测试升级路径。任何其他升级组合都没有经过测试。

有关升级的一般指导可以在selfhost模式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.2N/A1.14.2

在托管平台上升级

Dapr可以支持多个生产托管平台。在1.0版本发布时,支持的两个平台是Kubernetes和物理机。有关Kubernetes升级,请参阅Kubernetes上的生产指南

依赖项的支持版本

以下是最新版本的Dapr(v1.15.5)已测试的软件列表。

依赖项支持的版本
KubernetesDapr对Kubernetes的支持与Kubernetes版本偏差策略保持一致
Open Telemetry collector (OTEL)v0.101.0
Prometheusv2.28

相关链接

7.3 - 重大变更和弃用

处理重大变更和弃用

重大变更

重大变更是指对以下内容的修改,这些修改可能导致现有的第三方应用程序或脚本在升级到下一个稳定的小版本的 Dapr 工件(如 SDK、CLI、runtime 等)后出现编译错误或运行时问题:

  • 代码行为
  • 架构
  • 默认配置值
  • 命令行参数
  • 发布的指标
  • Kubernetes 资源模板
  • 公开访问的 API
  • 公开可见的 SDK 接口、方法、类或属性

以下情况可以立即应用重大变更:

  • 版本未达到 1.0.0 的项目
  • 预览功能
  • Alpha API
  • SDK 中的预览或 Alpha 接口、类、方法或属性
  • 处于 Alpha 或 Beta 阶段的 Dapr 组件
  • github.com/dapr/components-contrib 的接口
  • 文档和博客中的 URL
  • 例外情况,需要修复关键错误或安全漏洞。

应用重大变更的流程

应用重大变更需要遵循以下流程:

  1. 弃用通知必须作为发布的一部分进行发布。
  2. 重大变更将在弃用公告发布后的两个版本后生效。
    • 例如,功能 X 在 1.0.0 版本说明中宣布弃用,然后将在 1.2.0 中移除。

弃用

弃用可以应用于:

  1. API,包括 alpha API
  2. 预览功能
  3. 组件
  4. CLI
  5. 可能导致安全漏洞的功能

弃用信息会在发布说明中名为“弃用”的部分中列出,说明:

  • 当前弃用的功能将在未来某个版本中不再受支持。例如,发布 x.y.z。这至少是在两个版本之前。
  • 在发布说明中记录用户需要采取的任何步骤以修改其代码、操作等(如果适用)。

在宣布未来的重大变更后,该变更将在 2 个版本或 6 个月后生效,以较长者为准。弃用的功能应响应警告,但除此之外不执行任何操作。

已宣布的弃用

功能弃用公告移除
GET /v1.0/shutdown API(用户应使用 POST API 代替)1.2.01.4.0
Java 域构建器类已弃用(用户应使用 setters 代替)Java SDK 1.3.0Java SDK 1.5.0
当未指定内容类型时,服务调用将不再提供默认的 application/json 内容类型头。如果您的调用应用程序依赖于此头,则必须明确 设置内容类型头1.7.01.9.0
使用 invoke 方法的 gRPC 服务调用已弃用。请改用代理模式服务调用。请参阅 How-To: Invoke services using gRPC 以使用代理模式。1.9.01.10.0
CLI 标志 --app-ssl(在 Dapr CLI 和 daprd 中)已弃用,建议使用 --app-protocol,值为 httpsgrpcsdaprd:6158 cli:12671.11.01.13.0
Hazelcast PubSub 组件1.9.01.11.0
Twitter Binding 组件1.10.01.11.0
NATS Streaming PubSub 组件1.11.01.13.0
Workflows API Alpha1 /v1.0-alpha1/workflows 被弃用,建议使用 Workflow Client1.15.01.17.0

相关链接

7.4 - 报告安全问题

如何向 Dapr 维护者报告安全问题或漏洞。

Dapr 项目和维护者将安全性视为操作和设计软件的核心关注点。从 Dapr 二进制文件到 GitHub 发布流程,我们采取了多种措施以确保用户应用程序和数据的安全。有关 Dapr 安全功能的更多信息,请访问安全页面

涵盖的存储库和问题

提到“Dapr 中的安全漏洞”时,指的是dapr GitHub 组织下任何存储库中的安全问题。

此报告流程仅适用于 Dapr 项目本身的安全问题,不适用于使用 Dapr 的应用程序或不影响安全性的问题。

如果问题无法通过对上述涵盖的存储库之一的更改来解决,建议在适当的存储库中创建 GitHub 问题或在 Discord 中提出问题。

**如果您不确定,**请谨慎行事,在通过 GitHub、Discord 或其他渠道提出问题之前,使用报告流程进行联系。

明确不涵盖:漏洞扫描器报告

我们不接受仅仅是从漏洞扫描工具复制粘贴输出的报告,除非已经专门确认工具报告的漏洞确实存在于 Dapr 中,包括 CLI、Dapr SDKs、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:状态存储、pub/sub、bindingsN/A可插拔组件概念v1.9
Kubernetes 的多应用运行从单个配置文件配置多个 Dapr 应用程序,并在 Kubernetes 上通过单个命令运行dapr run -k -f多应用运行v1.12
工作流将工作流作为代码编写,以在应用程序中自动化和编排任务,如消息传递、状态管理和故障处理N/A工作流概念v1.10
加密加密或解密数据而无需管理密钥N/A加密概念v1.11
actor 状态 TTL允许 actor 将记录保存到状态存储中,并设置生存时间 (TTL) 以自动清理旧数据。在当前实现中,带有 TTL 的 actor 状态可能无法被客户端正确反映。请阅读 actor 状态事务 以获取更多信息。ActorStateTTLactor 状态事务v1.11
组件热重载允许 Dapr 加载的组件进行“热重载”。当在 Kubernetes 中或在自托管模式下更新文件中的组件规范时,组件会被重新加载。对 actor 状态存储和工作流后端的更改将被忽略。HotReload热重载v1.13
订阅热重载允许声明性订阅进行“热重载”。当在 Kubernetes 中更新订阅时,或在自托管模式下更新文件中的订阅时,订阅会被重新加载。重载时不会影响正在进行的消息。HotReload热重载v1.14
调度器 actor 提醒调度器 actor 提醒是存储在调度器控制平面服务中的 actor 提醒,与存储在放置控制平面服务中的 actor 提醒系统不同。SchedulerReminders 预览功能默认设置为 true,但您可以通过将其设置为 false 来禁用调度器 actor 提醒。SchedulerReminders调度器 actor 提醒v1.14

7.6 - Alpha 和 Beta API

当前 Alpha 和 Beta API 列表

Alpha API

模块/APIgRPCHTTP描述文档引入版本
查询状态查询状态 protov1.0-alpha1/state/statestore/query状态查询 API 可以让您检索、过滤和排序存储在状态存储组件中的键值数据。查询状态 APIv1.5
分布式锁锁 proto/v1.0-alpha1/lock分布式锁 API 可以让您对资源进行锁定。分布式锁 APIv1.8
批量发布批量发布 protov1.0-alpha1/publish/bulk批量发布 API 允许您在单个请求中向主题发布多条消息。批量发布和订阅 APIv1.10
批量订阅批量订阅 protoN/A批量订阅应用程序回调可以在一次调用中接收来自主题的多条消息。批量发布和订阅 APIv1.10
加密加密 protov1.0-alpha1/crypto加密 API 可以执行复杂的加密操作来加密和解密消息。加密 APIv1.11
任务任务 protov1.0-alpha1/jobs任务 API 可以让您调度和编排任务。任务 APIv1.14
对话对话 protov1.0-alpha1/conversation使用对话 API 可以在不同的大型语言模型之间进行交流。对话 APIv1.15

Beta API

当前没有 Beta API。

相关链接

了解有关 Alpha、Beta 和稳定生命周期阶段的更多信息。

8 - 调试与故障排除

提供工具、技术和常见问题,帮助用户有效调试和诊断Dapr相关问题

8.1 - 运行 Dapr 时的常见问题

运行 Dapr 应用程序时遇到的常见问题和问题

本指南涵盖了安装和运行 Dapr 时可能遇到的常见问题。

安装 Dapr CLI 时 Dapr 无法连接到 Docker

在安装和初始化 Dapr CLI 时,如果在运行 dapr init 后看到以下错误信息:

⌛  正在进行初始化...
❌  无法连接到 Docker。Docker 可能未安装或未运行

请通过以下步骤进行排查:

  1. 确保容器正确运行。

  2. 在 Docker Desktop 中,确认已选择 允许使用默认 Docker 套接字(需要密码) 选项。

我没有看到 Dapr sidecar 注入到我的 pod 中

sidecar 未注入到 pod 中可能有多种原因。首先,检查您的部署或 pod YAML 文件,确保在正确的位置有以下注释:

annotations:
  dapr.io/enabled: "true"
  dapr.io/app-id: "nodeapp"
  dapr.io/app-port: "3000"

示例部署:

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 规范模板注释正确,但仍未看到 sidecar 注入,请确保在部署或 pod 部署之前,Dapr 已部署到集群中。

    如果是这种情况,重启 pod 将解决问题。

  • 如果您在私有 GKE 集群上部署 Dapr,sidecar 注入在没有额外步骤的情况下不起作用。请参阅 设置 Google Kubernetes Engine 集群

    为了进一步诊断任何问题,请检查 Dapr sidecar 注入器的日志:

     kubectl logs -l app=dapr-sidecar-injector -n dapr-system
    

    注意:如果您将 Dapr 安装到不同的命名空间,请将上面的 dapr-system 替换为所需的命名空间

  • 如果您在 Amazon EKS 上部署 Dapr 并使用诸如 Calico 的覆盖网络,您需要将 hostNetwork 参数设置为 true,这是 EKS 在此类 CNI 上的限制。

    您可以使用 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 的入口规则。

由于 daprd sidecar,我的 pod 处于 CrashLoopBackoff 或其他失败状态

如果 Dapr sidecar (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 sidecar 未通过健康检查并将被重启。消息 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 表明健康检查失败是因为无法连接到 sidecar。

此故障的最常见原因是某个组件(如状态存储)配置错误,导致初始化时间过长。当初始化时间过长时,健康检查可能会在 sidecar 记录任何有用信息之前终止它。

要诊断根本原因:

  • 显著增加存活探测延迟 - 链接
  • 将 sidecar 的日志级别设置为调试 - 链接
  • 观察日志以获取有意义的信息 - 链接

解决问题后,请记得将存活检查延迟和日志级别配置回您期望的值。

我无法保存状态或获取状态

您是否在集群中安装了 Dapr 状态存储?

要检查,请使用 kubectl 获取组件列表:

kubectl get components

如果没有状态存储组件,则意味着您需要设置一个。 访问 这里 了解更多详细信息。

如果一切设置正确,请确保您获得了正确的凭据。 搜索 Dapr 运行时日志并查找任何状态存储错误:

kubectl logs <name-of-pod> daprd

我无法发布和接收事件

您是否在集群中安装了 Dapr 消息总线?

要检查,请使用 kubectl 获取组件列表:

kubectl get components

如果没有 pub/sub 组件,则意味着您需要设置一个。 访问 这里 了解更多详细信息。

如果一切设置正确,请确保您获得了正确的凭据。 搜索 Dapr 运行时日志并查找任何 pub/sub 错误:

kubectl logs <name-of-pod> daprd

调用 Dapr 时收到 500 错误响应

这意味着 Dapr 运行时内部存在一些问题。 要诊断,请查看 sidecar 的日志:

kubectl logs <name-of-pod> daprd

调用 Dapr 时收到 404 未找到响应

这意味着您正在尝试调用一个不存在的 Dapr API 端点或 URL 格式错误。 查看 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 输出。

本地运行 actor 时出现超时/连接错误

每个 Dapr 实例都会向放置服务报告其主机地址。放置服务然后将节点及其地址的表分发给所有 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

我的应用程序启动时没有加载任何组件。我不断收到“错误组件 X 找不到”

这通常是由于以下问题之一

  • 您可能在本地定义了 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 值丢失,首先检查过滤器是否已重新启用,然后再进行更广泛的故障排除。

准入 webhook 拒绝了请求

由于准入 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

您可以在 这里 了解有关 webhooks 的更多信息。

8.2 - 配置和查看 Dapr 日志

了解 Dapr 中日志的工作原理以及如何配置和查看日志

本节将帮助您了解 Dapr 中日志的工作原理,以及如何配置和查看日志。

概述

日志有不同的可配置级别。 以下列出的级别适用于系统组件和 Dapr sidecar 进程/容器:

  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 放置服务。

独立模式下的日志

在使用 Dapr CLI 运行应用程序时,可以通过传递 log-level 参数来设置日志级别:

dapr run --log-level warn node myapp.js

如上所述,每个 Dapr 二进制文件都接受一个 --log-level 参数。例如,要以警告级别启动放置服务:

./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 规范模板中提供以下注释,为每个 sidecar 单独设置日志级别:

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 sidecar 的日志。

Sidecar 日志

在 Kubernetes 中部署时,Dapr sidecar 注入器会将一个名为 daprd 的 Dapr 容器注入到您的注释 pod 中。 要查看 sidecar 的日志,只需通过运行 kubectl get pods 找到相关的 pod:

NAME                                        READY     STATUS    RESTARTS   AGE
addapp-74b57fb78c-67zm6                     2/2       Running   0          40h

接下来,获取 Dapr sidecar 容器的日志:

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 注入器
  • Dapr 放置服务

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,只需在上述命令中将命名空间替换为所需的命名空间

Sidecar 注入器日志

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,只需在上述命令中将命名空间替换为所需的命名空间

查看放置服务日志

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 sidecar 和/或系统组件(如果适用)的容器 ID 并查看其日志。

参考资料

8.3 - Dapr API 日志

了解 Dapr 中的 API 日志记录工作原理以及如何查看日志

API 日志记录可以让您查看应用程序对 Dapr sidecar 的 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 规范模板中添加以下注释来为 sidecar 启用 API 日志:

annotations:
  dapr.io/enable-api-logging: "true"

在 Kubernetes 上查看 API 日志

Dapr API 日志会被写入标准输出(stdout)和标准错误(stderr),您可以在 Kubernetes 上查看这些日志。

通过执行以下命令查看 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 配置规范,您可以为 --enable-api-logging 标志(以及在 Kubernetes 上运行时的相应注释)设置默认值,使用 logging.apiLogging.enabled 选项。此值适用于引用定义该配置文档或资源的所有 Dapr 运行时。

  • 如果 logging.apiLogging.enabled 设置为 false,即默认值,则 Dapr 运行时的 API 日志记录是禁用的,除非 --enable-api-logging 设置为 true(或添加 dapr.io/enable-api-logging: true 注释)。
  • 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)。

为了减少在启用 API 日志记录时意外包含 PII 的风险,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 和独立模式下启用性能分析。

独立模式

在独立模式下启用性能分析时,可以通过 Dapr CLI 传递 --enable-profiling--profile-port 标志: 注意,profile-port 是可选的,如果未指定,Dapr 会自动选择一个可用端口。

dapr run --enable-profiling --profile-port 7777 python myapp.py

Kubernetes

在 Kubernetes 中启用性能分析,只需在 Dapr 注解的 pod 中添加 dapr.io/enable-profiling 注解:

   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由两个主要部分组成:数据平面和控制平面。数据平面是运行在应用程序旁边的sidecar,而控制平面负责配置sidecar并提供证书和身份管理等功能。

自托管组件

  • sidecar(数据平面)
  • Sentry(可选,控制平面)
  • Placement(可选,控制平面)

更多信息请参见Dapr自托管模式概述

Kubernetes组件

  • sidecar(数据平面)
  • Sentry(可选,控制平面)
  • Placement(可选,控制平面)
  • Operator(控制平面)
  • sidecar注入器(控制平面)

更多信息请参见Dapr在Kubernetes上的概述

Dapr v1.0的性能总结

服务调用API是一个反向代理,内置了服务发现功能,用于连接其他服务。这包括跟踪、指标、用于流量传输加密的mTLS,以及通过重试网络分区和连接错误来实现的弹性。

通过服务调用,您可以实现从HTTP到HTTP、HTTP到gRPC、gRPC到HTTP和gRPC到gRPC的调用。Dapr在sidecar之间的通信中始终使用gRPC,但保留了应用程序调用时使用的协议语义。服务调用是与Dapr actor通信的底层机制。

更多信息请参见服务调用概述

Kubernetes性能测试设置

测试在一个3节点的Kubernetes集群上进行,使用普通硬件,每个节点配备4核CPU和8GB RAM,没有任何网络加速。 设置包括一个负载测试器(Fortio)pod,其中注入了一个Dapr sidecar,调用服务调用API以到达不同节点上的pod。

测试参数:

  • 每秒1000个请求
  • sidecar限制为0.5 vCPU
  • 启用sidecar mTLS
  • 启用sidecar遥测(采样率为0.1的跟踪)
  • 1KB的负载

基准测试包括直接、未加密的流量,没有遥测,直接从负载测试器到目标应用程序。

控制平面性能

Dapr控制平面在非高可用模式下运行时使用总共0.009 vCPU和61.6 Mb,这意味着每个系统组件只有一个副本。 在高可用生产设置中运行时,Dapr控制平面消耗约0.02 vCPU和185 Mb。

组件vCPU内存
Operator0.00112.5 Mb
Sentry0.00513.6 Mb
sidecar注入器0.00214.6 Mb
Placement0.00120.9 Mb

有许多因素会影响每个系统组件的CPU和内存消耗。这些因素在下表中显示。

组件vCPU内存
Operator请求组件、配置和订阅的pod数量
Sentry证书请求数量
sidecar注入器准入请求数量
Placementactor重新平衡操作数量连接的actor主机数量

数据平面性能

Dapr sidecar每秒处理1000个请求时使用0.48 vCPU和23Mb内存。 在端到端的调用中,Dapr sidecar(客户端和服务器)在第90百分位延迟中增加约1.40 ms,在第99百分位延迟中增加约2.10 ms。端到端是指从一个应用程序发出请求到另一个应用程序接收响应的全过程。这在此图的步骤1-7中显示。

这种性能与常用的服务网格相当或更好。

延迟

在测试设置中,请求通过Dapr sidecar在客户端(从负载测试工具服务请求)和服务器端(目标应用程序)进行。 在Dapr测试中启用了mTLS和遥测(采样率为0.1的跟踪)和指标,而在基准测试中禁用了这些功能。

第90百分位延迟
第99百分位延迟

9.2 - actor 性能激活

本文介绍了在 Kubernetes 上 Dapr 中 actor 的服务调用 API 的性能基准和资源使用情况。

系统概述

在 Dapr 中使用 actor 的应用程序需要考虑两个方面。首先,actor 调用的路由由 Dapr 的边车(sidecar)处理。其次,actor 的运行时在应用程序端实现和处理,这依赖于所使用的 SDK。目前,性能测试使用 Java SDK 在应用程序中提供 actor 运行时。

Kubernetes 组件

  • 边车(数据平面)
  • Placement(actor 所需,控制平面将 actor 类型映射到主机)
  • Operator(控制平面)
  • 边车注入器(控制平面)
  • Sentry(可选,控制平面)

Dapr v1.0 的性能总结

Dapr 边车中的 actor API 负责识别注册了特定 actor 类型的主机,并将请求路由到拥有该 actor ID 的合适主机。主机运行应用程序的一个实例,并使用 Dapr SDK(.Net、Java、Python 或 PHP)通过 HTTP 处理 actor 请求。

本次测试通过 Dapr 的 HTTP API 直接调用 actor。

有关更多信息,请参见 actor 概述

Kubernetes 性能测试设置

测试在一个由 3 个节点组成的 Kubernetes 集群上进行,使用普通硬件,每个节点配备 4 核 CPU 和 8GB RAM,没有网络加速。 设置包括一个负载测试器(Fortio)pod,其中注入了一个 Dapr 边车,调用服务 API 以访问不同节点上的 pod。

测试参数:

  • 每秒 500 个请求
  • 1 个副本
  • 持续 1 分钟
  • 边车限制为 0.5 vCPU
  • 启用 mTLS
  • 启用边车遥测(采样率为 0.1 的跟踪)
  • 空 JSON 对象的负载:{}

结果

  • 实际吞吐量约为 500 qps。
  • tp90 延迟约为 3ms。
  • tp99 延迟约为 6.2ms。
  • Dapr 应用程序消耗约 523m CPU 和约 304.7Mb 内存
  • Dapr 边车消耗 2m CPU 和约 18.2Mb 内存
  • 无应用程序重启
  • 无边车重启

相关链接