Skip to main content
Version: v1.2.x

Multi-Tenancy

PaletteAI is multi-tenant. It organizes teams, controls access, and manages GPU resources through a hierarchy of scopes, so platform engineering teams can set organization-wide policy while data science teams keep autonomy over their own workspaces.

For example, artificial intelligence and machine learning (AI/ML) platforms typically serve multiple teams with different needs. Platform teams need to control who can access what, set resource limits, and manage infrastructure, whereas data science teams need isolated workspaces where they can deploy and manage their own workloads. Scopes separate these concerns.

Scopes

Every PaletteAI resource lives in one of the following scopes, identified by the namespace it resides in. A Project is the unit of work, a Tenant groups Projects and shares resources across them, and the System scope shares resources across all Tenants and Projects. The Platform scope is separate: it holds the internal resources that PaletteAI installs and manages, and is not user-facing.

ScopeNamespaceOwnerDescriptionWho Can Use It
Project<project-name>Project adminsAn isolated workspace where a team deploys and manages AI/ML applications and models. Most day-to-day work happens here.Only within the Project itself.
Tenanttenant-<tenant-name>Tenant adminsAn organization or major division that groups Projects, sets GPU quotas, and shares resources across its Projects. App Deployments, Model Deployments, and Compute Pools can also be created directly at Tenant scope.Every Project in the Tenant, unless a resource narrows access with sharedWith.
Systempai-systemPlatform operatorsTop-level scope for resources you define and deploy once for the whole organization — the same kinds available at Tenant and Project scope (Compute Pools, AIWorkloads, Profile Bundles, and more). User-managed, not installer-managed.Every Tenant and Project, unless a resource narrows access with sharedWith.
Platformmural-system (default, configurable)PaletteAIInternal platform-wide resources reserved for core operations (controllers, ConfigMaps, Flux sources) and the built-in resources installed by the PaletteAI definitions installer (Definitions, Scaling Policies, Profile Bundles, etc.). Cannot be edited in place but can be cloned into any scope and customized.Any scope, by reference or by cloning. Not directly editable.

Each scope shares resources only with the level directly below it, opt-in and controlled per resource. For the sharing model, refer to Sharing Resources.

Scope Labels

PaletteAI applies scope-aware labels to every resource so that the UI can identify its scope. These labels are metadata only and are not used to enforce access.

  • palette.ai/scope records the scope itself, set to project, tenant, system, or built-in. The built-in value is used for the Platform scope.
  • palette.ai/project holds the project name, and palette.ai/tenant holds the tenant name. Which labels appear depends on the scope:
    • Project-scoped resources — Contain both palette.ai/project and palette.ai/tenant
    • Tenant-scoped resources — Contain only palette.ai/tenant
    • System-scoped resources — Contain neither
    • Platform-scoped resources — Contain neither

For example, the following labels are attached to the Profile Bundle ollama-model in the Project docs-project, which is a part of the default Tenant.

Example command
kubectl describe profilebundles ollama-model --namespace docs-project
Example output for a profilebundle object with labels
Name:         ollama-model
Namespace: docs-project
Labels: app=ollama
palette.ai/project=docs-project
palette.ai/scope=project
palette.ai/tenant=default

Resource Creation

The scope you are in determines the types of resources you can create or modify in the UI. Most of these resources can be created directly from the left main menu, while other are found under Project Settings, Tenant Settings, and System Settings.

ResourceKindSpecProject UITenant UISystem UI
App DeploymentAIWorkload-
Autoscaling PolicyScalingPolicy-
ComputeCompute-
Compute ConfigComputeConfig-
Compute PoolsComputePool-
DefinitionsDefinitionRevision-
Model as a Service MappingsProject, Tenant, or SystemmodelSettings.profileBundleMappings
Model DeploymentAIWorkload-
Models ListProject, Tenant, or SystemmodelSettings
Profile BundlesProfileBundle-Import onlyImport only
ProjectsProject-
RBACProject or TenanttenantRoleMapping or roleMapping
RepositoriesHelmRepository or OCIRepository-
Resource LimitsProject, Tenant, or SystemgpuResources
SettingsSettingsintegrations
SystemSystem-
Target NamespacesProject, Tenant, or SystemadmissionConfiguration
TenantsTenant-
VariablesVariableSet-
Workload ProfileWorkloadProfile-

Namespace Isolation

Many PaletteAI resources point to other resources by namespace. For example, a Compute Pool references the Profile Bundle it is built from. To keep Projects isolated, an admission webhook checks every one of these references when a resource is created or updated, and rejects any that points somewhere it should not. A resource can never reference another Project's namespace.

In the tables below, the allowed namespaces mean:

  • Project — The resource's own namespace (the Project it lives in)
  • Tenant — The parent Tenant namespace (tenant-<tenant-name>), where a Tenant admin shares resources across Projects
  • System — The system namespace (pai-system), whose resources may be shared with Tenants and their Projects by a system administrator
  • Built-in — The built-in platform namespace (mural-system), where default resources such as built-in ScalingPolicies live

Project-scoped Resources

ResourceFieldAllowed Namespaces
AIWorkloadspec.computePoolRef.namespace- Project
- Tenant (if shared with the Project)
- System (if shared with the Project)
AIWorkloadspec.profileBundles[].namespace- Project
- Tenant (if shared with the Project)
- System (if shared with the Project)
AIWorkloadspec.workloadDeploymentConfigs[].workloadProfileRef.namespace- Project
- Tenant
- System
ComputePoolspec.clusterVariant.imported.environmentRef.namespace- Project
ComputePoolspec.profileBundleRef.namespace- Project
- Tenant (if shared with the Project)
- System (if shared with the Project)
ComputePoolspec.workloadDeploymentConfigs[].workloadProfileRef.namespace- Project
- Tenant
- System
ComputePoolspec.clusterVariant.*.scalingPolicyRef.namespace- Project
- Tenant (if shared with the Project)
- System (if shared with the Project)
- Built-in
ProfileBundlespec.*.workloadProfileRefs[].namespace- Project
Projectspec.computeConfigRef.namespace- Project
- Tenant
Settingsspec.integrations.palette.namespace- Project

Tenant-scoped Resources

ResourceFieldAllowed Namespaces
AIWorkloadspec.computePoolRef.namespace- Tenant
- System (if shared with the Tenant)
AIWorkloadspec.profileBundles[].namespace- Tenant
- System (if shared with the Tenant)
AIWorkloadspec.workloadDeploymentConfigs[].workloadProfileRef.namespace- Tenant
- System
ComputePoolspec.clusterVariant.imported.environmentRef.namespace- Tenant
ComputePoolspec.profileBundleRef.namespace- Tenant
- System (if shared with the Tenant)
ComputePoolspec.workloadDeploymentConfigs[].workloadProfileRef.namespace- Tenant
- System
ComputePoolspec.clusterVariant.*.scalingPolicyRef.namespace- Tenant
- System (if shared with the Tenant)
- Built-in
ProfileBundlespec.*.workloadProfileRefs[].namespace- Tenant
Projectspec.computeConfigRef.namespace- Tenant
Settingsspec.integrations.palette.namespace- Tenant

System-scoped Resources

ResourceFieldAllowed Namespaces
AIWorkloadspec.computePoolRef.namespace- System
AIWorkloadspec.profileBundles[].namespace- System
AIWorkloadspec.workloadDeploymentConfigs[].workloadProfileRef.namespace- System
ComputePoolspec.clusterVariant.imported.environmentRef.namespace- System
ComputePoolspec.profileBundleRef.namespace- System
ComputePoolspec.workloadDeploymentConfigs[].workloadProfileRef.namespace- System
ComputePoolspec.clusterVariant.*.scalingPolicyRef.namespace- System
- Built-in
ProfileBundlespec.*.workloadProfileRefs[].namespace- System
Projectspec.computeConfigRef.namespace- System
Settingsspec.integrations.palette.namespace- System
info

A Settings resource does not have a dedicated namespace of its own. It lives in a Project, Tenant, or System namespace, and its spec.integrations.palette.namespace must point to that same namespace, so the Palette credential secret always sits alongside the Settings resource that uses it.

For information on how resources are shared across scopes, refer to Sharing Resources.

Access and Permissions

PaletteAI manages access with standard Kubernetes Role-Based Access Control (RBAC), bound to OpenID Connect (OIDC) groups rather than individual users. For an overview of the Tenant and Project roles, refer to Roles and Permissions. External integrations and credentials are configured through Settings.

Default Resources

PaletteAI creates a default Tenant and Project during installation. These provide a starting point for exploration but should be customized for production use.

To disable default resource creation, set global.featureFlags.systemDefaultResources to false in your Helm chart values.

global:
featureFlags:
systemDefaultResources: false