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

How to trigger Tekton Pipeline from GitLab CI directly with predefined GitLab CI variables & Tekton logs streamed into GitLab Pipeline logs

我们有一个 AWS EKS 运行ning(使用 Pulumi 设置),我们按照 Cloud Native Buildpacks Tekton docs. The example project is available.

中的描述安装了 Tekton

Our Tekton pipeline is configured like this (which is derived 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(在我们的 .gitlab-ci.yml 中)触发 Tekton PipelineRun要求:

TLDR;

我创建了一个完全易于理解的示例项目,显示了所有必要的步骤和 运行ning 管道: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 which provides an image, which is based on the official https://hub.docker.com/r/amazon/aws-cli 图片,可以通过 registry.gitlab.com/jonashackt/aws-kubectl-tkn:0.21.0.

访问

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

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

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

# 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. So we can transform the Cloud Native Buildpacks Tekton PipelineRun Yaml filetkn 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.解决every GitLab CI Pipeline is green 问题

这可能就是我们需要做的一切。但是:现在每个 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 管道的状态 运行。这可以通过 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 在线工具(即 <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 管道成功时,每个 GitLab CI 管道都变为绿色 - 当 Tekton 管道失败时变为红色。 The example project has some logs 如果您有兴趣。在 GitLab 中看到 Tekton 日志真是太酷了 CI logs: