diff --git a/helm/applications/science-portal/config/org.opencadc.science-portal.properties b/helm/applications/science-portal/config/org.opencadc.science-portal.properties index 0fbd503..867a46f 100644 --- a/helm/applications/science-portal/config/org.opencadc.science-portal.properties +++ b/helm/applications/science-portal/config/org.opencadc.science-portal.properties @@ -4,9 +4,9 @@ org.opencadc.science-portal.logoURL = {{ .Values.deployment.sciencePortal.logoUR org.opencadc.science-portal.themeName = {{ .Values.deployment.sciencePortal.themeName | required "Please set the deployment.sciencePortal.themeName to either src or canfar" }} {{- if empty .Values.deployment.sciencePortal.tabLabels }} - {{ required ".Values.deployment.sciencePortal.tabLabels is missing or empty" .Values.deployment.sciencePortal.tabLabels }} +{{ required ".Values.deployment.sciencePortal.tabLabels is missing or empty" .Values.deployment.sciencePortal.tabLabels }} {{- else }} - org.opencadc.science-portal.tabLabels = {{ .Values.deployment.sciencePortal.tabLabels | join "," }} +org.opencadc.science-portal.tabLabels = {{ .Values.deployment.sciencePortal.tabLabels | join "," }} {{- end }} {{- with .Values.deployment.sciencePortal.oidc }} @@ -31,7 +31,13 @@ org.opencadc.science-portal.tokenCache.url = redis://{{ $.Release.Name }}-redis- {{ with .Values.experimentalFeatures }} {{- with .storageHomePanel }} {{- if .enabled }} +# This feature is NOT namespaced with experimental as it's grandfathered. org.opencadc.science-portal.storageXmlInfoUrl = {{ .url }} {{- end }} {{- end }} +{{- with .slider }} +{{- if .enabled }} +org.opencadc.science-portal.experimental.slider.enabled = true +{{- end }} +{{- end }} {{- end }} diff --git a/helm/applications/science-portal/values.yaml b/helm/applications/science-portal/values.yaml index 5aa6bc4..848cb39 100644 --- a/helm/applications/science-portal/values.yaml +++ b/helm/applications/science-portal/values.yaml @@ -139,6 +139,9 @@ tolerations: [] # For the token caching redis: + image: + repository: redis + tag: 8.2.2-bookworm architecture: 'standalone' auth: enabled: false diff --git a/helm/applications/skaha/CHANGELOG.md b/helm/applications/skaha/CHANGELOG.md index c150561..fc47b2e 100644 --- a/helm/applications/skaha/CHANGELOG.md +++ b/helm/applications/skaha/CHANGELOG.md @@ -1,4 +1,8 @@ -# CHANGELOG for Skaha User Session API (Chart 1.0.5) +# CHANGELOG for Skaha User Session API (Chart 1.1.0) + +## 2025.09.29 (1.1.0) +- Bump Skaha API image to `1.1.0` +- Feature Gate to support `LimitRange` objects to enforce resource limits on User Sessions ## 2025.09.29 (1.0.5) - Fix for status reporting in User Sessions diff --git a/helm/applications/skaha/Chart.yaml b/helm/applications/skaha/Chart.yaml index 9fd86c5..bbfa38f 100644 --- a/helm/applications/skaha/Chart.yaml +++ b/helm/applications/skaha/Chart.yaml @@ -1,6 +1,7 @@ apiVersion: v2 name: skaha description: "A Helm chart to install the Skaha web service of the CANFAR Science Platform" +icon: https://www.canfar.net/css/images/logo.png # A chart can be either an 'application' or a 'library' chart. # @@ -15,13 +16,13 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.0.5 +version: 1.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.0.4" +appVersion: "1.1.0" dependencies: - name: "redis" diff --git a/helm/applications/skaha/README.md b/helm/applications/skaha/README.md index c2caa8b..bc03d05 100644 --- a/helm/applications/skaha/README.md +++ b/helm/applications/skaha/README.md @@ -95,6 +95,8 @@ The following table lists the configurable parameters for the Skaha Helm chart: | `deployment.skaha.sessions.gpuEnabled` | Enable GPU support for User Sessions. Defaults to `false` | `false` | | `deployment.skaha.sessions.nodeAffinity` | Kubernetes Node affinity for the Skaha User Session Pods | `{}` | | `deployment.skaha.sessions.tolerations` | Array of tolerations to pass to Kubernetes for fine-grained Node targeting of the `skaha` User Sessions | `[]` | +| `experimentalFeatures.enabled` | Enable experimental features in Skaha. | `false` | +| `experimentalFeatures.sessionLimitRange` | Kubernete LimitRange for User Sessions to enforce minimum and maximum resource usage. Only applied if `experimentalFeatures.enabled` and `sessionLimitRange.enabled` are `true`. | `{ enabled: false }` | | `secrets` | List of secrets to be mounted in the Skaha API defined as objects (i.e `secretName: {cert.pem: xxx}`) | `[]` | | `storage.service.spec` | Storage class specification for the Skaha API. Can be `persistentVolumeClaim` or a dynamic instantiation like `hostPath`. See [Volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/). | `{}` | | `redis` | [Redis sub-chart configuration](https://github.com/bitnami/charts/tree/main/bitnami/redis) for Skaha's caching of Harbor Docker image metadata. | See [`values.yaml`](https://github.com/bitnami/charts/blob/main/bitnami/redis/values.yaml) for available configuration values. | diff --git a/helm/applications/skaha/skaha-config/k8s-resources.json b/helm/applications/skaha/skaha-config/k8s-resources.json index 77f27ae..dab7a58 100644 --- a/helm/applications/skaha/skaha-config/k8s-resources.json +++ b/helm/applications/skaha/skaha-config/k8s-resources.json @@ -3,7 +3,6 @@ "default": 1, "defaultRequest": 1, "defaultLimit": 8, - "defaultHeadless": 1, "options": [ 1, 2, @@ -27,7 +26,6 @@ "default": 1, "defaultRequest": 4, "defaultLimit": 32, - "defaultHeadless": 4, "options": [ 1, 2, @@ -90,5 +88,6 @@ 27, 28 ] - } + }, + "maxInteractiveSessions": {{ .Values.deployment.skaha.sessions.maxCount }} } diff --git a/helm/applications/skaha/templates/NOTES.txt b/helm/applications/skaha/templates/NOTES.txt index b334749..19b5d77 100644 --- a/helm/applications/skaha/templates/NOTES.txt +++ b/helm/applications/skaha/templates/NOTES.txt @@ -31,3 +31,10 @@ If user Jobs remain Pending: - Ensure LocalQueue exists in {{ .Values.skahaWorkload.namespace }} and references your configured ClusterQueue. - Verify ClusterQueue quotas are sufficient. - Confirm priority classes referenced by sessions exist or are created. + +Experimental Features Configured: +{{- if and .Values.experimentalFeatures .Values.experimentalFeatures.enabled }} +{{ include "skaha.experimentalFeatureGates" $ }} +{{- else }} +None +{{- end }} diff --git a/helm/applications/skaha/templates/_helpers.tpl b/helm/applications/skaha/templates/_helpers.tpl index dc05d32..0b2ea79 100644 --- a/helm/applications/skaha/templates/_helpers.tpl +++ b/helm/applications/skaha/templates/_helpers.tpl @@ -42,6 +42,41 @@ app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} +{{/* +Obtain a comma-delimited string of Experimental Features and a flag to set if any are enabled. +*/}} +{{- define "skaha.experimentalFeatureGates" -}} +{{- $features := "" -}} +{{- $featureEnabled := false -}} +{{- with .Values.experimentalFeatures }} +{{- if .enabled }} +{{- range $feature, $map := . }} + +{{- if eq $feature "enabled" -}} +{{- continue -}} +{{- end -}} + +{{- if ne $feature "" }} +{{- $thisMap := $map | default dict }} + +{{- if or (not (hasKey $thisMap "enabled")) (not (kindIs "bool" $thisMap.enabled)) -}} +{{- fail ( printf "Feature gate '%s' must have 'enabled' (false | true) key" $feature ) -}} +{{- end }} + +{{- if eq $features "" -}} +{{- $features = printf "%s=%t" $feature $thisMap.enabled -}} +{{- else -}} +{{- $features = printf "%s,%s=%t" $features $feature $thisMap.enabled -}} +{{- end }} +{{- end }} + +{{- end }} +{{- end }} +{{- end }} +{{- printf "%s" $features -}} +{{- end }} +*/}} + {{/* Selector labels */}} @@ -85,7 +120,7 @@ The init containers for the launch scripts. drop: - ALL - name: init-users-groups - image: {{ $.Values.deployment.skaha.sessions.initContainerImage | default "redis:7.4.2-alpine3.21" }} + image: {{ $.Values.deployment.skaha.sessions.initContainerImage | default "redis:8.2.2-bookworm" }} command: ["/init-users-groups/init-users-groups.sh"] env: - name: HOME diff --git a/helm/applications/skaha/templates/limit-range.yaml b/helm/applications/skaha/templates/limit-range.yaml new file mode 100644 index 0000000..76ed965 --- /dev/null +++ b/helm/applications/skaha/templates/limit-range.yaml @@ -0,0 +1,60 @@ +{{- with .Values.experimentalFeatures }} +{{- if eq .enabled true }} +{{- with .sessionLimitRange }} +{{- if eq .enabled true }} +--- +apiVersion: v1 +kind: LimitRange +metadata: + name: {{ $.Release.Name }}-session-limit-range + namespace: {{ $.Values.skahaWorkload.namespace }} +spec: +{{- with .limitSpec }} + limits: + - type: Container +{{- if .max }} + max: +{{ toYaml .max | indent 8 }} +{{- end }} +{{- if .default }} + default: +{{ toYaml .default | indent 8 }} +{{- end }} +{{- if .defaultRequest }} + defaultRequest: +{{ toYaml .defaultRequest | indent 8 }} +{{- end }} +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ $.Release.Name }}-session-limit-range-role + namespace: {{ $.Values.skahaWorkload.namespace }} +rules: +- apiGroups: + - "" + resources: + - limitranges + verbs: + - get + - list + - status +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ $.Release.Name }}-session-limit-range + namespace: {{ $.Values.skahaWorkload.namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ $.Release.Name }}-session-limit-range-role +subjects: +- kind: ServiceAccount + name: {{ $.Values.deployment.skaha.serviceAccountName | required ".Values.deployment.skaha.serviceAccountName value is required" }} + namespace: {{ $.Release.Namespace }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/helm/applications/skaha/templates/skaha-config-configmap.yaml b/helm/applications/skaha/templates/skaha-config-configmap.yaml index 7f65f62..91d7d42 100644 --- a/helm/applications/skaha/templates/skaha-config-configmap.yaml +++ b/helm/applications/skaha/templates/skaha-config-configmap.yaml @@ -21,6 +21,6 @@ data: {{ base $path }}: | {{- tpl ($.Files.Get $path) $currContext | nindent 4 }} {{ end }} -{{ ($.Files.Glob "skaha-config/*.json").AsConfig | indent 2 }} +{{ tpl ($.Files.Glob "skaha-config/*.json").AsConfig . | indent 2 }} {{- include "utils.extraConfig" (dict "extraConfigData" .Values.deployment.skaha.extraConfigData) -}} {{- (.Files.Glob "image-cache/*").AsConfig | nindent 2 }} diff --git a/helm/applications/skaha/templates/skaha-tomcat-deployment.yaml b/helm/applications/skaha/templates/skaha-tomcat-deployment.yaml index 0c44d47..ee5994c 100644 --- a/helm/applications/skaha/templates/skaha-tomcat-deployment.yaml +++ b/helm/applications/skaha/templates/skaha-tomcat-deployment.yaml @@ -88,6 +88,8 @@ spec: value: "{{ .Release.Name }}-redis-master.{{ .Release.Namespace }}.svc.{{ .Values.kubernetesClusterDomain }}" - name: REDIS_PORT value: "6379" + - name: SKAHA_EXPERIMENTAL_FEATURE_GATES + value: "{{ include "skaha.experimentalFeatureGates" $ }}" {{- with .Values.deployment.skaha.extraEnv }} {{- toYaml . | nindent 8 }} {{- end }} diff --git a/helm/applications/skaha/values.yaml b/helm/applications/skaha/values.yaml index f046191..1b7cd07 100644 --- a/helm/applications/skaha/values.yaml +++ b/helm/applications/skaha/values.yaml @@ -15,7 +15,7 @@ skahaWorkload: deployment: hostname: myhost.example.com # Change this! skaha: - image: images.opencadc.org/platform/skaha:1.0.4 + image: images.opencadc.org/platform/skaha:1.1.0 imagePullPolicy: Always # Cron string for the image caching cron job schedule. Defaults to every half hour. @@ -97,10 +97,11 @@ deployment: imagePullPolicy: Always # Optionally configure the initContainer image for Redis. Useful for those not able to reach docker.io - # Defaults to redis-7.4.2-alpine3.21. + # Defaults to redis:8.2.2-bookworm. # Example: # initContainerImage: "private-image-repo/project/my-own-redis:1.0" # initContainerImage: + initContainerImage: "redis:8.2.2-bookworm" # Optionally configure the Kueue system to handle large workloads. Configurable per session type (e.g. desktop, notebook, etc.). # Leaving this empty will default to submitting Jobs to the base Kubernetes system. @@ -283,6 +284,35 @@ ingress: enabled: true path: /skaha +# Experimental features that can be enabled. These represent features that are not released and confined behind feature flags. +experimentalFeatures: + enabled: false + + # YAML to pass to a LimitRange object called "{{ .Release.Name }}-session-limit-range" in the workload Namespace to define the resource limits. + # These limits will be applied to Container objects (User Sessions). + # **NOTE**: This requires the experimentalFeatures.enabled to be true as well as the sessionLimitRange.enabled to be true. + # **NOTE**: The min clause is ignored due to hard-coded resources for Desktop and Firefly sessions. The `defaultRequest` is used instead for these session types. + # See https://kubernetes.io/docs/concepts/policy/limit-range/ + # + # Example: + # sessionLimitRange: + # enabled: true + # limitSpec: + # max: + # memory: "96Gi" + # cpu: "12" + # "nvidia.com/gpu": "4" + # default: # actually refers to default limit + # memory: "32Gi" + # cpu: "8" + # "nvidia.com/gpu": "1" + # defaultRequest: + # memory: "4Gi" + # cpu: "1" + sessionLimitRange: + enabled: false + limitSpec: {} + secrets: # Uncomment to enable local or self-signed CA certificates for your domain to be trusted. # skaha-cacert-secret: @@ -295,10 +325,13 @@ storage: # YAML for service mounted storage. # Example is the persistentVolumeClaim below. # persistentVolumeClaim: - # claimName: skaha-pvc\ + # claimName: skaha-pvc # For caching images from the Image Repository and for the writing the POSIX Users and Groups to be shared with Job files redis: + image: + repository: redis + tag: 8.2.2-bookworm architecture: 'standalone' auth: enabled: false diff --git a/helm/applications/storage-ui/values.yaml b/helm/applications/storage-ui/values.yaml index f3ed7c8..9f2630a 100644 --- a/helm/applications/storage-ui/values.yaml +++ b/helm/applications/storage-ui/values.yaml @@ -140,6 +140,9 @@ tolerations: [] # For the token caching redis: + image: + repository: redis + tag: 8.2.2-bookworm architecture: 'standalone' auth: enabled: false