Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions charts/platforma/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ apiVersion: v2
name: platforma
description: Platforma - Bioinformatics platform for Kubernetes
type: application
version: 4.1.5
appVersion: "4.1.5"
version: 4.2.2
appVersion: "4.2.2"
kubeVersion: ">=1.31.0-0"

keywords:
Expand Down
14 changes: 13 additions & 1 deletion charts/platforma/files/job-script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@
set -e
set -u

# Prepend PL_JOB_PATH to PATH if set
# Prepend GPU driver paths (set by the chart when the job runs on a GPU node).
# Done at runtime, not via k8s env, because k8s env can't reference $(PATH) /
# $(LD_LIBRARY_PATH) from the container image — setting them statically would
# wipe image-provided entries (e.g. conda's /opt/conda/bin).
if [ -n "${PL_GPU_BIN_PATH:-}" ]; then
export PATH="${PL_GPU_BIN_PATH}:${PATH}"
fi
if [ -n "${PL_GPU_LIB_PATH:-}" ]; then
export LD_LIBRARY_PATH="${PL_GPU_LIB_PATH}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
fi

# Prepend PL_JOB_PATH to PATH if set. Applied after PL_GPU_BIN_PATH so
# runenv-provided entries (e.g. a conda env's bin) win over GPU paths.
if [ -n "${PL_JOB_PATH:-}" ]; then
export PATH="${PL_JOB_PATH}:${PATH}"
fi
Expand Down
11 changes: 11 additions & 0 deletions charts/platforma/templates/configmap-job-template-kueue.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ data:
name: << .JobID >>
labels:
platforma.bio/job-id: << .JobID >>
platforma.bio/resource-id: << .ResourceID >>
app.kubernetes.io/managed-by: platforma
app.kubernetes.io/instance: {{ .Release.Name }}
# Queue label for Kueue - maps Platforma queue to Kueue LocalQueue
Expand Down Expand Up @@ -52,6 +53,7 @@ data:
name: << .JobID >>
labels:
platforma.bio/job-id: << .JobID >>
platforma.bio/resource-id: << .ResourceID >>
app.kubernetes.io/managed-by: platforma
spec:
backoffLimit: 0 # AppWrapper handles retries
Expand All @@ -62,6 +64,7 @@ data:
cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
labels:
platforma.bio/job-id: << .JobID >>
platforma.bio/resource-id: << .ResourceID >>
app.kubernetes.io/managed-by: platforma
spec:
serviceAccountName: {{ include "platforma.jobServiceAccountName" . }}
Expand Down Expand Up @@ -160,6 +163,14 @@ data:
value: "all"
- name: NVIDIA_DRIVER_CAPABILITIES
value: "compute,utility"
# These are marker vars consumed by job_script.sh,
# which prepends them to PATH/LD_LIBRARY_PATH at
# container start — preserving image-provided
# entries that a static k8s env value would wipe.
- name: PL_GPU_BIN_PATH
value: "/usr/local/nvidia/bin"
- name: PL_GPU_LIB_PATH
value: "/usr/local/nvidia/lib64:/usr/local/nvidia/lib"
- name: PLATFORMA_GPU_MEMORY
value: "<< .Resources.GPUMemory >>"
<<- end >>
Expand Down
35 changes: 34 additions & 1 deletion charts/platforma/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,26 @@ spec:
{{- if .Values.kueue.pools.gpu.enabled }}
- "--runner-gpu-available=enabled"
{{- if not (and .Values.kueue.maxJobResources .Values.kueue.maxJobResources.gpuMemory) }}
{{- fail "ERROR: kueue.maxJobResources.gpuMemory is required when kueue.pools.gpu.enabled=true.\nSet it to the largest VRAM available on a single GPU node in your cluster (e.g. 24Gi, 80Gi, 192Gi)." }}
{{- fail "ERROR: kueue.maxJobResources.gpuMemory is required when kueue.pools.gpu.enabled=true.\nSet it to the largest VRAM available on a single GPU node in your cluster (e.g. 24Gi, 80Gi)." }}
{{- end }}
- "--runner-max-gpu-memory-request={{ .Values.kueue.maxJobResources.gpuMemory }}"
# GPU jobs run on a separate node pool; ceiling their CPU/RAM to the largest GPU
# node's allocatable so oversized requests land there instead of staying Pending.
{{- if not .Values.kueue.maxJobResources.gpuCpu }}
{{- fail "ERROR: kueue.maxJobResources.gpuCpu is required when kueue.pools.gpu.enabled=true.\nSet it to the allocatable CPU cores of the largest GPU node in your cluster." }}
{{- end }}
{{- if not .Values.kueue.maxJobResources.gpuRam }}
{{- fail "ERROR: kueue.maxJobResources.gpuRam is required when kueue.pools.gpu.enabled=true.\nSet it to the allocatable RAM of the largest GPU node in your cluster (e.g. 128Gi, 192Gi)." }}
{{- end }}
- "--k8s-gpu-max-cpu-request={{ .Values.kueue.maxJobResources.gpuCpu }}"
- "--k8s-gpu-max-ram-request={{ .Values.kueue.maxJobResources.gpuRam }}"
{{- else }}
- "--runner-gpu-available=disabled"
{{- end }}
# OOM retries are off by default; set kueue.oomRetry=true to enable them.
{{- if .Values.kueue.oomRetry }}
- "--k8s-oom-retry"
{{- end }}
# Queue runners (hardcoded — 4 fixed queues, always K8s backend)
- "--queue-runner=ui-tasks:k8s"
- "--queue-runner=light:k8s"
Expand Down Expand Up @@ -273,6 +287,9 @@ spec:
{{- if .Values.auth.sso.prompt }}
- "--sso-idp-prompt={{ .Values.auth.sso.prompt }}"
{{- end }}
{{- if .Values.auth.sso.accessType }}
- "--sso-idp-access-type={{ .Values.auth.sso.accessType }}"
{{- end }}
{{- if .Values.auth.sso.userIdClaim }}
- "--sso-idp-user-id-claim={{ .Values.auth.sso.userIdClaim }}"
{{- end }}
Expand All @@ -286,6 +303,9 @@ spec:
{{- if .Values.masterSecret.secretName }}
- "--master-secret-file={{ include "platforma.path.secrets" . }}/master-secret/{{ .Values.masterSecret.secretKey }}"
{{- end }}
{{- if .Values.auth.sso.clientSecret.secretName }}
- "--sso-idp-client-secret-file={{ include "platforma.path.secrets" . }}/sso-client-secret/{{ .Values.auth.sso.clientSecret.secretKey }}"
{{- end }}
# Disable default host data library (exposes entire pod filesystem)
- "--no-host-data-library"
# Data library sources
Expand Down Expand Up @@ -481,6 +501,11 @@ spec:
mountPath: {{ include "platforma.path.secrets" . }}/master-secret
readOnly: true
{{- end }}
{{- if .Values.auth.sso.clientSecret.secretName }}
- name: sso-client-secret
mountPath: {{ include "platforma.path.secrets" . }}/sso-client-secret
readOnly: true
{{- end }}
{{- range .Values.dataSources }}
{{- if eq .type "pvc" }}
- name: datasource-{{ .name }}
Expand Down Expand Up @@ -540,6 +565,14 @@ spec:
- key: {{ .Values.masterSecret.secretKey }}
path: {{ .Values.masterSecret.secretKey }}
{{- end }}
{{- if .Values.auth.sso.clientSecret.secretName }}
- name: sso-client-secret
secret:
secretName: {{ .Values.auth.sso.clientSecret.secretName }}
items:
- key: {{ .Values.auth.sso.clientSecret.secretKey }}
path: {{ .Values.auth.sso.clientSecret.secretKey }}
{{- end }}
{{- range .Values.dataSources }}
{{- if eq .type "pvc" }}
- name: datasource-{{ .name }}
Expand Down
32 changes: 24 additions & 8 deletions charts/platforma/templates/kueue-clusterqueues.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,31 @@ spec:
{{- if .Values.kueue.provisioningRequest.enabled }}
admissionChecksStrategy:
admissionChecks:
# Scope ProvisioningRequest check to the CPU-only batch flavor.
# GPU jobs skip ProvReq because best-effort-atomic-scale-up's strict
# capacity planner often refuses GPU scale-ups that a plain MIG resize
# would satisfy (per (machine-type, zone) inventory variance), and
# atomic reservation is unnecessary for single-pod GPU blocks. Keep
# ProvReq on the CPU flavor where multi-pod batch atomicity helps.
- name: {{ include "platforma.kueue.admissionCheckName" . }}
onFlavors:
- {{ include "platforma.kueue.clusterResourceName" . }}-batch-flavor
{{- end }}
preemption:
reclaimWithinCohort: Never # Jobs not retryable, never preempt
withinClusterQueue: Never # No preemption within batch queue
resourceGroups:
{{- if .Values.kueue.pools.gpu.enabled }}
# Flavor declaration order matters: Kueue tries flavors top-down and
# assigns the first one whose quota fits the workload. batch-flavor
# is listed FIRST so CPU-only jobs land there and go through the
# ProvisioningRequest AdmissionCheck (admissionChecksStrategy above).
# If gpu-flavor came first, CPU-only jobs requesting < gpu.cpu/memory
# would silently be assigned to gpu-flavor and bypass ProvReq (the
# check is scoped onFlavors=[batch-flavor]), so multi-pod batch
# atomicity would only hold while gpu-flavor was fully saturated.
- coveredResources: ["cpu", "memory", "nvidia.com/gpu"]
flavors:
- name: {{ include "platforma.kueue.clusterResourceName" . }}-gpu-flavor
resources:
- name: cpu
nominalQuota: {{ .Values.kueue.dedicated.resources.gpu.cpu | quote }}
- name: memory
nominalQuota: {{ .Values.kueue.dedicated.resources.gpu.memory | quote }}
- name: "nvidia.com/gpu"
nominalQuota: {{ .Values.kueue.dedicated.resources.gpu.gpu | quote }}
- name: {{ include "platforma.kueue.clusterResourceName" . }}-batch-flavor
resources:
- name: cpu
Expand All @@ -81,6 +89,14 @@ spec:
borrowingLimit: {{ .Values.kueue.dedicated.resources.ui.memory | quote }}
- name: "nvidia.com/gpu"
nominalQuota: "0"
- name: {{ include "platforma.kueue.clusterResourceName" . }}-gpu-flavor
resources:
- name: cpu
nominalQuota: {{ .Values.kueue.dedicated.resources.gpu.cpu | quote }}
- name: memory
nominalQuota: {{ .Values.kueue.dedicated.resources.gpu.memory | quote }}
- name: "nvidia.com/gpu"
nominalQuota: {{ .Values.kueue.dedicated.resources.gpu.gpu | quote }}
{{- else }}
- coveredResources: ["cpu", "memory"]
flavors:
Expand Down
10 changes: 9 additions & 1 deletion charts/platforma/templates/nvidia-device-plugin.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
{{- if .Values.kueue.pools.gpu.enabled }}
{{- if and .Values.kueue.pools.gpu.enabled (eq .Values.kueue.mode "dedicated") .Values.kueue.dedicated.createClusterResources }}
# =============================================================================
# NVIDIA Device Plugin DaemonSet
# =============================================================================
# Exposes nvidia.com/gpu resources on GPU nodes so the K8s scheduler can
# assign GPU workloads. Only runs on nodes with NVIDIA GPUs.
#
# Gated on the same condition as the cluster-scoped Kueue resources
# (ClusterQueues, ResourceFlavors): this DaemonSet and its cluster-scoped RBAC
# are cluster-wide infrastructure, deployed once by the install that owns the
# Kueue cohort (dedicated mode + createClusterResources). Shared-mode and
# secondary installs still set kueue.pools.gpu.enabled=true to route GPU jobs
# and enable the runner GPU flag, but must NOT re-deploy these cluster-scoped
# objects — two releases doing so collide on the identical resource names.
# Based on: https://github.com/NVIDIA/k8s-device-plugin v0.17.0
#
# Startup taint protocol:
Expand Down
Loading