В сегодняшнем динамичном технологическом ландшафте востребованы быстрые, надежные, безопасные развертывания приложений. Исход гонки инноваций определяется слаженностью взаимодействия разработки и операций, где используются практики DevOps.

Среди фреймворков и инструментов этой экосистемы выделяется Kubernetes ― основа для развертывания масштабируемых приложений, а Jenkins остается главным инструментом автоматизации конвейеров сборки. Но по мере усложнения систем для обеспечения надежности и производительности незаменимой становится интеграция полноценного мониторинга с такими инструментами, как Prometheus и Grafana.

Эффективный конвейер DevOps создается гармоничным сочетанием проектирования, автоматизации и оркестрации компонентов. Воспользуемся передовыми технологиями: Jenkins, Ansible, Docker, Kubernetes, Prometheus, Grafana  —  и построим комплексный конвейер сборки, развертываемый на AWS. Продемонстрируем этим конвейером, как при объединении автоматизации инфраструктуры и мониторинга приложений создаются устойчивые системы, способные масштабироваться в соответствии с потребностями.

Начнем с высокоуровневой архитектуры, которой описывается рабочий процесс  —  от размещаемого на GitHub кода до контейнеризации, проверки безопасности и, наконец, развертывания в кластерах Kubernetes. Благодаря наблюдаемости  —  сбору метрик приложений в Prometheus и их визуализации в Grafana  —  расширяются возможности команд устранять потенциальные узкие места, повышать надежность системы.

Но мы не ограничимся теорией. Каждый описанный здесь конфигурационный файл, скрипт и этап тестируются в реальной среде  —  это настройка с тремя экземплярами AWS EC2, каждому из которых отводится конкретная роль в конвейере: Jenkins для оркестровки, Ansible для автоматизации, Kubernetes для оркестрации контейнеров. Настроив каждый экземпляр, сконфигурировав инструменты и подключив эти системы, создадим комплексный рабочий процесс.

Этот конвейер ориентирован на современные практики:

  1. Контейнеризация: приложение и его зависимости инкапсулируются при помощи Docker, чем обеспечивается его согласованная работа во всех средах.
  2. Безопасность: сканированием образов контейнеров, благодаря Trivy, уязвимости устраняются до развертывания, и это соответствует философии «сдвига влево» DevSecOps.
  3. Масштабируемость: благодаря развертыванию кластера Kubernetes осуществляется горизонтальное масштабирование, посредством реплик обеспечивается высокая доступность.
  4. Мониторинг и наблюдаемость: с Prometheus и Grafana в режиме реального времени получается представление о работоспособности и производительности системы.
  5. Автоматизация: применением Ansible упрощаются и автоматизируются развертывания Kubernetes, человеческое вмешательство и вызванные этим ошибки сокращаются.

Конвейер легко интегрируется с приложением Django и включенным в него django-prometheus, поэтому им собираются детализированные показатели на уровне приложения. В Prometheus регулярно предоставляются и извлекаются ключевые индикаторы производительности: скорость прохождения запросов, время выполнения запросов к базе данных, частота ошибок. Затем эти показатели визуализируются в динамических дашбордах Grafana, откуда получаются полезные сведения о производительности приложения и инфраструктуры. Само приложение проекта Django при помощи Docker контейнеризировано, в него включены передовые концепции автоматизации.

К концу статьи у вас сформируется четкое представление о том, как воспроизвести и адаптировать эту настройку к конкретному сценарию, с пониманием нюансов запуска надежного конвейера DevOps. Полученные здесь практические рекомендации и знания пригодятся и разработчику, который только знакомится с DevOps, и опытному инженеру, стремящемуся усовершенствовать рабочие процессы.

Сначала заложим основу, спроектировав архитектуру и настроив среду. Подробно описав каждую строку кода, конфигурационный файл и команду, сделаем из этой статьи полноценный ресурс для освоения конвейеров сборки.

Шаг 1. Создание основы: проект Django и контейнеризация

Первый этап создания надежного конвейера сборки начинается с самого приложения  —  это основа архитектуры проекта. Настроим проект, для мониторинга приложения воспользуемся django-prometheus, а при контейнеризации  —  для согласованности и масштабируемости  —  создадим Dockerfile.

1. Настройка проекта Django

Django  —  это высокоуровневый веб-фреймворк Python для быстрой разработки с чистым, прагматичным дизайном. Чтобы обеспечить детальный мониторинг на уровне приложения Django, в проект включены метрики Prometheus. Вот как он структурирован:

1.1 Структура проекта Django

studyPlat/
├── studyPlat/ # Основной каталог проекта
│ ├── settings.py # Настройки Django
│ ├── urls.py # Маршрутизация единых указателей ресурсов
│ ├── wsgi.py # Точка входа WSGI-стандарта для Gunicorn
│ └── ...
├── app/ # Каталог приложения Django
│ ├── models.py # Модели баз данных
│ ├── views.py # Логика приложения
│ ├── urls.py # Маршрутизация единых указателей ресурсов приложения
│ ├── admin.py # Конфигурация интерфейса администратора
├── requirements.txt # Зависимости Python
└── manage.py # Сценарий управления Django

1.2 requirements.txt

В файле requirements.txt содержатся зависимости проекта, в том числе django-prometheus для мониторинга.

asgiref==3.8.1
Django==5.1.4
django-debug-toolbar==4.4.6
django-prometheus==2.3.1
djangorestframework==3.14.0
gunicorn==20.1.0
Pillow==9.5.0
prometheus_client==0.21.1
python-decouple==3.8
pytz==2023.3
setuptools==75.6.0
sqlparse==0.4.3
tzdata==2022.7
whitenoise==6.4.0

1.3 Интегрирование метрик Prometheus

Для предоставления метрик приложения интегрирован django-prometheus с обновлением файла settings.py и промежуточной конфигурации:

В settings.py:

INSTALLED_APPS = [
...,
'django_prometheus',
]
MIDDLEWARE = [
...,
'django_prometheus.middleware.PrometheusBeforeMiddleware',
...,
'django_prometheus.middleware.PrometheusAfterMiddleware',
]# В основной файл «urls.py» добавляются URL-адреса Prometheus
urlpatterns = [
path('', include('app.urls')),
path('metrics/', include('django_prometheus.urls')),
]

После интеграции метрики предоставляются приложением в /metrics и позже извлекаются при помощи Prometheus. Среди этих метрик задержки при обработке запросов, продолжительность выполнения запросов, частота ошибок и другие.

2. Создание Dockerfile

Согласованное выполнение приложения в различных средах обеспечивается контейнеризацией. Приложение и его зависимости благодаря Docker упаковываются в легковесный, платформонезависимый контейнер.

Вот Dockerfile для этого проекта Django:

# В качестве базового используется официальный образ Python
FROM python:3.10-slim

# Задаются переменные окружения
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# Внутри контейнера задается рабочий каталог
WORKDIR /app

# В контейнер копируются файлы проекта
COPY . .

# Устанавливаются системные зависимости
RUN apt-get update && apt-get install -y \
libpq-dev gcc && \
rm -rf /var/lib/apt/lists/*

# Устанавливаются зависимости Python
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -r requirements.txt

# Предоставляется порт, на котором выполняется приложение Django
EXPOSE 8000

# Копируется конфигурационный файл Prometheus
COPY prometheus.yml /etc/prometheus/prometheus.yml

# Команда для выполнения приложения
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "studyPlat.wsgi:application"]

3. Тестирование локально

Прежде чем продолжить, протестируем приложение локально и убедимся, что все выполняется без неожиданностей.

Этапы:

3.1 Сборка образа Docker:

docker build -t studyplat:latest .

3.2 Запуск контейнера:

docker run -p 8000:8000 studyplat:latest

3.3 Проверка метрик Prometheus:
Проверяем предоставление метрик, обращаясь к конечной точке /metrics в браузере или командой curl:

curl http://localhost:8000/metrics

4. Подготовка к конвейеру сборки

Создав Dockerfile и сделав приложение Django функциональным, подготовим проект к интеграции с Jenkins. Dockerfile подгружается на GitHub вместе с YAML-файлами развертывания и служб для Kubernetes и интерактивным сценарием Ansible для автоматизации.

Готовность проекта к непрерывной интеграции и непрерывному развертыванию означает, что конвейер активируется любыми новыми коммитами в репозитории GitHub. А дальше дело за Jenkins.

На этом первый этап конвейера DevOps завершается. Теперь настроим инфраструктуру в AWS.

Шаг 2. Настройка инфраструктуры: экземпляры EC2, SSH-доступ и подготовка

Прежде чем переходить к Jenkins и автоматизировать конвейер, подготовим инфраструктуру: создадим экземпляры EC2 для Ansible, Jenkins и Kubernetes, настроим SSH-доступ, обеспечим полную готовность к бесперебойной работе.

1. Настройка экземпляров EC2

Подготовим три экземпляра AWS EC2, у каждого из которых конкретное назначение.

Обзор экземпляров EC2:

╔═══════════════════╦═════════════════════════╦═════════════════╦════════════════════╗
║Название экземпляра║ Назначение ║ Тип экземпляра ║Операционная система║
╠═══════════════════╬═════════════════════════╬═════════════════╬════════════════════╣
║ ansible-server ║ Узел управления Ansible ║ t2.micro ║ Ubuntu 24.04 LTS ║
║ jenkins-server ║ Сервер CI/CD Jenkins ║ t2.micro ║ Ubuntu 24.04 LTS ║
║ k8s-node ║ Одноузловой кластер K8s ║ t2.large ║ Ubuntu 24.04 LTS ║
╚═══════════════════╩═════════════════════════╩═════════════════╩════════════════════╝

Этапы создания экземпляров EC2:

  1. Вход в консоль управления AWS и переход к дашборду EC2.
  2. Запуск экземпляров EC2:
  • В качестве образа машины Amazon выбираем Ubuntu 24.04 LTS.
  • В качестве типа экземпляра  —  условно-бесплатный уровень t2.micro для Ansible и Jenkins.
  • А для Kubernetes  —  t2.large, чтобы выделенных ресурсов было достаточно.

3. Настройка деталей экземпляра:

  • Каждому экземпляру  —  ansible-server, jenkins-server и k8s-node  —  присваиваем уникальный тег-название.
  • Для SSH-доступа включаем автоприсвоение общедоступного IP-адреса.

4. Добавление хранилища:

  • Для Ansible и Jenkins достаточно 8 Гб эластичного блочного хранилища EBS по умолчанию.
  • Чтобы создать minikube в узле Kubernetes, воспользуемся 32 Гб.

5. Настройка групп безопасности:

  • Для удаленного доступа разрешаем SSH, порт 22.
  • Для Jenkins и Kubernetes открываем дополнительные порты: 8080 и 6443 соответственно, а также для служб NodePort Kubernetes 30000-32767.

6. Создание или использование имеющейся пары ключей:

  • Называем: devops-key-pair.
  • Загружаем закрытый ключ devops-key-pair.pem для SSH-доступа.

7. Запуск экземпляров.

2. Пара ключей для SSH-доступа

Для безопасного подключения к экземплярам EC2 воспользуемся парой ключей, созданной при подготовке экземпляров, а для SSH-доступа  —  инструментами вроде Termius или терминала.

3. Подготовка сервера Ansible

Узлом управления Ansible ansible-server автоматизируются конфигурации и развертывания в инфраструктуре.

Базовая настройка для Ansible

3.1 Обновление системы:

sudo apt update && sudo apt upgrade -y

3.2 Установка Ansible:

sudo apt install ansible -y

3.3 Настройка файла инвентаризации:

Создаем файл инвентаризации /etc/ansible/hosts и добавляем другие экземпляры  —  узлы Jenkins и Kubernetes:

[jenkins]
<jenkins-server-private-ip>

[k8s]
<k8s-node-private-ip>

3.4 Копирование ключа в управляемые узлы:

Чтобы скопировать закрытый ключ на сервер Ansible и настроить беспарольный SSH-доступ к узлам Jenkins и Kubernetes, используется SSH:

ssh-copy-id -i ~/.ssh/devops-key-pair.pem ubuntu@<jenkins-server-private-ip>
ssh-copy-id -i ~/.ssh/devops-key-pair.pem ubuntu@<k8s-node-private-ip>

4. Подготовка сервера Jenkins

На сервере Jenkins jenkins-server разместится конвейер сборки, вот начальная настройка сервера Jenkins:

4.1 Обновление системы:

sudo apt update && sudo apt upgrade -y

4.2 Установка Java для Jenkins:

sudo apt install openjdk-11-jdk -y

4.3 Загрузка и установка:

  • Добавляем репозиторий Jenkins:
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \
/usr/share/keyrings/jenkins-keyring.asc > /dev/null
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
  • Устанавливаем Jenkins:
sudo apt update
sudo apt install jenkins -y

4.4 Запуск и включение Jenkins:

sudo systemctl start jenkins
sudo systemctl enable jenkins

4.5 Открытие порта 8080 Jenkins:
Чтобы разрешить входящий трафик через порт 8080, добавляем в группу безопасности Jenkins правило.

4.6 Доступ к Jenkins:
Открываем Jenkins в браузере, используя общедоступные IP-адрес и порт: http://<jenkins-server-public-ip>:8080.

5. Подготовка узла Kubernetes

В узле Kubernetes k8s-node размещается приложение и оркестрируются контейнеры, для установки воспользуемся minikube.

Базовая настройка для Kubernetes:

5.1 Установка Docker:

sudo apt update
sudo apt install docker.io
sudo systemctl start docker
sudo systemctl enable docker
sudo apt install -y apt-transport-https ca-certificates curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

5.2 Установка Kubectl:

sudo snap install kubectl --classic
kubectl version --client

5.3 Установка Minikube:

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
minikube version

5.4 Запуск Minikube с драйвером Docker:

minikube start --driver=docker
minikube status

5.5 Тестирование K8s:

kubectl cluster-info
kubectl get pods
kubectl get nodes

Подготовив и подключив серверы, переходим к конфигурации Jenkins и настройке конвейера.

Шаг 3. Конфигурация сервера Jenkins и этапы конвейера сборки

Запустив сервер Jenkins, сконфигурируем его для непрерывной интеграции и непрерывного развертывания. Определим соответствующие этапы в конвейере, где автоматизируются сборка, тестирование, контейнеризация и развертывание приложения Django.

1. Доступ к Jenkins

1.1 Открываем Jenkins в браузере:
 http://<jenkins-server-public-ip>:8080

1.2 Получаем исходный пароль администратора:

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

1.3 Войдя, устанавливаем предлагаемые плагины и создаем пользователя-администратора.

2. Установка необходимых конвейеру плагинов

  • Pipeline: для создания конвейеров Jenkins.
  • Git: для клонирования проекта Django из репозитория.
  • SSH Agent: для использования SSH-ключей удаленного доступа.
  • Blue Ocean  —  дополнительно  —  для визуализации конвейеров в современном пользовательском интерфейсе.

3. Настройка учетных данных в Jenkins

a) Добавление учетных данных GitHub

  1. Переходим в Manage Jenkins («Управлять Jenkins») > Credentials («Учетные данные») > Global («Глобальные») > Add Credentials («Добавить учетные данные»).
  2. Для HTTPS выбираем Username with Password («Имя пользователя с паролем»), для SSH  —  SSH Key («SSH-ключ»).
  3. Сохраняем учетные данные.

б) Добавление SSH-ключа для удаленного доступа

  1. Загружаем закрытый ключ devops-key-pair.pem в Global Credentials.
  2. Сохраняем как remote-access-ssh-key.

4. Создание задачи конвейера

  1. В Jenkins создаем новый элемент, выбираем Pipeline («Конвейер») и даем название django-pipeline или любое другое.
  2. Настраиваем задачу на использование скрипта конвейера.

5. Этапы конвейера Jenkins

Вот структура этапов конвейера для приложения Django:

node {

stage('Git checkout'){
git 'https://github.com/KaramMajdi7/KubeDevOps'
}

stage('Sending docker file to Ansible server over ssh'){
sshagent(['remote-access-ssh-key']) {
sh 'ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip>'
sh 'scp -r /var/lib/jenkins/workspace/pipeline-demo/* ubuntu@<ansible-server-private-ip>:/home/ubuntu/'
}
}

stage('Docker Image Build'){
sshagent(['remote-access-ssh-key']) {
sh 'ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip> cd /home/ubuntu/'
sh 'ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip> sudo docker image build -t $JOB_NAME:v1.$BUILD_ID .'
}
}

stage('Docker image tagging'){
sshagent(['remote-access-ssh-key']) {
sh 'ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip> cd /home/ubuntu/'
sh 'ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip> sudo docker image tag $JOB_NAME:v1.$BUILD_ID your_dockerhub_username/$JOB_NAME:v1.$BUILD_ID'
sh 'ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip> sudo docker image tag $JOB_NAME:v1.$BUILD_ID your_dockerhub_username/$JOB_NAME:latest'
}
}

stage('Push Docker image to Docker Hub'){
sshagent(['remote-access-ssh-key']) {
withCredentials([string(credentialsId: 'dockerhub_password', variable: 'dockerhub_password')]) {
sh "ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip> docker login -u your_dockerhub_username-p ${dockerhub_password}"
sh 'ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip> docker image push your_dockerhub_username/$JOB_NAME:v1.$BUILD_ID'
sh 'ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip> docker image push your_dockerhub_username/$JOB_NAME:latest'

sh 'ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip> docker image rm your_dockerhub_username/$JOB_NAME:v1.$BUILD_ID your_dockerhub_username/$JOB_NAME:latest $JOB_NAME:v1.$BUILD_ID'
}
}
}

stage('Trigger Ansible Playbook'){
sshagent(['remote-access-ssh-key']) {
sh 'ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip> ansible-playbook /path/to/your/ansible.yaml'
}
}
}

6. Активация конвейера

  1. Ручная активация: конвейер запускается из Jenkins.
  2. Автоматическая активация:
  • Чтобы конвейер активировался при добавлениях кода, добавляем веб-хук GitHub.
  • Переходим в GitHub Repository («Репозиторий GitHub») > Settings («Настройки») > Webhooks («Веб-хуки»).
  • Добавляем URL-адрес Jenkins: http://<jenkins-server-public-ip>:8080/github-webhook/.

Шаг 4. Aqua Trivy для сканирования образов контейнеров

Сканером безопасности с открытым исходным кодом Aqua Trivy выявляются проблемы конфигурации, уязвимости и открытые секреты в образах контейнеров. Благодаря интегрированию Trivy в конвейер Jenkins развертываются только безопасные образы Docker.

1. Установка Aqua Trivy на сервере Ansible

1.1 SSH-подключение к серверу Ansible:

ssh -i devops-key-pair.pem ubuntu@<ansible-server-private-ip>

1.2 Установка Trivy:

curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin

1.3 Проверка установки:

trivy --version

2. Добавление в конвейер Jenkins этапа сканирования Trivy

Чтобы сканировать собранный образ Docker перед отправкой на DockerHub, Trivy интегрируется в Jenkinsfile и добавляется перед этапом отправки образа Docker на DockerHub.

stage('Trivy Scan') {
sshagent(['remote-access-ssh-key']) {
sh " ssh -o StrictHostKeyChecking=no ubuntu@<ansible-server-private-ip> trivy --config /dev/null image --no-progress --scanners vuln $JOB_NAME:v1.$BUILD_ID"
}
}

3. Обработка результатов сканирования

  • В Trivy выводится подробный отчет с перечислением уязвимостей, их серьезности и возможных исправлений.
  • Если обнаруживаются критические проблемы, конвейер настраивается на остановку процесса и уведомление заинтересованных по электронной почте или в Slack  —  здесь пригодятся плагины Jenkins.

4. Автоматизация обновлений базы данных Trivy

Чтобы поддерживать определения уязвимостей в актуальном состоянии, на обновление базы данных Trivy настраивается задание cron или Jenkins:

trivy --download-db-only

При такой интеграции уязвимые образы Docker не оказываются на продакшене и уровень безопасности процесса непрерывной интеграции и непрерывного развертывания повышается.

Шаг 5. Конфигурирование Ansible для автоматизации изменений Kubernetes

Благодаря Ansible автоматизируются задачи, связанные с обновлением конфигураций Kubernetes, обеспечивается согласованное развертывание, уменьшаются человеческие ошибки.

1. Настройка Ansible

Установка Ansible на сервере Ansible: Ansible устанавливается в экземпляре EC2 или на другом сервере для оркестрации задач, мы сделали это заранее.

2. Пример ansible-playbook.yml

---
- name: Automate Kubernetes Tasks
hosts: all
become: true
tasks:

- name: Ensure Deployment.yml file is absent
ansible.builtin.file:
path: /home/ubuntu/Deployment.yml
state: absent
ignore_errors: yes # Если файл не найден, ошибки игнорируются

- name: Ensure Service.yml file is absent
ansible.builtin.file:
path: /home/ubuntu/Service.yml
state: absent
ignore_errors: yes # Если файл не найден, ошибки игнорируются

- block:
- name: Copy Deployment.yml to the k8s server
ansible.builtin.copy:
src: /path/to/your/local/Deployment.yml
dest: /home/ubuntu/Deployment.yml
owner: ubuntu
group: ubuntu
mode: '0644'
when: ansible_facts['os_family'] == 'Debian'

- name: Copy Service.yml to the k8s server
ansible.builtin.copy:
src: /path/to/your/local/Service.yml
dest: /home/ubuntu/Service.yml
owner: ubuntu
group: ubuntu
mode: '0644'
when: ansible_facts['os_family'] == 'Debian'
name: Copy configuration files to the server

- name: Set KUBECONFIG environment variable
ansible.builtin.set_fact:
KUBECONFIG: "/home/ubuntu/.kube/config"

- name: Delete old deployment if exists
k8s:
kubeconfig: "{{ KUBECONFIG }}"
state: absent
definition: "{{ lookup('file', '/home/ubuntu/Deployment.yml') }}"
ignore_errors: yes # Так обрабатываются случаи, где «deployment» не существует

- name: Delete old service if exists
k8s:
kubeconfig: "{{ KUBECONFIG }}"
state: absent
definition: "{{ lookup('file', '/home/ubuntu/Service.yml') }}"
ignore_errors: yes # Так обрабатываются случаи, где «service» не существует

- name: Create new deployment
k8s:
kubeconfig: "{{ KUBECONFIG }}"
state: present
definition: "{{ lookup('file', '/home/ubuntu/Deployment.yml') }}"

- name: Create new service
k8s:
kubeconfig: "{{ KUBECONFIG }}"
state: present
definition: "{{ lookup('file', '/home/ubuntu/Service.yml') }}"

3. Разбор интерактивного сценария

  • Copy Configuration Files: в этом блоке задач файлы конфигурации Deployment.yml и Service.yml копируются с локальной машины на сервер Kubernetes, уже имеющиеся файлы предварительно удаляются.
  • Set KUBECONFIG Environment Variable: переменной окружения KUBECONFIG указывается на конфигурационный файл Kubernetes, благодаря чему Ansible «общается» с кластером Kubernetes.
  • Управление развертываниями и службами: в сценарии удаляются все старые развертывания и службы Kubernetes, затем с чистого листа создаются новые, как указано в файлах Deployment.yml и Service.yml.

Развертывание при таком подходе упрощается, а конфигурация Kubernetes всегда актуальна и без ручного вмешательства.

Шаг 6. Конфигурирование и развертывание Kubernetes

Сердце этого проекта  —  Kubernetes, где ради масштабируемости, надежности и эффективного использования ресурсов оркестрируются контейнеры. Вот как структурирована настройка Kubernetes, а также YAML-файлы с пояснениями:

1. Deployment.yml

Файлом Deployment.yml определяется, как управлять подами приложения.

kind: Deployment
apiVersion: apps/v1
metadata:
name: your_app_name
spec:
replicas: 2
selector:
matchLabels:
app: your_app_name
template:
metadata:
labels:
app: your_app_name
spec:
containers:
- name: your_app_name
image: dockerhub_username/django-pipeline
imagePullPolicy: Always
ports:
- containerPort: 8000

Основные характеристики:

  1. Replicas: для приложения всегда запускается два пода.
  2. Image: образ Docker dockerhub_username/django-pipeline извлекается из DockerHub.
  3. Ports: в каждом контейнере для приложения предоставляется порт 8000.

Применяемая команда:

Для развертывания применяется этот YAML-файл:

kubectl apply -f Deployment.yml

2. Service.yml

Файлом Service.yml к приложению предоставляется доступ извне:

kind: Service                             
apiVersion: v1
metadata:
name: your_app_name
labels:
app: your_app_name
spec:
ports:
- port: 8000
targetPort: 8000
nodePort: 31200
selector:
app: your_app_name
type: LoadBalancer

Основные характеристики:

  1. Type: благодаря LoadBalancer служба доступна извне по публичному IP-адресу.
  2. NodePort: для внешнего доступа на рабочих узлах открывается порт 31200.
  3. Target Port: запросы сопоставляются с портом 8000 внутри контейнеров.
  4. Selector: здесь эта служба подключается к подам с меткой app: your_app_name.

Применяемая команда:

Чтобы предоставить доступ к службе, применяется этот YAML-файл:

kubectl apply -f Service.yml

3. Проверка развертывания

3.1 Проверка подов:

kubectl get pods

Проверяем работоспособность подов меткой app=karammajdi.

3.2 Проверка службы:

kubectl get svc

Выполняется поиск внешнего IP-адреса, присвоенного службе.

3.3 Доступ к приложению:

  • Используется внешний IP-адрес или общедоступный DNS этого LoadBalancer с портом 8000.
  • Пример: http://<external-ip>:8000.

Шаг 7. Настройка Prometheus

В Prometheus мониторятся приложения Kubernetes и другие ресурсы, собираются и визуализируются метрики из заданных целей.

1. Развертывание с Prometheus

Создадим файл Prometheus и сохраним его как prometheus-deployment.yml:

apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
labels:
app: prometheus
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
containers:
- name: prometheus
image: prom/prometheus:v2.43.0
args:
- '--config.file=/etc/prometheus/prometheus.yml'
ports:
- containerPort: 9090
volumeMounts:
- name: prometheus-config
mountPath: /etc/prometheus
readOnly: true
volumes:
- name: prometheus-config
configMap:
name: prometheus-config

Пояснения:

  1. Deployment:
  • Запускается единственная реплика контейнера Prometheus  —  replicas: 1.

2. Image:

  • Используется образ Prometheus Docker версии v2.43.0.

3. Args:

  • Указывается конфигурационный файл Prometheus /etc/prometheus/prometheus.yml.

4. VolumeMount:

  • ConfigMap prometheus-config подключается к /etc/prometheus.

Применяемая команда:

kubectl apply -f prometheus-deployment.yml

2. Служба Prometheus

Переходим к prometheus-service.yml:

apiVersion: v1
kind: Service
metadata:
name: prometheus
spec:
ports:
- port: 9090
targetPort: 9090
nodePort: 30090
selector:
app: prometheus
type: LoadBalancer

Пояснения:

  1. Type:
  • Этим LoadBalancer к Prometheus предоставляется доступ извне по общедоступному IP-адресу.

2. Ports:

  • В Prometheus прослушивается порт 9090  —  изнутри и извне.
  • В NodePort задается 30090 для отладки или прямого доступа по IP-адресу узла.

3. Selector:

  • Эта служба связывается с развертыванием Prometheus меткой app: prometheus.

Применяемая команда:

kubectl apply -f prometheus-service.yml

3. ConfigMap Prometheus

Наконец, получаем prometheus-configmap.yml:

apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'django'
static_configs:
- targets: ['your_svc_name_for_django:8000']

Пояснения:

  1. ConfigMap:
  • Конфигурация Prometheus сохраняется так, как это свойственно для Kubernetes.

2. Scrape Interval:

  • Для частого сбора метрик глобально задается соответствующий интервал 15s.

3. Scrape Configs:

  • Job Name: этим django помечается целевое задание для мониторинга.
  • Target: указывается служба your_svc_name_for_django, запускаемая на порту 8000 и определяемая в файле Service.yml.

Применяемая команда:

kubectl apply -f prometheus-configmap.yml

Шаг 8. Настройка Grafana

Данные, особенно с источником данных Prometheus, визуализируются в Grafana. Настроим это в кластере Kubernetes.

1. Развертывание в Grafana

Вот grafana-deployment.yml:

apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
labels:
app: grafana
spec:
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: grafana/grafana:latest
ports:
- containerPort: 3000
volumeMounts:
- name: grafana-storage
mountPath: /var/lib/grafana
volumes:
- name: grafana-storage
emptyDir: {}

Пояснения:

  1. Deployment:
  • Replicas: ради упрощения запускается единственная реплика контейнера Grafana.

2. Container:

  • Image: в Grafana используется последний образ Docker.
  • Ports: и предоставляется порт по умолчанию 3000.
  • Volume Mount: для хранения данных подключается том в /var/lib/grafana.

3. Volume:

  • Type: для временного хранилища используется emptyDir. Данные сохраняются, только пока запускается под. Для постоянного хранения рекомендуется PersistentVolume.

Применяемая команда:

kubectl apply -f grafana-deployment.yml

2. Служба в Grafana

Теперь изучим grafana-service.yml:

apiVersion: v1
kind: Service
metadata:
name: grafana
spec:
type: LoadBalancer
ports:
- port: 3000
targetPort: 3000
nodePort: 30300
selector:
app: grafana

Пояснения:

  1. Type:
  • LoadBalancer: предоставляется Grafana с общедоступным IP-адресом для внешнего доступа.

2. Ports:

  • Port: в Grafana прослушивается порт 3000 извне.
  • В NodePort: задается 30300 для отладки или прямого доступа по IP-адресу узла.

3. Selector:

  • Эта служба связывается с развертыванием меткой app: grafana.

Применяемая команда:

kubectl apply -f grafana-service.yml

Что дальше

  1. Вход:
  • Учетные данные по умолчанию: Имя пользователя: admin | Пароль: admin
  • После первого входа пароль меняем.

2. Добавление Prometheus источником данных:

  • Переходим в Configuration («Конфигурация») > Data Sources («Источники данных»).
  • Добавляем Prometheus с вот этим:
URL: http://<prometheus-service-ip>:9090
  • Заменяем <prometheus-service-ip> на IP-адрес или DNS службы Prometheus.

3. Создание дашбордов:

  • Для визуализации метрик приложения или кластера импортируем или создаем дашборды.

С такой настройкой Grafana делается доступной и интегрируется с реализованным выше инструментарием мониторинга Prometheus.

Заключение

Современными практиками и инструментами в этом комплексном конвейере DevOps упрощается процесс сборки, сохраняются полноценные возможности обеспечения безопасности и мониторинга. Вот как легко интегрируется рабочий процесс:

  1. Рабочий процесс начинается отправкой разработчиком кода и соответствующего Dockerfile в репозиторий GitHub. Так активируется вебхук, которым инициируется конвейер Jenkins в экземпляре EC2.
  2. Автоматизация и безопасность: в Jenkins автоматизируется процесс сборки, выполняется проверка безопасности с Aqua Trivy и образ Docker отправляется в Docker Hub. Так перед развертыванием обеспечивается соблюдение всеми контейнерами стандартов безопасности.
  3. Управление конфигурацией: в Ansible, запускаемом в специальном экземпляре EC2, осуществляется управление конфигурацией кластеров Kubernetes. Так упрощается процесс развертывания, обеспечивается согласованность во всех средах.
  4. Оркестрация Kubernetes: кластером управления Kubernetes, размещаемым в экземпляре EC2, приложение развертывается и управляется. Так обеспечиваются масштабируемость, отказоустойчивость, эффективное использование ресурсов.
  5. Мониторинг и визуализация: в Prometheus из кластера Kubernetes извлекаются метрики, обеспечивается всесторонний мониторинг производительности приложения. Затем эти метрики визуализируются в настраиваемых дашбордах Grafana, откуда из них получаются полезные данные.

Такой архитектурой обеспечиваются не только автоматизация и безопасность процесса развертывания, но и полноценная система мониторинга для более надежного приложения. Интеграцией Jenkins, Docker, Ansible, Kubernetes, Prometheus и Grafana в этом конвейере демонстрируются возможности комбинирования практик DevOps с современными облачными технологиями.

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Karam Majdi: Building Seamless CI/CD Pipelines with Kubernetes at the Core

Предыдущая статьяНовые возможности CSS
Следующая статьяC++: полное руководство по Mutable