Введение
Непрерывная интеграция и непрерывное развертывание — сокращенно CI/CD — важны при разработке современного ПО: ими упрощаются автоматизированная интеграция кода и выпуск надежных приложений.
Jenkins — ведущий инструмент для создания конвейеров CI/CD, славится гибкостью и широкими возможностями плагинов.
Выполним с его помощью полную настройку конвейера CI/CD: от конфигурирования и интеграции Jenkins с системами контроля версий до оркестрации сборок, тестов и развертываний. Цель — усовершенствовать процесс разработки и выпуска ПО.
Применяемые инструменты и технологии:
- GitHub для контроля версий;
- Maven для управления проектами и для сборок;
- SonarQube для анализа качества кода;
- Docker для контейнеризации;
- Jenkins для непрерывной интеграции;
- ArgoCD и Helm для управления развертыванием Kubernetes;
- Kubernetes для оркестрации контейнеров.
Настройка Git
Заложим основу для конвейера Jenkins с приложением Java, сконфигурируем Git:
- Создаем приватный гит-репозиторий:
- В своей учетной записи на гит-хостинговой платформе — GitHub или GitLab — создаем репозиторий, для защиты кода устанавливаем видимость
private
.
2. Генерируем персональный токен доступа:
- В настройках учетной записи — обычно внутри профиля или в выпадающем меню — находим раздел Developer settings («Настройки разработчика») или Personal access tokens («Персональные токены доступа»).
- Создаем токен, присваиваем разрешения, например repo для доступа к репозиториям.
- Сохраняем токен, он понадобится для настройки доступа в конвейере Jenkins.
3. Клонируем репозиторий локально:
- Находим исходный код, в Git Bash или терминале переходим в каталог, куда клонируется репозиторий.
- Вводим команду ниже, заменив
<URL>
на url-адрес репозитория:
git clone <URL>
Создание экземпляра EC2
Этот этап автоматизируется с помощью Terraform, но ради простоты выполним его вручную.
- Под своими данными учетной записи заходим на консоль управления AWS. Нет учетной записи? Создаем.
2. Наверху, в меню Services («Службы»), переходим в раздел Compute, нажимаем EC2 и попадаем в дашборд EC2.
3. Запускаем экземпляр:
- Нажимая кнопку Launch Instances («Запустить экземпляры»), запускаем процесс создания экземпляра EC2.
4. Добавляем теги:
- Для совершенствования организации и управления добавляем экземпляру теги и названия.
5. Выбираем AMI, образ машины Amazon:
- Из списка AMI, то есть преднастроенных шаблонов серверов с различными операционными системами и настройками, выбираем AMI под свои требования.
- Простейший вариант для начинающих — Amazon Linux AMI или базовый сервер Ubuntu.
6. Выбираем тип экземпляра:
- Тип экземпляра выбирается под свои требования.
- Вариант по умолчанию — обычно это экземпляр
t2.micro
— хорош для тестирования и небольших рабочих нагрузок, он условно-бесплатного уровня. - Мы выбрали экземпляр
t2.large
с двумя виртуальными процессорами и 8 ГиБ памяти — для умеренных рабочих нагрузок. - Этот тип экземпляра платный, поэтому для эффективного управления своим бюджетом рекомендуем ознакомиться с текущими ценами в AWS.
7. Создаем пару ключей:
- Создаем пару ключей для SSH-доступа к экземпляру или используем имеющуюся.
- Загружаем
.pem
-файл с приватным ключом и сохраняем его. После создания он не загружается повторно.
8. Настраиваем данные экземпляра:
- При необходимости настраиваются данные экземпляра: сетевые параметры, подсети, роль IAM и т. д. Пока оставляем настройки по умолчанию.
9. Настраиваем группу безопасности:
- Группа безопасности — это как виртуальный брандмауэр, которым контролируется разрешенный входящий и исходящий трафик экземпляра.
- Создается новая группа безопасности либо выбирается имеющаяся. Открываем входящие порты, например SSH-порт 22, пользовательские TCP 8080 и 9000.
10. Добавляем хранилище:
- Указываем размер корневого тома — значение по умолчанию обычно применяют для тестирования.
11. Проверяем и запускаем:
- Проверяем настройки экземпляра: данные AMI, тип экземпляра, группы безопасности, пары ключей.
- Запускаем, нажимая Launch («Запустить»):
Получение доступа к экземпляру
После запуска экземпляр за несколько минут инициализируется.
Дальше подключаемся к экземпляру по SSH с помощью загруженного .pem
-файла и Mobaxterm — для компьютеров с Windows:
- Устанавливаем и открываем MobaXterm на рабочем столе или в меню «Пуск».
- Нажимаем кнопку Session («Сеанс»), затем выбираем SSH.
- Вводим IP-адрес или имя хоста сервера, указываем имя пользователя.
- Нажимаем Advanced SSH settings («Расширенные настройки SSH»), ставим галочку в Use private key («Использовать приватный ключ») и выбираем пару приватных ключей, задействованных ранее в экземпляре.
- Нажимая OK, подключаемся:
Настройка Jenkins
Устанавливаем Java:
Прежде чем запускать Jenkins, установим Java на сервере. Jenkins совместим и с Oracle Java, но оптимальное в целом взаимодействие у него с OpenJDK.
Устанавливаем Java на экземпляр, к которому подключились по SSH:
sudo apt update
sudo apt install openjdk-11-jdk
java -version
Устанавливаем Jenkins:
Имеется два варианта установки: с помощью скрипта или выполнением команд вручную.
Первый эффективен и воспроизводим, особенно если планируется развертывать Jenkins многократно или применять одну настройку в разных средах.
- В vim или любом другом редакторе создаем файл скрипта:
vim install_jenkins.sh
- Нажав
i
, переходим в режим вставки и пишем скрипт:
#!/bin/bash
# Загружаем GPG-ключ для Jenkins
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
# Добавляем репозиторий Jenkins в источники диспетчера пакетов
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
# Обновляем репозитории диспетчера пакетов
sudo apt-get update
# Устанавливаем Jenkins
sudo apt-get install jenkins -y
- Вводим
:wq
и нажимаемEnter
. Этой командой записываемw
в файл изменения и выходимq
из редактора. - Делаем файл исполняемым:
chmod +x install_jenkins.sh
- Теперь для установки Jenkins запускаем этот исполняемый скрипт:
./install_jenkins.sh
Настраиваем параметры брандмауэра:
Чтобы обеспечить доступ к Jenkins через браузер, важно корректно настроить параметры брандмауэра.
По умолчанию Jenkins запускается на порту 8080. Следует разрешить входящий трафик через этот порт в настройках группы безопасности.
Получаем доступ к пользовательскому интерфейсу Jenkins:
Доступ к ПИ Jenkins получаем, вводя в браузере IP-адрес экземпляра и :8080
, например http://192.168.1.2:8080
. То есть 192.168.1.2
заменяем фактическим IP-адресом сервера.
Разблокируем Jenkins исходным паролем администратора:
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
Устанавливаем предлагаемые плагины:
- Разблокировав Jenkins, установим предлагаемые плагины или выберем конкретные плагины вручную.
- Чтобы автоматически установить стандартный набор плагинов, рекомендуемый большинству пользователей, нажимаем Install suggested plugins («Установить предлагаемые плагины»):
Создаем пользователя-администратора:
- После установки плагина предлагается создать пользователя с правами администратора для Jenkins.
- Заполняем форму, указав имя пользователя, пароль, полное имя и электронную почту, нажимаем Save and Continue («Сохранить и продолжить»):
Jenkins готов:
- Настроим URL-адрес экземпляра Jenkins.
- Вводится URL-адрес по умолчанию — на основе IP-адреса и порта сервера.
- Нажимая Start using Jenkins («Начать использовать Jenkins»), завершаем настройку и оказываемся в дашборде Jenkins:
Устанавливаем необходимые плагины:
- В интерфейсе Jenkins дашборда переходим в Manage Jenkins («Управление Jenkins») > Plugins («Плагины»).
- Находим и устанавливаем плагины docker pipeline и sonarqube scanner, при необходимости перезапускаем Jenkins:
Задача компиляции
- В главном окне дашборда Jenkins нажимаем New Item («Новый элемент»).
- Называем конвейер, выбираем тип проекта Pipeline («Конвейер»), нажимаем OK:
Настраиваем конвейер:
- Нажимаем на созданную задачу и прокручиваем вниз до раздела Pipeline («Конвейер») на экране настройки.
- Выбираем Pipeline script («Скрипт конвейера») или Pipeline script from SCM («Скрипт конвейера из SCM»).
В первом варианте пишется Groovy-скрипт непосредственно в интерфейсе Jenkins, во втором скрипт извлекается из SCM — системы управления исходным кодом.
- Затем выбираем тип SCM, например Git.
- Вводим URL-адрес репозитория, в котором содержится Jenkinsfile.
- Если репозиторий приватный, добавляем учетные данные.
- Указываем ветку для сборки:
*/main
или*/master
. - Если Jenkinsfile находится в подкаталоге или назван по-другому, указываем путь, по умолчанию —
Jenkinsfile
:
Перезапускаем Jenkins:
- Чтобы корректно применить изменения или обновления настроек, перезапускаем Jenkins: в Manage Jenkins на боковой панели дашборда выбираем Reload Configuration from Disk («Перезагрузить конфигурацию с диска») или Restart Safely («Перезагрузить безопасно»).
Настройка сервера Sonarqube
Процесс настройки упрощается установкой SonarQube как контейнера Docker. Это популярный вариант, с которым легче управление и масштабирование.
Потребуется: установить на сервере Docker.
Установка Docker:
- В vim или любом другом редакторе создаем файл скрипта:
vim install_docker.sh
- Нажав
i
, переходим в режим вставки и пишем скрипт:
#!/bin/bash
# Обновляем репозитории диспетчера пакетов
sudo apt-get update
# Устанавливаем необходимые зависимости
sudo apt-get install -y ca-certificates curl
# Создаем папку GPG-ключа для Docker
sudo install -m 0755 -d /etc/apt/keyrings
# Загружаем GPG-ключ для Docker
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
# Обеспечиваем ключу корректные разрешения
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Добавляем репозиторий Docker в источники Apt
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Обновляем репозитории диспетчера пакетов
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
- Нажимая
Esc
, выходим в обычный режим, вводим:wq
и нажимаемEnter
. - Делаем файл исполняемым:
chmod +x install_docker.sh
- Теперь для установки Docker запускаем этот исполняемый скрипт:
./install_docker.sh
Устанавливаем Sonarqube:
- Извлекаем из Docker Hub официальный образ Docker для SonarQube:
docker pull sonarqube
- Запускаем SonarQube в контейнере Docker:
docker run -d --name sonarqube -p 9000:9000 sonarqube
По умолчанию SonarQube запускается на порту 9000. Обеспечим доступ к дашборду SonarQube, разрешив в брандмауэре входящий трафик через этот порт.
Доступ к SonarQube получаем, вводя в браузере http://<your_instance_ip>:9000
и заменяя <your_instance_ip>
IP-адресом сервера.
Вот учетные данные по умолчанию для входа в SonarQube:
- Имя пользователя: admin
- Пароль: admin
После первой настройки их рекомендуется сменить — по соображениям безопасности.
Интегрируем с Jenkins:
- Устанавливаем сканер SonarQube для плагина Jenkins.
- В дашборде SonarQube переходим в My Account («Моя учетная запись») > Security («Безопасность») и нажимаем Generate Token («Сгенерировать токен»).
- Указываем название токена, нажимаем Generate («Сгенерировать»), сгенерированный токен копируем.
Добавляем токен SonarQube как учетные данные в Jenkins:
- В Jenkins переходим в Manage Jenkins > Credentials («Учетные данные») > System («Система») > Global credentials («Глобальные учетные данные») или переходим к учетным данным проекта.
- Нажимаем Add Credentials («Добавить учетные данные»).
- В типе учетных данных выбираем Secret text («Секретный текст»).
- В поле Secret вставляем токен аутентификации SonarQube.
- Дополнительно указываем идентификатор и описание учетных данных.
- Нажимая Create, сохраняем учетные данные.
Настраиваем в Jenkins сканер SonarQube:
- В разделе для анализа SonarQube настроек задачи Jenkins указываем url-адрес сервера SonarQube, например
http://<your_instance_ip>:9000
, заменяя<your_instance_ip>
IP-адресом сервера. - Токен аутентификации — добавленный ранее токен SonarQube.
Учетные данные
Корректно настраиваем все необходимые учетные данные для конвейера CI/CD: аутентификации SonarQube и тиг-репозитория, доступа к Docker Hub:
Jenkinsfile
Jenkinsfile — это текстовый файл, которым определяется конфигурация конвейера Jenkins. Этот файл написан на Groovy, скриптовом языке для платформы Java.
В Jenkinsfile указываются шаги, этапы и действия, выполняемые Jenkins при запуске задачи конвейера.
Внимание: некоторые части Jenkinsfile потребуется заменить своими данными, в том числе учетными.
Этапы конвейера:
Этап 1. Извлечение исходного кода из Git.
Этап 2. Сборка Java-приложения с помощью Maven.
Этап 3. Запуск модульных тестов с JUnit и Mockito.
Этап 4. Запуск анализа SonarQube для проверки качества кода.
Этап 5. Упаковывание приложения в jar-файл.
Этап 6. Развертывание приложения в тестовой среде с помощью Helm.
Этап 7. Запуск в развернутом приложении пользовательских тестов приемки.
Этап 8. Перевод приложения в производственную среду с помощью Helm.
pipeline {
agent {
docker {
image 'abhishekf5/maven-abhishek-docker-agent:v1'
args '--user root -v /var/run/docker.sock:/var/run/docker.sock' // подключается сокет Docker для доступа к демону Docker хоста
}
}
stages {
stage('Checkout') {
steps {
sh 'echo passed'
//гит-ветка: 'main', url-адрес: 'https://github.com/wangoimwangi/jenkins-CICD.git'
}
}
stage('Build and Test') {
steps {
sh 'ls -ltr'
// проект собирается, и создается jar-файл
sh 'cd spring-boot-app && mvn clean package'
}
}
stage('Static Code Analysis') {
environment {
SONAR_URL = "http://54.252.140.131:9000"
}
steps {
withCredentials([string(credentialsId: 'sonarqube', variable: 'SONAR_AUTH_TOKEN')]) {
sh 'cd spring-boot-app && mvn sonar:sonar -Dsonar.login=$SONAR_AUTH_TOKEN -Dsonar.host.url=${SONAR_URL}'
}
}
}
stage('Build and Push Docker Image') {
environment {
DOCKER_IMAGE = "ultimate-cicd:${BUILD_NUMBER}"
// DOCKERFILE_LOCATION = "spring-boot-app/Dockerfile"
REGISTRY_CREDENTIALS = credentials('docker-cred')
}
steps {
script {
sh 'cd spring-boot-app && docker build -t ${DOCKER_IMAGE} .'
def dockerImage = docker.image("${DOCKER_IMAGE}")
docker.withRegistry('https://index.docker.io/v1/', "docker-cred") {
dockerImage.push()
}
}
}
}
stage('Update Deployment File') {
environment {
GIT_REPO_NAME = "jenkins-CICD"
GIT_USER_NAME = "wangoimwangi"
}
steps {
withCredentials([string(credentialsId: 'github', variable: 'GITHUB_TOKEN')]) {
sh '''
git config user.email "[email protected]"
git config user.name "Maria"
BUILD_NUMBER=${BUILD_NUMBER}
sed -i "s/replaceImageTag/${BUILD_NUMBER}/g" spring-boot-app-manifests/deployment.yml
git add spring-boot-app-manifests/deployment.yml
git commit -m "Update deployment image to version ${BUILD_NUMBER}"
git push @github.com/${GIT_USER_NAME}/${GIT_REPO_NAME">https://${GITHUB_TOKEN}@github.com/${GIT_USER_NAME}/${GIT_REPO_NAME} HEAD:main
'''
}
}
}
}
}
- Нажимая Build Now («Запустить сборку»), активируем сборку задачи конвейера: Jenkinsfile извлекается из репозитория и выполняется в Jenkins, как это определено.
- Ход выполнения задачи конвейера отслеживаем в дашборде Jenkins.
- Подробные логи и обновления статуса по мере выполнения каждого этапа конвейера просматриваем внутри задачи.
- Если во время выполнения конвейера появляются проблемы, ищем ошибки в Jenkinsfile и настройках задачи.
- В консольном выводе и логах содержится дополнительная информация о любых сбоях.
А в SonarQube — отчет о выполнении конвейера.
Настройка ArgoCD
Непрерывное развертывание конвейеров CI/CD с автоматизированием развертываний в Kubernetes контролируется в ArgoCD.
Выполняется локальное развертывание с Minikube или облачное с Amazon EKS.
Потребуется:
- На компьютере с Windows устанавливаем VirtualBox или Hyper-V для виртуализации, это требование Minikube.
Устанавливаем Minikube:
- Загружаем и устанавливаем Minikube согласно инструкциям по конкретной ОС из официальной документации Minikube.
- Запускаем локальный кластер Kubernetes:
minikube start
Устанавливаем Kubectl:
- Загружаем последнюю версию
kubectl
с официальной страницы выпуска Kubernetes. - Добавляем
kubectl
в PATH, чтобы запускать его в командной строке откуда угодно.
Установка оператора ArgoCD
Argo CD устанавливается в Kubernetes с помощью оператора Argo CD, которым автоматизируются развертывание экземпляров Argo CD и управление ими.
- На официальной странице Operator Hub в строке поиска вводим Argo CD и нажимаем Install («Установить»).
- Запускаем команды:
#Устанавливаем диспетчер жизненного цикла оператора — инструмент управления операторами, запускаемыми в кластере.
$ curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.27.0/install.sh | bash -s v0.27.0
#Устанавливаем оператор AgroCD
kubectl create -f https://operatorhub.io/install/argocd-operator.yaml
- Этот оператор установится в пространстве имен operators и будет доступен из всех пространств имен кластера.
# наблюдаем, как появляется оператор
$ kubectl get csv -n operators
Настройка контроллера ArgoCD
- В операторе Argo CD на странице Operator Hub прокручиваем вниз до Operator Documentation («Документация оператора»).
- Нажимаем Usage («Использование»), затем Basics («Основы»).
- Копируем имеющуюся yaml-конфигурацию для развертывания Argo CD в кластере Kubernetes.
- Чтобы определить экземпляр Argo CD, создаем файл
vim argocd-basic.yml
с таким содержимым:
apiVersion: argoproj.io/v1alpha1
kind: ArgoCD
metadata:
name: example-argocd
labels:
example: basic
spec: {}
- Применяем конфигурацию:
kubectl apply -f argocd-basic.yml
Настройка пользовательского интерфейса ArgoCD
- Чтобы получить доступ к ПИ сервера Argo CD через браузер, меняем тип службы с ClusterIP на NodePort:
kubectl get svc
- В Minikube генерируется url-адрес для прямого доступа к серверу Argo CD через браузер:
minikube service argocd-server --url
- url-адрес предыдущей команды копируем в браузер и оказываемся в ПИ Argo CD:
- Имя пользователя по умолчанию — admin. Пароль администратора извлекаем из секретов Kubernetes:
kubectl get secret
- Отредактировав секрет example-argocd-cluster, копируем пароль администратора:
kubectl edit secret example-argocd-cluster
- Секреты K8s шифруются в base 64, поэтому декодируем так:
echo <encoded password here>= | base64 -d
- Входим в ПИ Argo CD под именем пользователя admin и паролем, полученным на предыдущем этапе:
Развертывание с Argo CD
- В ПИ Argo CD нажимаем Create Application («Создать приложение»).
- Вводим обязательную информацию о приложении:
Application Name: вводим информативное название приложения.
Project Name: указываем название проекта, к которому относится приложение.
Sync: для автоматической синхронизации выбираем Automatic.
Repository URL: вводим url-адрес гит-репозитория, где содержится код приложения.
Path: указываем путь к файлам развертывания в репозитории.
Destination: вводим url-адрес кластера Kubernetes, например https://kubernetes.default.svc
.
Namespace: указываем пространство имен Kubernetes, в котором развернем приложение.
- Теперь нажимаем Create, и с помощью Argo CD в кластере Kubernetes на основе этой конфигурации автоматически создастся приложение:
Заключение
Интегрировав GitHub, Maven, SonarQube, Docker, Jenkins, Argo CD, Helm и Kubernetes в конвейер CI/CD, мы повысили эффективность и надежность программной разработки: благодаря оптимизированию процессов ускорили разработку и выпуск, увеличили качество ПО.
Продолжим и дальше дорабатывать конвейер, изучать новые инструменты совершенствования автоматизации.
Читайте также:
Читайте нас в Telegram, VK и Дзен
Перевод статьи Mary Wangoi: End-to-End CI/CD Pipeline Implementation