Skip to content

Workspaces

Workspaces provide multi-tenant isolation in DRLS. Each workspace gets dedicated Kubernetes namespaces, IAM roles, and network policies to ensure data and compute separation between teams.

Overview

A workspace represents an isolated environment with:

  • 3 dedicated K8s namespaces{id}-notebooks, {id}-drls-clusters, {id}-drls-pipelines
  • S3 prefix scoping — each workspace's IAM role only grants access to s3://{bucket}/{workspace_id}/*
  • Per-user ServiceAccounts — JIT-created on OIDC login with IRSA annotations for AWS credential injection
  • Network policies — namespace-level isolation preventing cross-workspace network traffic
  • Data-level scoping — all API queries (pipelines, runs, clusters, notebooks) are filtered by workspace

A default workspace is always present and uses the pre-existing namespaces (notebooks, drls-clusters, drls-pipelines).

Creating a Workspace

Navigate to System Settings > Workspaces in the management console.

  1. Click Create Workspace
  2. Enter a Workspace ID — lowercase alphanumeric with hyphens, 2-38 characters, no leading/trailing hyphen (e.g., data-science, team-alpha)
  3. Enter a Display Name — human-readable label shown in the UI
  4. Click Create

The workspace enters pending status while Kubernetes resources are provisioned asynchronously. Once complete, it transitions to active.

Note

Workspace IDs must be at most 38 characters because they become K8s namespace prefixes. The longest suffix (-drls-pipelines, 25 chars) plus the ID must fit within the 63-character namespace limit.

IAM Role Configuration

Each workspace can have an associated IAM role for S3 and Glue access via IRSA (IAM Roles for Service Accounts).

Setting the IAM Role

  1. Provision the IAM role using the Terraform module (see Terraform Provisioning below)
  2. Copy the role ARN from the Terraform output
  3. In System Settings > Workspaces, click the workspace row to edit
  4. Paste the ARN into the IAM Role ARN field and save
  5. Click Sync IAM to propagate the annotation to all existing ServiceAccounts

How IRSA Works

When an IAM role ARN is set on a workspace:

  1. All per-user ServiceAccounts in the workspace's namespaces receive the eks.amazonaws.com/role-arn annotation
  2. Pods running under those ServiceAccounts automatically receive AWS credentials via the EKS pod identity webhook
  3. The IAM role's trust policy allows assumption from any SA in the workspace's namespaces
  4. The IAM role's permission policy restricts S3 access to the workspace's prefix

Per-User ServiceAccounts

When a user logs in via OIDC SSO, the system JIT-creates a Kubernetes ServiceAccount named user-{sub} in all three of the user's workspace namespaces. This happens as a fire-and-forget background task, so it does not add latency to login.

  • Notebook pods in non-default workspaces run under the user's ServiceAccount
  • IRSA annotations are applied if the workspace has an IAM role configured
  • ServiceAccount records are tracked in the database for lifecycle management
  • On workspace deletion, all associated ServiceAccounts are cleaned up automatically

Network Isolation

Each workspace namespace has a NetworkPolicy that restricts traffic:

Notebook Namespace

Direction Allowed Ports
Ingress core-services (backend pod only) TCP/2718 (marimo)
Egress DNS UDP+TCP/53
Egress HTTPS (external, non-RFC1918) TCP/443

Ray Cluster Namespace

Direction Allowed Ports
Ingress core-services (dashboard proxy, log streaming) All
Ingress Intra-namespace (head ↔ workers, GCS) All
Egress DNS UDP+TCP/53
Egress HTTPS (S3, external APIs) TCP/443
Egress Intra-namespace (head ↔ workers) All

Pipeline Namespace

Direction Allowed Ports
Ingress core-services (ui-server log streaming) All
Ingress Intra-namespace (Spark driver ↔ executor) All
Egress DNS UDP+TCP/53
Egress HTTPS (S3, Polaris, external APIs) TCP/443
Egress Kafka TCP/9092, TCP/9093
Egress Intra-namespace (driver ↔ executor) All

Info

Network policies are namespace-scoped. When a workspace is deleted, its namespaces (and all policies within) are automatically removed.

Terraform Provisioning

The terraform/04-workspace-iam/ module creates per-workspace IAM roles with S3 prefix-scoped access.

Usage

cd terraform/04-workspace-iam

terraform init

# Create IAM role for a workspace
terraform apply \
  -var="workspace_id=data-science" \
  -var="bucket_arn=arn:aws:s3:::drls-datalake"

Inputs

Variable Required Default Description
workspace_id Yes Workspace identifier
cluster_name No drls EKS cluster name
region No us-west-2 AWS region
bucket_arn Yes Data lake S3 bucket ARN
kms_key_arn No "" KMS key ARN (if bucket uses custom key)

Outputs

Output Description
role_arn IAM role ARN — paste into workspace settings
role_name IAM role name

What It Creates

  • IAM Role (rls-workspace-{id}) with IRSA trust policy allowing any ServiceAccount in the workspace's namespaces
  • S3 PolicyListBucket (prefix-scoped), GetObject/PutObject/DeleteObject (prefix-scoped)
  • Glue Policy — read-only access to the shared Glue Data Catalog
  • KMS Policy (optional) — Decrypt/GenerateDataKey if a custom KMS key is provided

Troubleshooting

Workspace stuck in "pending" or "error"

The workspace provisioning creates K8s namespaces, RBAC roles, and network policies asynchronously. If it fails:

  1. Check the workspace error message in System Settings > Workspaces
  2. Common causes: K8s API unreachable, RBAC insufficient, namespace already exists with conflicting labels
  3. Click Retry Provisioning to re-run the provisioning task

ServiceAccounts not receiving IRSA annotation

  1. Verify the IAM role ARN is set on the workspace
  2. Click Sync IAM to force-propagate the annotation
  3. Check that the user has logged in at least once (SAs are JIT-created on login)

Pods cannot access S3

  1. Verify the pod is running under a user ServiceAccount (not default)
  2. Check the SA has the eks.amazonaws.com/role-arn annotation: kubectl get sa user-{sub} -n {ws}-drls-pipelines -o yaml
  3. Verify the IAM role trust policy includes the correct OIDC provider and namespace
  4. Check CloudTrail for AssumeRoleWithWebIdentity errors