第 13/60 天
引言
在上一篇文章中,我们学习了 Tekton Triggers 的核心组件——TriggerBinding、TriggerTemplate、EventListener 和 Interceptor,并通过一个简单的 Webhook 示例触发了流水线。但生产环境的 CI 要求远不止于此:我们需要真正接入 GitHub 或 GitLab 的事件,比如 push、pull_request、tag 创建等,然后根据事件内容动态决定构建参数、分支信息、镜像标签等。
本篇文章将带你从零到一,为 Tekton 流水线接入真实的 GitHub/GitLab Webhook 事件,实现代码提交即触发构建 + 镜像推送 + 通知的完整事件驱动 CI 流程。核心目标包括:
- 部署 EventListener 并暴露为 Ingress
- 配置 GitHub/GitLab Webhook 到 EventListener
- 使用 Interceptor 解析事件载荷并过滤分支
- 根据事件数据动态生成流水线参数
- 实现 PR 触发校验流水线、Push 触发构建流水线的多事件路由
核心概念
事件驱动 CI 的通信模型
GitHub/GitLab Tekton EventListener Trigger PipelineRun
│ │ │ │
│ push/Pull Request │ │ │
│───────────────────────►│ │ │
│ │ Interceptor 检查事件 │ │
│ │ (过滤分支/事件类型) │ │
│ │ 绑定 TriggerBinding │ │
│ │ 实例化 TriggerTemplate │ │
│ │──────────────────────────►│ │
│ │ │ 创建 │
│ │ │──────────────►│
│ │ │ │ 执行
│ │ │ │────►
关键组件回顾
| 组件 | 在本场景中的作用 |
|---|---|
| EventListener | 监听 HTTP Webhook 请求的入口,可配置多个 Trigger |
| Interceptor | 在事件到达 Trigger 前执行预处理,支持过滤、校验、变量提取 |
| TriggerBinding | 从 Webhook 载荷中提取字段(如分支名、提交 SHA、仓库 URL) |
| TriggerTemplate | 使用提取的变量生成 PipelineRun 或 TaskRun 的 YAML |
内置 Interceptor 类型
Tekton 提供三种内置 Interceptor:
- GitHub Interceptor — 自动校验 GitHub Webhook 签名(HMAC),解析事件载荷
- GitLab Interceptor — 自动校验 GitLab Webhook 的 Secret Token,解析事件载荷
- CEL Interceptor — 使用 Common Expression Language 编写过滤条件,支持分支名匹配、事件类型过滤等
生产环境的事件路由策略
| 分支模式 | 事件 | 触发动作 |
|---|---|---|
feature/* |
push | 启动校验流水线(lint + test) |
main |
push | 启动构建 + 推送镜像 + 更新 staging 环境 |
v* |
tag 创建 | 启动构建 + 推送镜像 + 打版本标签 |
| 任意 | pull_request | 启动 PR 校验流水线(不推送镜像) |
实战步骤
Step 1:部署 EventListener 并暴露为 Ingress
首先创建一个 EventListener,监听 /tekton/events 路径:
# eventlistener-github.yaml
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: github-listener
namespace: tekton-pipelines
spec:
serviceAccountName: tekton-triggers-admin
triggers:
- name: push-to-main
interceptors:
- ref:
name: github
params:
- name: secretRef
value:
secretName: github-webhook-secret
secretKey: secretToken
- name: eventTypes
value: ["push"]
- ref:
name: cel
params:
- name: filter
value: "body.ref == 'refs/heads/main'"
bindings:
- ref: github-push-binding
template:
ref: build-and-deploy-template
- name: pr-validation
interceptors:
- ref:
name: github
params:
- name: eventTypes
value: ["pull_request"]
- ref:
name: cel
params:
- name: filter
value: "body.action in ['opened', 'synchronize']"
bindings:
- ref: github-pr-binding
template:
ref: pr-validation-template
resources:
kubernetesResource:
spec:
template:
spec:
containers:
- resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: github-listener-ingress
namespace: tekton-pipelines
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- tekton-webhook.stellardata.top
secretName: tekton-webhook-tls
rules:
- host: tekton-webhook.stellardata.top
http:
paths:
- path: /tekton/events
pathType: Prefix
backend:
service:
name: el-github-listener
port:
number: 8080
Webhook Secret 需要通过 Kubernetes Secret 提供:
# 创建 Webhook Secret(与 GitHub 中配置的相同)
kubectl create secret generic github-webhook-secret
--namespace tekton-pipelines
--from-literal=secretToken="your-github-webhook-secret-here"
Step 2:创建 TriggerBinding 提取事件字段
TriggerBinding 从 Webhook 载荷中提取关键字段,传递给 TriggerTemplate:
# triggerbinding-github-push.yaml
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
name: github-push-binding
namespace: tekton-pipelines
spec:
params:
- name: git_repo_url
value: $(body.repository.clone_url)
- name: git_revision
value: $(body.after)
- name: git_branch
value: $(body.ref)
- name: git_commit_message
value: $(body.head_commit.message)
- name: git_committer
value: $(body.head_commit.committer.name)
- name: git_commit_timestamp
value: $(body.head_commit.timestamp)
- name: repository_full_name
value: $(body.repository.full_name)
---
# triggerbinding-github-pr.yaml
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
name: github-pr-binding
namespace: tekton-pipelines
spec:
params:
- name: git_repo_url
value: $(body.repository.clone_url)
- name: git_revision
value: $(body.pull_request.head.sha)
- name: git_branch
value: $(body.pull_request.head.ref)
- name: pr_number
value: $(body.number)
- name: pr_title
value: $(body.pull_request.title)
- name: git_commit_message
value: $(body.pull_request.title)
- name: repository_full_name
value: $(body.repository.full_name)
GitLab 版本的 TriggerBinding 参数路径略有不同,GitLab 的 Webhook 载荷中仓库 URL 在 $(body.project.git_http_url),分支在 $(body.ref),提交 SHA 在 $(body.checkout_sha)。使用 GitLab Interceptor 时自动解析。
Step 3:创建 TriggerTemplate 生成 PipelineRun
以下是构建部署流水线的模板,根据事件参数动态生成流水线运行:
# triggertemplate-build-deploy.yaml
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
name: build-and-deploy-template
namespace: tekton-pipelines
spec:
params:
- name: git_repo_url
- name: git_revision
- name: git_branch
- name: git_commit_message
- name: repository_full_name
resourcetemplates:
- apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: build-deploy-$(uid)
labels:
triggertemplate: build-and-deploy
repo: $(tt:params.repository_full_name)
branch: $(tt:params.git_branch)
spec:
pipelineRef:
name: ci-pipeline
params:
- name: repo-url
value: $(tt:params.git_repo_url)
- name: revision
value: $(tt:params.git_revision)
- name: branch
value: $(tt:params.git_branch)
- name: commit-message
value: $(tt:params.git_commit_message)
- name: image-tag
value: $(tt:params.git_revision)[0:7]
workspaces:
- name: shared-workspace
persistentVolumeClaim:
claimName: tekton-workspace-pvc
- name: dockerconfig
secret:
secretName: harbor-robot-secret
PR 校验模板只运行测试和 lint,不构建镜像:
# triggertemplate-pr-validation.yaml
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
name: pr-validation-template
namespace: tekton-pipelines
spec:
params:
- name: git_repo_url
- name: git_revision
- name: git_branch
- name: pr_number
- name: pr_title
- name: repository_full_name
resourcetemplates:
- apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: pr-validation-$(uid)
labels:
triggertemplate: pr-validation
pr-number: $(tt:params.pr_number)
repo: $(tt:params.repository_full_name)
spec:
pipelineRef:
name: pr-validation-pipeline
params:
- name: repo-url
value: $(tt:params.git_repo_url)
- name: revision
value: $(tt:params.git_revision)
- name: pr-number
value: $(tt:params.pr_number)
workspaces:
- name: shared-workspace
persistentVolumeClaim:
claimName: tekton-workspace-pvc
Step 4:配置 ServiceAccount 与 RBAC
EventListener 需要足够的权限来创建 PipelineRun 和其他资源:
# rbac-tekton-triggers.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: tekton-triggers-admin
namespace: tekton-pipelines
secrets:
- name: harbor-robot-secret
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: tekton-triggers-admin-clusterrole
rules:
- resources: ["pipelines", "pipelineruns", "taskruns", "tasks"]
apiGroups: ["tekton.dev"]
verbs: ["create", "get", "list", "watch", "update", "patch", "delete"]
- resources: ["pipelineresources"]
apiGroups: ["tekton.dev"]
verbs: ["create", "get", "list", "watch"]
- resources: ["eventlisteners", "triggerbindings", "triggertemplates", "triggers"]
apiGroups: ["triggers.tekton.dev"]
verbs: ["get", "list", "watch"]
- resources: ["configmaps", "secrets"]
apiGroups: [""]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tekton-triggers-admin-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: tekton-triggers-admin-clusterrole
subjects:
- kind: ServiceAccount
name: tekton-triggers-admin
namespace: tekton-pipelines
Step 5:在 GitHub/GitLab 配置 Webhook
GitHub 配置步骤:
1. 打开仓库 → Settings → Webhooks → Add webhook
2. Payload URL: https://tekton-webhook.stellardata.top/tekton/events
3. Content type: application/json
4. Secret: 输入与 github-webhook-secret 中一致的密钥
5. SSL verification: Enable SSL verification
6. Which events: 勾选 "Just the push event" 或 "Let me select individual events"
- 选择: Pushes, Pull requests, Tag creation
7. Active: ✅ 勾选
GitLab 配置步骤:
# 如果使用 GitLab Interceptor,EventListener 配置如下:
# 注意 GitLab 使用 Secret Token 而非 HMAC 签名验证
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: gitlab-listener
namespace: tekton-pipelines
spec:
triggers:
- name: gitlab-push
interceptors:
- ref:
name: gitlab
params:
- name: secretRef
value:
secretName: gitlab-webhook-secret
secretKey: secretToken
- name: eventTypes
value: ["Push Hook"]
bindings:
- ref: gitlab-push-binding
template:
ref: build-and-deploy-template
Step 6:验证 Webhook 接入
部署完成后,通过以下方式验证:
# 1. 检查 EventListener Pod 是否正常运行
kubectl get pods -n tekton-pipelines -l eventlistener=github-listener
# 2. 查看 EventListener 日志
kubectl logs -n tekton-pipelines -l eventlistener=github-listener --tail=50
# 3. 手动模拟 Webhook 请求(测试用)
curl -k -X POST
https://tekton-webhook.stellardata.top/tekton/events
-H "Content-Type: application/json"
-H "X-GitHub-Event: push"
-H "X-Hub-Signature-256: sha256=..."
-d '{
"ref": "refs/heads/main",
"after": "abc123def456",
"repository": {
"clone_url": "https://github.com/example/my-app.git",
"full_name": "example/my-app"
},
"head_commit": {
"message": "feat: add new feature",
"committer": {"name": "developer"},
"timestamp": "2026-08-24T00:00:00Z"
}
}'
# 4. 查看生成的 PipelineRun
kubectl get pipelineruns -n tekton-pipelines --sort-by=.metadata.creationTimestamp
# 5. 在 GitHub 仓库 Webhook 页面查看最近投递记录
# Settings → Webhooks → 点击你的 webhook → Recent Deliveries
Step 7:高级 CEL Interceptor 过滤示例
CEL Interceptor 支持复杂的表达式过滤,以下是几个生产场景示例:
# CEL 过滤示例:仅处理 main 分支、排除机器人提交、匹配特定路径
apiVersion: triggers.tekton.dev/v1beta1
kind: Trigger
metadata:
name: cel-filter-trigger
namespace: tekton-pipelines
spec:
interceptors:
- ref:
name: cel
params:
- name: filter
value: >
body.ref == 'refs/heads/main' &&
body.head_commit.committer.name != 'dependabot[bot]' &&
!has(body.head_commit.modified) ||
body.head_commit.modified.exists(f, f.startsWith('src/'))
- name: overlays
- name: short_sha
expression: "body.after.substring(0, 7)"
- name: image_tag
expression: "'v' + string(timestamp(body.head_commit.timestamp).getDate().toString())"
template:
ref: build-and-deploy-template
CEL 表达式说明:
| 表达式 | 作用 |
|---|---|
body.ref == 'refs/heads/main' |
只匹配 main 分支的推送 |
body.head_commit.committer.name != 'dependabot[bot]' |
排除机器人提交 |
body.head_commit.modified.exists(f, f.startsWith('src/')) |
仅当修改了 src/ 目录下的文件 |
body.after.substring(0, 7) |
提取提交 SHA 前 7 位作为短标识 |
overlays |
在 CEL 中计算新变量,附加到 TriggerBinding 参数中 |
常见问题
Q1: Webhook 配置后 EventListener 没有收到请求,怎么办?
排查步骤:
1. 确认 Ingress 外部域名 DNS 解析正确,nslookup tekton-webhook.stellardata.top
2. 检查 SSL/TLS 证书是否有效,openssl s_client -connect tekton-webhook.stellardata.top:443
3. 查看 EventListener Pod 日志是否有错误信息
4. 在 GitHub Webhook 页面查看 Recent Deliveries 是否有投递失败记录
5. 检查 Ingress 是否配置了正确的 backend service 名称和端口(默认 8080)
Q2: Webhook 签名验证失败,403 错误?
GitHub Interceptor 要求 Webhook Secret 必须一致:
– 确认 kubectl get secret github-webhook-secret -n tekton-pipelines -o jsonpath='{.data.secretToken}' | base64 -d 的值与 GitHub 仓库设置的 Secret 完全一致
– 注意 Secret 中不要有多余的换行符或空格
– 使用 echo -n "your-secret" 而不是 echo "your-secret" 创建 Secret,避免多余的换行
Q3: CEL Interceptor 过滤后流水线没有触发?
CEL 表达式返回 false 时不会触发。可以使用 cel 的 overlays 输出调试信息:
- name: debug_output
expression: "'debug: ref=' + body.ref + ' action=' + body.action"
在日志中查看 debug_output 的值,确认事件数据是否符合预期。
Q4: 如何区分 Push 事件和 Tag 事件?
Push 事件中 ref 字段格式不同:
– 分支推送:refs/heads/main
– 标签推送:refs/heads/v1.0.0
CEL 过滤:
# 只匹配标签事件
- name: filter
value: "body.ref.startsWith('refs/tags/')"
Q5: 多仓库复用同一个 EventListener 如何区分?
可以在 EventListener 中配置多个 Trigger,每个 Trigger 通过 CEL Interceptor 匹配不同的仓库 URL:
- name: app-a-trigger
interceptors:
- ref:
name: cel
params:
- name: filter
value: "body.repository.full_name == 'team-a/app-a'"
- name: app-b-trigger
interceptors:
- ref:
name: cel
params:
- name: filter
value: "body.repository.full_name == 'team-b/app-b'"
总结
本文详细介绍了如何为 Tekton 流水线接入 GitHub/GitLab 事件,实现真正的事件驱动 CI。以下是核心要点:
- 三层拦截体系:GitHub/GitLab Interceptor 负责签名验证和事件解析,CEL Interceptor 负责分支/事件类型过滤,TriggerBinding 负责变量提取,形成完整的事件处理链
- 多事件路由:通过一个 EventListener 配置多个 Trigger,实现 Push 触发构建、PR 触发校验、Tag 触发版本发布的不同路由策略,避免为每种事件类型部署多个入口
- 动态参数注入:TriggerBinding 从 Webhook 载荷中提取分支名、提交 SHA、仓库 URL 等参数,TriggerTemplate 将这些参数注入到 PipelineRun 中,实现完全动态的流水线运行
- 生产级过滤:CEL Interceptor 支持复杂的逻辑表达式,可以排除机器人提交、过滤特定文件路径、提取时间戳作为镜像标签等高级场景
下一篇文章将介绍 tkn CLI 完全指南,带你掌握用命令行管理 Tekton 资源的所有技巧。















暂无评论内容