Management overview
此内容尚不支持你的语言。
managementRoutes(...) builds a route tree of operational
endpoints. You bind it on its own port (8558 by convention),
separate from your app’s main HTTP server, exposing:
- Health probes — liveness + readiness for K8s.
- Cluster info — members, leader, sharding regions.
- Metrics — Prometheus exposition (optional).
- Admin endpoints — leave / down (optional, off by default).
import { managementRoutes } from 'actor-ts';
// Build the routes (cluster is optional — pass null to skip /cluster/*),// then bind them on a dedicated port.const { routes, health } = managementRoutes(system, cluster, { enableMetricsEndpoint: true,});
const binding = await system.http(8558, { host: '0.0.0.0' }).bind(routes);// management endpoints now serve on http://0.0.0.0:8558managementRoutes returns { routes, health }: routes is the
Route tree you bind, and health is the
HealthCheckRegistry
you register liveness / readiness checks on.
Configuration
Section titled “Configuration”The third argument is ManagementRoutesOptions — endpoint
toggles and optional middleware. The port and host are not
settings: they go to system.http(port, { host }), and the
cluster is the second positional argument.
type ManagementRoutesOptionsType = { enableLeaveEndpoint?: boolean; // POST /cluster/leave (default false) enableDownEndpoint?: boolean; // POST /cluster/down (default false) enableMetricsEndpoint?: boolean; // GET /metrics (default false) auth?: Middleware; // guards /cluster/* (+ /metrics) ipAllowlist?: Middleware; // guards EVERY endpoint, incl. /health + /ready authProtectHealth?: boolean; // also require `auth` on /health + /ready (default false)};A typical production wiring:
const { routes, health } = managementRoutes(system, cluster, { enableMetricsEndpoint: true, // for Prometheus enableLeaveEndpoint: false, // admin-only; gate behind auth enableDownEndpoint: false,});await system.http(8558).bind(routes);The endpoints
Section titled “The endpoints”| Endpoint | Always on? | Purpose |
|---|---|---|
GET /health | ✓ | Liveness — 200 iff every liveness check passes. |
GET /ready | ✓ | Readiness — 200 iff cluster up + every readiness check passes. |
GET /cluster/members | When cluster is set | Membership JSON. |
GET /cluster/leader | When cluster is set | Leader address. |
GET /cluster/shards?type=<name> | When cluster is set | Shard placement for a sharded type. |
POST /cluster/leave | Opt-in (enableLeaveEndpoint) | Trigger graceful cluster-leave. |
POST /cluster/down | Opt-in (enableDownEndpoint) | Force-down a peer by address. |
GET /metrics | Opt-in (enableMetricsEndpoint) | Prometheus text format. |
See HTTP endpoints for the full surface + response shapes.
Health checks
Section titled “Health checks”const { routes, health } = managementRoutes(system, cluster);
// Readiness — gates traffic; return { name, status, detail? }.health.addReadiness(async () => { const ok = await db.ping(); return { name: 'database', status: ok, detail: ok ? undefined : 'db unreachable' };});
await system.http(8558).bind(routes);Checks plug into /health (liveness) and /ready (readiness).
A failing check makes that endpoint return 503. See
Health checks.
K8s integration
Section titled “K8s integration”# In your pod spec:readinessProbe: httpGet: path: /ready port: 8558 initialDelaySeconds: 5 periodSeconds: 5
livenessProbe: httpGet: path: /health port: 8558 initialDelaySeconds: 30 periodSeconds: 10K8s polls these endpoints to decide if the pod should receive traffic (ready) or be restarted (live). See Kubernetes deployment for the full deployment recipe.
Why a separate port
Section titled “Why a separate port”App port (8080): public, behind a load balancerManagement (8558): internal-only, firewalled offThe management endpoints reveal internal state — cluster member addresses, metric values, etc. Exposing them publicly is a security risk. Bind them on a separate port and firewall it internally.
In K8s, this is per-pod — probes hit :8558 from the
kubelet (same node), but no Service exposes it externally.
Behind an auth proxy
Section titled “Behind an auth proxy”For more access control:
# In your Service / Ingress config:# - 8080 → public# - 8558 → not exposed publicly; mTLS internallySome production setups expose management behind a side-car proxy
that handles auth (Envoy + JWT, Linkerd + mTLS). Alternatively,
attach the built-in auth / ipAllowlist middleware via the
settings (see HTTP endpoints).
Mounting into an existing server
Section titled “Mounting into an existing server”managementRoutes returns plain routes, so you don’t need a
dedicated port at all — concat them into your app’s existing
HTTP routes:
import { managementRoutes, concat } from 'actor-ts';
const { routes: mgmt } = managementRoutes(system, cluster);await system.http(8080).bind(concat(appRoutes, mgmt));Two reasons you might do this instead of a separate port:
- You already have an HTTP server and want management inline.
- Single-node app without cluster — health checks alone might
not justify the extra port; wire
/healthinto your existing server.
(Mounting management on the public port re-exposes internal state —
gate it with the auth / ipAllowlist settings if you do.)
Where to next
Section titled “Where to next”- Health checks —
custom checks plumbed through
/healthand/ready. - HTTP endpoints — the full endpoint reference.
- Kubernetes deployment — the K8s recipe using these probes.
- Prometheus exporter — the metrics endpoint this exposes.
