如何使用预定义的 GitLab CI 变量和流式传输到 GitLab Pipeline 日志的 Tekton 日志直接从 GitLab CI 触发 Tekton Pipeline

Posted

技术标签:

【中文标题】如何使用预定义的 GitLab CI 变量和流式传输到 GitLab Pipeline 日志的 Tekton 日志直接从 GitLab CI 触发 Tekton Pipeline【英文标题】:How to trigger Tekton Pipeline from GitLab CI directly with predefined GitLab CI variables & Tekton logs streamed into GitLab Pipeline logs 【发布时间】:2021-12-27 16:04:54 【问题描述】:

我们正在运行 AWS EKS(使用 Pulumi 设置),我们在其中安装了 Tekton,如 Cloud Native Buildpacks Tekton docs 中所述。 example project is available。

Our Tekton pipeline 是这样配置的(也是派生的from the Cloud Native Buildpacks Tekton docs):

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: buildpacks-test-pipeline
spec:
  params:
    - name: IMAGE
      type: string
      description: image URL to push
    - name: SOURCE_URL
      type: string
      description: A git repo url where the source code resides.
    - name: SOURCE_REVISION
      description: The branch, tag or SHA to checkout.
      default: ""
  workspaces:
    - name: source-workspace # Directory where application source is located. (REQUIRED)
    - name: cache-workspace # Directory where cache is stored (OPTIONAL)
  tasks:
    - name: fetch-repository # This task fetches a repository from github, using the `git-clone` task you installed
      taskRef:
        name: git-clone
      workspaces:
        - name: output
          workspace: source-workspace
      params:
        - name: url
          value: "$(params.SOURCE_URL)"
        - name: revision
          value: "$(params.SOURCE_REVISION)"
        - name: subdirectory
          value: ""
        - name: deleteExisting
          value: "true"
    - name: buildpacks # This task uses the `buildpacks` task to build the application
      taskRef:
        name: buildpacks
      runAfter:
        - fetch-repository
      workspaces:
        - name: source
          workspace: source-workspace
        - name: cache
          workspace: cache-workspace
      params:
        - name: APP_IMAGE
          value: "$(params.IMAGE)"
        - name: BUILDER_IMAGE
          value: paketobuildpacks/builder:base # This is the builder we want the task to use (REQUIRED)

我们已经添加了SOURCE_URLSOURCE_REVISION 作为参数。

问题是:我们如何从 GitLab CI 触发 Tekton PipelineRun(在我们的 .gitlab-ci.yml 中)遵守以下要求:

最简单的方法 不要使用Tekton Triggers(包括commit-status-tracker)引入的额外复杂性,但仍将 GitLab 作为事实来源(例如,查看提交时运行的绿色/红色管道等) 报告 Tekton Pipelines 成功运行为绿色 GitLab CI Pipelines,失败的 Tekton Pipelines 为红色 GitLab CI Pipelines 将 Tekton Pipeline 日志保存/流式传输到 GitLab CI Pipeline 日志中 - 以防 Tekton Pipelines 内出现错误或成功 将GitLab CI Predefined Variables 用于通用方法

【问题讨论】:

【参考方案1】:

TLDR;

我创建了一个完全可理解的示例项目,在此处显示所有必要的步骤和运行管道:https://gitlab.com/jonashackt/microservice-api-spring-boot/ 和完整的 .gitlab-ci.yml 以直接触发 Tekton 管道:

image: registry.gitlab.com/jonashackt/aws-kubectl-tkn:0.21.0

variables:
  AWS_DEFAULT_REGION: 'eu-central-1'

before_script:
  - mkdir ~/.kube
  - echo "$EKSKUBECONFIG" > ~/.kube/config
  - echo "--- Testdrive connection to cluster"
  - kubectl get nodes

stages:
  - build

build-image:
  stage: build
  script:
    - echo "--- Create parameterized Tekton PipelineRun yaml"
    - tkn pipeline start buildpacks-test-pipeline
      --serviceaccount buildpacks-service-account-gitlab
      --workspace name=source-workspace,subPath=source,claimName=buildpacks-source-pvc
      --workspace name=cache-workspace,subPath=cache,claimName=buildpacks-source-pvc
      --param IMAGE=$CI_REGISTRY_IMAGE
      --param SOURCE_URL=$CI_PROJECT_URL
      --param SOURCE_REVISION=$CI_COMMIT_REF_SLUG
      --dry-run
      --output yaml > pipelinerun.yml

    - echo "--- Trigger PipelineRun in Tekton / K8s"
    - PIPELINE_RUN_NAME=$(kubectl create -f pipelinerun.yml --output=jsonpath='.metadata.name')

    - echo "--- Show Tekton PipelineRun logs"
    - tkn pipelinerun logs $PIPELINE_RUN_NAME --follow

    - echo "--- Check if Tekton PipelineRun Failed & exit GitLab Pipeline accordingly"
    - kubectl get pipelineruns $PIPELINE_RUN_NAME --output=jsonpath='.status.conditions[*].reason' | grep Failed && exit 1 || exit 0

以下是您需要执行的简短步骤:

1.为您的.gitlab-ci.yml 选择一个基本映像,提供aws CLI、kubectl 和 Tekton CLI (tkn)

这完全取决于您。我创建了一个示例项目https://gitlab.com/jonashackt/aws-kubectl-tkn,它提供了一个图像,该图像基于官方https://hub.docker.com/r/amazon/aws-cli 图像,可通过registry.gitlab.com/jonashackt/aws-kubectl-tkn:0.21.0 访问。

2。用于 aws CLI 和 Kubernetes 集群访问的 CI/CD 变量

在您的 GitLab CI 项目中(或者更好的是:在您的 GitLab CI 项目所在的组内)您需要创建 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 作为 CI/CD 变量,其中包含 aws cli 凭据(请注意 @ 987654346@ 它们同时创建它们,以防止它们被打印到 GitLab CI 日志中)。根据您的 EKS 集群(或其他 K8s 集群)配置,您需要提供 kubeconfig 来访问您的集群。一种方法是创建一个 GitLab CI/CD 变量,如 EKSKUBECONFIG,提供必要的文件(例如,在示例项目中,这是由 Pulumi 提供的 pulumi stack output kubeconfig > kubeconfig)。在这个使用 Pulumi 的设置中,kubeconfig 内没有秘密凭据,因此不需要屏蔽变量。但请注意此处可能的凭据,并在需要时相应地保护它们。

同时定义包含您的 EKS 集群区域的 AWS_DEFAULT_REGION

# As we need kubectl, aws & tkn CLI we use https://gitlab.com/jonashackt/aws-kubectl-tkn
image: registry.gitlab.com/jonashackt/aws-kubectl-tkn:0.21.0

variables:
  AWS_DEFAULT_REGION: 'eu-central-1'

3.在before_script部分使用kubeconfig和testdrive集群连接

稍后在其他步骤中准备我们需要的东西可以在before_script 部分中完成。因此,让我们在那里创建目录~/.kube,并根据变量EKSKUBECONFIG 的内容创建文件~/.kube/config。最后触发kubectl get nodes 以检查集群连接是否正常。我们的before_script 部分现在看起来像这样:

before_script:
  - mkdir ~/.kube
  - echo "$EKSKUBECONFIG" > ~/.kube/config
  - echo "--- Testdrive connection to cluster"
  - kubectl get nodes

4.将参数传递给 Tekton PipelineRun

通过kubectl 传递参数并非易事——甚至需要使用像 Helm 这样的模板引擎来完成。但幸运的是,Tekton CLI 为我们提供了一些帮助:tkn pipeline start accepts parameters。因此我们可以将Cloud Native Buildpacks Tekton PipelineRun Yaml file 转换为tkn CLI 命令,如下所示:

tkn pipeline start buildpacks-test-pipeline \
    --serviceaccount buildpacks-service-account-gitlab \
    --workspace name=source-workspace,subPath=source,claimName=buildpacks-source-pvc \
    --workspace name=cache-workspace,subPath=cache,claimName=buildpacks-source-pvc \
    --param IMAGE=registry.gitlab.com/jonashackt/microservice-api-spring-boot \
    --param SOURCE_URL=https://gitlab.com/jonashackt/microservice-api-spring-boot \
    --param SOURCE_REVISION=main \
    --timeout 240s \
    --showlog

现在有几点需要考虑。首先,tkn pipeline start 之后的名称 buildpacks-test-pipeline 相当于 yaml 文件 spec: pipelineRef: name: buildpacks-test-pipeline 定义。

它还可以作为对pipeline.yml 文件中定义的Pipeline 对象的引用,该文件以metadata: name: buildpacks-test-pipeline 开头,例如:

api版本:tekton.dev/v1beta1 种类:流水线 元数据: 名称:buildpacks-test-pipeline ...

第二次定义工作区并非易事。幸运的是there's help。我们可以像这样在tkn CLI 中定义一个工作区:--workspace name=source-workspace,subPath=source,claimName=buildpacks-source-pvc

第三次按预期使用参数现在变得容易了。只需相应地使用--param。我们还使用--showlog 将Tekton 日志与--timeout 一起直接流式传输到命令行(或GitLab CI!)。

最后使用GitLab CI Predefined variables我们的.gitlab-ci.yml的构建阶段是这样的:

build-image:
  stage: build
  script:
    - echo "--- Run Tekton Pipeline"
    - tkn pipeline start buildpacks-test-pipeline
      --serviceaccount buildpacks-service-account-gitlab
      --workspace name=source-workspace,subPath=source,claimName=buildpacks-source-pvc
      --workspace name=cache-workspace,subPath=cache,claimName=buildpacks-source-pvc
      --param IMAGE=$CI_REGISTRY_IMAGE
      --param SOURCE_URL=$CI_PROJECT_URL
      --param SOURCE_REVISION=$CI_COMMIT_REF_SLUG
      --timeout 240s
      --showlog

5.解决每个 GitLab CI 管道都是绿色的问题

这可能是我们需要做的一切。但是:现在每个 GitLab CI 管道都是绿色的,无论 Tekton 管道的状态如何。

因此我们再次删除--showlog--timeout,但添加--dry-run--output yaml 标志。如果没有--dry-runtkn pipeline start 命令将创建一个PipelineRun 对象定义,我们不能再使用kubectl 创建它:

build-image:
  stage: build
  script:
    - echo "--- Create parameterized Tekton PipelineRun yaml"
    - tkn pipeline start buildpacks-test-pipeline
      --serviceaccount buildpacks-service-account-gitlab
      --workspace name=source-workspace,subPath=source,claimName=buildpacks-source-pvc
      --workspace name=cache-workspace,subPath=cache,claimName=buildpacks-source-pvc
      --param IMAGE=$CI_REGISTRY_IMAGE
      --param SOURCE_URL=$CI_PROJECT_URL
      --param SOURCE_REVISION=$CI_COMMIT_REF_SLUG
      --dry-run
      --output yaml > pipelinerun.yml

现在我们删除了 --showlog 并且没有使用 tkn CLI 启动实际的 Tekton 管道,我们需要使用以下命令创建管道运行:

- PIPELINE_RUN_NAME=$(kubectl create -f pipelinerun.yml --output=jsonpath='.metadata.name')

有了包含确切管道运行 ID 的临时变量 PIPELINE_RUN_NAME,我们可以再次将 Tekton 管道日志流式传输到我们的 GitLab CI 日志中:

- tkn pipelinerun logs $PIPELINE_RUN_NAME --follow

最后,我们需要检查 Tekton 管道运行的状态并相应地退出我们的 GitLab CI 管道,以防止红色的 Tekton 管道导致绿色的 GitLab CI 管道。因此,让我们首先检查 Tekton 管道运行的状态。这可以通过using --output=jsonpath='.status.conditions[*].reason'kubectl get pipelineruns 一起实现:

kubectl get pipelineruns $PIPELINE_RUN_NAME --output=jsonpath='.status.conditions[*].reason'

然后我们将结果通过管道传送到a grep which checks, if Failed is inside status.condiditons.reason 字段中。

最后我们使用 bash onliner(即<expression to check true or false> && command when true || command when false)发出合适的exit 命令(参见https://askubuntu.com/a/892605):

- kubectl get pipelineruns $PIPELINE_RUN_NAME --output=jsonpath='.status.conditions[*].reason' | grep Failed && exit 1 || exit 0

现在,当 Tekton Pipeline 成功时,每个 GitLab CI Pipeline 都变为绿色 - 当 Tekton Pipeline 失败时变为红色。 The example project has some logs 如果您有兴趣。在 GitLab CI 日志中看到 Tekton 日志非常酷:

【讨论】:

以上是关于如何使用预定义的 GitLab CI 变量和流式传输到 GitLab Pipeline 日志的 Tekton 日志直接从 GitLab CI 触发 Tekton Pipeline的主要内容,如果未能解决你的问题,请参考以下文章