← Назад к вопросам

Хочу запустить приложение работающее с БД. Один экземпляр будет запущен как мастер, другие как воркеры. Опиши такой стейтфулсет

1.6 Junior🔥 131 комментариев
#Kubernetes

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Архитектура StatefulSet для Master-Worker приложения с базой данных

Для развертывания приложения с архитектурой Master-Worker, где требуется сохранение состояния и уникальная идентификация каждого пода, StatefulSet является оптимальным выбором в Kubernetes. StatefulSet обеспечивает стабильные сетевые идентификаторы и устойчивое хранилище, что критически важно для мастер–ноды и воркеров, взаимодействующих с БД.

Ключевые особенности StatefulSet для нашей архитектуры

  • Упорядоченное и предсказуемое развертывание: Поды создаются последовательно (сначала мастер, затем воркеры), что гарантирует инициализацию мастера до запуска воркеров
  • Стабильные идентификаторы: Каждый под получает постоянное имя вида <statefulset-name>-<ordinal> (напр., app-master-0, app-worker-0, app-worker-1)
  • Постоянное хранилище: Каждому поду выделяется индивидуальный PersistentVolume, который сохраняется при перезапуске пода
  • Сетевые идентификаторы: Стабильные DNS имена через Headless Service

Пример манифеста StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: app-cluster
  labels:
    app: db-app
spec:
  serviceName: "app-service"
  replicas:和外 3 # 1 мастер + 2 воркера
  selector:
    matchLabels:
      app: db-app
  template:
    metadata:
      labels:
        app: db-app
        role: node
    spec:
      containers:
      - name: app-container
        image: your-registry/db-app:latest
        env:
        - name: NODE_ROLE
          valueFrom:
            fieldRef:
              fieldPath: metadata.labels['role']
        - name: POD_NAME
          valueFrom:
            fieldPath: metadata.name
        - name: DB_HOST
          value: "postgres-primary" # Предполагаем внешнюю БД
        - name: DB_PORT
          value: "5432"
        ports:
        - containerPort: 8080
          name: app-port
        volumeMounts:
        - name: app-data
          mountPath: /var/app-data
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
  volumeClaimTemplates:
  - metadata:
      name: app-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "fast-ssd"
      resources:
        requests:
          storage: 10Gi

Конфигурация Service для идентификации ролей

apiVersion: v1
kind: Service
metadata:
  name: app-service
spec:
  clusterIP: None # Headless Service для стабильных DNS записей
  selector:
    app: db-app
  ports:
  - port: 8080
    name: app-port
---
apiVersion: v1
kind: Service
metadata:
  name: app-master
spec:
  selector:
    app: db-app
    statefulset.kubernetes.io/pod-name: app-cluster-0 # Явно селектим мастер-под
  ports:
  - port: 8080
    targetPort: app-port

Механизм определения роли (Master/Worker)

В приложении можно использовать несколько подходов для определения роли:

  1. На основе порядкового номера пода: Первый под (индекс 0) всегда мастер
#!/bin/bash
# Внутри контейнера
POD_INDEX=$(hostname | sed 's/.*-//')
if [ "$POD_INDEX" -eq 0 ]; then
  export NODE_ROLE="master"
else
  export NODE_ROLE="worker"
fi
  1. Через метки (labels) и селекторы:
# В spec.template.metadata.labels StatefulSet
labels:
  app: db-app
  role: "node-${POD_ORDINAL}" # Динамическое определение через Init Container

Init Container для инициализации мастера

Для гарантированной инициализации мастера перед запуском воркеров:

spec:
  template:
    spec:
      initContainers:
      - name: init-master
        image: busybox
        command:
        - sh
        - -c
        - |
          if [ "$(hostname)" = "app-cluster-0" ]; then
            # Выполнить миграции БД, инициализацию кластера
            echo "Initializing master node..."
            # Ожидание готовности БД
            until nc -z postgres-primary 5432; do
              sleep II 2
            done
          fi

Стратегии обновления и управления

  • RollingUpdate с разделением по партициям: Позволяет обновлять воркеры, не затрагивая мастер
spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 1 # Все поды с индексом >=1 (воркеры) будут обновлены, мастер (индекс 0) останется

Рекомендации по эксплуатации

  • Мониторинг: Отдельные метрики для мастера и воркеров
  • Бэкапы: Регулярные snapshot для PersistentVolume мастера
  • Автомасштабирование: Vertical Pod Autoscaler для мастера, Horizontal Pod Autoscaler для воркеров
  • Высокая доступность: Рассмотреть использование Operator для автоматического выбора нового мастера при сбое

Альтернативные подходы

Если требуется более динамичное управление мастер-нодой (автоматический failover), стоит рассмотреть:

  1. Использование отдельного Deployment для мастера + StatefulSet для воркеров
  2. Реализация через Kubernetes Operator
  3. Использование специализированных решений (Redis Sentinel, PostgreSQL Patroni)

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

Хочу запустить приложение работающее с БД. Один экземпляр будет запущен как мастер, другие как воркеры. Опиши такой стейтфулсет | PrepBro