快速开始

Tekton Results 的安装

本文档说明如何使用已有数据库安装 Tekton Results。

NOTE

当前不支持内置的 PostgreSQL 数据库,请使用外部数据库。

关于外部数据库,请参见 Using PostgreSQL from Data Services

TIP

Tekton Results 支持将日志存储在多种存储后端。推荐使用 S3 兼容的对象存储(如 AWS S3、Ceph、MinIO),以实现可扩展且持久的日志保存。详细的 S3 存储配置请参见 S3 Storage Configuration Guide。不建议在生产环境中使用本地 PVC 存储。

前提条件

  1. 集群中必须已安装 Tekton Pipelines。

    TIP

    以下说明默认假设您已将 Results 安装在 tekton-pipelines 命名空间中。

    如果安装在其他命名空间,请将 tekton-pipelines 替换为您的命名空间。

  2. 创建数据库 root 密码。

    用户必须生成数据库 root 密码,并在安装前将其存储在 Kubernetes Secret 中。默认情况下,Tekton Results 期望该 Secret 具有以下属性:

    • 命名空间:tekton-pipelines
    • 名称:tekton-results-postgres
    • 包含以下字段:
      • POSTGRES_USER=<your_username>
      • POSTGRES_PASSWORD=<your_password>

    您可以使用以下命令快速生成一个 Secret

    kubectl create secret generic tekton-results-postgres --namespace="tekton-pipelines" --from-literal=POSTGRES_USER={POSTGRES} --from-literal=POSTGRES_PASSWORD={PASSWORD}
  3. 生成证书/密钥对。注意:可以使用任何证书管理软件完成此操作!

    Tekton Results 期望将证书/密钥对存储在名为 tekton-results-tlsTLS Kubernetes Secret 中。

    • 生成新的自签名证书

      openssl req -x509 \
        -newkey rsa:4096 \
        -keyout key.pem \
        -out cert.pem \
        -days 365 \
        -nodes \
        -subj "/CN=tekton-results-api-service.tekton-pipelines.svc.cluster.local" \
        -addext "subjectAltName = DNS:tekton-results-api-service.tekton-pipelines.svc.cluster.local"
      TIP

      如果您的 openssl 版本过低且不支持某些参数,请从 openssl binaries 升级您的 openssl 版本。

    • 使用证书创建新的 TLS Secret。

      kubectl create secret tls -n tekton-pipelines tekton-results-tls \
        --cert=cert.pem \
        --key=key.pem
  4. (仅快速开始)如果使用传统的 File 存储类型(不推荐用于生产),请创建一个 PVC

    WARNING

    基于 PVC 的本地存储不推荐用于生产环境。推荐使用 S3 兼容的对象存储,以实现可扩展且持久的日志保存。有关 S3 存储配置,请参见 S3 Storage Configuration Guide

    如果您仍需使用 PVC 进行测试:

    cat <<EOF | kubectl create -f -
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: tekton-logs
      namespace: tekton-pipelines
    spec:
      accessModes:
        - ReadWriteOnce  # 访问模式,表示单个节点可读写
      resources:
        requests:
          storage: 100Gi  # 请求的存储大小
    EOF
    • 请根据需要调整 PVC 大小。
    • 注意:仅在使用传统 File 存储类型时需要。

使用 operator CRD 安装

$ cat <<EOF | kubectl create -f -
apiVersion: operator.tekton.dev/v1alpha1
kind: TektonConfig
metadata:
  name: config
spec:
  # 目标命名空间
  targetNamespace: tekton-pipelines
  result:
    # 数据库地址
    db_host: <database_host>
    db_port: 5432
    db_name: <database_name>
    # 使用外部数据库
    is_external_db: true
    # 之前创建的包含数据库账户信息的 secret
    db_secret_name: tekton-results-postgres
    # 基础设置
    server_port: 8080
    # 禁用认证
    auth_disable: true
    db_enable_auto_migration: true
    log_level: debug
    # 使用日志存储服务
    logs_api: true
    log_type: File
    logging_pvc_name: tekton-logs
    # logs_type: S3  # 推荐:使用 S3 兼容存储实现可扩展日志保存
    # secret_name: tekton-results-s3-credentials  # 包含 S3 凭据的 Secret
    logs_path: /logs
    logs_buffer_size: 92160
    # S3 存储不需要 PVC,区别于传统 File 存储
EOF
DETAILS

所有 Tekton Results 配置字段均嵌套在 TektonConfig 资源的 spec.result 下。

  • db_host:数据库主机。
  • db_port:数据库端口。
  • db_name:数据库名称。
  • is_external_db:是否使用外部数据库。
    • true:使用外部数据库。
  • db_secret_name:包含数据库账户信息的 Secret 名称。
    • 即前一步创建的 Secret。
  • server_port:服务器端口。
  • targetNamespace:Results 部署所在命名空间。
  • auth_disable:是否禁用认证。
  • db_enable_auto_migration:是否启用自动数据库迁移。
  • log_level:日志级别。
  • logs_api:是否启用日志 API。
    • true:启用日志 API。
  • logs_type:日志类型。
    • File:将日志存储在文件中(不推荐用于生产)。
    • S3:将日志存储在 S3 兼容对象存储中(如 AWS S3、Ceph、MinIO)。这是推荐的可扩展且持久的日志保存方式。详细配置请参见 S3 Storage Configuration Guide
  • secret_name:包含 S3 账户信息的 Secret 名称。详细配置请参见 S3 Storage Configuration Guide
  • logs_path:日志路径。
  • logs_buffer_size:日志缓冲区大小。
  • logging_pvc_name:用于存储日志的 PVC 名称(仅在使用传统 File 存储类型时需要)。
    • 即前一步创建的 PVC(S3 存储不需要)。
TIP

更多数据库配置,请参见 PostgreSQL Configuration

部署完成后,您可以看到 results-api / results-retention-policy-agent / results-watcher 的状态为 Running

$ kubectl get pods -n tekton-pipelines

NAME                                                    READY   STATUS    RESTARTS   AGE
tekton-results-api-68bb657996-bb487                     1/1     Running   0          14s
tekton-results-retention-policy-agent-c6ff5575b-prczg   1/1     Running   0          14s
tekton-results-watcher-6d7c68f576-p2gbl                 1/1     Running   0          14s

功能验证

可以通过一个简单的 taskrun 来验证功能。

1. 创建一个 TaskRun 资源

$ cat <<'EOF' | kubectl create -f -
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
  name: hello
spec:
  taskSpec:
    steps:
      - name: hello
        image: alpine
        command: ["echo", "hello"]
EOF
NOTE

对于隔离环境,请将 alpine 镜像地址替换为网络中可用的其他镜像

2. 等待任务执行完成

$ kubectl get taskruns.tekton.dev -n default -w

hello                                        Unknown     Pending     3s
hello                                        True        Succeeded   11s         0s

3. 使用 tkn-results CLI 查询结果

准备 CLI

tkn 是与 Tekton 交互的命令行工具。您可以从 官方页面 下载。

您需要使用 golang 构建 tkn-results

# 1. 克隆仓库
git clone https://github.com/tektoncd/results.git

# 2. 进入项目目录
cd results

# 3. 构建二进制文件
go build -o tkn-results ./cmd/tkn-results/main.go

# 4. 将二进制文件复制到 PATH 中的目录
查询执行记录列表
$ tkn results --insecure records list default/results/-

default/results/209dcb81-e3c0-47cd-b082-d910e15702ae/records/209dcb81-e3c0-47cd-b082-d910e15702ae  tekton.dev/v1.TaskRun                   2025-02-19 16:17:11 +0800 CST           2025-02-19 16:17:21 +0800 CST
default/results/209dcb81-e3c0-47cd-b082-d910e15702ae/records/a750035d-0479-34a1-9db2-9a256b53243f  results.tekton.dev/v1alpha3.Log         2025-02-19 16:17:21 +0800 CST           2025-02-19 16:17:21 +0800 CST
查询单条执行记录
$ tkn results --insecure records get -o textproto default/results/209dcb81-e3c0-47cd-b082-d910e15702ae/records/209dcb81-e3c0-47cd-b082-d910e15702ae

name: "default/results/209dcb81-e3c0-47cd-b082-d910e15702ae/records/209dcb81-e3c0-47cd-b082-d910e15702ae"
id: "0805bbd0-e390-40dc-a1ea-f65ae9401930"
uid: "0805bbd0-e390-40dc-a1ea-f65ae9401930"
data: {
  type: "tekton.dev/v1.TaskRun"
  value: "{\"kind\": \"TaskRun\", \"spec\": {\"timeout\": \"1h0m0s\", \"taskSpec\": {\"steps\": [{\"name\": \"hello\", \"image\": \"152-231-registry.alauda.cn:60070/ops/ubuntu:latest\", \"command\": [\"echo\", \"hello\"], \"computeResources\": {}}]}, \"serviceAccountName\": \"default\"}, \"status\": {\"steps\": [{\"name\": \"hello\", \"imageID\": \"alpine\", \"container\": \"step-hello\", \"terminated\": {\"reason\": \"Completed\", \"exitCode\": 0, \"startedAt\": \"2025-02-19T08:17:20Z\", \"finishedAt\": \"2025-02-19T08:17:20Z\", \"containerID\": \"containerd://5e2cb72ca758fc976744b06b5ee97564bcc0958ca9cee2a54fdaab64323a1bf9\"}, \"terminationReason\": \"Completed\"}], \"podName\": \"hello-pod\", \"taskSpec\": {\"steps\": [{\"name\": \"hello\", \"image\": \"152-231-registry.alauda.cn:60070/ops/ubuntu:latest\", \"command\": [\"echo\", \"hello\"], \"computeResources\": {}}]}, \"startTime\": \"2025-02-19T08:17:10Z\", \"conditions\": [{\"type\": \"Succeeded\", \"reason\": \"Succeeded\", \"status\": \"True\", \"message\": \"All Steps have completed executing\", \"lastTransitionTime\": \"2025-02-19T08:17:21Z\"}], \"provenance\": {\"featureFlags\": {\"Coschedule\": \"workspaces\", \"MaxResultSize\": 4096, \"EnableAPIFields\": \"beta\", \"EnableArtifacts\": false, \"EnableParamEnum\": false, \"DisableCredsInit\": false, \"EnableStepActions\": true, \"SetSecurityContext\": false, \"AwaitSidecarReadiness\": true, \"EnableKeepPodOnCancel\": false, \"EnableTektonOCIBundles\": false, \"ResultExtractionMethod\": \"termination-message\", \"SendCloudEventsForRuns\": false, \"DisableAffinityAssistant\": false, \"EnableProvenanceInStatus\": true, \"EnforceNonfalsifiability\": \"none\", \"EnableCELInWhenExpression\": false, \"VerificationNoMatchPolicy\": \"ignore\", \"ScopeWhenExpressionsToTask\": false, \"RequireGitSSHSecretKnownHosts\": false, \"RunningInEnvWithInjectedSidecars\": true}}, \"completionTime\": \"2025-02-19T08:17:21Z\"}, \"metadata\": {\"uid\": \"209dcb81-e3c0-47cd-b082-d910e15702ae\", \"name\": \"hello\", \"labels\": {\"app.kubernetes.io/managed-by\": \"tekton-pipelines\"}, \"namespace\": \"default\", \"finalizers\": [\"results.tekton.dev/taskrun\", \"chains.tekton.dev\"], \"generation\": 1, \"annotations\": {\"results.tekton.dev/log\": \"default/results/209dcb81-e3c0-47cd-b082-d910e15702ae/logs/a750035d-0479-34a1-9db2-9a256b53243f\", \"chains.tekton.dev/signed\": \"true\", \"results.tekton.dev/record\": \"default/results/209dcb81-e3c0-47cd-b082-d910e15702ae/records/209dcb81-e3c0-47cd-b082-d910e15702ae\", \"results.tekton.dev/result\": \"default/results/209dcb81-e3c0-47cd-b082-d910e15702ae\", \"pipeline.tekton.dev/release\": \"8bfd3273cbe7776847884d7fa5004481e6be8f4a\"}, \"managedFields\": [{\"time\": \"2025-02-19T08:17:10Z\", \"manager\": \"kubectl-create\", \"fieldsV1\": {\"f:spec\": {\".\": {}, \"f:taskSpec\": {\".\": {}, \"f:steps\": {}}}}, \"operation\": \"Update\", \"apiVersion\": \"tekton.dev/v1\", \"fieldsType\": \"FieldsV1\"}, {\"time\": \"2025-02-19T08:17:21Z\", \"manager\": \"controller\", \"fieldsV1\": {\"f:metadata\": {\"f:finalizers\": {\"v:\\\"chains.tekton.dev\\\"\": {}}, \"f:annotations\": {\"f:chains.tekton.dev/signed\": {}, \"f:pipeline.tekton.dev/release\": {}}}}, \"operation\": \"Update\", \"apiVersion\": \"tekton.dev/v1\", \"fieldsType\": \"FieldsV1\"}, {\"time\": \"2025-02-19T08:17:21Z\", \"manager\": \"controller\", \"fieldsV1\": {\"f:status\": {\".\": {}, \"f:steps\": {}, \"f:podName\": {}, \"f:taskSpec\": {\".\": {}, \"f:steps\": {}}, \"f:artifacts\": {}, \"f:startTime\": {}, \"f:conditions\": {}, \"f:provenance\": {\".\": {}, \"f:featureFlags\": {\".\": {}, \"f:Coschedule\": {}, \"f:MaxResultSize\": {}, \"f:EnableAPIFields\": {}, \"f:EnableArtifacts\": {}, \"f:EnableParamEnum\": {}, \"f:DisableCredsInit\": {}, \"f:DisableInlineSpec\": {}, \"f:EnableStepActions\": {}, \"f:SetSecurityContext\": {}, \"f:AwaitSidecarReadiness\": {}, \"f:EnableKeepPodOnCancel\": {}, \"f:ResultExtractionMethod\": {}, \"f:SendCloudEventsForRuns\": {}, \"f:EnableKubernetesSidecar\": {}, \"f:DisableAffinityAssistant\": {}, \"f:EnableProvenanceInStatus\": {}, \"f:EnforceNonfalsifiability\": {}, \"f:EnableCELInWhenExpression\": {}, \"f:VerificationNoMatchPolicy\": {}, \"f:EnableConciseResolverSyntax\": {}, \"f:RequireGitSSHSecretKnownHosts\": {}, \"f:RunningInEnvWithInjectedSidecars\": {}}}, \"f:completionTime\": {}}}, \"operation\": \"Update\", \"apiVersion\": \"tekton.dev/v1\", \"fieldsType\": \"FieldsV1\", \"subresource\": \"status\"}, {\"time\": \"2025-02-19T08:17:21Z\", \"manager\": \"watcher\", \"fieldsV1\": {\"f:metadata\": {\"f:finalizers\": {\".\": {}, \"v:\\\"results.tekton.dev/taskrun\\\"\": {}}, \"f:annotations\": {\".\": {}, \"f:results.tekton.dev/log\": {}, \"f:results.tekton.dev/record\": {}, \"f:results.tekton.dev/result\": {}}}}, \"operation\": \"Update\", \"apiVersion\": \"tekton.dev/v1\", \"fieldsType\": \"FieldsV1\"}], \"resourceVersion\": \"1592422\", \"creationTimestamp\": \"2025-02-19T08:17:10Z\"}, \"apiVersion\": \"tekton.dev/v1\"}"
}
etag: "0805bbd0-e390-40dc-a1ea-f65ae9401930-1739953041309658421"
created_time: {
  seconds: 1739953031
  nanos: 16922000
}
create_time: {
  seconds: 1739953031
  nanos: 16922000
}
updated_time: {
  seconds: 1739953041
  nanos: 309658000
}
update_time: {
  seconds: 1739953041
  nanos: 309658000
}
查询日志列表
$ tkn results --insecure logs list default/results/-

default/results/209dcb81-e3c0-47cd-b082-d910e15702ae/logs/a750035d-0479-34a1-9db2-9a256b53243f  results.tekton.dev/v1alpha3.Log         2025-02-19 16:17:21 +0800 CST           2025-02-19 16:17:21 +0800 CST
查询单条日志
$ tkn results --insecure logs get -o textproto default/results/209dcb81-e3c0-47cd-b082-d910e15702ae/logs/a750035d-0479-34a1-9db2-9a256b53243f

content_type: "text/plain"
data: "[prepare] 2025/02/19 08:17:12 Entrypoint initialization\n\n[hello] hello\n\n"

参考资料