拦截器
拦截器是 Tekton Triggers 中一个强大的组件,用于在事件数据到达 TriggerBindings 和 TriggerTemplates 之前对其进行处理和过滤。它充当了传入 webhook 事件的守门人和转换器,使您能够验证、过滤和修改事件数据,以确保只有相关事件能够触发您的流水线。
术语解释
术语 | 描述 |
---|
拦截器 | 在 webhook 事件到达 TriggerBindings 和 TriggerTemplates 之前处理的组件。 |
集群拦截器 | 一种集群范围的拦截器,可以在所有命名空间中使用。 |
CEL | 通用表达语言,用于过滤和转换事件数据。 |
扩展 | 拦截器添加的额外数据字段,TriggerBindings 可以访问这些字段。 |
Webhook | 当外部系统中发生特定事件时,交付事件数据的 HTTP 回调。 |
为什么我们需要拦截器
事件处理的挑战
在响应外部事件的 CI/CD 系统中,会面临若干挑战:
- 事件验证:需要对外部 webhook 进行验证,以确保它们来自受信任的来源。
- 事件过滤:并不是所有事件都应触发流水线;您需要根据事件类型或内容进行过滤。
- 数据转换:原始的 webhook 负载通常包含比所需更多的数据或需要重构。
- 安全问题:如果没有适当的验证,webhook 端点可能会面临滥用的风险。
在没有拦截器的情况下,解决这些挑战将需要:
- 针对每个 webhook 来源的自定义验证代码
- 在流水线定义中嵌入复杂逻辑
- 在脚本中进行手动过滤和转换
- 针对每个集成的单独安全机制
拦截器如何解决这些问题
拦截器提供了一种标准化的声明性方式来:
- 验证事件:验证 webhook 签名和令牌以确保其真实性。
- 过滤事件:基于类型、内容或其他标准仅处理相关事件。
- 转换数据:提取、修改或添加数据,以使其更适合流水线消费。
- 增强安全性:在所有 webhook 集成中实施一致的安全实践。
- 模块化逻辑:将事件处理关注点与流水线执行分离。
这种方法在事件接收、处理和流水线执行之间创建了清晰的分离,使您的 CI/CD 系统更易于维护和更安全。
优势
- 增强安全性:在处理之前验证 webhook 的真实性
- 减少流水线复杂性:将过滤和转换逻辑移出流水线
- 标准化处理:跨不同来源一致处理事件
- 灵活性:为复杂处理需求链式连接多个拦截器
- 可扩展性:为专业处理需求创建自定义拦截器
- 可重用性:仅需定义拦截器一次即可在多个触发器中重用
- 声明性配置:使用 Kubernetes 资源配置事件处理
适用场景
拦截器在以下场景中至关重要:
-
安全的 Webhook 处理:当您需要验证 webhook 事件是否来自受信任的来源。
-
条件流水线执行:当您希望仅针对特定事件类型或内容(例如,只有在主分支上进行推送事件时)触发流水线。
-
数据丰富:当您需要从复杂事件负载中添加计算值或提取特定数据。
-
多来源集成:当与多个 webhook 提供商(GitHub、GitLab、Bitbucket)集成时,保持一致的处理。
-
自定义事件处理:当实现超出标准拦截器可用功能的专业逻辑时。
限制与局限性
- 拦截器为事件处理增加了处理开销
- 复杂的 CEL 表达式可能难以调试
- 自定义拦截器需要额外的部署和管理
- 建议使用 HTTPS 以确保安全,并将在未来版本中移除对 HTTP 的支持
- 拦截器必须获得适当的保护,以防止未经授权的访问
原则
拦截器架构
拦截器位于 EventListener 和触发处理流水线之间:
- EventListener 接收 webhook 事件
- 拦截器 处理和过滤事件
- TriggerBindings 从处理后的事件中提取数据
- TriggerTemplates 使用提取的数据创建资源
拦截器可以链式连接,每个拦截器接收来自前一个拦截器的输出。这允许创建复杂的处理流水线,每个拦截器执行特定功能。
拦截器类型
Tekton Triggers 支持两种拦截器的实现:
-
独立拦截器:作为单独的 Kubernetes 服务实现
- 拦截器:命名空间范围的自定义资源
- 集群拦截器:集群范围的自定义资源
- 更灵活,且更易于扩展
- 可以使用任何可以提供 HTTP 请求的语言实现
-
内置拦截器:包含在 EventListener pod 中
- GitHub、GitLab、Bitbucket、CEL 等
- 为了向后兼容而保留
- 更易于使用,但扩展性较差
拦截器结构
基本的拦截器资源具有以下结构:
apiVersion: triggers.tekton.dev/v1alpha1
kind: Interceptor
metadata:
name: my-interceptor
spec:
clientConfig:
service:
name: my-interceptor-svc
namespace: default
path: "/optional-path" # 可选
port: 8081 # 默认为 80
在触发器中引用时:
triggers:
- name: trigger-with-interceptor
interceptors:
- ref:
name: "my-interceptor"
kind: Interceptor # 或 ClusterInterceptor
namespace: default # 仅对 Interceptor 必需
params: # 可选参数
- name: "param1"
value: "value1"
配置示例
GitHub 拦截器示例
triggers:
- name: github-push-trigger
interceptors:
- ref:
name: "github"
params:
- name: "secretRef"
value:
secretName: github-secret
secretKey: secretToken
- name: "eventTypes"
value: ["push"]
- name: "branches"
value: ["main", "release/*"]
带 CEL 的 GitLab 拦截器示例
triggers:
- name: gitlab-merge-request-trigger
interceptors:
- ref:
name: "gitlab"
params:
- name: "secretRef"
value:
secretName: gitlab-secret
secretKey: secretToken
- name: "eventTypes"
value: ["Merge Request Hook"]
- ref:
name: "cel"
params:
- name: "filter"
value: "body.object_attributes.state == 'opened' || body.object_attributes.state == 'reopened'"
- name: "overlays"
value:
- key: truncated_sha
expression: "body.object_attributes.last_commit.id.truncate(7)"
自定义拦截器示例
- 创建您自定义拦截器的 Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: custom-interceptor
spec:
replicas: 1
selector:
matchLabels:
app: custom-interceptor
template:
metadata:
labels:
app: custom-interceptor
spec:
containers:
- name: custom-interceptor
image: custom-interceptor:latest
ports:
- containerPort: 8080
- 创建您自定义拦截器的 Service:
apiVersion: v1
kind: Service
metadata:
name: custom-interceptor-svc
spec:
selector:
app: custom-interceptor
ports:
- port: 80
targetPort: 8080
- 注册您的自定义拦截器:
apiVersion: triggers.tekton.dev/v1alpha1
kind: ClusterInterceptor
metadata:
name: custom-interceptor
spec:
clientConfig:
service:
name: custom-interceptor-svc
namespace: default
port: 80
与拦截器相关的重要参数说明
CEL 表达式
CEL(通用表达语言)是用于过滤和转换事件数据的 CEL 拦截器的强大工具。
适用场景
- 基于复杂条件过滤事件
- 从事件负载中提取特定数据
- 根据现有数据创建新字段
- 实现条件逻辑
限制与局限性
- 复杂的表达式可能难以调试
- 仅限于 CEL 提供的功能
- 非常复杂的表达式可能对性能产生影响
原则/参数说明
常见的 CEL 模式:
- 访问主体字段:
body.repository.full_name
- 访问头字段:
header.X-GitHub-Event
- 字符串操作:
body.ref.split('/')[2]
- 条件判断:
body.action in ['opened', 'reopened', 'synchronize']
- 布尔逻辑:
body.pull_request.base.ref == 'main' && body.action == 'opened'
配置示例
- ref:
name: "cel"
params:
- name: "filter"
value: "header.match('X-GitHub-Event', 'pull_request') && body.action in ['opened', 'reopened', 'synchronize']"
- name: "overlays"
value:
- key: branch_name
expression: "body.pull_request.head.ref"
- key: is_main_target
expression: "body.pull_request.base.ref == 'main'"
HTTPS 配置
建议在 HTTPS 上运行拦截器以确保安全,并将在未来版本中强制要求。
适用场景
限制与局限性
- 需要适当的证书管理
- 与 HTTP 相比需要额外配置
原则/参数说明
要为拦截器配置 HTTPS:
- 为您的拦截器添加
server/type: https
标签
- 提供证书验证的 CA 包
- 确保您的拦截器服务配置为提供 HTTPS
配置示例
apiVersion: triggers.tekton.dev/v1alpha1
kind: Interceptor
metadata:
name: secure-interceptor
labels:
server/type: https
spec:
clientConfig:
caBundle: "BASE64_ENCODED_CA_BUNDLE"
service:
name: secure-interceptor-svc
namespace: default
port: 8443
参考材料