Azure Event Grid 绑定规范

关于 Azure Event Grid 绑定组件的详细文档

组件格式

要设置 Azure Event Grid 绑定,需创建一个类型为 bindings.azure.eventgrid 的组件。请参考本指南了解如何创建和应用绑定配置。

有关 Azure Event Grid 的更多信息,请访问此处

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <name>
spec:
  type: bindings.azure.eventgrid
  version: v1
  metadata:
  # 必需的输出绑定元数据
  - name: accessKey
    value: "[AccessKey]"
  - name: topicEndpoint
    value: "[TopicEndpoint]"
  # 必需的输入绑定元数据
  - name: azureTenantId
    value: "[AzureTenantId]"
  - name: azureSubscriptionId
    value: "[AzureSubscriptionId]"
  - name: azureClientId
    value: "[ClientId]"
  - name: azureClientSecret
    value: "[ClientSecret]"
  - name: subscriberEndpoint
    value: "[SubscriberEndpoint]"
  - name: handshakePort
    # 确保以字符串形式传递,值需加上引号
    value: "[HandshakePort]"
  - name: scope
    value: "[Scope]"
  # 可选的输入绑定元数据
  - name: eventSubscriptionName
    value: "[EventSubscriptionName]"
  # 可选元数据
  - name: direction
    value: "input, output"

规范元数据字段

字段必需绑定支持详情示例
accessKeyY输出用于向自定义主题发布 Event Grid 事件的访问密钥"accessKey"
topicEndpointY输出此输出绑定应发布事件的主题端点"topic-endpoint"
azureTenantIdY输入Event Grid 资源的 Azure 租户 ID"tenentID"
azureSubscriptionIdY输入Event Grid 资源的 Azure 订阅 ID"subscriptionId"
azureClientIdY输入绑定用于创建或更新 Event Grid 事件订阅并验证传入消息的客户端 ID"clientId"
azureClientSecretY输入绑定用于创建或更新 Event Grid 事件订阅并验证传入消息的客户端密钥"clientSecret"
subscriberEndpointY输入Webhook 的 HTTPS 端点,Event Grid 将事件(格式化为 Cloud Events)发送到此处。如果您不在入口处重写 URL,则应采用以下格式:"https://[YOUR HOSTNAME]/<path>"
如果在本地计算机上进行测试,可以使用类似 ngrok 的工具创建公共端点。
"https://[YOUR HOSTNAME]/<path>"
handshakePortY输入输入绑定在接收 Webhook 事件时监听的容器端口"9000"
scopeY输入需要创建或更新事件订阅的资源标识符。有关更多详细信息,请参阅范围部分"/subscriptions/{subscriptionId}/"
eventSubscriptionNameN输入事件订阅的名称。事件订阅名称必须在 3 到 64 个字符之间,并且只能使用字母数字字符"name"
directionN输入/输出绑定的方向"input", "output", "input, output"

范围

范围是需要创建或更新事件订阅的资源标识符。范围可以是订阅、资源组、属于资源提供程序命名空间的顶级资源或 Event Grid 主题。例如:

  • /subscriptions/{subscriptionId}/ 表示一个订阅
  • /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName} 表示一个资源组
  • /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} 表示一个资源
  • /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.EventGrid/topics/{topicName} 表示一个 Event Grid 主题

大括号 {} 中的值应替换为实际值。

绑定支持

此组件支持 输入和输出 绑定接口。

此组件支持以下操作的 输出绑定

  • create: 在 Event Grid 主题上发布消息

接收事件

您可以使用 Event Grid 绑定从各种来源和操作接收事件。了解有关与 Event Grid 一起使用的所有可用事件源和处理程序的更多信息。

在下表中,您可以找到可以引发事件的 Dapr 组件列表。

事件源Dapr 组件
Azure Blob 存储Azure Blob 存储绑定
Azure Blob 存储状态存储
Azure Redis 缓存Redis 绑定
Redis pub/sub
Azure Event HubsAzure Event Hubs pub/sub
Azure Event Hubs 绑定
Azure IoT HubAzure Event Hubs pub/sub
Azure Event Hubs 绑定
Azure Service BusAzure Service Bus 绑定
Azure Service Bus pub/sub 主题队列
Azure SignalR 服务SignalR 绑定

Microsoft Entra ID 凭据

Azure Event Grid 绑定需要 Microsoft Entra ID 应用程序和服务主体,原因有两个:

  • 在 Dapr 启动时创建一个事件订阅(如果 Dapr 配置更改则更新它)
  • 验证 Event Hubs 传递给您应用程序的消息。

要求:

  • 安装 Azure CLI
  • 安装 PowerShell 7
  • 为 PowerShell 安装 Az 模块
    Install-Module Az -Scope CurrentUser -Repository PSGallery -Force
  • 为 PowerShell 安装 Microsoft.Graph 模块
    Install-Module Microsoft.Graph -Scope CurrentUser -Repository PSGallery -Force

对于第一个目的,您需要创建一个 Azure 服务主体。创建后,记下 Microsoft Entra ID 应用程序的 clientID(一个 UUID),并使用 Azure CLI 运行以下脚本:

# 设置您创建的应用的客户端 ID
CLIENT_ID="..."
# 资源的范围,通常格式为:
# `/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.EventGrid/topics/{topicName}`
SCOPE="..."

# 首先确保 Azure 资源管理器提供程序已为 Event Grid 注册
az provider register --namespace "Microsoft.EventGrid"
az provider show --namespace "Microsoft.EventGrid" --query "registrationState"
# 为 SP 授予所需权限,以便它可以为 Event Grid 创建事件订阅
az role assignment create --assignee "$CLIENT_ID" --role "EventGrid EventSubscription Contributor" --scopes "$SCOPE"

对于第二个目的,首先下载一个脚本:

curl -LO "https://raw.githubusercontent.com/dapr/components-contrib/master/.github/infrastructure/conformance/azure/setup-eventgrid-sp.ps1"

然后,使用 PowerShell (pwsh) 运行:

# 设置您创建的应用的客户端 ID
$clientId = "..."

# 使用 Microsoft Graph 进行身份验证
# 如果需要,您可能需要在下一个命令中添加 -TenantId 标志
Connect-MgGraph -Scopes "Application.Read.All","Application.ReadWrite.All"
./setup-eventgrid-sp.ps1 $clientId

注意:如果您的目录没有应用程序 “Microsoft.EventGrid” 的服务主体,您可能需要运行命令 Connect-MgGraph 并以 Microsoft Entra ID 租户的管理员身份登录(这与 Microsoft Entra ID 目录的权限有关,而不是 Azure 订阅)。否则,请要求您的租户管理员登录并运行此 PowerShell 命令:New-MgServicePrincipal -AppId "4962773b-9cdb-44cf-a8bf-237846a00ab7"(UUID 是一个常量)

本地测试

  • 安装 ngrok
  • 使用自定义端口在本地运行,例如 9000,用于握手
# 以端口 9000 为例
ngrok http --host-header=localhost 9000
  • 将 ngrok 的 HTTPS 端点和自定义端口配置为输入绑定元数据
  • 运行 Dapr
# 以 .NET core web api 和 Dapr 的默认端口为例
dapr run --app-id dotnetwebapi --app-port 5000 --dapr-http-port 3500 dotnet run

在 Kubernetes 上测试

Azure Event Grid 需要一个有效的 HTTPS 端点用于自定义 webhooks;不接受自签名证书。为了启用从公共互联网到您应用程序的 Dapr sidecar 的流量,您需要启用 Dapr 的入口控制器。关于这个主题有一篇不错的文章:Kubernetes NGINX ingress controller with Dapr

首先,为 Dapr 注解创建一个 dapr-annotations.yaml 文件:

controller:
  podAnnotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "nginx-ingress"
    dapr.io/app-port: "80"

然后使用注解通过 Helm 3 将 NGINX ingress 控制器安装到您的 Kubernetes 集群中:

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install nginx-ingress ingress-nginx/ingress-nginx -f ./dapr-annotations.yaml -n default
# 获取入口控制器的公共 IP
kubectl get svc -l component=controller -o jsonpath='Public IP is: {.items[0].status.loadBalancer.ingress[0].ip}{"\n"}'

如果部署到 Azure Kubernetes 服务,您可以按照官方 Microsoft 文档的其余步骤

  • 向您的 DNS 区域添加 A 记录
  • 安装 cert-manager
  • 创建 CA 集群颁发者

启用 Event Grid 和 Dapr 之间通信的最后一步是定义 http 和自定义端口到您应用程序的服务和 Kubernetes 中的 ingress。此示例使用 .NET Core web api 和 Dapr 默认端口以及用于握手的自定义端口 9000。

# dotnetwebapi.yaml
kind: Service
apiVersion: v1
metadata:
  name: dotnetwebapi
  labels:
    app: dotnetwebapi
spec:
  selector:
    app: dotnetwebapi
  ports:
    - name: webapi
      protocol: TCP
      port: 80
      targetPort: 80
    - name: dapr-eventgrid
      protocol: TCP
      port: 9000
      targetPort: 9000
  type: ClusterIP

---
  apiVersion: extensions/v1beta1
  kind: Ingress
  metadata:
    name: eventgrid-input-rule
    annotations:
      kubernetes.io/ingress.class: nginx
      cert-manager.io/cluster-issuer: letsencrypt
  spec:
    tls:
      - hosts:
        - dapr.<your custom domain>
        secretName: dapr-tls
    rules:
      - host: dapr.<your custom domain>
        http:
          paths:
            - path: /api/events
              backend:
                serviceName: dotnetwebapi
                servicePort: 9000

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dotnetwebapi
  labels:
    app: dotnetwebapi
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dotnetwebapi
  template:
    metadata:
      labels:
        app: dotnetwebapi
      annotations:
        dapr.io/enabled: "true"
        dapr.io/app-id: "dotnetwebapi"
        dapr.io/app-port: "5000"
    spec:
      containers:
      - name: webapi
        image: <your container image>
        ports:
        - containerPort: 5000
        imagePullPolicy: Always

将绑定和应用程序(包括 ingress)部署到 Kubernetes

# 部署 Dapr 组件
kubectl apply -f eventgrid.yaml
# 部署您的应用程序和 Nginx ingress
kubectl apply -f dotnetwebapi.yaml

注意: 此清单将所有内容部署到 Kubernetes 的默认命名空间。

排查 Nginx 控制器可能出现的问题

初始部署后,“Dapr 化”的 Nginx 控制器可能会出现故障。要检查日志并修复问题(如果存在),请按照以下步骤操作。

$ kubectl get pods -l app=nginx-ingress

NAME                                                   READY   STATUS    RESTARTS   AGE
nginx-nginx-ingress-controller-649df94867-fp6mg        2/2     Running   0          51m
nginx-nginx-ingress-default-backend-6d96c457f6-4nbj5   1/1     Running   0          55m

$ kubectl logs nginx-nginx-ingress-controller-649df94867-fp6mg nginx-ingress-controller

# 如果您看到对 webhook 端点 '/api/events' 的调用记录了 503,请重启 pod
# .."OPTIONS /api/events HTTP/1.1" 503..

$ kubectl delete pod nginx-nginx-ingress-controller-649df94867-fp6mg

# 再次检查日志 - 它应该开始返回 200
# .."OPTIONS /api/events HTTP/1.1" 200..

相关链接