В недавней статье выдвинуто предложение использовать Tekton в качестве фреймворка для облачных пайплайнов CI/CD и Argo CD в качестве идеальной пары для GitOps. Методики GitOps поддерживают непрерывное развертывание в гибридных и мультикластерных средах Kubernetes.
В настоящей статье, состоящей из двух частей, мы построим рабочий поток CI/CD, который продемонстрирует возможности совместного использования Tekton и GitOps. Вы также познакомитесь с Red Hat OpenShift Serverless, так как мы будем использовать ресурсы сервисов Knative в нашем CI/CD процессе. Начнем же мы с обзора процесса CI/CD, который мы внедрим для примера.
CI/CD процесс
На схеме ниже изображен CI/CD процесс. Коммит, инициированный в исходном коде приложения, запускает полный CI/CD процесс, который завершается тем, что новая версия бессерверного приложения развертывается в Dev, Stage и Prod средах.
Рисунок 1. Демонстрационный пример CI/CD процесса.
Давайте подробнее рассмотрим каждый шаг этого процесса:
- Разработчик отправляет новое изменение в репозиторий исходного кода приложения.
- Созданный в репозитории исходного кода вебхук запускает пайплайн Tekton.
- Как только пайплайн запустился, первая задача вызывает исходный код из репозитория.
- Задача Maven упаковывает код приложения в файл JAR и проводит тесты модулей до того, как построить образ контейнера.
- Задача Buildah строит и отправляет образ контейнера в registry. И затем образ отправляется во внутренний registry OpenShift.
- Пайплайн обновляет у себя репозиторий, в котором хранится желаемое состояние конфигурации приложения и описание развертывания. В методологии GitOps мы используем репозиторий Git в качестве единственного источника истины о том, что и куда развертывается.
- Изначально Git-репозиторий может быть пуст, но это не проблема, и этот шаг, инициализирует репозиторий со всеми манифестами Kubernetes (в данном случае сервисы Knative и
ConfigMaps
), которые необходимы, чтобы впервые запустить приложение. Последующие коммиты репозитория будут лишь обновлять существующие дескрипторы новыми версиями приложения, настройки канареечного тестирования и связанные конфигурации. Как только все файлы манифеста были созданы или модифицированы, задача отправляет изменения в репозиторий. Этот шаг является связующим звеном между непрерывной интеграцией, производимой пайплайном Tekton, и непрерывным развертыванием, управляемым Argo CD. - Argo CD извлекает из репозитория конфигурации и синхронизирует существующие манифесты Kubernetes, которые заданы файлами Kustomize. Это действие создает последние объекты Kubernetes в неймспейсах
development
,staging
иproduction
. Синхронизация может производиться автоматически или вручную — в зависимости от требований неймспейса. - В финальной части процесса может понадобиться извлечь образы, на которые ссылались в развертывании манифеста Kubernetes из внутреннего registry OpenShift. Команда эксплуатации может также внести изменения в конфигурацию, например, сменив URL целевого микросервиса или определенную информацию, которая известна команде разработчиков. Последний шаг может также создать состояние
OutOfSync
, что приведет к новому процессу синхронизации (см. шаг 9 на схеме).
Далее мы настроим наш кластер с OpenShift Operators и сервисами, которые нам понадобятся.
Настройка кластера OpenShift
Мы используем набор скриптов для настройки и установки всех необходимых для данной демонстрации компонентов. Чтобы начать настройку демонстрационной среды, скопируйте следующий репозиторий исходного кода:
$ git clone https://github.com/dsanchor/rh-developers-cicd.git
Затем проверьте, что у вас в системе установлены все инструменты из списка ниже. Они понадобятся при запуске скриптов:
- Helm:
helm version
- Git:
git version
- oc:
oc version
- kustomize не ниже v3.1.0:
customize version
- envsubst (gettext):
envsubst --help
- tkn (опционально Tekton CLI):
tkn version
Проверив все вышеуказанные требования, залогиньтесь в ваш кластер OpenShift под пользователем с правами администратора кластера:
$ oc login -u USERNAME -p PASSWORD https://api.YOUR_CLUSTER_DOMAIN:6443
Операторы, неймспейсы и привязки ролей
Мы сначала установим OpenShift Pipelines и OpenShift Serverless операторов в неймспейс openshift-operators
.
Также создадим четыре новых неймспейса: cicd
, development
, staging
и production
. Образы помещаются в границы неймспейса cicd
, поэтому, чтобы получать новые образы, все остальные неймспейсы требуют привилегий system:image-puller
.
Наконец, добавим новую роль view
по умолчанию в сервисные аккаунты development
, staging
и production
. Эта роль обеспечивает доступ из наших подов приложения Quarkus к ConfigMaps
и Secrets
. (Приложение Quarkus я представлю чуть-чуть попозже).
Вот скрипт, которой по сути использует три чарта Helm для необходимых установок:
$ ./bootstrap.sh
---------------
Installing openshift-pipelines operator
Release "openshift-pipelines" does not exist. Installing it now.
NAME: openshift-pipelines
LAST DEPLOYED: Thu Sep 10 10:55:14 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
Installing openshift-serverless
Release "openshift-serverless" does not exist. Installing it now.
NAME: openshift-serverless
LAST DEPLOYED: Thu Sep 10 10:55:16 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
Creating cicd, development, staging and production namespaces
Added cicd system:image-puller role to default sa in development, staging and production namespaces
Added view role to default sa in development, staging and production namespaces
Release "bootstrap-projects" does not exist. Installing it now.
NAME: bootstrap-projects
LAST DEPLOYED: Thu Sep 10 10:55:18 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
Вы можете выполнить скрипты как есть или использовать чарты Helm независимо, переопределяя любые значения на ваш выбор. Например, вы можете переопределить значение канала подписки для каждого оператора OpenShift.
Рисунок 2 показывает текущее состояние установки: оба оператора установлены в неймспейсе openshift-operators
.
Рис. 2. Операторы OpenShift Serverless и OpenShift Pipelines установлены в неймспейсе openshift-operators.
Проверьте, что OpenShift Pipelines Operator установлен не ниже версии 1.1.1.
Теперь завершим установку компонентов OpenShift Serverless, установив панель управления Knative Serving.
Установка экземпляра Knative Serving
Нам нужно установить экземпляр Knative Serving, который предоставит нашим приложениям набор бессерверных возможностей. Чтобы создать экземпляр Knative Serving и установить панель управления, выполните следующее:
$ ./add-knative-serving.sh
------------------------------
Creating knative-serving namespace
namespace/knative-serving created
Installing basic knative serving control plane
knativeserving.operator.knative.dev/knative-serving created
Мы запустили набор подов, которые представляют базовую контрольную панель Knative Serving в неймспейс knative-serving
, как показано на Рисунке 3.
Рис. 3. Панель управления Knative Serving в неймспейсе knative-serving.
Как показано на Рисунке 4, мы также создали новый неймспейс knative-serving-ingress
для установочных входных шлюзов Knative.
Рис. 4. Новый неймспейс knative-serving-ingress.
Мы установили операторов OpenShift и создали неймспейс и экземпляр Knative Serving для управления нашими бессерверными процессами. Теперь мы готовы создать ресурсы Tekton, которые нам понадобятся для запуска пайплайна непрерывной интеграции.
Настройка задач и пайплайна Tekton
OpenShift Pipelines Operator поставляется с набором готовых кластерных задач, которые можно использовать для создания пайплайна. В некоторых ситуациях вам понадобятся другие задачи для получения определенного функционала. Эти задачи можно легко создать в Tekton. Вы также можете найти повторно используемые задачи и готовые пайплайны на Tekton Hub.
Для нашего пайплайна мы будем использовать одну задачу из Tekton Hub и две пользовательские. Чтобы эти задачи были доступны нашему пайплайну, нам нужно создать их в неймспейсе cicd
. (Обратите внимание, что вы можете создать ClusterTasks
, если считаете, что повторно используете их в разных пайплайнах из разных неймспейсов). Запустите следующий скрипт, чтобы установить необходимые задачи и создать пайплайн в том же неймспейсе.
$ ./add-tekton-customs.sh cicd
------------------------------
Installing buildah task from https://hub-preview.tekton.dev/
task.tekton.dev/buildah created
Installing custom tasks
task.tekton.dev/push-knative-manifest created
task.tekton.dev/workspace-cleaner created
Installing knative-pipeline
pipeline.tekton.dev/knative-pipeline created
Перейдите в консоль OpenShift и откройте меню Pipelines и проект cicd. Там вы увидите свои новые задачи, как показано на Рисунке 5.
Рис. 5. Новые задачи Tekton в неймспейсе cicd.
На Рисунке 6 представлен ваш новый пайплайн в том же неймспейсе.
Рис. 6. Пайплайн Tekton в неймспейсе cicd.
Рабочие области Tekton
Некоторые наши задачи в пайплайне требуют либо загрузки определенных конфигураций из ConfigMap
s, либо сохранения состояния полученного выполнения, чтобы разделить его с другими задачами. Например, задача Maven требует, чтобы мы включили определенный settings.xml
в ConfigMap
. С другой стороны, первая задача вызывает репозиторий исходного кода приложения. Задаче Maven, которая идет следующей, потребуются эти файлы, чтобы создать приложение JAR. Мы используем OpenShift PersistentVolume, чтобы поделиться этими исходными файлами.
Tekton для этих целей имеет концепцию рабочих областей. Запустите следующий скрипт, чтобы добавить набор ConfigMap
s и PersistentVolumeClaim
в неймспейс cicd
:
$ ./add-tekton-workspaces.sh cicd
-----------------------------------
Creating knative-kustomize-base ConfigMap with base kustomize files for Knative services
configmap/knative-kustomize-base created
Creating knative-kustomize-environment ConfigMap with environment dependent kustomize files
configmap/knative-kustomize-environment created
Creating maven ConfigMap with settings.xml
configmap/maven created
Creating PVC using default storage class
persistentvolumeclaim/source-pvc created
Заметьте, этот скрипт создает PersistentVolumeClaim, не определяя StorageClass. Если вы не выберете какой-то определенный, то будет использоваться StorageClass
по умолчанию. Без проблем можете раскомментировать любые строки в этом скрипте, чтобы он удовлетворял вашим требованиям.
Демо-приложение
До сих пор я почти ничего не сказал о демо-приложении. Оно основано на Quarkus, который идеально подходит для бессерверных приложений благодаря короткому времени загрузки и низкому потреблению памяти. Само приложение представляет из себя простой REST API “Hello, world”, который приветствует пользователей при вызове URI /hello
.
Приложение использует расширение kubernetes-config для того, чтобы упростить работу с ConfigMap
s и Secrets
в Kubernetes. Приложение “Hello, world!” читает список ConfigMap
s, что дает нам возможность управлять конфигурацией на разных уровнях, отменяя дублируемые свойства.
Рисунок 7 показывает фрагмент application.yaml, который определяет список ConfigMap
s.
Рис. 7. Приложение YAML со списком ConfigMaps.
Вы можете найти полный исходный код приложения в репозитории GitHub для этой статьи. Обратите внимание, что пайплайн также запускает и постоянно обновляет другой репозиторий, который декларативно содержит все манифесты Kubernetes для всех развертываний и конфигураций приложений. Далее в статье мы будем использовать Kustomize, чтобы декларативно настроить конфигурацию и развертывание приложения.
Создание собственного репозитория
На данном этапе вы должны создать репозиторий GitHub, который вы будете использовать для хранения файлов кастомизации, которые необходимы для демонстрации. Мой репозиторий называется quarkus-hello-world-deployment
, и я буду использовать это имя для отсылок к данному репозиторию в следующих скриптах. Вы можете взять то же самое имя или придумать репозиторию свое.
GitHub изменил имя по умолчанию на main
, что видно на Рисунке 8.
Рис. 8. Main задан веткой по умолчанию.
Вместо этого убедитесь, что вы создаете ветку master либо путем изменения настроек по умолчанию, либо через создание новой ветки вручную. После того как вы создали и назвали репозиторий, оставьте его пустым и инициализированным.
Чтобы пайплайн Tekton мог отправлять изменения в новый репозиторий, вам нужно будет предоставить валидные учетные данные GitHub. Учетные данные вы сохраните в Secret
и свяжете их с пайплайном ServiceAccount
, который был автоматически создан в неймспейсе cicd
.
Запустите следующий скрипт:
$ ./add-github-credentials.sh cicd YOUR_GITHUB_USER YOUR_GITHUB_PASSWORD
---------------------------------------------------------------------------
Creating secret with github credentials for user dsanchor
secret/github-credentials created
Linking pipeline sa in namespace cicd with your github credentials
serviceaccount/pipeline patched
Ручной запуск пайплайна
Теперь мы готовы к тому, чтобы вручную протестировать работу пайплайна и увидеть результаты. Рабочий процесс пайплайна включает настройку вебхука, который автоматически запускает пайплайн. Описание этого этапа мы оставим на конец этой статьи (см. Часть 2). На данный момент просто протестируем рабочий процесс, запустив пайплайн вручную.
Я написал два варианта запуска пайплайна вручную:
- Создать пайплайн из yaml-файла;
- Запустить пайплайн, используя Tekton CLI: tkn.
В обоих случаях мы используем заданный commit
из репозитория приложения. Нам также нужно предоставить репозиторий, в котором хранятся все наши манифесты конфигурации и развертывания. В скрипте, приведенном ниже, я ссылаюсь на свой репозиторий развертывания. Вам следует заменить эту отсылку на имя своего репозитория. По готовности выполните следующее:
$ cat tekton/pipelines/knative-pipeline-run.yaml | \
SOURCE_REPO=https://github.com/dsanchor/quarkus-hello-world.git \
COMMIT=9ce90240f96a9906b59225fec16d830ab4f3fe12 \
SHORT_COMMIT=9ce9024 \
DEPLOYMENT_REPO=https://github.com/dsanchor/quarkus-hello-world-deployment.git \
IMAGES_NS=cicd envsubst | \
oc create -f - -n cicd
------------------------------------------------------------------------------------------
pipelinerun.tekton.dev/knative-pipeline-run-54kpq created
Если вы предпочитаете второй вариант, можно запустить пайплайн через tkn CLI:
$ tkn pipeline start knative-pipeline -p application=quarkus-hello-world \
-p source-repo-url=https://github.com/dsanchor/quarkus-hello-world.git \
-p source-revision=9ce90240f96a9906b59225fec16d830ab4f3fe12 \
-p short-source-revision=9ce9024 \
-p deployment-repo-url=https://github.com/dsanchor/quarkus-hello-world-deployment.git \
-p deployment-revision=master \
-p dockerfile=./src/main/docker/Dockerfile.jvm \
-p image-registry=image-registry.openshift-image-registry.svc.cluster.local:5000 \
-p image-repository=cicd \
-w name=source,claimName=source-pvc \
-w name=maven-settings,config=maven \
-w name=knative-kustomize-base,config=knative-kustomize-base \
-w name=knative-kustomize-environment,config=knative-kustomize-environment \
-n cicd
Еще один вариант — запустить пайплайн через консоль OpenShift.
Отслеживание работы пайплайна
Для проверки рабочего прогресса откройте панель Pipeline Runs на консоли OpenShift, как показано на Рисунке 9.
Рис. 9. Использование панели Pipeline Runs для проверки рабочего прогресса.
Если вы хотите увидеть подробности каждой задачи пайплайна, кликните на имя пайплайна. Вы получите логи по каждой задаче, как показано на Рисунке 10.
Рис.10. Просмотр логов каждой задачи пайплайна.
Если вдруг вы дважды запустите пайплайн с одними и теми же параметрами (например, используя оба примера, которые я описал), вы увидите, что второй запуск завершится ошибкой при отправке манифестов Kustomization. Ошибка происходит, потому что нет ничего нового для выполнения — отлично!
Результаты работы пайплайна
Диаграмма на Рисунке 11 иллюстрирует, чего мы уже достигли:
Рис. 11. Выполнение процесса CI/CD.
Заметьте, мы заменили шаги, относящиеся к «Отправке кода» и «вебхуку репозитория», на ручной запуск пайплайна, основанный на ID определенного коммита.
На данный момент мы уже отправили новый образ во внутренний registry OpenShift. Мы также запустили репозиторий, который будет содержать все манифесты конфигурации и развертывания вместе со всеми манифестами Kubernetes, которые требуются для запуска первой версии нашего бессерверного приложения.
Обзор структуры репозитория развертывания
Сейчас самое время для обзора структуры репозитория развертывания и того, что в итоге станет окончательными манифестами, которые мы создадим с помощью Kustomize. Если вы не знакомы с Kustomize и его возможностями, не стесняйтесь узнать о нем больше. Понимание Kustomize может помочь лучше разбираться в структуре репозитория.
Обновите репозиторий развертывания (git pull)
, вы должны увидеть похожий результат:
├── base
│ ├── global-ops-configmap.yaml
│ ├── kservice.yaml
│ └── kustomization.yaml
├── development
│ ├── env-ops-configmap.yaml
│ ├── kustomization.yaml
│ ├── r9ce9024
│ │ ├── configmap.yaml
│ │ ├── revision-patch.yaml
│ │ └── routing-patch.yaml
│ └── traffic-routing.yaml
├── production
│ ├── env-ops-configmap.yaml
│ ├── kustomization-r9ce9024.yaml
│ ├── r9ce9024
│ │ ├── configmap.yaml
│ │ ├── revision-patch.yaml
│ │ └── routing-patch.yaml
│ └── traffic-routing.yaml
├── README.md
└── staging
├── env-ops-configmap.yaml
├── kustomization-r9ce9024.yaml
├── r9ce9024
│ ├── configmap.yaml
│ ├── revision-patch.yaml
│ └── routing-patch.yaml
└── traffic-routing.yaml
Для простоты я пока рассмотрю только папки base
и development
:
- Папка
base
содержит все ресурсы, общие для трех сред. В ней есть базовая структура сервиса Knative и карта глобальной конфигурации. - Папка
development
содержит наложения для завершения генерации манифеста сервиса Knative в данной версии приложения (примером служит папкаr9ce9024
) и двух ConfigMap, связана с уровнем настроек самого окружения и уровнем настроек разработчика. То, что находится в папке ревизии, было скопировано из исходного кода приложения, что позволяет разработчику самому задавать гибкие настройки.
Мы пользуемся простотой сервисов Knative, чтобы определить независимые маршруты для каждой версии сервиса и распределить трафик между версиями. Таким образом, traffic-routing.yaml
и routing-patch.yaml
формируют окончательную секцию маршрутизации трафика сервиса Knative.
Каждый раз когда в development
появляется новая версия, для нее создается независимый маршрут, чтобы она точно была доступна для тестирования. Основной маршрут остается неизменным (например, направленный на две предыдущие версии). Мы достигаем такого поведения не путем изменения основного traffic-routing.yaml
автоматически из пайплайна, а благодаря добавлению нового маршрута (routing-patch.yaml
) для новой версии.
Эти детали станет проще понимать, когда мы проведем дополнительные тесты в Части 2. На данный момент просто отметьте для себя существенную разницу между неймспейсами staging
и production
и средой development
. Пайплайн CI не создает файл kustomization.yaml (именно с таким именем) для них. Всегда будет файл с дополнительным префиксом версии: kustomization-r9ce9024.yaml. Эти изменения не будут учитываться в процессе синхронизации, если только в kustomization.yaml
нет отсылки на эту новую версию. Чтобы изменения стали видны Kustomize, это надо настроить вручную.
Примечание: Суть различий в именах файлов заключается в том, чтобы лучше различать наши демо-окружения. Я хотел, чтобы эти две среды вели себя по-разному, чтобы требовалось одобрение изменений от кого-то. Переименование файла — простой подход к одобрению, который не делает демонстрацию слишком сложной. Я бы предпочел создавать отдельную ветку для каждой новой версии, а потом генерировать pull request, когда в ней завершена работа.
Kustomize: соберем все кусочки пазла вместе
Мы рассмотрели наполнение и структуру репозитория развертывания, но у нас до сих пор нет окончательной композиции сервиса Knative и ConfigMap
s. Приведенный ниже скрипт использует kustomize
для построения окончательных манифестов, чтобы мы смогли увидеть, как они выглядят:
$ kustomize build development
------------------------------
apiVersion: v1
kind: ConfigMap
metadata:
name: env-ops-quarkus-hello-world
---
apiVersion: v1
kind: ConfigMap
metadata:
name: global-ops-quarkus-hello-world
---
apiVersion: v1
data:
application.yaml: |-
message: hola
environment:
name: dev
kind: ConfigMap
metadata:
name: quarkus-hello-world
---
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: quarkus-hello-world
spec:
template:
metadata:
name: quarkus-hello-world-r9ce9024
spec:
containers:
- image: image-registry.openshift-image-registry.svc.cluster.local:5000/cicd/quarkus-hello-world:9ce90240f96a9906b59225fec16d830ab4f3fe12
livenessProbe:
httpGet:
path: /health/live
readinessProbe:
httpGet:
path: /health/ready
traffic:
- percent: 100
revisionName: quarkus-hello-world-r9ce9024
- revisionName: quarkus-hello-world-r9ce9024
tag: r9ce9024
Заключение
На данном этапе мы могли бы применить наш набор объектов в неймспейсе development
, чтобы получить рабочее бессерверное приложение, но мы не хотим вручную запускать развертывание. Во второй части статьи я покажу, как интегрировать Argo CD в пайплайн CI/CD, который мы уже создали.
От редакции: Узнать о внедрении CI/CD и интеграции Gitlab CI с Kubernetes можно с помощью практического видеокурса Слёрма. На уроках курса инженеры компаний Tinkoff и Southbridge делятся лучшими практиками построения пайплайнов.
Вторая часть статьи доступна здесь.