如何使用预定义的 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的主要内容,如果未能解决你的问题,请参考以下文章

Gitlab Ci中自动生成版本号

关于gitlab ci在include中使用变量

变量 gitlab ci 中的变量

规则中无法识别 GitLab CI 自定义变量

如何将值传递给 Gitlab CI 作业

我们如何在 gitlab-ci.yml 中使用“变量”关键字?