Развертывание безопасных Java-приложений на AWS EKS с GitLab CI/CD, Maven, Trivy и SonarQube
В современном DevOps для эффективного, надежного и последовательного развертывания программного обеспечения важна автоматизация. Весь процесс разработки и выпуска ПО оптимизируется при помощи мощного инструмента GitLab CI/CD. Развернем с ним приложение Java в мультикластере Kubernetes, управляемом на AWS и настраиваемом в eksctl. Рассмотрим процесс от создания кластера Kubernetes до развертывания контейнеризованного приложения Java, попутно интегрируя инструменты DevOps Trivy и SonarQube.
Рабочий процесс пошагово
Обзор проекта
- Регистрация экземпляра AWS в качестве GitLab Runner
- Создание конвейера GitLab CI/CD
- Модульное тестирование с Maven
- Сканирование зависимостей с Trivy
- Анализ качества кода с SonarQube
- Сборка и контейнеризация приложения
- Сканирование образа контейнера с Trivy
- Отправка образа контейнера в реестр контейнеров GitLab
- Развертывание приложения в Kubernetes
- Настройка кластера AWS EKS с помощью
eksctl - Подключение кластера EKS к GitLab
- Запуск конвейера
Шаг 1. Создание проекта в Gitlab
Шаг 2. Настройка экземпляра AWS как агента Gitlab
- Заходим на консоль управления AWS.
- Запускаем экземпляр EC2 с такими характеристиками:
- AMI — образ машины Amazon: выбираем Ubuntu или Amazon Linux.
- Тип экземпляра: выбираем его под требования задания, например t2.micro для тестирования.
- Группа безопасности: разрешаем экземпляру SSH-доступ.
Установка GitLab Runner на экземпляр EC2
- Подключаемся по SSH к экземпляру EC2.
- Устанавливаем GitLab Runner:
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
sudo chmod +x /usr/local/bin/gitlab-runner
sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell
/bin/bashsudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start
Регистрация GitLab Runner в проекте
- Чтобы зарегистрировать этот экземпляр в качестве GitLab Runner проекта, нужен токен аутентификации.
- Переходим в Project > settings > CI/CD > Runners.
- Указываем соответствующее название тега:
- Регистрируем экземпляр такой командой:
sudo gitlab-runner run
Следуем инструкциям:
- Вводим URL-адрес экземпляра GitLab:
https://gitlab.com/. - Указываем исполнителя: ради простоты выбираем
shell, хотя можно воспользоваться Docker или другими исполнителями. - Проверяем в файле
/home/ubuntu/.gitlab-runner/config.toml.
Шаг 3. Создание конвейера GitLab CI/CD
Подготовив инфраструктуру, приступим к определению конвейера GitLab CI/CD в файле .gitlab-ci.yml. Этапы конвейера: тестирование, сканирование, сборка, развертывание приложения Java и другие.
- Клонируем репозиторий в локальной среде:
2. Добавляем код и отправляем в репозиторий Github:
Шаг 4. Настройка конвейера: .gitlab-ci.yml
1. Этапы
- Сначала задаем в файле этапы:
2. Необходимые инструменты
- Прежде чем переходить к проекту, устанавливаем инструменты:
- sudo apt install -y openjdk-17-jre-headless
- sudo apt install -y maven
- sudo apt-get install -y wget apt-transport-https gnupg lsb-release
- wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
- echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
- sudo apt -y install docker.io && chmod 666 /var/run/docker.sock
- sudo apt-get update && sudo apt-get install -y trivy
- sudo snap install kubectl --classic
- Для этого предоставим пользователю
gitlab-runnerправа суперпользователя, иначе эти команды не выполнятся. - Переходим в папку
/etc/sudoers.dи редактируем файл ниже:
3. Модульное тестирование с Maven
Это первый этап, которым обеспечивается надежность приложения. Для запуска модульных тестов привлекается Maven:
mvn test
- Этой командой компилируется код, запускаются определенные в проекте тесты. В выводе выявляются сбои или проблемы, которые необходимо устранить.
4. Сканирование зависимостей с Trivy
- Trivy — это сканер уязвимостей для образов контейнеров, файловых систем, гит-репозиториев. Просканируем им зависимости приложения Java:
trivy fs --format table -o fs.html .
- Этой командой в текущем каталоге сканируются уязвимости применяемых в приложении зависимостей, вывод сохраняется в файле
fs.html. - Это важный этап для обеспечения безопасности проекта. Чтобы получить вывод, после мы «артефактируем» файл
fs.html.
- Запуская его, получаем примерно такой вывод:
5. Анализ качества кода с SonarQube
- SonarQube — инструмент анализа исходного кода на предмет выявления багов, уязвимостей и кода с запашком.
- Интегрируя SonarQube в конвейер сборки, вы поддерживаете высокое качество кода.
- SonarQube состоит из двух частей: сканерной и серверной. Сначала настроим сервер вручную с помощью Docker:
- Доступ к порталу SonarQube получаем в
https://public-ip:9000:
- Имя пользователя и пароль по умолчанию —
admin.
- Чтобы получить персональный токен, переходим в Project > Settings > Access Tokens и нажимаем
Add Token:
- Копируем код и вставляем в SonarQube:
- Сохраняем настройку.
- Вводим персональный токен и сохраняем.
- Нажимаем
Set up.
- Выбираем
otherи копируем код:
- Переходим в репозиторий Gitlab, создаем файл
sonar-project.propertiesи вставляем в него этот код:
- Сохраняем файл и нажимаем
continueна портале SonarQube:
- Затем переходим к следующему этапу
Add environment variables:
- Согласно второму этапу, создадим две переменные:
- По завершении нажимаем
continueна 2-м этапе SonarQube. - И получаем целиком задание, которое нужно скопировать и вставить в файл
.gitlab-ci.yml:
- Добавляем конвейер и сохраняем:
- Запускаем конвейер и благодаря SonarQube видим на сервере примерно такой результат:
6. Сборка, контейнеризация и сканирование приложения
- Завершив тестирование и сканирование, переходим к следующему этапу — сборке пакета приложения и созданию образа Docker.
- Прежде чем отправлять образ, с помощью Trivy сканируем его на уязвимости.
- Этот важнейший этап для безопасности: им выявляются любые проблемы в собранном образе Docker.
- Запуская конвейер, получаем примерно такой вывод:
7. Отправка образа контейнера в реестр контейнеров GitLab
Созданный образ Docker отправляем на хранение в реестр контейнеров GitLab, где он будет доступен для развертывания:
- Запуская это задание, находим добавленный в реестр контейнеров образ в Deploy > Container Registry:
8. Развертывание приложения в Kubernetes
Наконец, развертываем контейнеризованное приложение в кластере Kubernetes.
- В этом задании декодируем детали конфигурации, закодированные ранее в целях безопасности:
- Здесь создается переменная KUBE_CONTEXT
project-path:k8s-agentи используется образbitnamiдля kubectl. - В манифесте включено несколько переменных Gitlab, поэтому ключевым словом
envsubstзаменяем их на исходные значения.
deployment-service.yaml.template:
apiVersion: apps/v1
kind: Deployment # Создаваемый Kubernetes вид ресурса
metadata:
name: java-app
spec:
selector:
matchLabels:
app: java-app
replicas: 2 # Количество реплик, создаемых для этого развертывания
template:
metadata:
labels:
app: java-app
spec:
imagePullSecrets:
- name: registry-credentials # Для аутентификации в реестре контейнеров
containers:
- name: java-app-container
image: $CI_REGISTRY/harsh005/java-app/java-app:$CI_PIPELINE_ID # Образ, используемый для контейнеров в кластере
imagePullPolicy: Always
ports:
- containerPort: 8080 # Порт, на котором запускается контейнер в кластере
---
apiVersion: v1 # Версия API Kubernetes
kind: Service # Создаваемый Kubernetes вид ресурса
metadata: # Метаданные создаваемого вида ресурса
name: java-app-svc
spec:
selector:
app: java-app
ports:
- protocol: "
;TCP"
port: 80 target
Port: 8080 type: LoadBalancer # тип службы.
Этап 5. Настройка кластера AWS EKS с помощью eksctl
eksctl — простой инструмент CLI для создания кластеров и управления ими в EKS, его предпочитают за простоту и удобство. Вот как с помощью eksctl создается кластер EKS.
1. Установка eksctl
- Нажимаем ссылку.
- Устанавливаем версию для Windows.
- Извлекаем папку на локальном компьютере:
2. Настройка интерфейса командной строки AWS
- Загружаем инструмент интерфейса командной строки AWS на локальный компьютер:
- Загружаем отсюда интерфейс командной строки AWS и настраиваем его для учетной записи.
- Для этого в учетке создаем пользователя IAM.
- В Security credentials нажимаем
Create access keyи создаем ключ доступа и секретный ключ, оба копируем:
- Теперь в локальной командной строке вводим
aws configureи вставляем туда эти учетные данные:
- Вставляем ключ доступа в Access Key ID, а секретный ключ — в Secret Access Key ID. Указываем также регион по умолчанию.
Настроив интерфейс командной строки AWS, установим и инструмент клиента для Kubernetes, то есть Kubectl, с помощью которого приложения будут развертываться в кластере.
3. Создание кластера EKS
- Создаем yaml-файл настройки кластера EKS:
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: my-test-cluster
region: us-east-1
nodeGroups:
- name: small-nodegroup
instanceType: t2.micro
desiredCapacity: 2
- name: medium-nodegroup
instanceType: t2.small
desiredCapacity: 2
- Теперь весь кластер запустится в EKS одной командой:
eksctl create cluster -f cluster-setup.yml
Этап 6. Подключение кластера EKS к GitLab
Создав кластер EKS, переходим к следующему этапу — подключению кластера к GitLab для управления развертываниями напрямую из конвейера сборки.
- Создаем в репозитории конфигурационный файл агента
.gitlab/agents/eks-k8s/config.yaml:
user_access:
access_as:
agent: {}
projects:
- id: <your-project-id>
- Переходим в Operate («Управление») > Kubernetes Cluster («Кластер Kubernetes») > Connect a cluster («Подключить кластер»).
- Выбираем агента из выпадающего списка и зарегистрируем:
- После этого этапа копируем команды настройки токена и агента.
- Чтобы развернуть GitLab-агент, запускаем эти команды в кластере:
helm repo add gitlab https://charts.gitlab.io
helm repo update
helm upgrade --install eks-k8s gitlab/gitlab-agent \
--namespace gitlab-agent-eks-k8s \
--create-namespace \
--set image.tag=v17.3.0-rc7 \
--set config.token= <your-token> \
--set config.kasAddress= <your-kasAddress>
- После того как агент развернут, статус подключения в Gitlab становится
Connected:
- Теперь, чтобы извлечь образ при создании развертывания, добавим учетные данные реестра в манифесте Kubernetes.
- Для этого создаем секрет
registry-credentials. - Так что для этого этапа понадобится токен аутентификации в реестре.
- Переходим в Settings («Настройки») > Repository («Репозиторий») > Display tokens («Показать токены») > Add Token («Добавить токен»):
- Создаем токен развертывания и копируем учетные данные как имя пользователя и пароль для реестра контейнеров:
- Переходим в кластер и создаем секрет реестра Docker
registry-credentials:
kubectl create secret docker-registry registry-credentials --docker-server=registry.gitlab.com --docker-username=<1st-token> --docker-password=<2nd-token> --dry-run=client -o yaml > registry-credentials.yml
Этап 7. Запуск конвейера
Все настроено, пора запустить конвейер.
1. Коммитим и добавляем код
- Коммитим в репозиторий GitLab файл
.gitlab-ci.yml, исходный код Java и манифесты развертывания Kubernetes, Dockerfile:
.gitlab-ci.yml:
stages:
- pre-requisite
- unit_test
- trivy_scan
- sonar_test
- build_and_scan
- image_push
- deploy_to_eks
install_tools:
stage: pre-requisite
script:
- sudo apt install -y openjdk-17-jre-headless
- sudo apt install -y maven
- sudo apt-get install -y wget apt-transport-https gnupg lsb-release
- wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
- echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
- sudo apt-get update && sudo apt-get install -y trivy
- sudo apt -y install docker.io && sudo chmod 666 /var/run/docker.sock
- sudo snap install kubectl --classic
tags:
- dedicated-runner
only:
- main
unit_testing:
stage: unit_test
script:
- mvn test
tags:
- dedicated-runner
only:
- main
trivy_fs_scan:
stage: trivy_scan
script:
- trivy fs --format table -o fs.html .
tags:
- dedicated-runner
artifacts:
paths:
- fs.html
only:
- main
sonarqube-check:
stage: sonar_test
image:
name: sonarsource/sonar-scanner-cli:latest
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Определяется местоположение кеша задач
и анализа. GIT_DEPTH: "0" # В git дается указание извлечь все ветки проекта, треб
уемые за
даче анализа cache: k
ey: "
${CI_JOB_NAME}"
paths:
- .sonar/cach
e script: - sona
r-scann
er allow_
failure: true only:
- mainimage_build_&
;_scan: sta
ge: build_and_scan variables: Image_tag: $CI_REGISTRY/harsh005/jav
a-app/jav
a-app:$CI_PIPELINE_ID
script: - mvn clean package
- docker build -t $Image_tag . - trivy image $Image_ta
g --for
mat table -o image.htm
l tags:
- dedicate
d-runner artifact
s: p
aths:
- image.ht
ml only: - main
image_push:
stage: image_push variables: Image_tag: $CI_REGISTRY/harsh005/jav
a-app/java-app:$
CI_PIPELINE_ID before_script: - docker login $CI_REGISTRY -u $CI_REGISTRY
_USER -p
$CI_REGISTRY_PASSWORD script
: -
docker push $Image_tag
tags
: - ded
icated-runn
er only: - maink8s
-deploy: st
age: deploy_to_eks variables: KUBE_CONT
EXT: hars
h005/java-app:eks-k8s image:
name: bitnami/kube
ctl:latest en
trypoint: [''] before_script: - ku
bectl con
fig use-context "$KUBE_CONTEXT" script: - envsubst < deployment-
service.yaml.template > deployment-service.
yaml
- kubectl
apply -f deployment-service.yaml only: - main when: manual
- Чтобы все задания выполнялись в ветке
main, здесь также поместили элементы управления заданиями. И если все задания до этапаdeploy_to_eksвыполнены успешно, вручную запускается заданиеk8s-deploy, которым код развернется в самоуправляемом Kubernetes.
2. Активируем конвейер
- После того как код добавлен, в GitLab файл
.gitlab-ci.ymlавтоматически обнаруживается, и конвейер активируется:
3. Отслеживаем конвейер
- Переходим в CI/CD («Непрерывная интеграция и непрерывное развертывание») > Pipelines («Конвейеры») проекта GitLab и отслеживаем ход выполнения.
- В ветке
testвидим последовательное выполнение каждого этапа — установки, тестирования, сканирования, сборки и развертывания:
- С результатами сканирования Trivy или тестирования SonarQube можно ознакомиться.
- Завершив все тестирование и сборку, вручную активируем задание
k8s-deployдля финального развертывания:
4. Просматриваем результаты конвейера
- Логи выходных данных просматриваются для каждого задания. Если все настроено корректно, конвейер успешно завершается, и приложение Java развертывается в кластере Kubernetes:
5. Вывод
- Копируем внешний ip-адрес — URL-адрес балансировщика нагрузки — и вставляем в браузер:
Заключение
С помощью GitLab CI/CD мы настроили и развернули приложение Java в самоуправляемом Kubernetes-мультикластере проекта. Провели при этом модульное тестирование, сканирование безопасности, анализ качества кода, сборку и контейнеризацию.
Этим конвейером автоматизируется процесс разработки и выпуска программного обеспечения, безопасно и эффективно осуществляется последовательное развертывание высококачественного кода. Запустив конвейер, мы увидели, как с GitLab CI/CD упрощаются сложные развертывания, а инструменты и процессы интегрируются в единый автоматизированный рабочий поток.
