В этой статье мы расскажем о том, что такое Tekton и как мы можем построить CI/CD конвейер с помощью Tekton.
Под шапкой Tekton скрывается множество проектов, но сердцем является «Tekton Pipeline».
Tekton Pipelines
Проект Tekton Pipelines предоставляет ресурсы в стиле kubernetes для декларирования трубопроводов в стиле CI/CD.
Прежде чем перейти к пониманию концепций Tekton, давайте рассмотрим пару общих примеров, а затем соотнесем их с Tekton…
(Здесь мы будем считать, что наш CI будет делать следующие вещи
- Тестирование сборки,
- Юнит-тест,
- Создание образа контейнера,
- перемещение его в удаленный реестр
- развертывание образа на кластере kubernetes).
Если мы хотим запустить CI вручную на нашей машине, как мы это сделаем?
Может быть, написав скрипт?
или выполняя команды одну за другой?
Возьмем сценарий, в котором мы хотим запустить CI/CD на проекте go
(A):
Шаг 1: Мы клонируем проект (git clone).
Шаг 2: Выполнить команду go build
Шаг 3: Выполнить команду go test для запуска теста
Шаг 4: Использование команды docker build для сборки образа
Шаг 5: Команда Docker push для отправки образа в удаленный реестр
Шаг 6: Создание/обновление развертывания Kubernetes с новым собранным образом
Теперь рассмотрим другой сценарий, в котором мы хотим запустить CI на Java
проекте (B):
Шаг 1: Мы клонируем проект (git clone).
Шаг 2: Выполнить команду javac для компиляции проекта
Шаг 3: Запуск тестов
Шаг 4: Использование команды docker build для сборки образа
Шаг 5: Команда Docker push для отправки образа в удаленный реестр
Шаг 6: Создание/обновление развертывания Kubernetes с новым собранным образом
Если мы сравним оба сценария, то увидим следующее
- Шаг 4 & Шаг 5 являются общими в обоих сценариях и выполняются вместе в определенном порядке, не так ли? Мы будем продвигать образ только после сборки. Здесь мы представляем Tekton Task.
Задача — это набор шагов, которые вы определяете и располагаете в определенном порядке выполнения как часть вашего потока непрерывной интеграции.
Шаг 5 всегда будет выполняться после Шага 4. Таким образом, мы можем иметь задачу Tekton Task, состоящую из двух шагов -> сборка образа и его размещение в реестре образов. Эта задача может быть общей для обоих проектов.
-
Шаг 1, который клонирует проект, также может быть Tekton Task, который может быть общим для обоих проектов.
-
Шаг 6, создающий/обновляющий развертывание Kubernetes, может быть задачей, которую также можно разделить.
Остальные шаги были специфичны для проекта или языка и также могли быть Tekton Task. В данном сценарии мы не могли поделиться ими, но для других проектов мы определенно можем использовать их повторно.
Как использовать задачу в конвейере, мы рассмотрим далее в статье.
Здесь мы увидели, что задача Tekton — это набор шагов, которые могут быть выполнены в определенном порядке, и задача может быть повторно использована в различных конвейерах путем изменения параметров.
У Tekton есть каталог, который представляет собой коллекцию задач, поддерживаемых сообществом. Вы можете получить к ним доступ по адресу hub.tekton.dev. Вы можете напрямую использовать задачу в своем конвейере или изменить существующую в соответствии с вашими требованиями.
В Hub вы можете найти задачи для клонирования кода, запуска теста и многих других сценариев.
Но Tekton Task — это всего лишь шаблон, если вы примените его на кластере Kubernetes, ничего не произойдет.
Рассмотрим следующую задачу hello world Task, если применить ее на кластере Kubernetes с установленным Tekton, ничего не произойдет.
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: hello
spec:
params:
- name: text
type: string
steps:
- name: say-hello-to
image: registry.access.redhat.com/ubi8/ubi
command:
- /bin/bash
args: ['-c', 'echo Hello $(params.text)!']
Чтобы запустить задачу, необходимо создать TaskRun, который представляет собой запущенный экземпляр.
TaskRun позволяет вам инстанцировать и выполнять задачу на кластере.
В приведенном выше примере вы можете видеть, что определены параметры, которые могут передаваться при выполнении TaskRun.
TaskRun будет выглядеть следующим образом
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
generateName: hello-
spec:
taskRef:
name: hello
params:
- name: text
value: "sm43"
Вы можете создать столько TaskRun, сколько необходимо, изменяя параметры.
Если вы создали TaskRun, вы можете проверить журналы с помощью tkn CLI.
tkn CLI — это еще один подпроект Tekton, который упрощает взаимодействие с ресурсами Tekton с помощью командной строки.
Вы можете проверить журналы, используя
# get the name of taskrun created
tkn taskrun ls
# get the logs
tkn taskrun logs <taskrun-name>
Мы видели задачу и как ее запустить, но нам придется запускать несколько задач, верно? Одна для запуска теста, другая для сборки и отправки образа… это звучит неэффективно 🤔.
Итак, у нас есть Tekton Pipeline, где мы можем определить различные задачи в том порядке, в котором мы хотим их выполнять.
Прежде чем мы начнем строить конвейер, мы рассмотрим еще одну концепцию Tekton, а именно [Workspace](https://tekton.dev/docs/pipelines/workspaces/#overview)
.
Рабочие пространства позволяют задачам объявлять части файловой системы, которые должны быть предоставлены во время выполнения TaskRuns
У нас будет несколько задач в конвейере, любой из них нужен доступ к коду приложения, чтобы запустить тест или собрать образы и т.д.
Рабочее пространство может быть томом, который совместно используется задачами в конвейере для выполнения их специфической логики на коде.
В примере, который мы рассматривали ранее, мы можем использовать рабочее пространство, где задача git clone будет клонировать код, а остальные задачи будут иметь доступ к этому рабочему пространству и выполнять свою логику на этом коде.
Давайте построим конвейер
Мы будем использовать приложение go под названием news-demo.
Вы можете клонировать репозиторий и выполнить следующие шаги.
Необходимые условия:
Кластер Kubernetes.
Вы можете установить Tekton с помощью Tekton Operator, шаги можно найти здесь.
ПРИМЕЧАНИЕ: это также приведет к установке других проектов Tekton.
Или вы можете просто установить Tekton Pipeline, который мы рассматриваем в этой статье. шаги по установке можно найти здесь
Для приложения News-Demo мы собираемся создать конвейер, который будет выполнять следующие задачи
- клонировать код в рабочую область
- собрать код
- протестировать код
- собрать и распространить образ
- проверить, существует ли уже развертывание
- если нет, создайте развертывание
- если да, то обновите развертывание.
Конвейер может выглядеть следующим образом
Полную версию конвейера вы можете найти здесь
Ниже показана часть конвейера…
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: news-demo-deploy
namespace: news-demo
spec:
params:
- name: REPO
- name: REVISION
- name: IMAGE
- name: TAG
- name: NAMESPACE
workspaces:
- name: shared-workspace
tasks:
- name: fetch-repository
taskRef:
name: git-clone
workspaces:
- name: output
workspace: shared-workspace
params:
- name: url
value: $(params.REPO)
- name: subdirectory
value: ""
- name: deleteExisting
value: "true"
- name: revision
value: $(params.REVISION)
- name: build-test
runAfter:
- fetch-repository
taskRef:
name: golang-build
params:
- name: packages
value: ./...
- name: package
value: github.com/sm43/news-demo
workspaces:
- name: source
workspace: shared-workspace
- name: unit-tests
runAfter:
- fetch-repository
taskRef:
name: golang-test
params:
- name: package
value: github.com/sm43/news-demo
- name: flags
value: -v -mod=vendor
workspaces:
- name: source
workspace: shared-workspace
- name: build-push-image
taskRef:
name: buildah
workspaces:
- name: source
workspace: shared-workspace
params:
- name: IMAGE
value: $(params.IMAGE):$(params.TAG)
- name: FORMAT
value: "docker"
runAfter:
- build-test
- unit-tests
- name: check-deployment
taskRef:
name: kubernetes-actions
params:
- name: script
value: |
kubectl describe deployment news-demo -n "$(params.NAMESPACE)" >/dev/null 2>/dev/null
if [[ $? -eq 0 ]]; then
printf yes | tee /tekton/results/output-result
else
printf no | tee /tekton/results/output-result
fi
runAfter:
- build-push-image
- name: patch-image
taskRef:
name: kubernetes-actions
params:
- name: script
value: |
kubectl patch deployment news-demo --patch='{"spec":{"template":{"spec":{
"containers":[{
"name": "news-demo",
"image": "$(params.IMAGE):$(params.TAG)"
}]
}}}}' -n $(params.NAMESPACE)
when:
- input: "$(tasks.check-deployment.results.output-result)"
operator: in
values: ["yes"]
runAfter:
- check-deployment
- name: create-deployment
taskRef:
name: kubernetes-actions
workspaces:
- name: manifest-dir
workspace: shared-workspace
params:
- name: script
value: |
kubectl -n $(params.NAMESPACE) apply -f <(sed "s@image:.*@image: $(params.IMAGE):$(params.TAG)@" k8s/02-deployment.yaml)
when:
- input: "$(tasks.check-deployment.results.output-result)"
operator: in
values: ["no"]
Давайте разберемся, как работает конвейер
-
Первая задача — git-clone, которую мы будем использовать из Tekton Hub. Мы установим ее на кластер и будем ссылаться на нее в нашем конвейере.
Вы можете видеть, что мы использовали рабочее пространство, где задача будет клонировать код, и мы передаем это же рабочее пространство другим задачам для доступа к коду.
В зависимости от проекта мы будем передавать параметры. -
Аналогично мы собираемся использовать golang-build и golang-test из Tekton Hub и направить их на наш Pipeline.
Здесь нужно обратить внимание на полеrunAfter
. Если вы видите вbuild-test
у нас есть
runAfter:
- fetch-repository
что означает, что эта задача будет запущена после завершения fetch-repostitory, которая является ничем иным, как git-clone. Вот как мы можем указать порядок.
-
После выполнения теста сборки и модульного теста мы используем задачу buildah Task для сборки и распространения образа.
-
Наконец, когда образ собран, мы создадим или обновим развертывание.
-
Здесь мы используем выражение when, чтобы решить, какое действие нужно выполнить. Когда мы запускаем
check-deployment
, она проверяет, существует ли развертывание, используя задачуkubernetes-actions
из Tekton Hub, и добавляет ее результат в результаты. -
Таким образом, следующие 2 задачи в конвейере будут выполняться на основе результатов задачи check-deployment.
Если результатом проверки развертывания будетyes
, то будет выполненаpatch-image
, в противном случае будет выполнена create-deployment.
when:
- input: "$(tasks.check-deployment.results.output-result)"
operator: in
values: ["yes"]
Давайте выполним это…
Установка приложения
Вы можете клонировать репозиторий с помощью
git clone https://github.com/sm43/news-demo.git
Для работы приложения требуется учетная запись News API и ее ключ. Зарегистрируйте учетную запись News API и получите бесплатный ключ API.
Как только вы получите ключ
cd news-demo
Отредактируйте configMap в директории k8s
и добавьте свой ключ API для переменной NEWS_API_KEY.
После обновления configMap вы можете применить манифест на кластере с помощью kubectl.
kubectl apply -f k8s/
Это развернет приложение в пространстве имен news-demo и создаст службу для развертывания.
Чтобы получить доступ к приложению вне кластера, создайте маршрут, если вы используете кластер OpenShift или Ingress на кластере kubernetes.
kubectl apply -f k8s/openshift/
Вы можете получить маршрут и получить к нему доступ через браузер.
echo "https://$(kubectl get routes news-demo -n news-demo -ojsonpath='{.spec.host}')"
Вы сможете увидеть следующее приложение
Настройка трубопровода
Перед применением конвейера нам нужно создать некоторые ресурсы, запустите bash-скрипт в директории конвейера.
Отредактируйте скрипт, добавив учетные данные реестра изображений, чтобы pipeline мог передавать изображения в ваш реестр. и обновите имя пользователя в реестре в pipelineRun.
Выполните scipt
./pipeline/run.sh
Этот сценарий устанавливает задачу из каталога, создает учетную запись службы, которая имеет доступ к вашему реестру для проталкивания образа, rbac, необходимый для создания/обновления развертывания, трубопровод и запускает трубопровод, создавая pipelineRun.
Вы можете использовать tkn для доступа к ресурсу
# List the pipelineRuns
tkn pipelinerun ls
# follow the logs of pipelineRun
tkn pipelinerun logs -f
Дождитесь завершения pipelineRun и затем проверьте изображение в развертывании.
Ранее, когда мы развертывали приложение, образ был quay.io/sm43/news-demo:latest
, а теперь трубопровод обновил образ до quay.io/sm43/news-demo:v0.1
.
Мы успешно запустили конвейер.
Теперь, если вы внесете какие-либо изменения в свой код и запустите конвейер, вы увидите изменения, развернутые на кластере после успешного завершения конвейера.
Но это вручную, верно? Мы не можем продолжать запускать вручную каждый раз. Мы хотим запускать на основе событий.
Мы хотим запускать CI, когда мы создаем запрос на притяжение или переносим коммит на ветку.
Поэтому для этого нам необходимо настроить Tekton Triggers. О том, как настроить Tekton Trigger, мы расскажем в следующей статье.
До тех пор вы можете ознакомиться с полным циклом статей о Tekton здесь.
Если вам понравилась статья, пожалуйста, оставьте отзыв.