Skip to content
Merged
16 changes: 2 additions & 14 deletions .github/workflows/lint.yaml
Comment thread
pmeier marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,10 @@ jobs:
- name: Lint chart
run: helm lint chart/

- name: Template chart (NebariApp disabled)
run: helm template test chart/ --set nebariapp.enabled=false

- name: Template chart (NebariApp enabled)
run: |
helm template test chart/ \
--set nebariapp.enabled=true \
--set nebariapp.hostname=test.example.com \
--set nebariapp.serve.enabled=true \
--set nebariapp.serve.hostname=test.example.com \
--set nebariapp.dashboard.enabled=true \
--set nebariapp.dashboard.hostname=dashboard.example.com

- name: Template chart (NebariApp + auth enabled)
run: |
helm template test chart/ \
--set nebariapp.enabled=true \
--set nebariapp.hostname=test.example.com \
--set nebariapp.dashboard.enabled=true \
--set nebariapp.dashboard.hostname=dashboard.example.com \
--set nebariapp.auth.enabled=true
9 changes: 4 additions & 5 deletions .github/workflows/test-integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,8 @@ jobs:
run: |
helm install rayserve chart/ \
--set kuberay-operator.enabled=false \
--set nebariapp.enabled=true \
--set nebariapp.hostname=rayserve.nebari.local \
--set nebariapp.serve.enabled=true \
--set nebariapp.serve.hostname=rayserve.nebari.local \
--set nebariapp.dashboard.enabled=true \
--set nebariapp.dashboard.hostname=ray-dashboard.nebari.local \
--set head.resources.requests.cpu=500m \
Expand Down Expand Up @@ -178,12 +177,12 @@ jobs:
# "generation is 2, but latest observed generation is 1".
helm upgrade rayserve chart/ \
--set kuberay-operator.enabled=false \
--set nebariapp.enabled=true \
--set nebariapp.hostname=rayserve.nebari.local \
--set nebariapp.serve.enabled=true \
--set nebariapp.serve.hostname=rayserve.nebari.local \
--set nebariapp.serve.auth.enabled=true \
--set nebariapp.dashboard.enabled=true \
--set nebariapp.dashboard.hostname=ray-dashboard.nebari.local \
--set nebariapp.auth.enabled=true \
--set nebariapp.dashboard.auth.enabled=true \
--set head.resources.requests.cpu=500m \
--set head.resources.requests.memory=512Mi \
--set head.resources.limits.cpu=1 \
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/test.yaml
Comment thread
pmeier marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ jobs:
run: |
helm install rayserve chart/ \
--set kuberay-operator.enabled=false \
--set nebariapp.enabled=false \
--set nebariapp.serve.enabled=false \
--set nebariapp.dashboard.enabled=false \
--set head.resources.requests.cpu=500m \
--set head.resources.requests.memory=512Mi \
--set head.resources.limits.cpu=1 \
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Helm
chart/charts/
chart/Chart.lock
Comment thread
pmeier marked this conversation as resolved.

# Dev environment
dev/.cache/
Expand Down
20 changes: 7 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,13 @@ spec:
releaseName: rayserve
values: |
nebariapp:
enabled: true
serve:
enabled: false # Keep serve endpoint internal-only
dashboard:
enabled: true
hostname: ray-dashboard.example.com
auth:
enabled: true
provider: keycloak
provisionClient: true
redirectURI: /oauth2/callback
auth:
enabled: true
destination:
server: https://kubernetes.default.svc
namespace: rayserve
Expand Down Expand Up @@ -195,14 +191,12 @@ Key values in `chart/values.yaml`:

| Value | Default | Description |
|-------|---------|-------------|
| `nebariapp.enabled` | `false` | Create NebariApp resources for routing/TLS/auth |
| `nebariapp.serve.enabled` | `false` | Expose the serve endpoint externally (set `false` to keep internal-only) |
| `nebariapp.hostname` | - | Hostname for the Ray Serve endpoint (required when serve.enabled) |
| `nebariapp.dashboard.enabled` | `true` | Create a separate NebariApp for the Ray Dashboard |
| `nebariapp.dashboard.hostname` | - | Hostname for the Ray Dashboard (required when dashboard enabled) |
| `nebariapp.auth.enabled` | `false` | Enable OIDC authentication via Keycloak |
| `nebariapp.auth.redirectURI` | `/oauth2/callback` | OAuth callback path (Envoy Gateway rejects `/`) |
| `nebariapp.gateway` | `public` | Gateway to use (`public` or `internal`) |
| `nebariapp.serve.hostname` | - | Hostname for the Ray Serve endpoint (required when serve.enabled) |
| `nebariapp.serve.auth.enabled` | `false` | Enable OIDC authentication for the Ray Serve endpoint via Keycloak |
| `nebariapp.dashboard.enabled` | `false` | Create a separate NebariApp for the Ray Dashboard |
| `nebariapp.dashboard.hostname` | - | Hostname for the Ray Dashboard (required when dashboard.enabled) |
| `nebariapp.dashboard.auth.enabled` | `false` | Enable OIDC authentication for the Ray Dashboard endpoint via Keycloak |

### Ray Cluster

Expand Down
9 changes: 9 additions & 0 deletions chart/Chart.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
dependencies:
- name: nebari-app
repository: oci://quay.io/nebari/charts
version: 0.1.1
- name: kuberay-operator
repository: https://ray-project.github.io/kuberay-helm/
version: 1.3.0
digest: sha256:09645189c12af2207c6ee2eb4283da5a5264128fc84f142c82242fa064519f92
generated: "2026-09-10T09:36:11.521304057+02:00"
5 changes: 4 additions & 1 deletion chart/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ apiVersion: v2
name: nebari-rayserve-pack
description: A Nebari Software Pack for Ray Serve
type: application
version: 0.4.1
version: 0.5.0

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've bumped the chart version as part of this PR. LMK if you want to do it in a follow-up instead.

appVersion: "2.43.0"
dependencies:
- name: nebari-app
repository: oci://quay.io/nebari/charts
version: ">=0.1.1"
- name: kuberay-operator
version: 1.3.0
repository: https://ray-project.github.io/kuberay-helm/
Expand Down
32 changes: 20 additions & 12 deletions chart/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,35 @@
The RayService controller manages the Ray cluster and Serve proxy.
Serve is pre-initialized with host 0.0.0.0 on port 8000.

{{- if .Values.nebariapp.enabled }}
Comment thread
pmeier marked this conversation as resolved.
{{ $tplCtx := . }}
{{- range $name, $component := dict
"Ray Serve" (dict
"nebariapp" .Values.nebariapp.serve
"serviceName" (include "nebari-rayserve.serve-service-name" .)
"servicePort" 8000
)
"Ray Dashboard" (dict
"nebariapp" .Values.nebariapp.dashboard
"serviceName" (include "nebari-rayserve.head-service-name" .)
"servicePort" 8265
) -}}
{{- if $component.nebariapp.enabled }}
{{- $nebariapp := include "nebari-app.deepTplJson" (dict "value" (omit $component.nebariapp "enabled") "ctx" $tplCtx) | fromJson }}

NebariApp is ENABLED. The nebari-operator will configure:
{{- if ne (toString (dig "serve" "enabled" true .Values.nebariapp)) "false" }}
- HTTPRoute for Ray Serve: {{ .Values.nebariapp.hostname }}
{{- end }}
{{- if .Values.nebariapp.dashboard.enabled }}
- HTTPRoute for Ray Dashboard: {{ .Values.nebariapp.dashboard.hostname }}
{{- end }}
{{- if .Values.nebariapp.auth.enabled }}
- OIDC authentication via {{ .Values.nebariapp.auth.provider }}
NebariApp for {{ $name }} is ENABLED. The nebari-operator will configure:
- HTTPRoute: {{ $nebariapp.hostname }}
{{- if (and $nebariapp.auth $nebariapp.auth.enabled) }}
- OIDC authentication via {{ $nebariapp.auth.provider | default "keycloak" }}
{{- end }}

{{- else }}

To access locally:

kubectl port-forward svc/{{ include "nebari-rayserve.serve-service-name" . }} 8000:8000 -n {{ .Release.Namespace }}
kubectl port-forward svc/{{ include "nebari-rayserve.head-service-name" . }} 8265:8265 -n {{ .Release.Namespace }}
kubectl port-forward svc/{{ $component.serviceName }} {{ $component.servicePort }}:{{ $component.servicePort }} -n {{ $tplCtx.Release.Namespace }}

{{- end }}
{{- end }}

=== Deploying Models ===

Expand Down
131 changes: 40 additions & 91 deletions chart/templates/nebariapp.yaml
Original file line number Diff line number Diff line change
@@ -1,96 +1,45 @@
{{- if and .Values.nebariapp.enabled (ne (toString (dig "serve" "enabled" true .Values.nebariapp)) "false") }}
{{- if .Values.nebariapp.hostname }}
# NebariApp for Ray Serve endpoint
apiVersion: reconcilers.nebari.dev/v1
kind: NebariApp
metadata:
name: {{ include "nebari-rayserve.fullname" . }}
labels:
{{- include "nebari-rayserve.labels" . | nindent 4 }}
spec:
hostname: {{ .Values.nebariapp.hostname }}
service:
name: {{ .Values.nebariapp.service.name | default (include "nebari-rayserve.serve-service-name" .) }}
port: {{ .Values.nebariapp.service.servePort }}
routing:
routes:
- pathPrefix: /
pathType: PathPrefix
Comment thread
pmeier marked this conversation as resolved.
{{- if .Values.nebariapp.auth.enabled }}
auth:
enabled: true
provider: {{ .Values.nebariapp.auth.provider }}
provisionClient: {{ .Values.nebariapp.auth.provisionClient }}
redirectURI: {{ .Values.nebariapp.auth.redirectURI }}
scopes:
{{- toYaml .Values.nebariapp.auth.scopes | nindent 6 }}
{{- if hasKey .Values.nebariapp.enabled -}}
{{- fail "nebariapp.enabled was removed in version 0.5.0. Set nebariapp.serve.enabled and nebariapp.dashboard.enabled instead." -}}
{{- end -}}

{{- end }}
gateway: {{ .Values.nebariapp.gateway }}
{{- end }}
{{- if hasKey .Values.nebariapp.hostname -}}
{{- fail "nebariapp.hostname was removed in version 0.5.0. Set nebariapp.serve.hostname instead." -}}
{{- end -}}

{{- if hasKey .Values.nebariapp.service -}}
{{- fail "nebariapp.service was removed in version 0.5.0. Set nebariapp.serve.service.{name,port} and nebariapp.dashboard.service.{name,port} instead." -}}
{{- end -}}

{{- if hasKey .Values.nebariapp.auth -}}
{{- fail "nebariapp.auth was removed in version 0.5.0. Set nebariapp.serve.auth and nebariapp.dashboard.auth instead." -}}
{{- end -}}

{{- if hasKey .Values.nebariapp.gateway -}}
{{- fail "nebariapp.gateway was removed in version 0.5.0. Set nebariapp.serve.gateway and nebariapp.dashboard.gateway instead." -}}
{{- end -}}

{{- if .Values.nebariapp.serve.enabled -}}
# NebariApp for Ray Serve endpoint
{{ include "nebari-app.nebariApp" (dict
"metadata" (dict
"name" (include "nebari-rayserve.fullname" .)
"namespace" .Release.Namespace
"labels" (include "nebari-rayserve.labels" . | fromYaml)
)
"spec" (omit .Values.nebariapp.serve "enabled")
"tplCtx" .
) -}}
{{- end }}
---
{{- if and .Values.nebariapp.enabled .Values.nebariapp.dashboard.enabled }}
{{- if .Values.nebariapp.dashboard.enabled -}}
# NebariApp for Ray Dashboard
apiVersion: reconcilers.nebari.dev/v1
kind: NebariApp
metadata:
name: {{ include "nebari-rayserve.fullname" . }}-dashboard
labels:
{{- include "nebari-rayserve.labels" . | nindent 4 }}
spec:
hostname: {{ required "nebariapp.dashboard.hostname is required when dashboard is enabled" .Values.nebariapp.dashboard.hostname }}
service:
name: {{ .Values.nebariapp.service.name | default (include "nebari-rayserve.head-service-name" .) }}
port: {{ .Values.nebariapp.service.dashboardPort }}
routing:
routes:
- pathPrefix: /
pathType: PathPrefix
{{- if .Values.nebariapp.auth.enabled }}
auth:
enabled: true
provider: {{ .Values.nebariapp.auth.provider }}
provisionClient: {{ .Values.nebariapp.auth.provisionClient }}
redirectURI: {{ .Values.nebariapp.auth.redirectURI }}
scopes:
{{- toYaml .Values.nebariapp.auth.scopes | nindent 6 }}

{{- end }}
{{- with .Values.nebariapp.dashboard.landingPage }}
landingPage:
enabled: {{ .enabled | default false }}
{{- with .displayName }}
displayName: {{ . | quote }}
{{- end }}
{{- with .description }}
description: {{ . | quote }}
{{- end }}
{{- with .icon }}
icon: {{ . | quote }}
{{- end }}
{{- with .category }}
category: {{ . | quote }}
{{- end }}
{{- if kindIs "float64" .priority }}
priority: {{ .priority }}
{{- end }}
{{- with .externalUrl }}
externalUrl: {{ . | quote }}
{{- end }}
{{- with .healthCheck }}
healthCheck:
enabled: {{ .enabled | default false }}
{{- with .path }}
path: {{ . | quote }}
{{- end }}
{{- if .intervalSeconds }}
intervalSeconds: {{ .intervalSeconds }}
{{- end }}
{{- if .timeoutSeconds }}
timeoutSeconds: {{ .timeoutSeconds }}
{{- end }}
{{- end }}
{{- end }}
gateway: {{ .Values.nebariapp.gateway }}
{{ include "nebari-app.nebariApp" (dict
"metadata" (dict
"name" (printf "%s-dashboard" (include "nebari-rayserve.fullname" .))
"namespace" .Release.Namespace
"labels" (include "nebari-rayserve.labels" . | fromYaml)
)
"spec" (omit .Values.nebariapp.dashboard "enabled")
"tplCtx" .
) -}}
{{- end }}
41 changes: 19 additions & 22 deletions chart/values.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
# =============================================================================
# Nebari Integration
# =============================================================================
# Creates a NebariApp CRD that configures routing, TLS, and auth via nebari-operator.
# Set enabled: true when deploying on a Nebari cluster.
# Creates NebariApp CRs that configure routing, TLS, and auth via nebari-operator.
nebariapp:
Comment thread
pmeier marked this conversation as resolved.
enabled: false
Comment thread
pmeier marked this conversation as resolved.
# hostname: rayserve.nebari.example.com # Required when serve.enabled is true
Comment thread
pmeier marked this conversation as resolved.
serve:
enabled: false # Set to true and provide nebariapp.hostname to expose the serve endpoint externally
enabled: false
hostname: '{{ fail "nebariapp.serve.hostname is required if nebariapps.serve.enabled is true" }}'
service:
name: '{{ include "nebari-rayserve.serve-service-name" . | toJson }}'
port: 8000
routing:
routes:
- pathPrefix: /
pathType: PathPrefix
dashboard:
enabled: true
# hostname: ray-dashboard.nebari.example.com # Separate hostname for dashboard
enabled: false
hostname: '{{ fail "nebariapp.dashboard.hostname is required if nebariapps.dashboard.enabled is true" }}'
service:
name: '{{ include "nebari-rayserve.head-service-name" . | toJson }}'
port: 8265
landingPage:
enabled: false
displayName: "Ray Dashboard"
Expand All @@ -23,21 +31,10 @@ nebariapp:
path: /api/component_activities
intervalSeconds: 30
timeoutSeconds: 5
service:
name: "" # Defaults to <release>-<chart>-serve-svc (serve) or -head-svc (dashboard)
servePort: 8000
dashboardPort: 8265
Comment thread
pmeier marked this conversation as resolved.
auth:
enabled: false
provider: keycloak
provisionClient: true
redirectURI: /oauth2/callback
scopes:
- openid
- profile
- email
Comment thread
pmeier marked this conversation as resolved.

gateway: public
Comment thread
pmeier marked this conversation as resolved.
routing:
routes:
- pathPrefix: /
pathType: PathPrefix

# =============================================================================
# KubeRay Operator
Expand Down
Loading