Deployment Guide¶
This guide covers running Istos services in production with Zenoh routers, containers, and observability.
Architecture¶
graph TB
subgraph "Kubernetes Cluster"
R[Zenoh Router]
S1[Istos Service A]
S2[Istos Service B]
S3[Istos Service C]
end
S1 --> R
S2 --> R
S3 --> R
R --> OTel[OpenTelemetry Collector]
OTel --> Prom[Prometheus / Grafana]
Quick Start with Docker Compose¶
# Start Zenoh router + Redis + Postgres
docker compose up -d zenoh-router redis postgres
# Run your service locally, connected to the router
export ISTOS_ZENOH_MODE=client
export ISTOS_ZENOH_CONNECT_ENDPOINTS='["tcp/127.0.0.1:7447"]'
python main.py
Production Configuration¶
from istos import Istos
from istos.communication.sessions import AsyncZenohSession, IstosZenohConfig
from istos.consistency import RedisStoragePlugin
config = IstosZenohConfig(
mode="client",
connect_endpoints=["tls/zenoh-router.prod:7447"],
)
istos = Istos(
session_manager=AsyncZenohSession(config.build()),
storage=RedisStoragePlugin(url="redis://redis.prod:6379/0"),
log_level="INFO",
json_logs=True,
enable_health=True,
enable_metrics=True,
enable_tracing=True,
tracing_endpoint="http://otel-collector:4317",
service_name="robot-fleet",
)
Health Checks¶
Istos registers built-in Zenoh query handlers:
| Endpoint | Purpose |
|---|---|
.istos/health |
Liveness — process is alive |
.istos/ready |
Readiness — service is ready to accept traffic |
.istos/metrics |
Prometheus-format metrics |
.istos/capabilities |
Tool / handler manifest (when enable_discovery=True) |
Query from any node on the network:
When Istos(http_port=8080) is set you also get plain HTTP probes (no Zenoh
client needed on the kubelet side):
| Path | Purpose |
|---|---|
GET /livez, GET /healthz |
liveness |
GET /readyz |
readiness (503 if not ready) |
GET /metrics |
Prometheus |
See HTTP Gateway.
Custom Readiness Checks¶
async def check_database():
# Return {"status": "ok"} when healthy
return {"status": "ok", "connections": 5}
istos.add_health_check("database", check_database)
Graceful Shutdown¶
Istos handles SIGINT and SIGTERM automatically:
- Stops accepting new work
- Marks readiness as
not_ready - Unbinds all Zenoh handlers and subscribers
- Closes the session cleanly
In Kubernetes, configure a preStop hook with adequate terminationGracePeriodSeconds (30s recommended).
Observability¶
Structured Logging¶
Logs are emitted as JSON for aggregation by ELK, Loki, or Datadog.
Prometheus Metrics¶
Query .istos/metrics or access the in-process collector:
OpenTelemetry Tracing¶
istos = Istos(
enable_tracing=True,
tracing_endpoint="http://localhost:4317",
service_name="my-service",
)
Storage Backends¶
| Plugin | Use Case | Install |
|---|---|---|
InMemoryStoragePlugin |
Development, testing | Built-in |
RedisStoragePlugin |
Distributed, fast | pip install 'istos[redis]' |
SqlAlchemyStoragePlugin |
Any SQL database (Postgres, MySQL, ...); you choose the async driver via the URL | pip install 'istos[sqlalchemy]' + your driver |
SqlAlchemyStoragePlugin targets any SQLAlchemy-supported database — bring your own
async driver in the URL, e.g. postgresql+asyncpg://…, postgresql+psycopg://…, or
mysql+asyncmy://…:
from istos.consistency import SqlAlchemyStoragePlugin
storage = SqlAlchemyStoragePlugin("postgresql+asyncpg://user:pass@db:5432/istos")
Kubernetes Example¶
apiVersion: apps/v1
kind: Deployment
metadata:
name: istos-robot-service
spec:
replicas: 3
template:
spec:
containers:
- name: robot-service
image: my-registry/istos-robot:latest
env:
- name: ISTOS_ZENOH_MODE
value: "client"
- name: ISTOS_ZENOH_CONNECT_ENDPOINTS
value: '["tcp/zenoh-router:7447"]'
ports:
- containerPort: 8080
name: http
# With Istos(http_port=8080):
livenessProbe:
httpGet:
path: /livez
port: http
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /readyz
port: http
initialDelaySeconds: 5
periodSeconds: 10
No HTTP port?
Fall back to an exec probe that runs query_once('.istos/health'). Works,
just clumsier than /livez.
Security Checklist¶
- [ ] TLS on router connections
- [ ] Zenoh username/password or mTLS
- [ ]
require_auth=True+ an authorizer (or consciousPublicopt-outs) - [ ] Secrets not on disk as PEM files if you can help it
- [ ] Non-root containers
- [ ] Network policy: Zenoh port (+ HTTP if you opened a gateway)
See Security & TLS.
Related guides¶
- Observability — logging, health, metrics, tracing
- Storage — Redis and SQLAlchemy ledgers
- CLI —
istos new/istos docs - Recipe: Production service