Tekton Pipelines — это мощный и гибкий, cloud-native фреймворк для CI/CD систем. Он позволяет создавать, тестировать и развертывать приложения в облачных и локальных системах.
Tekton Pipelines предоставляет основные строительные блоки, в виде CRD Kubernetes, для создания CI/CD пайплайнов, задачи которых выполняются в виде подов, управляемых и оркестрируемых Kubernetes.
Основные блоки Tekton:
У сборки в виде контейнеров есть множество преимуществ: портативность, повторное использование и возможность подключить все возможности Kubernetes. Однако, поскольку эти контейнеры не являются постоянными, для оптимизации выполнения сборки через кэширование потребуется выполнение дополнительных действий по сравнению с тем, к чему вы могли привыкнуть на автономном CI-сервере.
В следующих разделах приведем примеры использования кэширования для ускорения сборки образов в пайплайнах Tekton с использованием Kaniko. Kaniko — это инструмент с открытым исходным кодом, который помогает создавать контейнерные образы из Dockerfile. Ему не требуется демон Docker для выполнения, что делает его идеальным для сборки образов в средах, где Docker демоны недоступны или не могут быть запущены, например, в кластерах Kubernetes.
Чтобы выполнить инструкции, вам понадобится:
В этом примере используются кластер GKE на Google Cloud, репозиторий GitHub и Artifact Registry, но шаги воспроизводимы на любой стандартной платформе Kubernetes, SCM на основе git и реестре контейнеров с минимальными модификациями.
Пример кода и ресурсов доступен в этом репозитории: https://github.com/ggalloro/tekton-speed-builds
Чтобы следовать за примерами, вам нужно сделать форк этого репозитория в вашем личном аккаунте GitHub или перенести/скопировать его в вашу SCM, если она отличается.
После того как вы скопировали репозиторий, клонируйте его локально и посмотрите его содержимое.
FROM maven as build
COPY mvnw .
COPY pom.xml .
COPY src src
RUN mvn package -Dmaven.test.skip=true
FROM eclipse-temurin:19-jdk-alpine
COPY --from=build /target/demo-0.0.1-SNAPSHOT.jar app.jar
CMD ["java", "-jar", "app.jar"]
Папка tekton-assets содержит манифесты ресурсов для Tekton, используемые в этой статье:
Теперь создадим необходимые ресурсы Tekton и запустим пайплайн. Из локально клонированного репозитория примените ресурсы из папки tekton-assets к вашему кластеру:
kubectl apply -f tekton-assets
Это создаст PVC, задачи и пайплайн, описанные выше.
Теперь запустим пайплайн вручную. В зависимости от вашей конфигурации, возможно, вам потребуется указать учетную запись службы (Service Account) для аутентификации в реестре, используя параметр -s. Подробнее смотрите в разделе документации Tekton.
Введите следующую команду для запуска пайплайна.
tkn pipeline start pipeline-clone-and-build --workspace name=source,claimName=source-pvc --showlog
В ? Value for param git-url of type string? введите URL вашего репозитория git.
В ? Value for param image-name of type string? введите URL вашего образа, включая имя репозитория и имя образа.
Пример конфигурации:
➜ ~ tkn pipeline start pipeline-clone-and-build --workspace name=source,claimName=source-pvc --showlog
? Value for param `git-url` of type `string`? https://github.com/ggalloro/tekton-speed-builds
? Value for param `image-name` of type `string`? europe-west1-docker.pkg.dev/galloro-demos/tektoncd/javasample
Если выполнение пайплайна прошло успешно, последний шаг задачи image-build выведет URL вашего образа в консоль, и ваш образ будет отправлен в целевой реестр:
[image-build : write-url]
europe-west1-docker.pkg.dev/galloro-demos/tektoncd/javasample:457848d
Выполнение пайплайна создало 2 ресурса TaskRun для выполнения двух задач. Введите следующую команду, чтобы увидеть информацию о TaskRun:
tkn tr ls
Вы увидите что-то подобное:
NAME STARTED DURATION STATUS
pipeline-clone-and-build-run-68hjg-image-build 4 minutes ago 50s Succeeded
pipeline-clone-and-build-run-68hjg-git-clone 4 minutes ago 11s Succeeded
Так как ваша сборка всегда выполняется в новом контейнере, если вы измените только одну строку в исходном коде, сборка будет загружать базовые образы и зависимости Maven, не используя кэш. Попробуем.
Измените текст на 25-й строке файла index.html в sample-app/src/main/resources/templates на «Hello, Slow Builder!».
Зафиксируйте изменения и отправьте их в удалённый репозиторий.
git add .
git commit -m "change to index.html"
git push
Запустите ваш пайплайн снова, следуя тем же инструкциям, которые были даны ранее.
После завершения выполнения пайплайна посмотрите информацию о TaskRuns снова:
NAME STARTED DURATION STATUS
pipeline-clone-and-build-run-fnzxj-image-build 55 seconds ago 49s Succeeded
pipeline-clone-and-build-run-fnzxj-git-clone 1 minute ago 12s Succeeded
pipeline-clone-and-build-run-68hjg-image-build 4 minutes ago 50s Succeeded
pipeline-clone-and-build-run-68hjg-git-clone 4 minutes ago 11s Succeeded
Как видите, даже если вы измените только одну строку кода, сборка займет примерно столько же времени, как и до этого.
В следующих разделах мы рассмотрим возможности оптимизации скорости сборки с помощью кэширования.
Kaniko может кэшировать слои, создаваемые командами RUN и COPY в удалённом репозитории. Перед выполнением команды Kaniko проверяет кэш на наличие слоя. Если слой существует в кэше, Kaniko извлечёт его вместо выполнения команды. Если слоя нет в кэше, Kaniko выполнит команду, а затем отправит вновь созданный слой в кэш.
Это может помочь ускорить сборку в Tekton.
Чтобы использовать кэш Kaniko, необходимо добавить флаг --cache=true к Kaniko в задаче image-build, чтобы шаг build-and-push выглядел следующим образом:
- name: build-and-push
workingDir: $(workspaces.source.path)/sample-app/
image: gcr.io/kaniko-project/executor:latest
args:
- --dockerfile=$(params.DOCKERFILE)
- --context=$(params.CONTEXT) # The user does not need to care the workspace and the source.
- --destination=$(params.IMAGE):$(params.commit)
- --digest-file=$(results.IMAGE_DIGEST.path)
- --cache=true
securityContext:
runAsUser: 0
Вы можете применить изменённый image-build-cache.yaml из папки kaniko-cache, чтобы обновить задачу image-build:
kubectl apply -f kaniko-cache/image-build-cache.yaml
Чтобы использовать возможности кэширования слоев Kaniko, также следует правильно настроить ваш Dockerfile, переместив инструкции, которые, скорее всего, не изменятся между сборками, наверх, а те, которые изменятся, вниз.
Отредактируйте Dockerfile в директории sample-app, чтобы разделить скачивание зависимостей Maven и сборку кода. Это позволит кэшировать зависимости в отдельном слое, чтобы любые изменения в коде не вызывали повторную загрузку зависимостей. Добавьте строку RUN mvn dependency
в ваш Dockerfile, чтобы он выглядел так:
FROM maven as build
COPY mvnw .
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src src
RUN mvn package -Dmaven.test.skip=true
FROM eclipse-temurin:19-jdk-alpine
COPY --from=build /target/demo-0.0.1-SNAPSHOT.jar app.jar
CMD ["java", "-jar", "app.jar"]
После изменения Dockerfile вам нужно зафиксировать и отправить изменения, чтобы ваша сборка использовала их:
git add .
git commit -m "update to Dockerfile"
git push
Теперь снова запустите ваш пайплайн, как вы это делали ранее. Результат первого выполнения должен быть похож на предыдущий, и все зависимости будут загружены.
Посмотрите информацию о TaskRun. Продолжительность сборки должна быть примерно такой же, как и раньше (хотя она может быть немного длиннее из-за загрузки слоев в реестр):
NAME STARTED DURATION STATUS
pipeline-clone-and-build-run-gsgwx-image-build 1 minute ago 58s Succeeded
pipeline-clone-and-build-run-gsgwx-git-clone 1 minute ago 17s Succeeded
pipeline-clone-and-build-run-fnzxj-image-build 55 seconds ago 49s Succeeded
pipeline-clone-and-build-run-fnzxj-git-clone 1 minute ago 12s Succeeded
pipeline-clone-and-build-run-68hjg-image-build 4 minutes ago 50s Succeeded
pipeline-clone-and-build-run-68hjg-git-clone 4 minutes ago 11s Succeeded
Слои образа были загружены в ваш реестр, как показано на картинке ниже для Artifact Registry (папка javasample/cache):
Теперь обновим код (используйте «Hello, Fast Builder!» в этот раз), зафиксируйте изменения и снова запустите пайплайн, следуя инструкциям из предыдущего раздела. В журнале вывода вы должны заметить, что основная часть зависимостей не будет загружаться заново, а будет использован кэшированный слой:
Выполнение задачи image-build TaskRun должно быть быстрее по сравнению с предыдущим выполнением (42 секунды против 58 секунд в этом примере):
NAME STARTED DURATION STATUS
pipeline-clone-and-build-run-5s87p-image-build 1 minute ago 42s Succeeded
pipeline-clone-and-build-run-5s87p-git-clone 1 minute ago 17s Succeeded
pipeline-clone-and-build-run-gsgwx-image-build 7 minutes ago 58s Succeeded
pipeline-clone-and-build-run-gsgwx-git-clone 7 minutes ago 17s Succeeded
pipeline-clone-and-build-run-fnzxj-image-build 18 minutes ago 49s Succeeded
pipeline-clone-and-build-run-fnzxj-git-clone 18 minutes ago 12s Succeeded
pipeline-clone-and-build-run-68hjg-image-build 21 minutes ago 50s Succeeded
pipeline-clone-and-build-run-68hjg-git-clone 22 minutes ago 11s Succeeded
Вы увидели, как включение кэширования слоев в реестре контейнеров может ускорить вашу сборку в Tekton. Эффективный прирост скорости будет зависеть от различных факторов, таких как конфигурация проекта и подключение к вашему реестру.
Помимо кэширования слоев в реестре контейнеров, Kaniko может использовать постоянный том для хранения кэшированных базовых образов. По умолчанию, Kaniko будет искать кэшированные базовые образы в папке /cache, но вы можете изменить это с помощью флага --cache-dir.
Постоянный том должен быть заполнен до использования. Kaniko предоставляет образ для этого: gcr.io/kaniko-project/warmer.
Добавим монтирование тома, сопоставляющего путь /cache с PVC под названием basecache-pvc, в задачу build-image:
- name: build-and-push
workingDir: $(workspaces.source.path)/sample-app/
image: gcr.io/kaniko-project/executor:latest
args:
- --dockerfile=$(params.DOCKERFILE)
- --context=$(params.CONTEXT) # The user does not need to care the workspace and the source.
- --destination=$(params.IMAGE):$(params.commit)
- --digest-file=$(results.IMAGE_DIGEST.path)
- --cache=true
# kaniko assumes it is running as root, which means this example fails on platforms
# that default to run containers as random uid (like OpenShift). Adding this securityContext
# makes it explicit that it needs to run as root.
securityContext:
runAsUser: 0
volumeMounts:
- name: basecache
mountPath: /cache
- name: write-url
image: docker.io/library/bash:5.1.4@sha256:b208215a4655538be652b2769d82e576bc4d0a2bb132144c060efc5be8c3f5d6
script: |
set -e
image="$(params.IMAGE):$(params.commit)"
echo -n "${image}" | tee "$(results.IMAGE_URL.path)"
volumes:
- name: basecache
persistentVolumeClaim:
claimName: basecache-pvc
Вы можете применить изменённый image-build-basecache.yaml из папки kaniko-basecache, чтобы обновить задачу image-build.
kubectl apply -f kaniko-basecache/image-build-basecache.yaml
Теперь создадим basecache-pvc PVC:
kubectl apply -f kaniko-basecache/pvc-basecache.yaml
Затем запустим pod kaniko-warmer, чтобы заполнить диск:
kubectl apply -f kaniko-basecache/kaniko-warmer.yaml
Проверьте логи pod'а kaniko-warmer:
kubectl logs -f kaniko-warmer
Пока вы не увидите вывод с подтверждением того, что 2 базовых образа были загружены.
INFO[0000] Retrieving image manifest maven
INFO[0000] Retrieving image maven from registry index.docker.io
INFO[0004] Retrieving image manifest eclipse-temurin:19-jdk-alpine
INFO[0004] Retrieving image eclipse-temurin:19-jdk-alpine from registry index.docker.io
Когда это будет сделано, вы можете снова внести изменения в свой код («Hello, Base Builder!»), зафиксировать его и запустить ваш пайплайн снова, как это было сделано в предыдущих тестах.
Эта операция будет использовать кэшированные слои, как и предыдущее, а также базовые образы из вашего постоянного тома basecache-pvc, что видно в выводе:
И в этом случае улучшение скорости будет зависеть от различных факторов, таких как размер базовых образов, производительность хранилища и подключение к вашему реестру.
Другой способ ускорить сборки — кэшировать зависимости локально. В нашем примере проекта на Maven мы можем использовать тот факт, что по умолчанию Maven кэширует модули зависимостей в директорию $HOME/.m2. Это зависит от используемого языка и инструментов сборки.
В данном примере мы добавим еще один постоянный том к задаче build-image и сопоставим его с папкой /root/.m2, чтобы сохранить кэш Maven между сборками.
Применим изменённый image-build-m2cache.yaml из папки m2cache для обновления задачи image-build:
kubectl apply -f m2cache/image-build-m2cache.yaml
Теперь создадим PVC m2cache-pvc:
kubectl apply -f m2cache/pvc-m2cache.yaml
Так как нам больше не нужно кэшировать зависимости Maven в слое образа, удалим строку RUN mvn dependency из нашего Dockerfile и вернём его к исходной структуре. Зафиксируйте и отправьте ваши изменения.
Теперь снова запустите ваш пайплайн, как делали это ранее. Maven снова загрузит ваши зависимости, когда будет запущен mvn package, поскольку ранее кэшированный слой больше не упоминается в вашем Dockerfile. Продолжительность выполнения должна быть похожа на наш первоначальный тест.
Снова внесите изменения в ваш код («Hello, Very Fast Builder»), зафиксируйте их и снова запустите пайплайн, как это было сделано в предыдущих тестах.
Этот запуск будет использовать кэшированные слои, как и предыдущий, а также базовые образы из вашего постоянного тома basecache-pvc и кэшированные зависимости.
В списке TaskRun вы должны увидеть улучшение скорости по сравнению с первым запуском.
Готово!
NAME STARTED DURATION STATUS
pipeline-clone-and-build-run-lk8x2-image-build 1 minute ago 46s Succeeded
pipeline-clone-and-build-run-lk8x2-git-clone 1 minute ago 14s Succeeded
pipeline-clone-and-build-run-w7sd5-image-build 3 minutes ago 59s Succeeded
pipeline-clone-and-build-run-w7sd5-git-clone 3 minutes ago 12s Succeeded
Узнайте об услуге devops support и закажите звонок у наших менеджеров. Поможем с любой задачей
Узнать больше