Skip to content
 
 

Repository files navigation

Масштабирование приложений (Отчёт)

Дисциплина "Проектирование и развертывание веб-решений в эко-системе Python"

Docker registry for Linux Part 1

  1. Содержимое registry:
1

Docker registry for Linux Parts 2 & 3

  1. Успешная аутентификация
2 1
  1. Неуспешная аутентификация
2 2

Docker Orchestration Hands-on Lab

  1. Узлы в состоянии Active
3
  1. Узлы в состоянии Drain
4

Восстановилась ли работа запущенного сервиса на этом узле после перевода из Drain в Active?

Нет, автоматического восстановления работы не происходит.
Когда узел переводится в режим Drain, Docker Swarm останавливает все задачи на этом узле и перемещает их на другие доступные узлы кластера. После возврата узла в режим Active он снова становится доступным для планировщика Swarm и может принимать новые задачи, но ранее перемещённые задачи на него автоматически не возвращаются.

Что необходимо сделать, чтобы запустить работу службы на этом узле снова?

  1. Принудительное обновление сервиса:
docker service update --force sleep-app
  1. Масштабирование сервиса:
docker service scale sleep-app=N

Где N — новое количество реплик.

Swarm stack introduction

Как конфигурируется количество нодов (реплик) в стэке?

Количество нодов (реплик) для каждого сервиса в стеке задаётся через параметр replicas в секции deploy docker-compose.yml файла.

vote:
  # ...
  deploy:
    replicas: 2
worker:
  # ...
  deploy:
    replicas: 2

Docker Swarm запустит:

  • 2 реплики сервиса vote
  • 2 реплики сервиса worker

Как организуется проверка жизнеспособности сервисов в docker-compose.yml?

  1. Прямая проверка жизнеспособности через healthcheck
  2. Зависимости между сервисами с условием готовности (depends_on -> service_healthy)

Кластеризация приложения Counter (Docker Swarm)

Конфигурация Docker Swarm

Файл docker-compose.swarm.yml содержит конфигурацию для кластеризованного развертывания:

services:
  app:
    image: ${DOCKER_REGISTRY:-localhost:5000}/counter-app:latest
    ports:
      - "80:8000"
    deploy:
      replicas: 4  # 4 экземпляра Flask приложения
      endpoint_mode: vip  # Встроенная балансировка нагрузки
      update_config:
        parallelism: 2
        delay: 10s
        failure_action: rollback
      resources:
        limits:
          cpus: '0.50'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M
      placement:
        preferences:
          - spread: node.id
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - REDIS_DB=0

  redis:
    image: redis:7-alpine
    command: ["redis-server", "--save", "60", "1", "--appendonly", "yes"]
    deploy:
      replicas: 1

Нагрузочное тестирование с использованием Docker Swarm

Для проверки производительности приложения используется Locust. Сценарии нагрузочного тестирования содержатся в файле locustfile.py.
Нагрузочное тестирование будет использоваться для сравнения производительности: 1 реплика vs 4 реплики.

Параметры тестирования:

  1. Максимальное количество пользователей - 300
  2. Увеличение количества пользователей в секунду - 30
  3. Длительность тестирования - 60 секунд

Результаты тестирования:

Метрика 1 реплика 4 реплики Изменение
RPS (запросов/сек) 219.50 222.49 +1.4%
Среднее время отклика 46.18 мс 30.39 мс -34.2%
95-й перцентиль 150.00 мс 110.00 мс -26.7%
99-й перцентиль 270.00 мс 190.00 мс -29.6%
Процент ошибок 0% 0% -

Анализ результатов тестирования:

Увеличение количества реплик с 1 до 4 показало ограниченное улучшение пропускной способности, но значительное снижение времени отклика:

  1. Минимальный прирост RPS (+1.4%)

    • Пропускная способность практически не изменилась
    • Узкое место - не CPU приложения, а Redis
    • Приложение выполняет простые операции (чтение/запись в Redis) без сложных вычислений
  2. Значительное улучшение времени отклика (-34.2%)

    • Среднее время отклика снизилось с 46.18 мс до 30.39 мс
    • 95-й перцентиль улучшился на 26.7%
    • 99-й перцентиль улучшился на 29.6%
    • Распределение нагрузки между репликами снижает вероятность длинных очередей
  3. Факторы, ограничивающие эффект масштабирования:

    • Приложение легковесное — простые CRUD операции без тяжелой бизнес-логики
    • Redis обрабатывает запросы быстрее, чем приложение
    • Локальное тестирование исключает реальные сетевые задержки
    • Все реплики работают на одной машине

Выводы:

Для данного приложения кластеризация Flask дает умеренный эффект:

  • Пропускная способность: практически не изменяется, так как узкое место в Redis
  • Время отклика: значительно улучшается за счет распределения нагрузки
  • Отказоустойчивость: основное преимущество — при падении одной реплики система продолжает работать
  • Production сценарий: при более сложной логике (аутентификация, внешние API, обработка данных) эффект от масштабирования был бы более выраженным

Конфигурация Docker Swarm с репликацией Redis

Файл docker-compose.swarm-replicated.yml содержит конфигурацию для кластеризованного развертывания (3 реплики Redis):

services:
  app:
    image: ${DOCKER_REGISTRY:-localhost:5000}/counter-app:latest
    ports:
      - "80:8000"
    deploy:
      replicas: 4  # 4 экземпляра Flask приложения
      endpoint_mode: vip  # Встроенная балансировка нагрузки
      update_config:
        parallelism: 2
        delay: 10s
        failure_action: rollback
      resources:
        limits:
          cpus: '0.50'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M
      placement:
        preferences:
          - spread: node.id
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - REDIS_DB=0

  redis:
    image: redis:7-alpine
    command: ["redis-server", "--save", "60", "1", "--appendonly", "yes"]
    deploy:
      replicas: 3  # 3 реплики Redis

Особенности при использовании нескольких реплик Redis в Docker Swarm:

  1. Независимые экземпляры БД

    • Каждая реплика Redis является независимым экземпляром
    • Данные не синхронизируются автоматически между репликами
    • Каждое подключение может попасть на любой экземпляр Redis
  2. Проблема консистентности данных

    • Запись в одну реплику не отражается в других
    • Разные экземпляры приложения могут видеть разные данные
    • Потеря целостности данных счетчика
  3. Балансировка подключений

    • Docker Swarm распределяет подключения между репликами случайным образом
    • Нет контроля, какое приложение к какой реплике подключается

Пути решения проблем репликации:

  1. Redis Sentinel

    • Автоматическое управление master и replicas
    • Автоматический failover при отказе master
    • Требует дополнительной настройки конфигурации
  2. Redis Cluster

    • Распределение данных по нескольким узлам
    • Автоматическая репликация
    • Более сложная настройка, но лучшая производительность
  3. Внешний managed Redis (AWS ElastiCache, Redis Cloud и т.д.)

    • Управляемый сервис с автоматической репликацией
    • Минимальная настройка, максимальная надежность

Кластеризация приложения Counter (Kubernetes)

Файл k8s-deployment.yaml содержит конфигурацию для кластеризованного развертывания:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: counter-app
  labels:
    app: counter-app
spec:
  replicas: 4  # 4 реплики Flask приложения
  selector:
    matchLabels:
      app: counter-app
  template:
    metadata:
      labels:
        app: counter-app
    spec:
      containers:
      - name: counter-app
        image: localhost:5000/counter-app:latest
        imagePullPolicy: Never
        ports:
        - containerPort: 8000
        env:
        - name: REDIS_HOST
          value: "redis-service"
        - name: REDIS_PORT
          value: "6379"
        - name: REDIS_DB
          value: "0"
        resources:
          limits:
            cpu: "500m"
            memory: "512Mi"
          requests:
            cpu: "250m"
            memory: "256Mi"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  labels:
    app: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:7-alpine
        command: ["redis-server", "--save", "60", "1", "--appendonly", "yes"]
        ports:
        - containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: counter-app-service
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8000
    protocol: TCP
  selector:
    app: counter-app
---
apiVersion: v1
kind: Service
metadata:
  name: redis-service
spec:
  ports:
  - port: 6379
    targetPort: 6379
    protocol: TCP
  selector:
    app: redis

Изменения при использовании Kubernetes вместо Docker Swarm:

  1. Формат конфигурации

    • Swarm использует docker-compose.yml с синтаксисом Compose
    • Kubernetes использует YAML-манифесты с декларативным API Kubernetes
  2. Архитектура

    • Swarm интегрирован в Docker, более простая настройка
    • Kubernetes - отдельная оркестрационная система, более мощная, но сложнее
  3. Балансировка нагрузки

    • Swarm: встроенная балансировка через VIP (Virtual IP)
    • Kubernetes: Service с типами ClusterIP, NodePort, LoadBalancer
  4. Масштабирование

    • Swarm: docker service scale
    • Kubernetes: kubectl scale deployment или изменение replicas в манифесте

Нагрузочное тестирование с использованием Kubernetes

Для проверки производительности приложения используется Locust. Сценарии нагрузочного тестирования содержатся в файле locustfile.py.
Нагрузочное тестирование будет использоваться для сравнения производительности: Docker Swarm vs Kubernetes.

Параметры тестирования:

  1. Максимальное количество пользователей - 300
  2. Увеличение количества пользователей в секунду - 30
  3. Длительность тестирования - 60 секунд

Результаты тестирования:

Метрика Docker Swarm (4 реплики) Kubernetes (4 реплики) Изменение
RPS (запросов/сек) 222.49 223.91 +0.6%
Среднее время отклика 30.39 мс 18.89 мс -37.8%
95-й перцентиль 110.00 мс 96.00 мс -12.7%
99-й перцентиль 190.00 мс 180.00 мс -5.3%
Процент ошибок 0% 100% -

Анализ результатов тестирования:

Сравнение производительности (при условии исправления конфигурации):

  1. Пропускная способность (RPS)

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

    • Более низкое время отклика в Kubernetes может объясняться оптимизацией сетевого стека
  3. Особенности платформ:

    • Docker Swarm: проще в настройке, интегрирован в Docker, встроенная балансировка через VIP
    • Kubernetes: более гибкая конфигурация, расширенные возможности (автомасштабирование, политики безопасности, ресурсы)

Выводы:

Для данного простого приложения:

  • Docker Swarm предпочтительнее — проще настройка и управление для простых сценариев
  • Kubernetes оправдан, если требуются его продвинутые функции (автомасштабирование, сетевые политики, сложные стратегии развертывания)
  • Обе платформы показывают сопоставимую производительность при корректной конфигурации
  • Основное ограничение производительности — Redis, а не выбор оркестратора

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

Проект поддерживает два способа кластеризованного развертывания:

  • SWARM.md - Развертывание с использованием Docker Swarm
  • K3S.md - Развертывание с использованием Kubernetes (k3s)

About

Масштабирование приложений

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages