Облачные технологии

Окружение курсового проектаzip

Курсовой проект

Тема

Контейнеризация и оркестрация веб-приложения: от исходного кода до развертывания в кластере.

Описание

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

Разработка самого приложения не входит в задачу курсового проекта. Исходный код приложения предоставляется в каталоге app/ и состоит из трех компонентов:

  • frontend — статическая веб-страница, обслуживаемая сервером nginx, который также выполняет роль обратного прокси для API;
  • backend — REST API на JavaScript (Node.js, Express), предоставляющее операции создания, чтения и удаления заметок;
  • database — СУБД PostgreSQL для хранения данных приложения.

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

Структура исходного приложения

app/
├── backend/
│   ├── app.js              # API-сервер
│   └── package.json        # зависимости Node.js
└── frontend/
    ├── index.html           # веб-интерфейс
    └── nginx.conf           # конфигурация nginx

Для компонента database используется официальный образ PostgreSQL; собственный Dockerfile для него не требуется.

Этапы выполнения

Этап 1. Контейнеризация компонентов

На этом этапе необходимо подготовить Dockerfile для каждого прикладного компонента (backend и frontend), собрать образы и убедиться, что контейнеры запускаются и работают корректно.

1.1. Подготовка рабочего окружения

Убедиться, что Docker установлен и доступен:

docker --version
docker info

Если Docker не установлен, воспользоваться официальной инструкцией:

1.2. Создание файла .dockerignore

Перед написанием Dockerfile создать файл .dockerignore в корне каждого компонента. Этот файл указывает Docker, какие файлы и каталоги не следует включать в контекст сборки. Исключение лишних файлов ускоряет сборку и уменьшает размер образа.

Пример .dockerignore для backend:

node_modules
npm-debug.log

Документация: https://docs.docker.com/build/building/context/#dockerignore-files

1.3. Dockerfile для backend

Создать файл docker/backend/Dockerfile. Dockerfile должен использовать многоэтапную сборку (multi-stage build) — прием, при котором один Dockerfile содержит несколько инструкций FROM, а итоговый образ формируется на основе последнего этапа. Это позволяет установить зависимости на первом этапе (включая инструменты сборки), а во второй этап скопировать только файлы, необходимые для запуска приложения.

Требования:

  • Базовый образ: использовать node:22-alpine (или другую конкретную версию). Alpine-образы существенно меньше стандартных образов на основе Debian. Тег latest использовать запрещено — фиксация версии обеспечивает воспроизводимость сборки.
  • Первый этап (установка зависимостей): скопировать package.json в рабочий каталог и выполнить npm ci. Команда npm ci (clean install) предпочтительнее npm install для контейнерных сборок, так как она устанавливает зависимости строго по package-lock.json и не модифицирует его.
  • Второй этап (итоговый образ): скопировать установленные зависимости (node_modules) и исходный код приложения из первого этапа. Задать рабочий каталог, определить непривилегированного пользователя для запуска процесса.
  • Непривилегированный пользователь: образы на основе node:alpine содержат встроенного пользователя node. Использовать инструкцию USER node, чтобы приложение не запускалось от имени root. Это уменьшает последствия возможной компрометации контейнера.
  • Точка входа: инструкция CMD ["node", "app.js"]. Форма exec (массив строк) предпочтительнее shell-формы, так как процесс Node.js получает PID 1 и корректно обрабатывает сигналы завершения.
  • HEALTHCHECK: добавить инструкцию, которая периодически проверяет доступность API. Например:
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD wget --quiet --spider http://localhost:8000/api/health || exit 1

Утилита wget используется вместо curl, так как curl отсутствует в alpine-образах по умолчанию. Параметр --start-period задает период ожидания после запуска контейнера, в течение которого неудачные проверки не считаются ошибкой.

Документация:

1.4. Dockerfile для frontend

Создать файл docker/frontend/Dockerfile. Этот образ проще, чем backend: необходимо скопировать статические файлы и конфигурацию nginx в стандартные каталоги образа nginx.

Требования:

  • Базовый образ: использовать nginx:1.27-alpine (или другую конкретную версию).
  • Статические файлы: скопировать index.html в каталог /usr/share/nginx/html/.
  • Конфигурация nginx: скопировать nginx.conf в каталог /etc/nginx/conf.d/, заменив конфигурацию по умолчанию. Стандартный конфигурационный файл nginx называется default.conf; если его не заменить, он будет конфликтовать с пользовательской конфигурацией.
  • HEALTHCHECK: проверять доступность nginx, например:
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD wget --quiet --spider http://localhost:80/ || exit 1

1.5. Сборка и проверка образов

Собрать образы, находясь в корневом каталоге проекта:

docker build -t notes-backend:1.0 -f docker/backend/Dockerfile app/backend/
docker build -t notes-frontend:1.0 -f docker/frontend/Dockerfile app/frontend/

Флаг -f указывает путь к Dockerfile, последний аргумент — контекст сборки (каталог, из которого копируются файлы).

После сборки проверить размер образов:

docker images | grep notes

Для анализа слоев образа использовать:

docker history notes-backend:1.0

Запустить контейнер backend вручную для проверки (без базы данных он покажет ошибку в health check, но сам процесс должен стартовать):

docker run --rm -p 8000:8000 notes-backend:1.0

Результат этапа: оба образа собираются без ошибок, размеры образов минимизированы, контейнеры запускаются от непривилегированного пользователя.


Этап 2. Локальная композиция (Docker Compose)

На этом этапе необходимо описать все три компонента приложения в файле docker-compose.yml и обеспечить их совместную работу одной командой.

2.1. Структура файла docker-compose.yml

Создать файл docker-compose.yml в корне проекта. Файл описывает три сервиса (frontend, backend, db), пользовательскую сеть и именованный том.

Документация по формату файла: https://docs.docker.com/reference/compose-file/

2.2. Сервис db (PostgreSQL)

Для базы данных используется официальный образ PostgreSQL (например, postgres:17-alpine). Собственный Dockerfile не требуется.

Основные параметры:

  • Переменные окружения: POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD — задают имя базы данных, пользователя и пароль при первом запуске контейнера. Значения следует читать из переменных окружения Compose (синтаксис ${VARIABLE}), а значения по умолчанию определить в файле .env.
  • Том: подключить именованный том к каталогу /var/lib/postgresql/data внутри контейнера. Это обеспечивает сохранность данных при пересоздании контейнера.
  • Сеть: подключить к пользовательской сети.

Документация по образу PostgreSQL: https://hub.docker.com/_/postgres

2.3. Сервис backend

Основные параметры:

  • Сборка: указать путь к Dockerfile и контекст сборки через секцию build.
  • Переменные окружения: DB_HOST (имя сервиса db — Docker Compose автоматически разрешает его в IP-адрес контейнера), DB_PORT, DB_NAME, DB_USER, DB_PASSWORD.
  • Зависимости: секция depends_on с условием service_started для сервиса db. Это гарантирует, что контейнер базы данных будет запущен до backend, хотя не гарантирует, что PostgreSQL будет готов принимать соединения (эту задачу решает retry-логика в app.js).
  • Сеть: подключить к той же пользовательской сети, что и db.

2.4. Сервис frontend

Основные параметры:

  • Сборка: указать путь к Dockerfile и контекст.
  • Публикация порта: секция ports, например "80:80" (порт хоста : порт контейнера). После запуска приложение будет доступно в браузере по адресу http://localhost.
  • Зависимости: depends_on для сервиса backend.
  • Сеть: подключить к пользовательской сети. nginx обращается к backend по имени backend (см. nginx.conf, директива proxy_pass), поэтому оба сервиса должны находиться в одной сети.

2.5. Файл переменных окружения (.env)

Создать файл .env в каталоге, где расположен docker-compose.yml. Docker Compose автоматически читает этот файл и подставляет значения переменных в docker-compose.yml.

Пример содержимого:

DB_NAME=notes
DB_USER=notes
DB_PASSWORD=notes

Документация: https://docs.docker.com/compose/how-tos/environment-variables/variable-interpolation/

2.6. Пользовательская сеть

Определить сеть в секции networks файла docker-compose.yml и подключить к ней все три сервиса. В пользовательской сети Docker Compose предоставляет встроенное разрешение имен: каждый сервис доступен другим по имени, указанному в конфигурации (например, backend, db).

Документация: https://docs.docker.com/compose/how-tos/networking/

2.7. Ограничения ресурсов и политика перезапуска

Для каждого сервиса задать:

  • Ограничения ресурсов через секцию deploy.resources.limits (CPU и память). Например, для backend: cpus: "0.5", memory: 256M. Ограничения предотвращают ситуацию, когда один контейнер потребляет все ресурсы хостовой машины.
  • Политику перезапуска через секцию restart. Значение unless-stopped перезапускает контейнер при любом завершении, кроме явной остановки пользователем.

Документация: https://docs.docker.com/reference/compose-file/services/#deploy

2.8. Запуск и проверка

# Запуск всех сервисов (сборка образов при первом запуске)
docker compose up --build

# Или в фоновом режиме
docker compose up --build -d

# Проверка состояния сервисов
docker compose ps

# Просмотр журналов
docker compose logs backend

# Остановка и удаление контейнеров (том сохраняется)
docker compose down

# Остановка с удалением тома (данные будут потеряны)
docker compose down -v

Убедиться, что:

  • веб-интерфейс доступен по адресу http://localhost;
  • индикатор состояния API показывает «подключено»;
  • заметки создаются и отображаются;
  • после выполнения docker compose down и повторного docker compose up ранее созданные заметки сохранились (том не был удален).

Результат этапа: приложение запускается одной командой, все компоненты взаимодействуют корректно, данные сохраняются между перезапусками.


Этап 3. Развертывание в локальном кластере Kubernetes

На этом этапе необходимо развернуть локальный кластер Kubernetes, подготовить YAML-манифесты для всех компонентов и развернуть приложение в кластере.

3.1. Установка и настройка локального кластера

Установить minikube и kubectl:

Запуск кластера:

minikube start --cpus=2 --memory=4096

Проверка работоспособности:

kubectl cluster-info
kubectl get nodes

3.2. Загрузка образов в кластер

Локальный кластер minikube не имеет доступа к образам, собранным на хостовой машине. Чтобы использовать локально собранные образы, необходимо загрузить их в minikube:

minikube image load notes-backend:1.0
minikube image load notes-frontend:1.0

Альтернативный подход — собирать образы непосредственно внутри Docker-среды minikube:

eval $(minikube docker-env)
docker build -t notes-backend:1.0 -f docker/backend/Dockerfile app/backend/
docker build -t notes-frontend:1.0 -f docker/frontend/Dockerfile app/frontend/

В манифестах Deployment необходимо указать imagePullPolicy: Never или imagePullPolicy: IfNotPresent, чтобы Kubernetes не пытался скачать образ из внешнего реестра.

Документация: https://minikube.sigs.k8s.io/docs/handbook/pushing/

3.3. Организация манифестов

Создать каталог k8s/ и разместить в нем манифесты, организованные по компонентам:

k8s/
├── backend/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── configmap.yaml
├── frontend/
│   ├── deployment.yaml
│   └── service.yaml
├── db/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── pvc.yaml
├── secrets.yaml
└── ingress.yaml

Каждый манифест — это YAML-файл, описывающий один ресурс Kubernetes. Все манифесты начинаются с полей apiVersion, kind и metadata.

3.4. Манифесты для компонента database

PersistentVolumeClaim (pvc.yaml) — запрос на выделение постоянного хранилища. В minikube используется встроенный StorageClass (provisioner), который автоматически создает PersistentVolume.

Основные поля:

  • spec.accessModes: ["ReadWriteOnce"] — том доступен для чтения и записи одному узлу.
  • spec.resources.requests.storage: например, 1Gi.

Документация: https://kubernetes.io/docs/concepts/storage/persistent-volumes/

Secret (secrets.yaml) — хранилище для чувствительных данных (паролей). Значения кодируются в Base64.

Создать Secret с паролем базы данных:

# Закодировать значение в Base64
echo -n "notes" | base64

В манифесте:

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  password: <значение в Base64>

Документация: https://kubernetes.io/docs/concepts/configuration/secret/

Deployment (deployment.yaml) — описание развертывания PostgreSQL.

Основные параметры:

  • spec.replicas: 1 — для базы данных достаточно одной реплики.
  • В секции containers указать образ postgres:17-alpine.
  • Переменные окружения POSTGRES_DB, POSTGRES_USER задать явно, а POSTGRES_PASSWORD — через ссылку на Secret (valueFrom.secretKeyRef).
  • Том PVC подключить к каталогу /var/lib/postgresql/data через секции volumes и volumeMounts. Для PostgreSQL рекомендуется монтировать том в подкаталог, указав subPath, так как PostgreSQL требует, чтобы каталог данных был пустым при инициализации.

Документация: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

Service (service.yaml) — обеспечивает стабильный сетевой доступ к PostgreSQL внутри кластера.

apiVersion: v1
kind: Service
metadata:
  name: db
spec:
  selector:
    app: db
  ports:
    - port: 5432
      targetPort: 5432
  type: ClusterIP

Имя сервиса db используется в качестве DNS-имени: backend обращается к базе данных по адресу db:5432.

Документация: https://kubernetes.io/docs/concepts/services-networking/service/

3.5. Манифесты для компонента backend

ConfigMap (configmap.yaml) — хранилище нечувствительных параметров конфигурации.

apiVersion: v1
kind: ConfigMap
metadata:
  name: backend-config
data:
  DB_HOST: "db"
  DB_PORT: "5432"
  DB_NAME: "notes"
  DB_USER: "notes"

В Deployment переменные окружения читаются из ConfigMap (envFrom или valueFrom.configMapKeyRef), а пароль — из Secret.

Документация: https://kubernetes.io/docs/concepts/configuration/configmap/

Deployment (deployment.yaml):

  • spec.replicas: 2 — не менее двух реплик для обеспечения доступности.
  • Образ notes-backend:1.0, imagePullPolicy: IfNotPresent.
  • Переменные окружения из ConfigMap и Secret.
  • Readiness probe — определяет, готов ли под принимать трафик. Kubernetes не направляет запросы на под, пока readiness probe не вернет успешный результат:
readinessProbe:
  httpGet:
    path: /api/health
    port: 8000
  initialDelaySeconds: 5
  periodSeconds: 10
  • Liveness probe — определяет, жив ли процесс. Если liveness probe несколько раз подряд возвращает ошибку, Kubernetes перезапускает контейнер:
livenessProbe:
  httpGet:
    path: /api/health
    port: 8000
  initialDelaySeconds: 15
  periodSeconds: 20
  • Ограничения ресурсов через resources.requests и resources.limits (необходимы для корректной работы HPA на этапе 4).

Документация по probes: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

Service (service.yaml):

  • Тип ClusterIP, порт 8000.
  • Selector должен совпадать с метками (labels) подов в Deployment.

3.6. Манифесты для компонента frontend

Deployment (deployment.yaml):

  • spec.replicas: 2.
  • Образ notes-frontend:1.0.
  • Readiness probe с HTTP-запросом к порту 80.

Особенность: nginx.conf содержит директиву proxy_pass http://backend:8000. В Kubernetes DNS-имя backend должно совпадать с именем Service компонента backend. Если Service backend назван иначе, необходимо либо скорректировать конфигурацию nginx, либо создать Service с именем backend.

Service (service.yaml):

  • Тип ClusterIP, порт 80.

3.7. Ingress

Ingress — ресурс, обеспечивающий внешний HTTP-доступ к сервисам кластера. В minikube необходимо предварительно включить аддон Ingress:

minikube addons enable ingress

Манифест Ingress направляет входящий трафик на Service компонента frontend:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: notes-ingress
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend
                port:
                  number: 80

После применения манифеста узнать IP-адрес для доступа:

minikube ip

Приложение будет доступно по этому IP-адресу в браузере.

Документация: https://kubernetes.io/docs/concepts/services-networking/ingress/

3.8. Применение манифестов и проверка

Применить все манифесты:

# Применить все файлы из каталога k8s/ рекурсивно
kubectl apply -R -f k8s/

Порядок создания ресурсов не критичен: Kubernetes работает по модели желаемого состояния и периодически пытается привести текущее состояние к заданному. Поды backend будут перезапускаться до тех пор, пока база данных не станет доступна (retry-логика в app.js).

Команды для проверки:

# Состояние всех ресурсов
kubectl get all

# Состояние подов (подробно)
kubectl get pods -o wide

# Журналы конкретного пода
kubectl logs <имя-пода>

# Описание пода (события, причины ошибок)
kubectl describe pod <имя-пода>

# Состояние Ingress
kubectl get ingress

# Состояние PVC
kubectl get pvc

Результат этапа: все поды в состоянии Running, приложение доступно через Ingress, данные сохраняются в постоянном томе.


Этап 4. Обновление и масштабирование

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

4.1. Rolling update (последовательное обновление)

Внести видимое изменение в backend — например, добавить поле version в ответ эндпоинта /api/health:

res.json({ status: "ok", version: "2.0" });

Пересобрать образ с новым тегом и загрузить в minikube:

docker build -t notes-backend:2.0 -f docker/backend/Dockerfile app/backend/
minikube image load notes-backend:2.0

Обновить образ в Deployment:

kubectl set image deployment/backend backend=notes-backend:2.0

Наблюдать за процессом обновления:

# Статус обновления в реальном времени
kubectl rollout status deployment/backend

# Наблюдение за подами: старые завершаются, новые запускаются
kubectl get pods -w

Kubernetes заменяет поды постепенно: сначала создает новый под с образом 2.0, дожидается прохождения readiness probe, затем завершает один старый под. Процесс повторяется, пока все реплики не будут обновлены. Благодаря этому приложение остается доступным на протяжении всего обновления.

Проверить, что обновление применилось:

kubectl exec <имя-нового-пода> -- wget -qO- http://localhost:8000/api/health

Документация: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment

4.2. Откат (rollback)

Посмотреть историю обновлений:

kubectl rollout history deployment/backend

Откатить к предыдущей версии:

kubectl rollout undo deployment/backend

Убедиться, что поды вернулись к образу 1.0:

kubectl describe deployment/backend | grep Image

Документация: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-back-a-deployment

4.3. Horizontal Pod Autoscaler (HPA)

HPA автоматически изменяет количество реплик Deployment в зависимости от загрузки. Для его работы необходим metrics-server — компонент, собирающий метрики потребления ресурсов с узлов и подов.

Установка metrics-server в minikube:

minikube addons enable metrics-server

Убедиться, что в Deployment для backend заданы resources.requests (как минимум для CPU). HPA сравнивает текущее потребление CPU с запрошенным и принимает решение о масштабировании.

Создать манифест HPA (k8s/backend/hpa.yaml):

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: backend-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: backend
  minReplicas: 2
  maxReplicas: 5
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50

Применить манифест и проверить состояние:

kubectl apply -f k8s/backend/hpa.yaml
kubectl get hpa

Для демонстрации масштабирования можно создать искусственную нагрузку, например, запустив в отдельном терминале цикл запросов:

kubectl run load-test --rm -i --tty --image=busybox -- sh -c \
  "while true; do wget -qO- http://backend:8000/api/notes; done"

Наблюдать за изменением количества реплик:

kubectl get hpa -w
kubectl get pods -w

Масштабирование происходит не мгновенно: HPA проверяет метрики каждые 15 секунд (по умолчанию), а решение об увеличении или уменьшении реплик принимается с задержкой для предотвращения колебаний.

Документация: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/

4.4. Автоматическое восстановление

Kubernetes поддерживает заданное количество реплик: если под завершается (аварийно или принудительно), контроллер Deployment создает новый.

Продемонстрировать:

# Список подов до удаления
kubectl get pods

# Принудительное удаление одного пода
kubectl delete pod <имя-пода-backend>

# Наблюдение: Kubernetes немедленно создает замену
kubectl get pods -w

Зафиксировать в пояснительной записке: имя удаленного пода, имя нового пода, время восстановления.

Результат этапа: в пояснительной записке задокументированы все четыре операции с командами и их выводом (или снимками экрана).


Этап 5. Безопасность

На этом этапе необходимо применить базовые меры усиления безопасности контейнерной среды и выполнить аудит собранных образов.

5.1. Непривилегированный пользователь в Dockerfile

Убедиться, что в Dockerfile для backend и frontend контейнеры запускаются от непривилегированного пользователя (инструкция USER). Если это не было сделано на этапе 1, внести исправления.

Проверить, от какого пользователя запущен процесс внутри контейнера:

docker run --rm notes-backend:1.0 whoami

Ожидаемый результат: node (для backend) или nginx (для frontend), но не root.

5.2. SecurityContext в манифестах Kubernetes

Добавить в манифесты Deployment для backend и frontend секцию securityContext на уровне контейнера:

securityContext:
  runAsNonRoot: true
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true

Пояснение:

  • runAsNonRoot: true — Kubernetes откажется запускать контейнер, если его образ настроен на запуск от root. Это страховка на случай ошибки в Dockerfile.
  • allowPrivilegeEscalation: false — запрещает процессу внутри контейнера получать привилегии выше тех, с которыми он был запущен.
  • readOnlyRootFilesystem: true — файловая система контейнера монтируется в режиме только для чтения. Это затрудняет модификацию файлов при компрометации контейнера. Если приложению необходимо писать во временные каталоги (например, nginx пишет в /var/cache/nginx и /var/run), следует подключить к ним emptyDir-тома.

После применения обновленных манифестов убедиться, что поды запускаются без ошибок:

kubectl apply -R -f k8s/
kubectl get pods

Если под не запускается, изучить причину через kubectl describe pod <имя-пода> и скорректировать конфигурацию.

Документация: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

5.3. Сканирование образов на уязвимости

Выполнить сканирование собранных образов с помощью Trivy (рекомендуется) или Docker Scout.

Установка Trivy:

Сканирование:

trivy image notes-backend:1.0
trivy image notes-frontend:1.0

Trivy проверяет все пакеты в образе (системные пакеты ОС и зависимости приложения) по базам данных известных уязвимостей (CVE). Результат содержит список найденных уязвимостей с указанием критичности (CRITICAL, HIGH, MEDIUM, LOW).

Альтернатива — Docker Scout (встроен в Docker Desktop):

docker scout cves notes-backend:1.0
docker scout cves notes-frontend:1.0

В пояснительную записку включить:

  • вывод сканирования (полный или сводку);
  • краткий анализ: какие уязвимости обнаружены, какой критичности, возможно ли их устранить обновлением базового образа или зависимостей;
  • если уязвимости устранимы — описать, какие изменения в Dockerfile потребуются (например, обновление версии базового образа или зависимостей в package.json).

Документация:

Результат этапа: манифесты содержат настройки безопасности, поды запускаются без ошибок, отчет о сканировании включен в пояснительную записку.

Состав отчетных материалов

Курсовой проект оформляется в виде репозитория и пояснительной записки.

Репозиторий

Рекомендуемая структура каталогов:

project/
├── app/                        # исходный код приложения (предоставлен)
│   ├── backend/
│   └── frontend/
├── docker/                     # Dockerfile для каждого компонента
│   ├── backend/
│   │   └── Dockerfile
│   └── frontend/
│       └── Dockerfile
├── docker-compose.yml          # композиция для локального запуска
├── .env                        # переменные окружения (значения по умолчанию)
├── k8s/                        # манифесты Kubernetes
│   ├── backend/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   ├── configmap.yaml
│   │   └── hpa.yaml
│   ├── frontend/
│   │   ├── deployment.yaml
│   │   └── service.yaml
│   ├── db/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   └── pvc.yaml
│   ├── secrets.yaml
│   └── ingress.yaml
└── README.md                   # инструкция по сборке и запуску

Пояснительная записка

Пояснительная записка должна содержать следующие разделы:

  1. Введение — краткое описание цели работы и состава приложения.
  2. Контейнеризация — описание структуры Dockerfile для каждого компонента, обоснование выбора базовых образов и приемов оптимизации, анализ слоев и размера итоговых образов.
  3. Локальная композиция — описание файла docker-compose.yml, параметров конфигурации, сетевой топологии и политики хранения данных.
  4. Развертывание в кластере — описание манифестов Kubernetes, схема архитектуры развертывания, настройки проверок состояния и внешнего доступа.
  5. Обновление и масштабирование — описание выполненных операций (rolling update, откат, HPA, восстановление после отказа) с подтверждением в виде команд и их вывода.
  6. Безопасность — описание примененных мер, результаты сканирования образов.
  7. Заключение — выводы о проделанной работе, сравнение подходов (ручной запуск, Compose, Kubernetes).

Схема архитектуры

Пояснительная записка должна включать схему архитектуры развертывания приложения в кластере. Схема должна отображать: компоненты приложения (Deployment, Pod), сервисы (Service), внешний доступ (Ingress), хранилище (PVC) и направления сетевого взаимодействия.

Критерии оценки

КритерийДоля
Корректность Dockerfile: многоэтапная сборка, непривилегированный пользователь, health check, оптимизация размера15%
Корректность docker-compose.yml: сеть, том, переменные окружения, ограничения ресурсов, воспроизводимость запуска15%
Манифесты Kubernetes: Deployment, Service, ConfigMap, Secret, PVC, Ingress, probes25%
Обновление и масштабирование: rolling update, откат, HPA, восстановление15%
Безопасность: securityContext, сканирование образов10%
Пояснительная записка: полнота, обоснованность решений, схема архитектуры15%
Структура репозитория и инструкция по запуску (README)5%

Минимальные системные требования

  • Docker Desktop или Docker Engine;
  • minikube (рекомендуется) или kind;
  • kubectl;
  • 4 ядра CPU, 8 ГБ оперативной памяти (рекомендуется).

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