在 GitLab CI 中使用 Paketo.io / CloudNativeBuildpacks (CNB) 以及 Kubernetes 执行器和非特权运行器(没有包 CLI 和 docker)

jon*_*ckt 3 gitlab docker gitlab-ci kubernetes paketo

我们希望以最简单的方式使用Paketo.io / CloudNativeBuildpacks (CNB) GitLab CI 。我们的 GitLab 设置使用 AWS EKS 集群,其中包含利用Kubernetes 执行器的非特权 GitLab CI 运行器。我们也不想在构建中使用 Docker带来安全风险。所以我们没有/var/run/docker.sock暴露我们的主机\xe2\x80\x99s,也不想使用docker:dind.

\n

我们找到了一些有关如何将 Paketo 与 GitLab CI 结合使用的指南,例如https://tanzu.vmware.com/developer/guides/gitlab-ci-cd-cnb/。但正如标题下面所述Use Cloud Native Buildpacks with GitLab in GitLab Build Job WITHOUT Using the GitLab Build Template,该方法依赖于 Docker 和 pack CLI。我们试图在我们的.gitlab-ci.yml代码中类似:

\n
image: docker:20.10.9\n\nstages:\n  - build\n\nbefore_script:\n  - |\n    echo "install pack CLI (see https://buildpacks.io/docs/tools/pack/)"\n    apk add --no-cache curl\n    (curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.21.1/pack-v0.21.1-linux.tgz" | tar -C /usr/local/bin/ --no-same-owner -xzv pack)\n\nbuild-image:\n  stage: build\n  script:\n    - pack --version\n    - >\n      pack build $REGISTRY_GROUP_PROJECT/$CI_PROJECT_NAME:latest\n      --builder paketobuildpacks/builder:base\n      --path . \n
Run Code Online (Sandbox Code Playgroud)\n

但正如所概述的,我们的设置不支持 docker,最终我们的日志中出现以下错误:

\n
...\n$ echo "install pack CLI (see https://buildpacks.io/docs/tools/pack/)" # collapsed multi-line command\ninstall pack CLI (see https://buildpacks.io/docs/tools/pack/)\nfetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz\nfetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz\n(1/4) Installing brotli-libs (1.0.9-r5)\n(2/4) Installing nghttp2-libs (1.43.0-r0)\n(3/4) Installing libcurl (7.79.1-r0)\n(4/4) Installing curl (7.79.1-r0)\nExecuting busybox-1.33.1-r3.trigger\nOK: 12 MiB in 26 packages\npack\n$ pack --version\n0.21.1+git-e09e397.build-2823\n$ pack build $REGISTRY_GROUP_PROJECT/$CI_PROJECT_NAME:latest --builder paketobuildpacks/builder:base --path .\nERROR: failed to build: failed to fetch builder image \'index.docker.io/paketobuildpacks/builder:base\': Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?\nCleaning up project directory and file based variables 00:01\nERROR: Job failed: command terminated with exit code 1\n
Run Code Online (Sandbox Code Playgroud)\n

关于如何在 GitLab CI 中使用 Paketo Buildpacks 而不让 Docker 出现在我们的 GitLab Kubernetes 运行器中(这似乎是一种最佳实践)有什么想法吗?我们也不希望我们的设置变得复杂 - 例如通过添加kpack

\n

jon*_*ckt 8

太长了;

直接在您的内部使用 Buildpack 的生命周期(.gitlab-ci.yml 这是一个完整的工作示例):

image: paketobuildpacks/builder

stages:
  - build

# We somehow need to access GitLab Container Registry with the Paketo lifecycle
# So we simply create ~/.docker/config.json as stated in /sf/answers/2919720401/
before_script:
  - mkdir ~/.docker
  - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_JOB_TOKEN\"}}}" >> ~/.docker/config.json

build-image:
  stage: build
  script:
    - /cnb/lifecycle/creator -app=. $CI_REGISTRY_IMAGE:latest
Run Code Online (Sandbox Code Playgroud)

详细信息:“直接使用生命周期”

关于这个话题的讨论正在进行中。特别是查看https://github.com/buildpacks/pack/issues/564https://github.com/buildpacks/pack/issues/413#issuecomment-565165832。正如那里所说:

如果您希望在 CI 中(而不是本地)构建映像,我鼓励您直接使用生命周期,这样就不需要 Docker。这是一个例子:

该示例的链接已损坏,但它引用了有关如何在 Kubernetes 环境中使用构建包的Tekton实现。在这里,我们可以得到关于斯蒂芬·莱文所说的第一个粘合剂。其中的关键点是 的用法。这就是每个人都在谈论的生命周期!在 CNB RFC 中可以找到有关此命令的良好文档。"to use the lifecycle directly"command: ["/cnb/lifecycle/creator"]

选择一个好的镜像:paketobuildpacks/builder:base

那么如何开发一个工作.gitlab-ci.yml呢?让我们从简单开始吧。深入研究 Tekton 实现,您会发现生命周期命令是在 中定义的环境中执行的BUILDER_IMAGE,该环境本身被记录为The image on which builds will run (must include lifecycle and compatible buildpacks).听起来很熟悉!我们不能简单地paketobuildpacks/builder:base从 pack CLI 命令中选择构建器映像吗?让我们先在我们的工作站上本地尝试一下,然后再给 GitLab 带来太多干扰。选择您想要构建的项目(如果您愿意,我在gitlab.com/jonashackt/microservice-api-spring-boot上创建了一个示例 Spring Boot 应用程序,您可以克隆)并运行:

docker run --rm -it -v "$PWD":/usr/src/app -w /usr/src/app paketobuildpacks/builder bash
Run Code Online (Sandbox Code Playgroud)

现在,在paketobuildpacks/builder镜像驱动的容器内尝试直接运行 Paketo 生命周期:

/cnb/lifecycle/creator -app=. microservice-api-spring-boot:latest
Run Code Online (Sandbox Code Playgroud)

我只使用了命令的许多可能参数-app中的参数,因为它们中的大多数都有很好的默认值。但由于默认的应用程序目录路径不是默认的- 而是当前目录,所以我配置了它。此外,我们还需要在末尾定义 ,它将简单地用作生成的容器映像名称。creator/workspace<image-name>

第一个.gitlab-ci.yml

这两个命令都在我的本地工作站上工作,所以让我们最终.gitlab-ci.yml使用这种方法创建一个(这是一个完整的工作示例.gitlab-ci.yml):

image: paketobuildpacks/builder

stages:
  - build

build-image:
  stage: build
  script:
    - /cnb/lifecycle/creator -app=. $CI_REGISTRY_IMAGE:latest
Run Code Online (Sandbox Code Playgroud)

无需使用 docker 即可进行 docker 登录

由于我们的 Kubernetes Runner 内部没有docker可用的,因此我们无法按照文档中所述登录 GitLab 容器注册表。因此,使用第一种方法时,我出现了以下错误:

===> ANALYZING
ERROR: failed to get previous image: connect to repo store "gitlab.yourcompanyhere.cloud:4567/yourgroup/microservice-api-spring-boot:latest": GET https://gitlab.yourcompanyhere.cloud/jwt/auth?scope=repository%3Ayourgroup%2Fmicroservice-api-spring-boot%3Apull&service=container_registry: DENIED: access forbidden
Cleaning up project directory and file based variables 00:01
ERROR: Job failed: command terminated with exit code 1
Run Code Online (Sandbox Code Playgroud)

使用此答案中描述的方法解决了问题。我们需要创建一个~/.docker/config.json包含 GitLab 容器注册表登录信息的文件 - 然后Paketo 构建将拾取它们,如文档中所述

如果CNB_REGISTRY_AUTH未设置并且存在 docker config.json 文件,则生命周期应该使用此文件的内容通过任何匹配的注册表进行身份验证。

在我们的内部.gitlab-ci.yml,这可能看起来像:

# We somehow need to access GitLab Container Registry with the Paketo lifecycle
# So we simply create ~/.docker/config.json as stated in /sf/answers/2919720401/
before_script:
  - mkdir ~/.docker
  - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_JOB_TOKEN\"}}}" >> ~/.docker/config.json
Run Code Online (Sandbox Code Playgroud)

我们最终的 .gitlab-ci.yml

由于我们image: paketobuildpacks/builder在 的顶部使用.gitlab-ci.yml,因此我们现在可以直接利用生命周期。这就是我们首先想做的。只需记住使用正确的 GitLab CI 变量来描述您的内容,<image-name>如下所示:

/cnb/lifecycle/creator -app=. $CI_REGISTRY_IMAGE:latest
Run Code Online (Sandbox Code Playgroud)

否则,Buildpack 流程分析器步骤将中断,并且最终不会被推送到 GitLab 容器注册表。所以最后我们.gitlab-ci.yml看起来像这样(这是完整的工作示例):

image: paketobuildpacks/builder

stages:
  - build

# We somehow need to access GitLab Container Registry with the Paketo lifecycle
# So we simply create ~/.docker/config.json as stated in /sf/answers/2919720401/
before_script:
  - mkdir ~/.docker
  - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_JOB_TOKEN\"}}}" >> ~/.docker/config.json

build-image:
  stage: build
  script:
    - /cnb/lifecycle/creator -app=. $CI_REGISTRY_IMAGE:latest
Run Code Online (Sandbox Code Playgroud)

我们的构建现在应该使用 Paketo/Buildpacks 成功运行,无需包 CLI 和 Docker:

在此输入图像描述

请参阅此处示例项目的完整日志