Легковесный одноузловой механизм оркестрации для изоляции рабочих процессов на основе Docker.
Разработан для инженеров, которым необходим контроль над контейнерами без сложностей Kubernetes.
EN: Lightweight Python orchestration over Docker & Redis • RU: Легковесная оркестрация Python-воркеров • 中文: 基于 Docker 和 Redis 的轻量级 Python 编排
RedTailFox — для вашего сервера.
RedTailFox is for your server.
Modern orchestration solutions like Kubernetes are powerful — but often overkill for single-node infrastructure or lightweight workloads.
Celery handles task queues well, but does not manage Docker containers.
RedTailFox fills the gap between:
- Simple task queues
- Full-scale Kubernetes clusters
It is designed for:
- Large numbers of isolated worker processes
- Account- or tenant-based job separation
- Self-healing infrastructure without DevOps overhead
- Single-server or small-cluster deployments
Если коротко: Kubernetes слишком жирный, Celery не умеет управлять контейнерами, а вручную поднимать 100 Docker-контейнеров и следить за ними — боль.
RedTailFox — это ровно тот слой оркестрации, который нужен, когда у вас:
- Много однотипных воркеров (боты, парсеры, автоответчики)
- Каждый воркер — отдельный аккаунт/задача со своим конфигом
- Нужно, чтобы система чинила себя сама
- Нет отдельного DevOps, но хочется жить спокойно
| Feature | Description |
|---|---|
| Умные слоты | Менеджер распределяет задачи по слотам внутри контейнеров |
| Автомасштабирование | При нехватке слотов автоматически поднимаются новые Docker-контейнеры |
| Автовосстановление | Монитор проверяет heartbeat'ы и перезапускает упавшие слоты/контейнеры |
| Graceful shutdown | Воркеры корректно завершаются и отписываются от менеджера |
| Хранение конфигов в Redis | Слот можно перезапустить даже без внешних данных |
| Мониторинг через HeadBear | Своя легкая система метрик (опционально) |
| Никакого YAML | Всё настраивается переменными окружения и Python-словарями |
graph TD
%% Входные данные
A["📥 ЗАДАЧА В REDIS<br/><b>manager_tasks</b>"] --> B["⚙️ МЕНЕДЖЕР<br/><i>manager.py</b>"]
%% Принятие решения
B --> C{"🔍 ЕСТЬ СВОБОДНЫЙ<br/>СЛОТ В КОНТЕЙНЕРЕ?"}
%% Ветка "Нет свободных слотов"
C -->|❌ НЕТ| D["🐳 ЗАПУСТИТЬ DOCKER КОНТЕЙНЕР<br/><i>docker_utils.py</i><br/><b>worker_N</b>"]
D --> E["📝 ЗАРЕГИСТРИРОВАТЬ КОНТЕЙНЕР<br/>в <b>manager:active_containers</b>"]
%% Ветка "Есть свободный слот"
C -->|✅ ДА| F["📋 НАЗНАЧИТЬ СЛОТ<br/>в <b>manager:slot_to_container</b>"]
%% Объединение потоков
E --> F
F --> G["📤 КОМАНДА 'START'<br/>в очередь <b>COMMAND_CHANNEL_N</b>"]
%% Работа воркера
G --> H["👷 ВОРКЕР В КОНТЕЙНЕРЕ<br/><i>worker.py</i><br/>запускает слот"]
H --> I["💓 HEARTBEAT КАЖДЫЕ 3 СЕК<br/>в <b>hb:container:name</b>"]
%% Мониторинг
I --> J["🔍 МОНИТОР<br/><i>monitor.py</i><br/>проверка каждые 10 сек"]
%% Проверки монитора
J --> K{"⏳ СЛОТ<br/>НЕАКТИВЕН >600с?"}
K -->|ДА| L["🔄 КОМАНДА <b>restart_worker</b><br/>в autoreply_queue"]
J --> M{"🔇 КОНТЕЙНЕР<br/>БЕЗ HEARTBEAT >500с?"}
M -->|ДА| N["🚨 КОМАНДА <b>restart_container</b><br/>в autoreply_queue"]
J --> O{"👻 КОНТЕЙНЕР-ЗОМБИ<br/>(есть в Docker, нет в Redis)?"}
O -->|ДА| N
%% Замыкание цикла
L --> B
N --> B
%% Отчеты от воркера
H --> P["📊 ОТЧЕТ О СТАТУСЕ<br/>в <b>WORKER_REPORTS</b>"]
P --> Q["📝 ЗАПИСЬ В БАЗУ ДАННЫХ<br/>в <b>db_write_requests</b>"]
%% Простая легенда
subgraph Legend [УСЛОВНЫЕ ОБОЗНАЧЕНИЯ]
direction LR
L1["📥 Очередь Redis"] --- L2["⚙️ Компонент"] --- L3{"Проверка"} --- L4["🔄 Действие"]
end
%% Стилизация с контрастными цветами и четким текстом
style A fill:#f9f9c0,stroke:#000,stroke-width:2px,color:#000
style B fill:#2196F3,stroke:#0d47a1,stroke-width:2px,color:#fff
style C fill:#FFC107,stroke:#000,stroke-width:2px,color:#000
style D fill:#FF9800,stroke:#000,stroke-width:2px,color:#000
style E fill:#4CAF50,stroke:#1b5e20,stroke-width:2px,color:#fff
style F fill:#8BC34A,stroke:#33691e,stroke-width:2px,color:#000
style G fill:#9C27B0,stroke:#4a148c,stroke-width:2px,color:#fff
style H fill:#4CAF50,stroke:#1b5e20,stroke-width:2px,color:#fff
style I fill:#FF5722,stroke:#bf360c,stroke-width:2px,color:#fff
style J fill:#F44336,stroke:#b71c1c,stroke-width:2px,color:#fff
style K,M,O fill:#FFC107,stroke:#000,stroke-width:2px,color:#000
style L,N fill:#FF5722,stroke:#000,stroke-width:2px,color:#fff
style P fill:#673AB7,stroke:#311b92,stroke-width:2px,color:#fff
style Q fill:#009688,stroke:#004d40,stroke-width:2px,color:#fff
%% Пояснительные подписи
linkStyle 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 stroke-width:2px,fill:none
| Компонент | Что делает | Где лежит |
|---|---|---|
| Менеджер | Распределяет задачи, управляет контейнерами, хранит состояние в Redis | manager/manager.py |
| Воркер | Живет в Docker, запускает слоты, шлет heartbeat | worker/worker.py |
| Монитор | Следит за здоровьем, инициирует рестарты | monitor/monitor.py |
| HeadBear | Собирает метрики по слотам и контейнерам | worker/heartbeat.py |
# Клонируем
git clone https://github.com/Dark-F0X/RedTailFox
cd RedTailFox
# Ставим зависимости
pip install -r requirements.txt
# Настраиваем окружение
cp .env.example .env
# Отредактируйте .env под свой Redisdocker build -t rtf-worker:latest -f worker/Dockerfile .python manager/main.pypython monitor/monitor.pyimport redis, json
r = redis.Redis(host='localhost', port=6379)
task = {
"command": "start",
"slot_id": 1,
"config": {
"job": {
"name": "demo_worker",
"interval": 300
}
}
}
r.lpush("manager_tasks", json.dumps(task))
print("Задача отправлена!")Через несколько секунд менеджер поднимет контейнер и запустит слот.
Каждый воркер пишет heartbeat в Redis:
{
"container": "rtf_worker_1",
"ts": 1678901234,
"slots": [
{
"slot_id": 1,
"running": true,
"status": "IDLE",
"last_active": 1678901200
}
]
}Монитор читает эти ключи и принимает решения:
- Если
tsстарееHEARTBEAT_TIMEOUT→ рестарт контейнера - Если слот неактивен больше
SLOT_IDLE_TIMEOUT→ рестарт слота - Если контейнер есть в
ACTIVE_CONTAINERS_KEY, но heartbeat отсутствует → рестарт
Каждый слот представляет собой изолированный контекст задания.
Примеры:
- Веб-скрейперы
- API-клиенты
- Торговые боты
- Фоновые обработчики данных
- Рабочие процессы SaaS-клиентов
RedTailFox предоставляет:
- Автоматическое масштабирование контейнеров
- Изоляцию для каждого задания
- Самовосстановление в случае сбоя
- Непрерывный мониторинг
В ходе производственных тестов один сервер обработал более 1000 изолированных рабочих процессов без Kubernetes.
Each slot represents an isolated job context.
Examples:
- Web scrapers
- API clients
- Trading bots
- Background data processors
- SaaS tenant workers
RedTailFox ensures:
- Automatic container scaling
- Per-job isolation
- Self-recovery on crash
- Continuous monitoring
In production tests, a single server handled 1000+ isolated workers without Kubernetes.
Основные переменные окружения (полный список в .env.example):
| Переменная | По умолчанию | Описание |
|---|---|---|
REDIS_HOST |
localhost | Хост Redis |
REDIS_PORT |
6379 | Порт Redis |
MAX_SLOTS_PER_CONTAINER |
10 | Максимум слотов в одном контейнере |
WORKER_IMAGE |
rtf-worker:latest | Docker-образ воркера |
HEARTBEAT_TIMEOUT |
500 | Таймаут heartbeat (сек) |
SLOT_IDLE_TIMEOUT |
600 | Таймаут простоя слота (сек) |
WORKER_TASKS_LIST |
autoreply_queue | Очередь задач для менеджера |
RedTailFox/
├── manager/ # Менеджер (распределение задач)
├── worker/ # Воркер (исполнение, heartbeat)
├── monitor/ # Монитор (автовосстановление)
├── .env # Шаблон конфига
└── README.md # Этот файл
Нам нужна помощь с:
- Тестами (особенно интеграционными)
- Документацией на английском и китайском
- Поддержкой большего количества хостов (сейчас только одна нода)
- Метриками в Prometheus
MIT © 2025 RedTailFox Team MIT © 2025 RTF Labs Team
- Telegram: @rtf_labs
- GitHub: github.com/Dark-F0X/RedTailFox
Сделано с 🦊 и любовью к Python