Tekton 101🥷

В этой статье мы расскажем о том, что такое 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 здесь.

Если вам понравилась статья, пожалуйста, оставьте отзыв.

Оцените статью
Procodings.ru
Добавить комментарий