В новой статье рассмотрим основы CI/CD и познакомимся Jenkins. Вы узнаете, где применяется Jenkins и какие проблемы помогает решить, поймёте логику архитектурных решений и особенности структуры каталогов. А ещё научитесь устанавливать Jenkins и производить базовую конфигурацию.
За основу статьи взят первый урок нашего практического курса «CI/CD с Jenkins».
CI/CD: что это такое и зачем нужно
Скорость разработки продуктов — одно из главных конкурентных преимуществ в разработке ПО. Поэтому на смену старым моделям программирования пришла новая концепция CI/CD.
CI (Continuous Integration) — непрерывная интеграция. Разработчики, применяющие данный паттерн, могут проверять основную ветку репозитория каждый раз, когда что-то замержили в неё. Не просто запускать локальные проверки, а в рамках CI-пайплайна выполнять автоматические тесты, unit-тесты и др.
CD, (Continuous Delivery) — непрерывная поставка. На этой стадии происходит автоматическое развертывание на стенды и тестовые окружения. Ещё CD расшифровывают как Continuous Deployment — непрерывное развёртывание. Это более продвинутый путь, на шаг дольше, чем непрерывная поставка. При таком подходе каждое изменение, которое мы коммитим в основную ветку репозитория, автоматически проходит все этапы CI и CD и затем попадает на продакшн.
Continuous Deployment Pipeline — высший пилотаж, который редко встречается на практике, потому что всегда есть определённые ограничения. Эти ограничения могут быть как в самом пайплайне, так и в бизнес-процессах с точки зрения безопасности. Но, однозначно, Continuous Deployment Pipeline — то, к чему нужно стремиться.
Цели CI/CD:
обеспечение последовательного и автоматизированного способа сборки, упаковки и тестирования;
автоматизация развёртывания в разных окружениях;
сведение к минимуму ошибок и проблем.
Добиться этих целей помогают четыре принципа, на которых основана концепция CI/CD. Первый принцип — разделение активности. Каждый из участников процесса делит ответственность за жизненные циклы продукта. Проектируется бизнес-логика, выбираются сквозные функции, проводятся тесты, организуется доставка кода из одного окружения в другое.
Второй принцип — снижение рисков. Чтобы баги не доходили до продакшена, контролируется корректность бизнес-логики, проверяется пользовательский опыт на стендах, улучшается процесс хранения и обработки данных. Чем раньше мы обнаружим риск, тем быстрее идентифицируем проблему и тем меньше средств потратим на её решение.
Третий принцип — сокращение цикла обратной связи. В рамках CI/CD мы стремимся увеличить скорость внесения изменений и согласования правок.
Четвертый принцип — реализация среды. У разработчиков должно быть общее пространство для работы с основной веткой или со вспомогательными ветками. Это пространство должно быть отказоустойчивым и удобным для работы.
Основные этапы CI/CD выглядят так:
Планирование основывается на пользовательском опыте и бизнес-функционале. Обычно за этот этап отвечают люди из анализа: они переводят требования с языка бизнеса на язык, понятный разработчикам и администраторам. Затем начинается этап работы с кодом — разработчики пишут код, проводят тестирования в ручном режиме и добавляют изменения в основную ветку репозитория.
После того, как изменения попадают в репозиторий, система контроля версии инициирует сборку и тестирование проекта. Тестирование может быть как ручным, так и автоматическим — зависит от того, как работает команда. Далее всё уходит сначала на релиз, а затем на развёртывание. На этапе развёртывания уже протестированная версия приложения отправляется на продакшн и становится доступна пользователям.
Когда продукт попадает к пользователям, мы продолжаем следить за ним — этап поддержки и мониторинга. Мы контролируем, как пользователь идёт по бизнес-процессу, корректно ли работают интеграции. Если на стадии мониторинга мы обнаруживаем ошибку, возвращаемся к самому началу — к планированию. Аналитики разбирают, что пошло не так и предлагают новое решение, разработчики пишут код, и снова начинается процесс сборки.
Как и у любой методологии, у CI/CD есть свои плюсы и минусы:
Плюсы | Минусы |
Минимальное время от запроса клиента до запуска в использование — мы быстрее доставляем новые фичи | Сложность обеспечения взаимодействия — и DevOps-инженеры, и разработчики должны понимать, что было сделано и зачем |
Возможность проверки вариантов — можем моментально проверять изменения и при необходимости откатывать назад | Требования к опыту — нужен опыт настройки CI/CD, который почти всегда добывается с болью |
Качество результата — можем быстро обнаружить и пофиксить ошибки |
Реализовать принципы CI/CD, свести к минимуму ошибки интеграции, а также ускорить релизы и повысить их качество помогает Jenkins.
Что такое Jenkins
Jenkins – не просто инструмент CI/CD. Это Framework, потому что он:
Гибок и расширяем. Jenkins — опенсорсный проект с множеством внешних расширений.
Минимален из коробки. У Jenkins есть контроллер. Вы можете подключить к нему несколько слоев и уже на этом сетапе собрать минимальный пайплайн, который позволит автоматизировать работу по обновлению сервисов.
Требует настройки. Jenkins — один из кубиков, с помощью которого можно построить большую систему автоматизации. Но прежде чем сделать что-то, его придётся настроить.
Jenkins — это Java-приложение. У него есть контроллер или Master Mode — управляющий центр, который занимается планированием задач. Он запускает задачи согласно установленному расписанию на слэйвах, которые вы к нему прикрепили. Помимо этого контроллер хранит логи наших задач. Вся история хранится только на Master Mode, поэтому важно помнить о настройке правильной ротации логов.
Слэйвы или агенты — это то, что непосредственно выполняет сами задания.
Коротко их взаимодействие можно описать так: контроллер запускает задачу и говорит агенту выполнить её, агент выполняет задачу и возвращает результат контроллеру. Контроллер получает результат и сохраняет его в build-логе.
Установка Jenkins
Разберём, как установить Jenkins, как настроить параметры JVM и почему это важно. Дополнительно познакомимся с Jenkins Home: что это за зверь и с чем его едят. Все действия будем выполнять на Ubuntu.
Перед установкой Jenkins нужно установить Java — без этого никак. Мы проверяем, есть ли на нашем виртуальном энвайронменте Java:
root@vs01:~# java --version
По умолчанию из коробки Java нет:
Рекомендуется использовать Java 11, потому что у неё более продвинутый Garbage Collector. Поставим её:
root@vs01:~# apt install openjdk-11-jre-headless
Проверим, что Java установилась:
root@vs01:~# java --version
Теперь нужно сконфигурировать файл limit.com. Но в Linux всё — файл, поэтому нужно установить фан-лимит, чтобы снять ограничения и позволить Jenkins генерировать файлы, дампы и др. Если не сделать этого, в каких-то случаях мы не сможем получить данные и понять, что же с Jenkins пошло не так.
Редактируем лимиты на Ubuntu:
root@vs01:~# vi/etс/security/limits.conf
И добавляем секцию управления и устанавливаем права на различные лимиты: хардовые, софтовые, size-файлы и др:
Дальше нужно установить фаервол на Ubuntu:
root@vs01:~# apt-get install ufw
Обязательно разрешаем OpenSSH-порт, потому что больше не сможем подключиться к этой машине:
root@vs01:~# ufw allow OpenSSH
8080 — порт, по которому работает Jenkins.
root@vs01:~# ufw allow 8080
Проверяем Jenkins репозиторий, потому что по умолчанию его нет в стоке Ubuntu:
root@vs01:~# wget -q -o – http://pkg.jenkins.io/Debian-stable/jenjins.io.key|sudo gpg --dearmor -o /usr/share/keyrings/Jenkins.gpg
После того, как скопировали ключи, устанавливаем Jenkins в sources list:
Важно для Ubuntu делать apt-get update:
root@vs01:~# apt-get update -y
Теперь можем поставить Jenkins:
root@vs01:~# apt-get install Jenkins -y
Установка проходит довольно быстро. Если посмотреть верхнеуровнево, то Jenkins — это war-файл. И вы можете не устанавливать его в систему через system, а просто скачать war-файл и запускать через war.
Мы можем посмотреть статус Jenkins App:
root@vs01:~# systemctl status jenkins
Он активный, но нам этого недостаточно. Jenkins — это Java, а Java очень требовательно относится к памяти. Поэтому дальше поговорим про Garbage Collector — службу, которая очищает память от неиспользованных объектов.
Мы немного «подтюним» Java-машину и добавим опции в файл etc systemd/system/jenkins.service:
root@vs01:~# vi /lib/systemd/system/Jenkins.service
Найдём Java OPTS:
Добавим больше опций:
Обратите внимание, что в настройках мы указываем Xmx512m и Xms512 — размер оперативной памяти, который выделяем Java-машине для работы. Вообще размер зависит от количества доступной памяти в операционной системе и корректируется в соответствии с ней. По рекомендациям Cloud Business и личному опыту, нужно ставить не больше 16 гигабайт на hip size. Но при этом важно не забывать, что у вас есть Meta Space и система, которые тоже занимают память. Если у вас на машине 20 гигабайт памяти, смело можно ставить 16. Если у вас всего 18 гигабайт памяти, и вы выделяете 16 гигабайт под Jenkins и Java, не удивляйтесь, когда машина начнёт работать плохо, а в какой-то момент просто умрёт.
Здесь выставляем Garbage Collector — UseG1GC:
И добавляем снятие автоматического дампа при out of memory:
Это полезная опция, когда Jenkins падает. Конечно, падения все равно будут случаться — мы не всегда можем рассчитать нагрузку и определить, сколько потребуется памяти для работы. Но параметр поможет понять, что произошло.
Также в Garbage Collector выставляем лог — /var/lib/jenkins/gc.log:
Сохраняем.
Нужно перезагрузить Jenkins, но перед этим сделать daemon-reload:
root@vs01:~# systemctl daemon-reload
root@vs01:~# systemctl restart Jenkins
Проверим:
root@vs01:~# systemctl status Jenkins
oot@vs01:~# cat /proc/http://Jenkins.s043218.edu.slurm.io^C
root@vs01:~# cat /proc/67043/cmdline
Видим, что Java настроена как раз под те опции, что мы ей передали, и запускается Jenkins war:
Теперь откроем веб-интерфейс http://jenkins.s043218.edu.slurm.io. Он предлагает разблокировать Jenkins:
То есть первоначальная установка предполагает, что вы введете некий мастер-пароль. Jenkins сам подсказывает, где этот мастер-пароль можно найти — var/lib/jenkins/secret/initialAdminPassword. Давайте пойдём туда и посмотрим:
root@vs01:~# cd var/lib/jenkins/
root@vs01:/var/lib/jenkins/# cd secrets/
root@vs01:/var/lib/jenkins/secrets# ls -al
Initial password — пароль, который вы можете использовать один раз при первой установке Jenkins. После вы переключитесь на внутреннюю базу авторизации.
Следующий шаг — установить Suggested-плагины или самостоятельно выбрать плагины, которые хотите поставить.
Список плагинов, которые используются в Suggested, достаточно правильный, поэтому рекомендуется просто поставить эти плагины автоматом.
А пока Jenkins делает плагины, посмотрим на Home-директорию:
root@vs01:/var/lib/jenkins/secrets# cd ..
root@vs01:/var/lib/jenkins# ls -la
У Jenkins нет выделенной базы, как у некоторых систем. В качестве базы данных он использует директорию Jenkins Home, которая есть в каталоге файловой системы того сервера, на который выставили контролер. Здесь хранятся: конфиги, плагины, задания, которые мы делаем и всё, что связано с ними и т.д.
Вернёмся к Jenkins — он уже поставил домен и предлагает нам настроить первого пользователя. Заполним поля:
Далее Jenkins предлагает настроить URL:
Этот параметр достаточно важный, потому что его параметр будут использовать различные слэйвы для автоматического коннекта к мастеру.
Итак, мы поставили Jenkins. Пока нет никаких заданий, но мы можем немного пройтись по Manage Jenkins:
Из наиболее интересного здесь:
System information — хранит всю основную информацию (Java Home, версия Java, версия Ubuntu и т.д.).
System log — то, куда нужно смотреть, если непонятно, почему не подключается агент или не работает скрип.
Load statistics — показывает, сколько экзекьюторов всего онлайн.
На этом всё. В рамках первого урока мы повторили цели CI/CD, узнали, что такое Jenkins и рассмотрели область его применения. Ещё попробовали самостоятельно установить Jenkins на Ubuntu-сервер и познакомились с содержимым Jenkins Home. В следующих уроках подробно разберём администрирование Jenkins, научимся настраивать интеграции, создавать конфигурации Jenkins As a Code и многое другое.