1. Knative Eventing 架构总览
Knative Eventing 是 Knative 生态中负责事件驱动架构的核心子系统。要理解触发器(Trigger)在控制面通信机制中的角色,首先需要厘清整个 Eventing 架构的两大平面:控制面(Control Plane)与数据面(Data Plane)。控制面负责事件路由规则的定义、状态管理和元数据协调;数据面则负责事件的实际传输、过滤和投递。
1.1 核心组件全景
Knative Eventing 围绕几个关键抽象构建,下表列出了主要组件及其所属平面:
| 组件 | 所属平面 | 核心职责 | 典型实现 |
|---|---|---|---|
| Broker | 控制面 + 数据面 | 事件网格入口,管理事件路由策略,维护 Trigger 列表 | InMemoryBroker、RabbitMQBroker、KafkaBroker |
| Trigger | 控制面 | 定义事件过滤规则(属性/类型)并绑定到目标 Sink | CRD 资源,由 Broker 控制器协调 |
| Channel | 数据面 | 事件缓冲、持久化、多订阅分发 | InMemoryChannel、KafkaChannel、NATSChannel |
| Source | 数据面 | 事件生产者,从外部系统生成或导入事件 | ApiServerSource、PingSource、KafkaSource |
| Sink | 数据面 | 事件消费者,接收并处理事件 | Service、Function、Knative Service |
| Subscription | 控制面 | 将 Channel 与 Sink 关联,定义事件投递链路 | CRD 资源,由 Channel 控制器解析 |
关键理解:Broker 是唯一横跨控制面与数据面的组件。它既通过 Kubernetes CRD 存储 Trigger 规则(控制面),又通过内置的 Channel 或自定义实现完成事件的实际路由(数据面)。这种双重身份是故障排查时最容易混淆的边界。
1.2 控制面组件职责详解
控制面组件负责事件路由的声明式配置与状态协调。它们不直接参与事件字节流的传输,而是通过 Kubernetes API Server 维护资源对象,驱动数据面组件做出相应行为。
- Broker(控制面部分):作为事件网格的命名空间级入口,Broker 资源本身存储了所有关联 Trigger 的引用列表。Broker 控制器监听 Trigger 的创建、更新、删除事件,并动态更新内部路由表。Broker 的
.spec.config字段定义了底层数据面实现(如使用哪个 Channel 类型)。 - Trigger:定义事件过滤条件(
.spec.filter)和目标 Sink(.spec.subscriber)。Trigger 控制器将过滤规则写入 Broker 的数据面配置,确保只有匹配的事件被转发。Trigger 的状态(.status.conditions)反映了其是否成功绑定到 Broker 且 Sink 可达。 - Subscription:在 Channel 模式下,Subscription 将 Channel 与一个或多个 Sink 绑定。它定义了事件投递的拓扑结构,包括重试策略和死信队列(DLQ)配置。
故障排查要点:控制面组件的问题通常表现为 Trigger 或 Subscription 的
Ready 条件为 False。常见原因包括:Broker 未就绪、Sink 地址不可解析、过滤表达式语法错误、RBAC 权限不足。排查时应首先检查 kubectl get trigger -o yaml 中的 status.conditions 字段。
1.3 数据面组件职责详解
数据面组件负责事件的实际传输、缓冲、过滤和投递。它们运行在 Pod 中,处理事件字节流,是性能瓶颈和运行时故障的高发区。
- Source:事件生产者。Source 控制器将外部事件(如 Kubernetes API 变更、定时心跳、Kafka 消息)转换为 CloudEvents 格式,并发送到指定的 Broker 或 Sink。Source 通常包含一个接收器适配器(Adapter)Pod,负责轮询或监听外部系统。
- Channel:事件缓冲区。Channel 提供事件的临时存储和扇出能力。当多个 Trigger 或 Subscription 匹配同一事件时,Channel 负责复制事件并分发给所有订阅者。Channel 的实现决定了事件的持久性、顺序保证和吞吐量。
- Sink:事件消费者。Sink 可以是任何可寻址的 HTTP 端点(如 Knative Service、Kubernetes Service、甚至外部 URL)。事件最终被投递到 Sink 的
/路径(默认),由用户代码处理。
1.4 控制面与数据面的交互流程
下图展示了从 Source 产生事件到 Sink 消费事件的完整路径,并标注了控制面与数据面的边界:
1.5 平面职责对比总结
下表从多个维度对比控制面与数据面的差异,帮助在故障排查时快速定位问题平面:
| 对比维度 | 控制面 | 数据面 |
|---|---|---|
| 资源类型 | CRD 对象(Broker、Trigger、Subscription) | Pod、Service、ConfigMap(Channel 实现、Source Adapter) |
| 通信协议 | Kubernetes API(HTTP/gRPC) | HTTP/HTTPS(CloudEvents 格式) |
| 状态来源 | etcd(通过 API Server) | Pod 日志、指标、事件 |
| 故障表现 | 资源状态为 False、Reconciling 循环 | 事件丢失、投递延迟、HTTP 5xx 错误 |
| 排查工具 | kubectl describe、kubectl get events |
kubectl logs、kubectl port-forward、指标监控 |
| 典型瓶颈 | API Server QPS、控制器并发 | 网络带宽、Pod 资源限制、Channel 持久化性能 |
常见误区:很多初学者将 Trigger 视为数据面组件,认为它直接参与事件过滤和转发。实际上,Trigger 只是一个控制面声明,真正的过滤逻辑由 Broker 的数据面实现(如 InMemoryBroker 的过滤器)在事件到达时执行。Trigger 的状态异常通常反映的是控制面协调失败,而非数据面事件丢失。
1.6 平面边界与故障排查切入点
在实际故障排查中,明确控制面与数据面的边界可以大幅缩小排查范围。以下是一个典型的排查决策树:
- 检查 Trigger 状态:
kubectl get trigger -n <namespace>。如果READY列为True,说明控制面配置已成功下发,问题大概率在数据面。 - 检查 Broker 数据面 Pod:
kubectl get pods -n knative-eventing。Broker 的数据面实现(如in-memory-channel-dispatcher)必须处于 Running 状态。 - 检查 Source Adapter 日志:确认 Source 是否成功生成事件并发送到 Broker 入口地址。
- 检查 Sink 可达性:从 Broker Pod 内部
curlSink 地址,验证网络连通性和响应状态码。
通过以上步骤,可以快速判断故障发生在控制面协调阶段还是数据面传输阶段,为后续深入排查奠定基础。