A miniature Kubernetes-style container orchestrator. A Django/DRF control plane stores desired state, a scheduler assigns work to nodes, controllers reconcile observed state toward desired state, and per-node agents drive a container runtime.
The repository follows the cookiecutter-django layout.
config/
settings/ base.py, local.py, test.py, production.py
api_router.py Every app's viewsets, mounted at /api/v1/
urls.py Root URLconf (admin, /healthz, API)
klystr/
cluster/ Cluster-scoped objects: namespaces, quotas, events
nodes/ Node registration, capacity, heartbeats, cordon/drain
workloads/ Deployments, pods/tasks, specs and lifecycle phases
scheduler/ Placement: filters, scoring, node assignment
controllers/ Reconciliation loops; `run_worker` management command
agents/ Node-agent API: heartbeats, status reports, work pull
utils/ Cross-app helpers: logging, errors, pagination, permissions
infrastructure/ DB advisory locks, container runtime interface, event bus
workers/ Long-running control loops (workers/runner.py)
cli/ klystrctl: commands and HTTP client
conftest.py Shared pytest fixtures
compose/
local/django/ Dev image and start script
production/django/ Production image, entrypoint and gunicorn start script
requirements/ base.txt, local.txt, production.txt
.envs/.local/ Env files for docker-compose.local.yml (committed)
.envs/.production/ Env files for docker-compose.production.yml (git-ignored)
Each app has the same shape: models.py, services.py (business logic),
admin.py, apps.py, api/serializers.py, api/views.py, tests/.
New viewsets are registered in config/api_router.py.
| Module | Used by |
|---|---|
config.settings.local |
manage.py (default) |
config.settings.test |
pytest (--ds in pyproject.toml) |
config.settings.production |
wsgi.py / asgi.py, the production image |
Configuration comes from environment variables through django-environ. The
database is a single DATABASE_URL.
make up # API on http://127.0.0.1:8000/healthz, plus the node-lifecycle workerpython -m venv venv
make install
cp .env.example .env
make services # Postgres + Redis in Docker
make migrate
make run # http://127.0.0.1:8000/healthzTo run without Postgres, set DATABASE_URL=sqlite:///db.sqlite3 in .env.
| Command | Does |
|---|---|
make test |
Run the pytest suite |
make lint |
Ruff lint |
make fmt |
Ruff format |
make worker |
Run the node-lifecycle control loop |
./venv/bin/python manage.py run_worker <name> |
Run any control loop |
python -m klystr.cli.main |
klystrctl |
./venv/bin/pre-commit install |
Lint and format on every commit |
Create .envs/.production/.django (at least DJANGO_SECRET_KEY,
DJANGO_ALLOWED_HOSTS) and .envs/.production/.postgres (the POSTGRES_*
variables in .envs/.local/.postgres), then:
docker compose -f docker-compose.production.yml up -d --buildVersioned under /api/v1/ (e.g. /api/v1/nodes/); route names live in the
api namespace (reverse('api:node-list')). /healthz is an unauthenticated
liveness probe.