Skaha Helm Chart¶
The Skaha Helm chart facilitates the deployment of the Skaha application within a Kubernetes cluster. This chart is designed to streamline the installation and management of Skaha, ensuring a seamless integration into your Kubernetes environment.
Chart source
The Skaha Helm chart is co-located with the Skaha service in opencadc/science-platform under helm/. Install from the published chart science-platform/skaha. An archived copy of the former deployments-repo chart is under helm/applications/archived/skaha/ and is no longer released from this repository.
Prerequisites¶
Before deploying the Skaha Helm chart, ensure that the following conditions are met:
- Kubernetes Cluster: A running Kubernetes cluster, version 1.29 or higher.
- Helm: Helm package manager, version 3, installed on your machine. Refer to the official Helm documentation for installation instructions.
- Traefik: Required before Skaha install (
IngressRoute,Middleware). See the deployment guide. - Kueue: Recommended; install and configure per the deployment guide before Skaha if you use session queueing.
Installation¶
To deploy the Skaha application using the Helm chart, follow these steps:
-
Add the Skaha Helm Repository:
-
Update Helm Repositories:
-
Install the Skaha Chart:
Replacehelm --namespace skaha-system upgrade --install --values <your-skaha-values.yaml> skaha-release skaha-repo/skahaskaha-releasewith your desired release name.
Configuration¶
The Skaha Helm chart comes with a default configuration suitable for most deployments. However, you can customize the installation by providing your own values.yaml file. This allows you to override default settings such as resource allocations, environment variables, and other parameters.
To customize the installation:
- Create a
values.yamlFile: Define your custom configurations in this file. - Install the Chart with Custom Values:
LimitRange¶
You can define a LimitRange for User Session Pods by modifying the deployment.skaha.sessions.limitRange section in your values.yaml file. This configuration allows you to set resource limits and requests for different session types. The min clause is ignored due to hard-coded resources for Desktop and Firefly sessions. This will go directly into a LimitRange object created in the Skaha workload Namespace, and, as such, supports the Kubernetes
units.
When limit-range integration is enabled, the Skaha service uses the first LimitRange object returned for the workload namespace (not a specific name); the object name is therefore mostly irrelevant at runtime, though this chart uses a stable name when it creates the resource.
The rbac section allows you to create the necessary Role and RoleBinding for the LimitRange object. If your organization does not permit the creation of RBAC objects, you can set create to false and manage the RBAC externally.
deployment:
skaha:
sessions:
limitRange:
rbac:
create: true
limitSpec:
max:
# maximum resource limit to grow to, also used by the UI to limit selectable resources
memory: "96Gi"
cpu: "12"
default:
# actually refers to default limit
memory: "32Gi"
cpu: "8"
defaultRequest:
# default resource requests
memory: "4Gi"
cpu: "1"
Flexible Session Pods¶
You can customize the User Session Pods by modifying the deployment.skaha.sessions section in your values.yaml file. This includes settings for resource requests, storage allocation, and more.
Flexible User sessions are created with a small amount of CPU and memory by default and are allowed to grow to a specified limit in the LimitRange configuration. You can adjust these minimum (request) settings as needed:
deployment:
skaha:
sessions:
flexResourceRequests:
# The headless session type resource requests get slightly more resources to start.
headless:
memoryInGB: "2"
cpuCores: "1"
notebook:
memoryInGB: "2"
cpuCores: "0.5"
The headless, notebook, desktop, contributed, and firefly session types can all be customized individually. Any session type not specified will use the values defined in the LimitRange configuration.
Note that Kubernetes resource units are not supported in this configuration; only floating point or integer numbers as strings are valid. For example, for 100m of CPU, use "0.1".
Notes on tolerations and nodeAffinity¶
Ensure that tolerations and nodeAffinity are at the expected indentation! These are YAML configurations passed directly to Kubernetes, and the base .tolerations and .deployment.skaha.nodeAffinity values apply to the skaha API only, whereas the .deployment.skaha.sessions.tolerations and .deployment.skaha.sessions.nodeAffinity apply to all User Session Pods.
Kueue¶
Skaha leverages Kueue for efficient job queueing and management when properly installed and configured in your cluster. For detailed information on Kueue's features and setup, refer to the Kueue documentation.
Installation¶
https://kueue.sigs.k8s.io/docs/installation/#install-a-released-version
Will install the Kueue Chart, with a default ClusterQueue, and whatever defined LocalQueues were declared in the deployment.skaha.sessions.kueue section:
To determine your cluster's allocatable resources, checkout a small Python utility (requires uv):
https://github.com/opencadc/deployments/tree/main/configs/kueue/kueuer
Then run:
git clone https://github.com/opencadc/deployments.git
cd deployments/configs/kueue/kueuer
# if not using the default ~/.kube/config
export KUBECONFIG=/home/user/.kube/my-config
# 60% of cluster resources
uv run kr cluster resources -f allocatable -s 0.6
# 80% of cluster resources
uv run kr cluster resources -f allocatable -s 0.8
Uninstallation¶
To remove the Skaha application from your cluster:
This command will delete all resources associated with the Skaha release.
License¶
This project is licensed under the MIT License. For more information, refer to the LICENSE file in the repository.
Values Reference¶
skaha¶
A Helm chart to install the Skaha web service of the CANFAR Science Platform
| Chart | AppVersion | Type |
|---|---|---|
| 1.6.0-rc.5 | 1.3.0 | application |
Requirements¶
| Repository | Name | Version |
|---|---|---|
| file://../../utils | utils | ^0.1.0 |
| oci://registry-1.docker.io/bitnamicharts | redis | ^18.19.0 |
Values¶
| Key | Type | Default | Description |
|---|---|---|---|
| autoscaling.enabled | bool | true |
Enable HorizontalPodAutoscaler for skaha-tomcat. Target and scaling behavior are intentionally chart-managed (CPU 65%). |
| autoscaling.maxReplicas | int | 6 |
Maximum number of skaha-tomcat replicas. |
| autoscaling.minReplicas | int | 2 |
Minimum number of skaha-tomcat replicas. |
| deployment.hostname | string | "myhost.example.com" |
Public hostname for the Skaha API. |
| deployment.skaha.apiVersion | string | "v1" |
Skaha API version path segment (for example, v1 -> /skaha/v1/...). |
| deployment.skaha.defaultQuotaGB | string | "10" |
Default user storage quota in GiB for first-time users. |
| deployment.skaha.identityManagerClass | string | "org.opencadc.auth.StandardIdentityManager" |
Java IdentityManager implementation used for authentication. |
| deployment.skaha.image | string | "images.opencadc.org/platform/skaha:1.3.0" |
Container image for the Skaha API service. |
| deployment.skaha.imageCache.refreshSchedule | string | "*/30 * * * *" |
Cron schedule used to refresh cached images. |
| deployment.skaha.imagePullPolicy | string | "Always" |
Image pull policy for the Skaha API container. |
| deployment.skaha.init.image | string | "busybox:1.37.0" |
Init container image used to bootstrap user storage paths. |
| deployment.skaha.init.imagePullPolicy | string | "IfNotPresent" |
Image pull policy for the bootstrap init container. |
| deployment.skaha.posixMapperCacheTTLSeconds | string | "86400" |
TTL in seconds for cached POSIX mapper entries. |
| deployment.skaha.registryHosts | string | "images.canfar.net" |
Space-delimited list of image registry hosts allowed for sessions. |
| deployment.skaha.resources.limits.cpu | string | "2000m" |
CPU limit for the Skaha API container. |
| deployment.skaha.resources.limits.memory | string | "3Gi" |
Memory limit for the Skaha API container. |
| deployment.skaha.resources.requests.cpu | string | "1000m" |
CPU request for the Skaha API container. |
| deployment.skaha.resources.requests.memory | string | "2Gi" |
Memory request for the Skaha API container. |
| deployment.skaha.sessions | object | {"authorization":{"group":{"enabled":false,"uri":""},"permissionsAPI":{"authAPIBaseURL":"","baseURL":"","enabled":false,"method":"","name":"skaha","route":"","type":"route","version":""}},"expirySeconds":"345600","flexResourceRequests":{"headless":{"cpuCores":"1","memoryInGB":"4"}},"headlessPriorityClass":{"create":false,"description":"For high-priority headless jobs. Preempting.","globalDefault":false,"preemptionPolicy":"PreemptLowerPriority","value":2000},"imagePullPolicy":"Always","ingress":{"customResponseHeaders":{},"tls":{}},"initContainerImage":"redis:8.2.2-bookworm","kueue":{"rbac":{"create":false}},"limitRange":{"create":true,"enabled":false},"maxCount":"5","maxEphemeralStorage":"200Gi","minEphemeralStorage":"20Gi","namespace":{"create":false,"name":"skaha-workload"},"nodeLabelSelector":null,"priorityClass":{"create":false,"description":"For high-priority user pods. Preempting.","globalDefault":false,"name":"uber-user-preempt-high","preemptionPolicy":"PreemptLowerPriority","value":2000},"tolerations":[],"userStorage":{"admin":{},"homeDirectory":"home","projectsDirectory":"projects","spec":{},"topLevelDirectory":"/cavern"}} |
@deprecated Prefer deployment.skaha.sessions.authorization or deprecated usersGroup alone. Still honoured when sessions.authorization.group.enabled is false. The IVOA GMS Group URI to verify users against for permission to use the Science Platform. See https://www.ivoa.net/documents/GMS/20220222/REC-GMS-1.0.html#tth_sEc3.2 usersGroup: "ivo://example.org/gms?prototyping-groups/mini-src/platform-users" Group URI for users to ensure priority for their headless jobs. See https://www.ivoa.net/documents/GMS/20220222/REC-GMS-1.0.html#tth_sEc3.2 headlessPriorityGroup: "ivo://example.org/gms?skaha-priority-headless-users" Array of GMS Group URIs allowed to set the logging level. If none set, then nobody can change the log level. See https://www.ivoa.net/documents/GMS/20220222/REC-GMS-1.0.html#tth_sEc3.2 for GMS Group URIs See https://github.com/opencadc/core/tree/main/cadc-log for Logging control loggingGroups: - "ivo://example.org/gms?prototyping-groups/mini-src/platform-users" The Resource ID (URI) of the Service that contains the Posix Mapping information posixMapperResourceID: "ivo://example.org/posix-mapper" URI or URL of the OIDC (IAM) server. Used to validate incoming tokens. oidcURI: https://iam.example.org/ The Resource ID (URI) of the GMS Service. gmsID: ivo://example.org/gms The absolute URL of the IVOA Registry where services are registered registryURL: https://spsrc27.iaa.csic.es/reg This applies to Skaha itself. Meaning, this Pod will be scheduled as described by the nodeAffinity clause. Note the different indentation level compared to the sessions.nodeAffinity. See https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/ nodeAffinity: {} Settings for User Sessions. Sensible defaults supplied, but can be overridden. For units of storage, see https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-memory. |
| deployment.skaha.sessions.authorization.group.enabled | bool | false |
When true, SKAHA_USERS_GROUP is set from uri. Required uri when enabled (Helm validates). The Skaha service enforces mutually exclusive authorization modes at runtime. |
| deployment.skaha.sessions.authorization.permissionsAPI.authAPIBaseURL | string | "" |
Base URL for the SRCNet Auth API used by the permissions client. |
| deployment.skaha.sessions.authorization.permissionsAPI.baseURL | string | "" |
Required when enabled is true (Helm validates). |
| deployment.skaha.sessions.authorization.permissionsAPI.enabled | bool | false |
When true, SKAHA_PERMISSIONS_API_* vars are set from baseURL, authAPIBaseURL, type, route, name, version, and method. Required baseURL and authAPIBaseURL when enabled (Helm validates). The Skaha service enforces mutually exclusive authorization modes at runtime. |
| deployment.skaha.sessions.authorization.permissionsAPI.method | string | "" |
Method of the permissions API. |
| deployment.skaha.sessions.authorization.permissionsAPI.name | string | "skaha" |
Name of the permissions API. |
| deployment.skaha.sessions.authorization.permissionsAPI.route | string | "" |
Route of the permissions API. |
| deployment.skaha.sessions.authorization.permissionsAPI.type | string | "route" |
Type of the permissions API. |
| deployment.skaha.sessions.authorization.permissionsAPI.version | string | "" |
Version of the permissions API. |
| deployment.skaha.sessions.expirySeconds | string | "345600" |
Session lifetime in seconds before expiry and shutdown. |
| deployment.skaha.sessions.flexResourceRequests.headless.cpuCores | string | "1" |
Default CPU request (cores) for flex headless sessions. |
| deployment.skaha.sessions.flexResourceRequests.headless.memoryInGB | string | "4" |
Default memory request (GiB) for flex headless sessions. |
| deployment.skaha.sessions.headlessPriorityClass | object | {"create":false,"description":"For high-priority headless jobs. Preempting.","globalDefault":false,"preemptionPolicy":"PreemptLowerPriority","value":2000} |
Effective headless PriorityClass configuration (merged with legacy headlessPriorityClass). |
| deployment.skaha.sessions.imagePullPolicy | string | "Always" |
Image pull policy applied to all user session containers. |
| deployment.skaha.sessions.ingress.customResponseHeaders | object | {} |
Custom response headers added to user-session ingress responses. |
| deployment.skaha.sessions.ingress.tls | object | {} |
TLS configuration for the user-session Traefik IngressRoute. |
| deployment.skaha.sessions.initContainerImage | string | "redis:8.2.2-bookworm" |
Image used by the session init container that manages POSIX data. |
| deployment.skaha.sessions.kueue | object | {"rbac":{"create":false}} |
Per-session-type Kueue configuration. |
| deployment.skaha.sessions.limitRange.create | bool | true |
When true together with enabled, the chart creates the LimitRange <release>-session-limit-range in the workload namespace from spec below. When false, do not create one here; ensure the namespace has a LimitRange Skaha can use (Skaha uses the first LimitRange returned; the name is mostly irrelevant). |
| deployment.skaha.sessions.limitRange.enabled | bool | false |
When true, set SKAHA_SESSION_LIMIT_RANGE_ENABLED on the Skaha deployment so it loads the first LimitRange in the workload namespace (name is mostly irrelevant). Also gates this chart's LimitRange Role/RoleBinding (rbac.create). Must also be true (with create) for the chart to render the LimitRange manifest. |
| deployment.skaha.sessions.maxCount | string | "5" |
Maximum number of active sessions allowed per user. |
| deployment.skaha.sessions.maxEphemeralStorage | string | "200Gi" |
Maximum ephemeral storage limit for sessions (non-desktop). |
| deployment.skaha.sessions.minEphemeralStorage | string | "20Gi" |
Initial ephemeral storage request for new sessions (non-desktop). |
| deployment.skaha.sessions.nodeLabelSelector | string | nil |
Node label selector used when discovering schedulable worker nodes. |
| deployment.skaha.sessions.priorityClass | object | {"create":false,"description":"For high-priority user pods. Preempting.","globalDefault":false,"name":"uber-user-preempt-high","preemptionPolicy":"PreemptLowerPriority","value":2000} |
PriorityClass assigned to the Skaha API Pod. |
| deployment.skaha.sessions.tolerations | list | [] |
Tolerations applied to user session Pods. |
| deployment.skaha.sessions.userStorage.homeDirectory | string | "home" |
Relative path under topLevelDirectory for user home directories. |
| deployment.skaha.sessions.userStorage.projectsDirectory | string | "projects" |
Relative path under topLevelDirectory for shared projects storage. |
| deployment.skaha.sessions.userStorage.topLevelDirectory | string | "/cavern" |
Absolute mount path containing user home and projects directories. |
| experimentalFeatures.enabled | bool | false |
Enable processing of experimental feature gates. |
| ingress.enabled | bool | true |
Enable ingress routing for the Skaha API. |
| ingress.path | string | "/skaha" |
Ingress path prefix routed to the Skaha API Service. |
| kubernetesClusterDomain | string | "cluster.local" |
Kubernetes DNS domain used when building internal service hostnames. |
| metricsBackend.enabled | bool | false |
When true, install Kueue-read ClusterRole/Binding first (Helm kind order), then Metrics Service and Deployment. Applies fail if cluster RBAC cannot be created (for example forbidden). |
| metricsBackend.env | object | {} |
Map of environment variables for the Metrics container (typically METRICS_*). GitOps should supply the full map per environment. |
| metricsBackend.image.pullPolicy | string | "IfNotPresent" |
imagePullPolicy for the Metrics API container. |
| metricsBackend.image.repository | string | "images.opencadc.org/platform/metrics" |
Metrics container image repository. |
| metricsBackend.image.tag | string | "v0.1.5" |
Metrics container image tag. |
| metricsBackend.ingress.enabled | bool | false |
When true and top-level ingress.enabled is true, add a path on the same host routing to the Metrics Service. |
| metricsBackend.ingress.path | string | "/metrics" |
Ingress path prefix for the Metrics API (Traefik). |
| metricsBackend.rbac.enabled | bool | false |
When true, create metricsBackend Kueue-read ClusterRole/ClusterRoleBinding. Set false to disable cluster-scoped RBAC while keeping the metrics workload enabled. |
| metricsBackend.redis.enabled | bool | true |
When true, set METRICS_REDIS_URL to this release's Bitnami Redis master Service ( |
| metricsBackend.replicaCount | int | 1 |
Fixed replica count for the Metrics API (no HPA in this chart version). |
| metricsBackend.resources | object | {"limits":{"cpu":"1","memory":"1Gi"},"requests":{"cpu":"100m","memory":"256Mi"}} |
Resource requests and limits for the Metrics API container. |
| metricsBackend.revisionHistoryLimit | int | 3 |
revisionHistoryLimit for the Metrics API Deployment. |
| metricsBackend.test.enabled | bool | true |
Run helm test hook that retries /healthz until success (requires metricsBackend.enabled). |
| metricsBackend.test.image | string | "busybox:1.37.0" |
Image for the helm test hook Pod. |
| metricsBackend.test.maxWaitSeconds | int | 180 |
Maximum seconds to wait for Metrics /healthz (should exceed startupProbe worst case plus scheduling margin). |
| podSecurityContext | object | {} |
|
| rbac.clusterRole.create | bool | false |
|
| rbac.create | bool | true |
|
| redis.architecture | string | "standalone" |
Redis deployment architecture. |
| redis.auth.enabled | bool | false |
Enable Redis authentication. |
| redis.image.repository | string | "redis" |
Redis image repository used by the bundled chart dependency. |
| redis.image.tag | string | "8.2.2-bookworm" |
Redis image tag used by the bundled chart dependency. |
| redis.master.containerSecurityContext.allowPrivilegeEscalation | bool | false |
Disallow privilege escalation in the Redis master container. |
| redis.master.containerSecurityContext.capabilities.drop | list | ["ALL"] |
Linux capabilities dropped from the Redis master container. |
| redis.master.containerSecurityContext.readOnlyRootFilesystem | bool | true |
Mount Redis master root filesystem as read-only. |
| redis.master.containerSecurityContext.runAsGroup | int | 1001 |
Group ID for the Redis master container. |
| redis.master.containerSecurityContext.runAsNonRoot | bool | true |
Require Redis master to run as a non-root user. |
| redis.master.containerSecurityContext.runAsUser | int | 1001 |
User ID for the Redis master container. |
| redis.master.containerSecurityContext.seccompProfile.type | string | "RuntimeDefault" |
Seccomp profile type for Redis master. |
| redis.master.persistence.enabled | bool | false |
Enable persistence for the Redis master StatefulSet. |
| replicaCount | int | 1 |
Number of skaha-tomcat replicas when autoscaling is disabled. |
| secrets | string | nil |
|
| securityContext | object | {} |
Optional Pod-level security context for the Skaha API Deployment. |
| service.port | int | 8080 |
Service port exposed for the Skaha API Service. |
| serviceAccount | object | {"annotations":{},"automount":true,"create":true,"name":""} |
ServiceAccount used by the Skaha API Pod. |
| tolerations | list | [] |
Tolerations applied to the Skaha API Pod. |
metricsBackend install ordering¶
When metricsBackend.enabled is true, the chart emits ClusterRole, ClusterRoleBinding, Service, and Deployment for metrics. Helm applies manifest groups in a deterministic kind order so RBAC objects are reconciled before typical namespaced workload kinds. If the API server rejects creating or updating those cluster-scoped RBAC rules (for example the caller lacks permission), the release fails instead of only rolling out a broken metrics Deployment. helm test (optional) still targets the running Service after install; it does not replace RBAC admission checks.
If metricsBackend.enabled=true and metricsBackend.rbac.enabled=false, this chart will not create the metrics ClusterRole/ClusterRoleBinding. In that mode, the deployer is responsible for ensuring the Skaha ServiceAccount (deployment.skaha.serviceAccountName) already has get/list permissions on the Kueue ClusterQueue API before installation.