architect/arh/concept/platform-cluster-model.md

type: concept
title: "Теоретическая модель кластера платформы"
version: 0.1.0
date: 2026-04-02
status: draft


Теоретическая модель кластера платформы


1. СЕТЬ КЛАСТЕРА

Все серверы связаны через WireGuard VPN. Топология — звезда с центром в Ядре.

                    ИНТЕРНЕТ
                       │
          ┌────────────┼────────────┐
          ▼            ▼            ▼
    :80/:443      :80/:443       :22/:51820
          │            │
┌─────────┴──────┐  ┌──┴──────────────────┐
│   ЯДРО         │  │   ИСПОЛНИТЕЛЬ × N   │
│   DEV-PRO      │  │   pm-platform       │
│   EU           │  │   РФ                │
│   10.10.0.1    │  │   10.10.0.10        │
│                │  │                     │
│  WireGuard HUB │◄─►  WireGuard CLIENT   │
└────────────────┘  └─────────────────────┘

Новый исполнитель → wg: 10.10.0.11, 10.10.0.12 ...

Какой трафик куда

ЧЕРЕЗ VPN (закрыто снаружи):
  Portainer Agent  Portainer Server     :9001
  Backup Agent     Restic Server        :8000
  Uptime Kuma      healthcheck сервисов :9001
  git pull/push    Gitea               :3000

НАПРЯМУЮ (открыто снаружи):
  Пользователи     Исполнитель         :80/:443
  Оператор         SSH                 :22
  Let's Encrypt   → ACME challenge      :80
  Claude Code     → Anthropic API       outbound

ТОЛЬКО ВНУТРИ СЕРВЕРА (не выходит):
  PostgreSQL      :5432
  Redis           :6379
  внутренние UI   → через reverse proxy

Порты на серверах

ЯДРО (DEV-PRO):
  ОТКРЫТО:  22 (SSH), 80 (HTTP), 443 (HTTPS), 51820/udp (WireGuard)
  ЗАКРЫТО:  всё остальное

ИСПОЛНИТЕЛЬ (pm-platform и др.):
  ОТКРЫТО:  22 (SSH аварийный), 80 (HTTP), 443 (HTTPS)
  ЗАКРЫТО:  5432, 6379, 9000, всё остальное

2. КОМПОНЕНТЫ И ИХ МЕСТО

BASE — на каждом сервере

BASE (ставится первым, везде одинаковый)
├── Portainer Agent    подключается к Portainer Server по VPN
├── WireGuard          клиент (или сервер на Ядре)
├── Nginx local        роутинг сервисов этого сервера
└── Backup Agent       restic  Beget S3

МАТКА — только на Ядре

CORE (критично  падёт = платформа умерла):
├── PostgreSQL         питает Gitea + Authelia
├── Gitea              git, источник истины
├── Authelia           SSO для всех UI
└── Nginx              главный домен, SSL

NET (сетевые):
├── WireGuard Server   VPN хаб
└── Certbot            SSL сертификаты

OPS (управление):
├── Portainer Server   центральный UI контейнеров
├── Uptime Kuma        мониторинг
└── Telegram Bot       алерты

BACKUP (резервирование):
├── Restic Server      принимает бэкапы от агентов
└── S3 Client          отправляет в Beget S3

СОЗДАТЕЛЬ — на Ядре или отдельно

CREATOR
├── Claude Code        интерактивный терминал
└── workspace/
    ├── architect/    rw
    ├── library/      rw
    ├── system/       rw
    └── infra/        rw

ПРОЕКТОР — на Ядре или отдельно

PROJECTOR
├── Claude Code        интерактивный терминал
└── workspace/
    ├── projects/     rw
    ├── architect/    ro
    ├── library/      ro
    └── infra/        ro

ИСПОЛНИТЕЛЬ — отдельный сервер(а)

EXECUTOR (на каждом исполнителе свой)
├── Nginx + Certbot   → домены проектов, SSL
├── PostgreSQL        → БД проектов этого исполнителя
├── Redis             → кэш, очереди
├── MinIO             → S3 для медиа (опционально)
└── project-* стеки  → сервисы проектов клиентов

3. КАК ВСЁ РАБОТАЕТ — ПОТОКИ

А. Создатель обновляет стандарт

Создатель (Claude Code)
    │
    ├─ редактирует architect/standards/...
    ├─ git commit + git push → Gitea
    │
    └─ Проектор при следующей сессии:
       git pull → получает обновление

Б. Проектор деплоит проект

Проектор (Claude Code)
    │
    ├─ git clone шаблон → projects/org/shop-x/
    ├─ настройка docker-compose.yml + .env
    ├─ git push → Gitea (project-shop-x.git)
    │
    ├─ на Исполнителе (через Portainer API или SSH по VPN):
    │   git clone Gitea → /opt/shop-x-stack/
    │   docker compose up -d
    │
    ├─ Nginx: добавить домен → shop-x.ru → контейнер
    ├─ Certbot: выпустить SSL
    │
    └─ Проверка: curl -I https://shop-x.ru → 200 OK

В. Разработка фичи

Создатель пишет код
    │
    ├─ ветка: git checkout -b feature/catalog
    ├─ код → projects/org/shop-x/modules/catalog/
    ├─ git push → Gitea (feature ветка)
    │
    ├─ тест на dev-стеке Исполнителя:
    │   git pull (feature) → docker compose up --build
    │   → shop-x.dev.0kt.ru
    │
    ├─ git merge → main → git push
    │
    └─ прод:
        git pull (main) → docker compose up --build
        → shop-x.ru

Г. Мониторинг обнаружил проблему

Uptime Kuma (каждые 60 сек проверяет)
        ├─ shop-x.ru  502 (3 раза подряд)
        ├─ Telegram: "DOWN: shop-x.ru — 14:32"
        └─ Оператор:
        ssh 10.10.0.10 (VPN)
        cd /opt/shop-x-stack
        docker compose ps         смотрит что упало
        docker compose logs -f    читает ошибку
        docker compose restart    перезапускает
        curl -I https://shop-x.ru  200 OK
        Telegram: "UP: shop-x.ru — downtime 3m"

Д. Бэкап (каждую ночь 04:00)

На каждом сервере (Backup Agent):
    
    ├─ pg_dump всех БД  /var/backups/
    ├─ restic backup /mnt/data/  Beget S3
    ├─ restic backup /opt/*-stack/  Beget S3
    
    └─ Ядро дополнительно:
       git mirror  GitHub (страховка Gitea)

Е. Восстановление после потери сервера

Потерян ИСПОЛНИТЕЛЬ:
    ├─ заказать новый VPS (~5 мин)
    ├─ ./setup.sh --profile executor (~15 мин)
    ├─ restic restore /mnt/data/ (~20 мин)
    ├─ git clone стеки проектов из Gitea
    ├─ docker compose up -d
    ├─ DNS → новый IP
    └─ Итого: ~45-60 минут

Потеряно ЯДРО (худший случай):
    ├─ заказать новый VPS EU (~5 мин)
    ├─ ./setup.sh --profile core (~15 мин)
    ├─ restic restore Gitea data (~20 мин)
    ├─ восстановить WireGuard конфиг
    ├─ Исполнители переподключаются автоматически
    └─ Итого: ~45 минут. Проекты всё время живут.

4. ЭТАПЫ РАЗВИТИЯ

Этап 0 — Один сервер (старт, POC)

┌─────────────────────────────────────┐
│  ОДИН СЕРВЕР                        │
│  4 CPU / 8 GB / 80 GB               │
│                                     │
│  BASE + МАТКА + СОЗДАТЕЛЬ +         │
│  ПРОЕКТОР + ИСПОЛНИТЕЛЬ             │
│                                     │
│  Всё вместе. Риск: SPOF полный.    │
│  Для: 1-2 проекта, старт.           │
└─────────────────────────────────────┘

Порядок установки: PostgreSQL → Nginx → Gitea → Portainer → Uptime Kuma → Restic → первый проект

Этап 1 — Два сервера (текущий план)

┌───────────────────┐    ┌───────────────────┐
│  ЯДРО (EU)        │    │  ИСПОЛНИТЕЛЬ (РФ) │
│  DEV-PRO          │VPN │  pm-platform      │
│                   │◄──►│                   │
│  BASE + МАТКА     │    │  BASE + EXECUTOR  │
│  СОЗДАТЕЛЬ        │    │  проекты клиентов │
│  ПРОЕКТОР         │    │                   │
└───────────────────┘    └───────────────────┘

Что даёт: изоляция рантайма от управления. Нагрузка проектов не мешает Ядру.

Этап 2 — Три сервера

┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│  ЯДРО (EU)   │  │  ПРОЕКТОР    │  │  ИСПОЛНИТЕЛЬ │
│              │  │  (РФ)        │  │  (РФ)        │
│  BASE        │  │  BASE        │  │  BASE        │
│  МАТКА       │  │  OPS стек    │  │  EXECUTOR    │
│  СОЗДАТЕЛЬ   │  │  ПРОЕКТОР    │  │  проекты     │
└──────────────┘  └──────────────┘  └──────────────┘

Что даёт: мониторинг и управление независимы от Ядра и рантайма.

Этап 3 — N серверов

         ┌──────────┐
            ЯДРО     (один, EU)
         └────┬─────┘
                  ┌─────────┴─────────┐
                       │
┌───┴──────┐      ┌─────┴────┐
│ПРОЕКТОР        │ПРОЕКТОР  │
│ (наш)          (клиента) │
└───┬──────┘      └─────┬────┘
                       │
┌───┴──┬──────┐   ┌─────┴────┐
│EXEC-1EXEC-2    EXEC-C   │
│РФ    │РФ        VPS клиента│
└──────┴──────┘   └──────────┘

Масштабируется горизонтально: +1 VPS = +N проектов.


5. ОТКАЗОУСТОЙЧИВОСТЬ

Что реплицировать vs что бэкапить

РЕПЛИЦИРОВАТЬ — не нужно на текущем масштабе (< 10 проектов).
Оправдано при SLA-контрактах или revenue > $5000/мес.

БЭКАПИТЬ (достаточно):
├── PostgreSQL:      pg_dump каждые 6ч → Beget S3
├── Gitea repos:     push mirror → GitHub (каждые 8ч)
├── Медиа проектов:  restic ежедневно → Beget S3
├── Docker compose:  в git (уже есть)
├── Конфиги nginx:   в git или restic
└── SSH ключи:       restic → S3 (шифрованно)

Главные риски

Что упало Последствия Восстановление
Nginx на EXEC Все сайты 502 restart → 30 сек
PostgreSQL (проекты) Сайты с БД down restart → 30 сек
PostgreSQL (Gitea) Нет деплоев, сайты живут restore из бэкапа → 30 мин
Gitea Нет git push/pull restore → 30 мин
WireGuard Нет VPN, сайты живут restart → 10 сек
Весь EXEC упал Все проекты down новый VPS + restore → 45-60 мин
Всё ЯДРО упало Нет управления, сайты живут новый VPS + restore → 45 мин
Anthropic API Claude Code не работает OpenRouter как fallback

Главный SPOF: ЯДРО

Если потеряно полностью — управление стоит, проекты живут.
Митигация:
- pg_dump каждые 6ч в Beget S3
- Gitea push mirror → GitHub
- Задокументированный runbook восстановления
- Конфиги WireGuard в бэкапе


6. КОМПОНЕНТЫ — ТАБЛИЦА

Компонент Блок Критичность Место Реплицировать
PostgreSQL (Gitea) ЯДРО-CORE FATAL Ядро Нет → бэкап
Gitea ЯДРО-CORE FATAL Ядро Нет → mirror
Nginx BASE FATAL на сервере каждый каждый свой
WireGuard ЯДРО-NET HIGH Ядро Нет
Authelia ЯДРО-CORE HIGH Ядро Нет
Portainer Server МАТКА-OPS HIGH Ядро Нет
Uptime Kuma МАТКА-OPS HIGH Ядро/Проектор Нет
PostgreSQL (проекты) EXECUTOR HIGH каждый EXEC Нет → бэкап
Claude Code СОЗДАТЕЛЬ HIGH Ядро Нет
Redis EXECUTOR MEDIUM каждый EXEC Нет
Certbot EXECUTOR MEDIUM каждый EXEC Нет
Restic ЯДРО-BACKUP MEDIUM Ядро Beget S3
Telegram Bot МАТКА-OPS MEDIUM Ядро Нет
Планировщик ПРОЕКТОР MEDIUM Проектор Нет
docs (md-viewer) ЯДРО LOW Ядро Нет
MinIO EXECUTOR LOW EXEC (опционально) Beget S3
Portainer Agent BASE MEDIUM каждый N/A

Версия: 0.1.0 draft