PAC Resolver

对于普通用户

本指南面向普通用户,介绍如何使用 PAC 解析器自动解析并嵌入来自本地仓库、Tekton Hub 以及远程 URL 的任务和流水线。

本指南讲解如何使用 Pipelines as Code (PAC) 解析器,自动解析并嵌入来自三种来源的任务和流水线:仓库中定义的本地任务、Tekton Hub 的远程任务,以及远程 Git 仓库或 HTTP URL 的任务。

目录

前提条件

  • 已部署并运行 PAC 组件
  • 已配置 Repository CR(参见配置仓库
  • 理解 Tekton PipelineRun 结构

关于 PAC 解析器

PAC 解析器会自动获取并嵌入远程任务和流水线到你的 PipelineRun 定义中,免去了手动定义任务或在流水线代码中使用解析器语法的需求。

任务嵌入工作原理

当 PAC 从 Tekton Hub 解析任务时:

  1. PAC 从 Hub 获取任务定义(YAML)
  2. PAC 将 taskRef 转换为 taskSpec,并将任务定义内联嵌入 PipelineRun 中
  3. 嵌入的任务成为 PipelineRun 定义的一部分
  4. 该任务无需作为独立的 Task 资源存在于集群中

这意味着你可以直接使用 Tekton Hub 的任务,无需手动复制定义或在集群中创建 Task 资源。

支持的来源

  • 本地任务:在 Git 仓库中定义的任务(使用 taskSpec 或解析器语法)
  • Tekton Hub:来自 Tekton Hub 目录的任务和流水线
  • 远程 URL:来自远程 Git 仓库或 HTTP URL 的任务和流水线

官方文档

有关 Pipelines as Code 远程解析功能的详细信息,请参阅:

PAC 解析器工作原理

理解解析器工作流程有助于排查问题和优化流水线配置。

解析器工作流程

当 PAC 处理带有解析器注解的 PipelineRun 时,执行以下步骤:

  1. 事件触发:Git 事件(push、pull request 等)触发 PAC 控制器
  2. 流水线获取:PAC 控制器从 Git 仓库获取 PipelineRun 定义
  3. 注解检测:PAC 控制器扫描注解中的解析器指令:
    • pipelinesascode.tekton.dev/task: "task-name"
    • pipelinesascode.tekton.dev/task-1: "task-name"
    • pipelinesascode.tekton.dev/pipeline: "pipeline-name"
  4. 任务解析:针对每个任务注解:
    • PAC 控制器查询 Tekton Hub API(或配置的 hub URL)
    • 获取任务定义(YAML)
    • 验证任务结构
  5. 任务嵌入:PAC 将解析的任务定义嵌入 PipelineRun:
    • taskRef 转换为 taskSpec,并将任务定义内联嵌入每个任务条目
    • 嵌入的任务成为 PipelineRun 定义的一部分,无需在集群中存在独立 Task 资源
  6. 创建 PipelineRun:PAC 在 Kubernetes 中创建最终带有嵌入任务的 PipelineRun
  7. 执行:Tekton Pipeline 控制器接收并执行 PipelineRun

详细示例:逐步解析

下面通过完整示例演示解析器的工作过程:

第 1 步:原始 PipelineRun 定义

你在仓库中定义一个 PipelineRun(.tekton/pipelinerun.yaml):

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: my-pipeline
  annotations:
    pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
    pipelinesascode.tekton.dev/on-event: "[push]"
    pipelinesascode.tekton.dev/task: "git-clone"
spec:
  pipelineSpec:
    tasks:
    - name: fetch-code
      taskRef:
        name: git-clone
      params:
        - name: url
          value: "https://github.com/tektoncd/catalog.git"
        - name: revision
          value: "main"

第 2 步:PAC 控制器处理注解

当发生 push 事件时,PAC 控制器:

  1. 从 Git 读取 PipelineRun:获取仓库中的 .tekton/pipelinerun.yaml 文件

  2. 检测注解:扫描类似 pipelinesascode.tekton.dev/task: "git-clone" 的任务注解

  3. 解析任务名称和版本

    • 仅任务名(如 "git-clone"):从 Hub 获取最新版本
    • 带版本(如 "git-clone:0.1"):获取指定版本
    • 版本选择规则
      • 未指定版本 → PAC 查询 Hub 最新稳定版本
      • 指定版本(格式:task-name:version)→ PAC 获取该版本
      • 版本格式遵循语义版本(如 0.10.91.2.3
  4. 查询 Tekton Hub API

    • Hub URL:默认指向集群内 Hub (http://tekton-hub-api.tekton-pipelines:8000/v1) 或公共 Hub (https://api.hub.tekton.dev/v1)
    • 查询最新版本:PAC 查询 Hub 获取最新可用版本
    • 查询指定版本:PAC 请求注解中指定的版本
    • 示例查询
      • 最新版本:"git-clone" → Hub 返回最新版本
      • 指定版本:"git-clone:0.1" → Hub 返回 0.1 版本
  5. 接收 Hub 返回的任务定义:Hub 返回完整 Task YAML:

    apiVersion: tekton.dev/v1
    kind: Task
    metadata:
      name: git-clone
    spec:
      params:
      - name: url
        description: git url to clone
      - name: revision
        description: revision to checkout
      steps:
      - name: clone
        image: gcr.io/tekton-releases/git-init
        script: |
          #!/bin/sh
          git clone $(params.url) $(workspaces.output.path)
          cd $(workspaces.output.path)
          git checkout $(params.revision)

版本选择最佳实践

  • 生产环境:指定确切版本(如 "git-clone:0.1")以保证可复现性和稳定性
  • 开发/测试:使用最新版本(无版本后缀)以自动获得新功能和修复
  • 版本锁定:生产环境务必锁定具体版本,避免 Hub 更新导致破坏性变更
  • 版本更新:定期审查并受控更新锁定版本

第 3 步:PAC 将任务嵌入 PipelineRun

PAC 修改 PipelineRun,将 taskRef 转换为 taskSpec 并嵌入解析后的任务定义:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: my-pipeline
  annotations:
    pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
    pipelinesascode.tekton.dev/on-event: "[push]"
spec:
  pipelineSpec:
    tasks:
    - name: fetch-code
      # PAC 将 taskRef 转换为 taskSpec 并嵌入任务定义
      taskSpec:
        params:
        - name: url
          description: git url to clone
        - name: revision
          description: revision to checkout
        steps:
        - name: clone
          image: gcr.io/tekton-releases/git-init
          script: |
            #!/bin/sh
            git clone $(params.url) $(workspaces.output.path)
            cd $(workspaces.output.path)
            git checkout $(params.revision)
      params:
        - name: url
          value: "https://github.com/tektoncd/catalog.git"
        - name: revision
          value: "main"

第 4 步:在 Kubernetes 中创建 PipelineRun

PAC 在集群中创建最终的 PipelineRun。你可以通过以下命令验证:

kubectl get pipelinerun my-pipeline -n <namespace> -o yaml

示例输出(简略,显示嵌入任务):

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: my-pipeline
spec:
  pipelineSpec:
    tasks:
    - name: fetch-code
      # 任务定义以 taskSpec 形式嵌入
      taskSpec:
        params:
        - name: url
        - name: revision
        steps:
        - name: clone
          image: gcr.io/tekton-releases/git-init
          script: |
            #!/bin/sh
            git clone $(params.url) $(workspaces.output.path)
      params:
        - name: url
          value: "https://gitlab.com/user/repo"
        - name: revision
          value: "abc1234"

解析器时机

重要:任务解析发生在 PipelineRun 创建到 Kubernetes 之前。这意味着:

  • 任务在流水线定义阶段解析,而非执行阶段
  • 若任务无法解析,PipelineRun 创建将失败
  • 可通过查看 Kubernetes 中的 PipelineRun YAML 验证任务解析情况
  • PAC 会缓存解析的任务以提升性能

验证任务解析

验证任务是否正确解析:

  1. 检查 Kubernetes 中的 PipelineRun

    kubectl get pipelinerun <name> -n <namespace> -o yaml

查找任务中内联的 taskSpec

spec:
  pipelineSpec:
    tasks:
    - name: fetch-code
      taskSpec:
        params:
        - name: url
        - name: revision
        steps:
        - name: clone
          image: gcr.io/tekton-releases/git-init
          script: |
            #!/bin/sh
            git clone $(params.url) $(workspaces.output.path)
      params:
        - name: url
          value: "https://gitlab.com/user/repo"
        - name: revision
          value: "abc1234"
理解任务嵌入

PAC 通过将 taskRef 转换为 taskSpec 来嵌入解析后的任务,任务定义以内联形式作为 PipelineRun 的一部分,符合 Tekton 标准语法。

  1. 查看 PAC 控制器日志

    kubectl logs -n <pac-namespace> -l app=pipelines-as-code-controller --tail=100 | grep -i "task.*resolve"  # 将 <pac-namespace> 替换为实际命名空间(默认:tekton-pipelines)

示例输出(显示任务解析):

{"level":"info","ts":"2024-01-01T12:00:00Z","logger":"controller","msg":"Resolving task","task":"git-clone","source":"hub"}
{"level":"info","ts":"2024-01-01T12:00:01Z","logger":"controller","msg":"Task resolved successfully","task":"git-clone","version":"0.9"}
{"level":"info","ts":"2024-01-01T12:00:02Z","logger":"controller","msg":"Task embedded in PipelineRun","task":"git-clone","pipelineRun":"my-pipeline"}
  1. 验证任务引用是否正确

    # 检查 taskRef.name 是否与注解中的任务名匹配
    kubectl get pipelinerun <name> -n <namespace> -o jsonpath='{.spec.pipelineSpec.tasks[*].taskRef.name}'

示例输出:

git-clone golangci-lint
  1. 检查 PipelineRun 是否成功创建

    kubectl get pipelinerun <name> -n <namespace> -o jsonpath='{.status.conditions[*].type}'

示例输出:

Succeeded

若任务解析失败,PipelineRun 可能未创建,或状态为 Failed 并带有错误信息。

使用本地任务

本地任务是直接在 Git 仓库中定义的任务。PAC 支持两种使用本地任务的方式:

内联任务定义(taskSpec)

你可以在 PipelineRun 中直接使用 taskSpec 定义任务:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: my-pipeline
  annotations:
    pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
    pipelinesascode.tekton.dev/on-event: "[push]"
spec:
  pipelineSpec:
    tasks:
    - name: build
      taskSpec:
        steps:
        - name: build
          image: golang:1.21
          script: |
            #!/bin/sh
            go build -o app ./cmd
    - name: test
      taskSpec:
        steps:
        - name: test
          image: golang:1.21
          script: |
            #!/bin/sh
            go test ./...

工作原理

  • 任务以内联 taskSpec 形式定义在流水线中
  • 无需外部解析,任务成为 PipelineRun 定义的一部分
  • 适用于简单且特定于仓库的任务

引用仓库中的任务文件

你也可以通过 PAC 注解引用仓库中存储的任务文件,使用特殊语法指向仓库内的任务。

重要:对于仓库中的任务,使用 pipelinesascode.tekton.dev/taskpipelinesascode.tekton.dev/task-<N> 注解格式。

仓库结构示例:

.tekton/
├── pipelinerun.yaml
└── tasks/
    ├── build-task.yaml
    └── test-task.yaml

使用 PAC 注解的 PipelineRun 定义:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: my-pipeline
  annotations:
    pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
    pipelinesascode.tekton.dev/on-event: "[push]"
    # 使用相对路径引用本地任务
    pipelinesascode.tekton.dev/task: ".tekton/tasks/build-task.yaml"
    pipelinesascode.tekton.dev/task-1: ".tekton/tasks/test-task.yaml"
spec:
  pipelineSpec:
    tasks:
    - name: build
      taskRef:
        name: build-task
    - name: test
      taskRef:
        name: test-task
      runAfter: [build]

工作原理

  • 当任务注解使用相对路径时,PAC 会自动解析并嵌入仓库中的任务
  • taskRef.name 应与 YAML 文件中定义的任务名称匹配
  • 该方式比使用 resolver: git 语法更简单,是 PAC 推荐的做法

何时使用本地任务

适合以下场景:

  • 任务特定于项目,不适合共享
  • 需要完全控制任务定义和版本
  • 任务随代码频繁变更
  • 希望任务和流水线一起纳入版本控制

使用远程任务注解

你可以使用 PAC 注解引用来自 Tekton Hub 或远程 HTTP URL 的任务,PAC 会自动获取并嵌入这些任务到 PipelineRun。

来自 Tekton Hub 的远程任务

引用单个 Tekton Hub 任务:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: my-pipeline
  annotations:
    pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
    pipelinesascode.tekton.dev/on-event: "[push]"
    pipelinesascode.tekton.dev/task: "git-clone"
spec:
  pipelineSpec:
    tasks:
    - name: fetch-code
      taskRef:
        name: git-clone
      params:
        - name: url
          value: "https://github.com/tektoncd/catalog.git"
        - name: revision
          value: "main"

工作原理

  • 注解 pipelinesascode.tekton.dev/task: "git-clone" 指示 PAC 从 Tekton Hub 获取 git-clone 任务
  • PAC 自动将任务定义嵌入 PipelineRun
  • 你可以通过 taskRef.name: git-clone 引用该任务

来自 HTTP URL 的远程任务

也可以引用远程 HTTP URL 的任务:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: my-pipeline
  annotations:
    pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
    pipelinesascode.tekton.dev/on-event: "[push]"
    # 引用远程 URL 的任务
    pipelinesascode.tekton.dev/task: "https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.9/git-clone.yaml"
spec:
  pipelineSpec:
    tasks:
    - name: fetch-code
      taskRef:
        name: git-clone
      params:
        - name: url
          value: "https://github.com/tektoncd/catalog.git"
        - name: revision
          value: "main"

工作原理

  • PAC 从指定 HTTP URL 获取任务定义
  • 自动将任务嵌入 PipelineRun
  • taskRef.name 应与远程 YAML 文件中定义的任务名称匹配

多任务注解

使用编号注解引用多个任务:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: build-pipeline
  annotations:
    pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
    pipelinesascode.tekton.dev/on-event: "[push]"
    pipelinesascode.tekton.dev/task: "git-clone"
    pipelinesascode.tekton.dev/task-1: "golangci-lint"
    pipelinesascode.tekton.dev/task-2: "buildah"
spec:
  pipelineSpec:
    tasks:
    - name: fetch
      taskRef:
        name: git-clone
      params:
        - name: url
          value: "https://github.com/tektoncd/catalog.git"
        - name: revision
          value: "main"
    - name: lint
      taskRef:
        name: golangci-lint
      runAfter: [fetch]
    - name: build
      taskRef:
        name: buildah
      runAfter: [lint]

任务列表语法

你也可以使用括号语法在单个注解中指定多个任务:

metadata:
  annotations:
    pipelinesascode.tekton.dev/task-1: "[golangci-lint, buildah]"

等同于:

metadata:
  annotations:
    pipelinesascode.tekton.dev/task-1: "golangci-lint"
    pipelinesascode.tekton.dev/task-2: "buildah"

任务版本指定

默认情况下,PAC 从 Hub 获取任务的最新版本。若需指定版本,使用格式 task-name:version

参考:更多远程任务解析细节,请参阅 Red Hat OpenShift Pipelines as Code 文档

最新版本(推荐用于开发):

metadata:
  annotations:
    pipelinesascode.tekton.dev/task: "git-clone"

指定版本(推荐用于生产):

metadata:
  annotations:
    pipelinesascode.tekton.dev/task: "git-clone:0.9"

多个任务指定版本

metadata:
  annotations:
    pipelinesascode.tekton.dev/task: "git-clone:0.9"
    pipelinesascode.tekton.dev/task-1: "golangci-lint:0.4"
    pipelinesascode.tekton.dev/task-2: "buildah"  # 使用最新版本

自定义 Hub URL

默认 hub-url 指向默认命名空间中的集群内 Tekton Hub 服务(http://tekton-hub-api.tekton-pipelines:8000/v1)。若 Tekton Hub 部署在其他命名空间,请相应调整 URL 中的命名空间。若需使用不同的 Hub 实例,可在 OpenShiftPipelinesAsCode CR 中配置:

apiVersion: operator.tekton.dev/v1alpha1
kind: OpenShiftPipelinesAsCode
metadata:
  name: pipelines-as-code
spec:
  settings:
    # 集群内不同命名空间的 Hub
    hub-url: "http://tekton-hub-api.<your-namespace>:8000/v1"
    
    # 或外部/公共 Hub
    hub-url: "https://api.hub.tekton.dev/v1"
    
    # 或自定义 Hub 实例
    hub-url: "https://custom-hub.example.com/v1"

注意:仅 PAC 控制器需要访问 Hub URL。若使用集群内 Hub,确保 PAC 控制器能访问该服务。

使用远程流水线注解

使用场景有限

远程流水线注解在实际中较少使用。大多数用户倾向于使用 pipelineSpec 内联定义流水线,而非引用远程流水线。本节内容为完整性保留。

你可以引用来自 Tekton Hub 的远程流水线,尽管这不如内联定义常见:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: my-pipeline
  annotations:
    pipelinesascode.tekton.dev/on-target-branch: "[refs/heads/main]"
    pipelinesascode.tekton.dev/on-event: "[push]"
    # 引用 Tekton Hub 的远程流水线
    pipelinesascode.tekton.dev/pipeline: "pipeline-name"
spec:
  pipelineRef:
    name: pipeline-name
  params:
  - name: image-url
    value: "registry.example.com/myapp"

工作原理

  • 注解 pipelinesascode.tekton.dev/pipeline: "pipeline-name" 指示 PAC 从 Tekton Hub 获取流水线
  • PAC 自动嵌入流水线定义
  • 通过 pipelineRef.name 引用该流水线

注意:大多数情况下,建议在仓库中使用 pipelineSpec 内联定义流水线,以便更好地进行版本控制和流水线定义的可见性。

结合远程任务和流水线

与解析器语法的比较

PAC 注解提供了比 Tekton 解析器语法更简洁的替代方案:

使用 PAC 注解(推荐)

metadata:
  annotations:
    pipelinesascode.tekton.dev/task: "git-clone"
spec:
  pipelineSpec:
    tasks:
    - name: clone
      taskRef:
        name: git-clone

使用解析器语法

spec:
  pipelineSpec:
    tasks:
    - name: clone
      taskRef:
        resolver: hub
        params:
        - name: name
          value: git-clone
        - name: kind
          value: task

PAC 注解优势

  • 语法更简单
  • 自动嵌入任务
  • 无需指定解析器参数
  • 与 PAC 任务解析无缝配合

故障排查

任务未找到

  1. 验证任务名称:确认 Tekton Hub 中任务名称正确

  2. 检查 Hub URL:确认 hub URL 配置正确

  3. 查看 PAC 日志

    kubectl logs -n <pac-namespace> -l app=pipelines-as-code-controller --tail=100 | grep -i task

示例输出:

{"level":"info","ts":"2024-01-01T12:00:00Z","logger":"controller","msg":"Resolving task","task":"git-clone","source":"hub"}
{"level":"info","ts":"2024-01-01T12:00:01Z","logger":"controller","msg":"Task resolved successfully","task":"git-clone","version":"0.9"}
{"level":"info","ts":"2024-01-01T12:00:02Z","logger":"controller","msg":"Task embedded in PipelineRun","task":"git-clone","pipelineRun":"my-pipeline"}

任务解析失败

  1. 检查网络连通性:确保 PAC 控制器能访问 Tekton Hub

    # 从 PAC 控制器 Pod 测试 Hub 连接
    kubectl exec -n <pac-namespace> \
      $(kubectl get pod -n <pac-namespace> -l app=pipelines-as-code-controller -o jsonpath='{.items[0].metadata.name}') \
      -- curl -I https://api.hub.tekton.dev/v1/resource/task/git-clone

示例输出(可访问时):

HTTP/1.1 200 OK
Content-Type: application/json
  1. 验证 Hub 配置:检查 OpenShiftPipelinesAsCode CR 中的 hub-url 设置

    kubectl get openshiftpipelinesascodes.operator.tekton.dev pipelines-as-code -o jsonpath='{.spec.settings.hub-url}'

示例输出:

http://tekton-hub-api.tekton-pipelines:8000/v1
  1. 检查任务版本:确认指定版本存在

    # 查询 Tekton Hub 可用版本
    curl https://api.hub.tekton.dev/v1/resource/task/git-clone

示例输出(简略):

{
  "id": 1,
  "name": "git-clone",
  "kind": "Task",
  "latestVersion": {
    "id": 1,
    "version": "0.9"
  },
  "versions": [
    {"version": "0.9"},
    {"version": "0.8"},
    {"version": "0.7"}
  ]
}

任务未嵌入

  1. 验证注解语法:检查注解键和值格式是否正确
  2. 检查 PipelineRun:确保 taskRef.name 与注解中的任务名匹配
  3. 查看 PAC 控制器日志,排查嵌入错误

后续步骤