Tenant and Namespace Management
Ark uses Kubernetes namespaces as tenants. Each namespace is an isolated environment with its own agents, models, tools, and queries. Isolation is enforced at the Kubernetes level via RBAC.
Setting Up a Tenant
Set your kubectl context to the target namespace and use the Ark CLI to install:
kubectl create namespace tenant-a
kubectl config set-context --current --namespace=tenant-a
ark install ark-tenant
ark install ark-broker
ark install ark-api
ark install ark-dashboardThis installs the tenant chart (service account, roles, builtin tools), the broker (per-tenant message and session storage), the API layer, and the dashboard. You can then open the dashboard with:
ark dashboardThe Ark CLI uses your current kubectl context namespace. You can also install the charts directly with Helm — see the Deploying Ark guide.
Cross-Tenant Access
By default, tenants are fully isolated. A user accessing Tenant A’s dashboard cannot see resources in Tenant B. A cluster administrator can grant cross-tenant access using standard Kubernetes RBAC.
Example: Two Tenants with Cross-Access
Install two full tenants:
kubectl create namespace tenant-a
kubectl config set-context --current --namespace=tenant-a
ark install ark-tenant
ark install ark-broker
ark install ark-api
ark install ark-dashboard
kubectl create namespace tenant-b
kubectl config set-context --current --namespace=tenant-b
ark install ark-tenant
ark install ark-broker
ark install ark-api
ark install ark-dashboardAt this point both tenants are fully isolated. To grant Tenant A access to Tenant B’s resources, apply a RoleBinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: tenant-a-access
namespace: tenant-b
subjects:
- kind: ServiceAccount
name: ark-api-sa
namespace: tenant-a
roleRef:
kind: Role
name: ark-tenant-role
apiGroup: rbac.authorization.k8s.ioA user on Tenant A’s dashboard can now view and manage Tenant B’s resources by adding ?namespace=tenant-b to the URL.
Without the RoleBinding, the API returns a 403 error when attempting to access another tenant’s resources.
Broker storage isolation
The cross-tenant isolation above applies to Kubernetes resources and is enforced by RBAC. The broker’s message storage is a separate concern. The broker is a per-tenant component — each tenant namespace runs its own broker — while only the controller is a cluster-wide singleton.
When the broker uses the default in-memory message store, each broker pod holds its own messages, so isolation follows the deployment. With the Postgres message backend (backends.message: postgres) the messages table has no tenant_id column and no row-level security — its columns are sequence_number, conversation_id, query_id, message, created_at, and expires_at. Data isolation between tenants therefore depends entirely on the deployment, not on the data.
Each per-tenant broker must point at its own database (or at least its own schema) with its own credentials. Do not share one DATABASE_URL across brokers of different tenants — their messages would be commingled in the same messages table with no way to separate them after the fact.
The same applies to the Redis chunks backend (backends.chunk: redis): chunk streams carry no per-tenant separation, and REDIS_KEY_PREFIX namespaces keys but is not an isolation boundary. Each per-tenant broker must point at its own Redis instance (or keyspace) with its own credentials — never share one REDIS_URL across brokers of different tenants. Traces, events, and sessions remain in memory regardless of backend.
See Message backend (Postgres) and Chunk backend (Redis) for backend configuration.
Developing with Tenants
During development, use devspace to deploy into a tenant namespace:
devspace dev -n tenant-aOr set your kubectl context and use the CLI:
kubectl config set-context --current --namespace=tenant-a
ark dashboardAdd ?namespace=tenant-b to the URL to view another tenant’s resources.