Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
6901038
[Feature] Add mTLS support to RayClusters
kryanbeane Mar 5, 2026
4d6ef53
fix(mtls): inject loopback RAY_ADDRESS on head pod to prevent TLS SAN…
chipspeak May 26, 2026
65ca629
Only inject tls config into wait-gcs-ready init container
chipspeak May 27, 2026
dede92a
Add cert-manager to e2e test environment
chipspeak May 27, 2026
07c32fb
restore TLS injection on Ray container and filter inits
chipspeak May 27, 2026
3a2c405
fix(mTLS): use head service FQDN for RAY_ADDRESS instead of loopback
chipspeak May 27, 2026
362f25e
fix(mTLS): fix case of success assertion in tls test
chipspeak May 28, 2026
f6545fd
Use k8serrors in mtls test
chipspeak Jun 1, 2026
5202efe
Handle partial discovery errors in certManagerAPIAvailable
chipspeak Jun 2, 2026
10e6f00
Errant networkpolicy code removal
chipspeak Jun 24, 2026
3c816fb
Post rebase deepcopy gen
chipspeak Jun 24, 2026
3d86db8
fix test assertion
chipspeak Jun 24, 2026
0b392c4
fix(test): cancel manager context before stopping envtest in AfterSuite
chipspeak Jun 24, 2026
ea578d6
fix(suite_test): wait for manager shutdown before stopping envtest
chipspeak Jun 24, 2026
db8fb75
enable mTLS featuregate during test for raycluster unit tests
chipspeak Jun 24, 2026
ac799f1
use loopback RAY_ADDRESS and wait-for-tls-ip-san init container to fi…
chipspeak Jun 26, 2026
7a68851
validate autoscalerOptions.env against forbidden TLS vars and check c…
chipspeak Jun 26, 2026
13de8e3
add mtls buildkite label and test
chipspeak Jun 26, 2026
3f7b5e1
add timeout to wait-for-tls-ip-san
chipspeak Jun 26, 2026
d1430f1
verify cert generation in secret readiness check and test helper
chipspeak Jun 26, 2026
45598fa
check that pod IP is not empty before checking cert match
chipspeak Jun 26, 2026
37c74f9
scope cert IP SANs to node type to avoid spurious reissues
chipspeak Jun 26, 2026
3811218
check manager start error in AfterSuite instead of background goroutine
chipspeak Jun 26, 2026
4ea07ee
test fix + unblock deletion and suspend when controller inactive or c…
chipspeak Jun 26, 2026
c85e490
unify pod IP env var and tighten IP SAN match
chipspeak Jun 29, 2026
6365f45
drop loopback, simplify DNS SANs, enforce feature gate, rename finali…
chipspeak Jul 3, 2026
ad0795d
Remove remaining BYOC-related code
chipspeak Jul 4, 2026
ab06fb3
Added utils functions for getting cert-related details
chipspeak Jul 4, 2026
fbc9381
Init container now fails fast if POD_IP is empty
chipspeak Jul 4, 2026
b0894c7
Add security context to wait-for-tls-ip-san init container
chipspeak Jul 4, 2026
bbe71ad
Remove redundant outer gomega declarations from TLS e2e tests
chipspeak Jul 4, 2026
d6a414a
use isCertificateReady in RayCluster controller
chipspeak Jul 4, 2026
00ed9e8
Remove FQDN and convert init script to python to account for IPv6
chipspeak Jul 4, 2026
9cce994
Gate mTLS readiness check on pod creation only, not pod deletion
chipspeak Jul 4, 2026
8c85403
Revert to shell init script + remove stale BYOC refs
chipspeak Jul 4, 2026
836bdc9
strip wait-for-tls-ip-san init container from redis cleanup
chipspeak Jul 6, 2026
af9242f
strip TLS config from Redis cleanup Job to avoid ContainerCreating on…
chipspeak Jul 6, 2026
9cf68a9
use sets to normalize pod IPs
chipspeak Jul 6, 2026
bd48b9d
replace mTLS cleanup finalizer with Secret-Certificate owner refs for GC
chipspeak Jul 6, 2026
1cd627e
extend mTLS pod recreation check to multi-host worker groups
chipspeak Jul 6, 2026
4425b37
add helper to gate pod recreation behind mtls feature-gate
chipspeak Jul 6, 2026
16aac73
add python IP check fallback for when OpenSSL is not present
chipspeak Jul 6, 2026
0c28a2c
remove stale FQDN mtls logic from buildHeadPod
chipspeak Jul 6, 2026
be5eed4
simplify cert-manager API check using ServerResourcesForGroupVersion …
chipspeak Jul 7, 2026
2c738ab
move cert-manager availability check closer to its use in RayClusterR…
chipspeak Jul 7, 2026
e28e809
remove mTLS pod recreation logic in favour of RayClusterUpgradeStrategy
chipspeak Jul 7, 2026
f894b4d
remove unused delete/patch verbs from cert-manager and secrets rules
chipspeak Jul 7, 2026
0e62470
use controllerutil.SetOwnerReference in ensureSecretOwnedByCertificate
chipspeak Jul 7, 2026
70a421f
check if RayCluster is managed by external controller
chipspeak Jul 7, 2026
d9119fc
revert unrelated changes to suite_test.go and raycluster controller
chipspeak Jul 7, 2026
92c1dd0
filter terminated pods from cert SAN IP collection
chipspeak Jul 7, 2026
0c45255
reject conflicting TLS volume mounts in validateTLSOptions
chipspeak Jul 7, 2026
6897181
SetOwnerReference to explicitly set BlockOwnerDeletion
chipspeak Jul 7, 2026
ec7fb4b
validate autoscaler TLS volume mount conflicts in validateTLSOptions
chipspeak Jul 7, 2026
b923ca3
enable mTLS featuregate in buildkite values
chipspeak Jul 8, 2026
d645fd5
remove trailing semicolon from rbac
chipspeak Jul 8, 2026
68c520f
remove python fallback + handle empty POD_IP + deadline + existence c…
chipspeak Jul 8, 2026
195335a
remove unused fqdnRayIP param from DefaultHeadPodTemplate
chipspeak Jul 8, 2026
a244672
add missing feature gate to TestConfigureTLS_Disabled
chipspeak Jul 8, 2026
b312cb4
update incorrect comment re head pods having wait-gcs-ready
chipspeak Jul 8, 2026
19b5cfd
require wait-gcs-ready container exists before asserting TLS env var
chipspeak Jul 8, 2026
63a1ff3
remove stale references to finalizer in tests
chipspeak Jul 8, 2026
b47bb8d
issuer static spec needs no reconcile drift-check
chipspeak Jul 8, 2026
7a6e697
add TLS env/mount assertions and certificate SAN scale-down coverage
chipspeak Jul 11, 2026
d4d3990
make reconcileCACertificate create-only to prevent spurious CA re-iss…
chipspeak Jul 11, 2026
a5b6dcc
Merge remote-tracking branch 'upstream/master' into enhanced-security…
chipspeak Jul 21, 2026
6bc438e
Migrate RayClusterMTLS controller to events.EventRecorder
chipspeak Jul 21, 2026
e26f84f
remove mode field from tlsOptions
chipspeak Jul 23, 2026
e7f3673
Merge remote-tracking branch 'upstream/master' into enhanced-security…
chipspeak Jul 23, 2026
81137fa
change tlsOptions to a bool
chipspeak Jul 24, 2026
8859240
TLSOptions.Enabled to optional *bool + remove enabled:false validatio…
chipspeak Jul 27, 2026
942dcf3
use ptr.Deref for TLSOptions.Enabled nil check in IsTLSEnabled
chipspeak Jul 27, 2026
f694985
Merge remote-tracking branch 'upstream/master' into enhanced-security…
chipspeak Jul 27, 2026
c5bd23e
drop blockOwnerDeletion from cert secret owner reference
chipspeak Jul 27, 2026
a8ea8a3
fix test assertion after previous commit
chipspeak Jul 27, 2026
39ec73a
add delete to secrets rbac to prevent OpenShift rejection
chipspeak Jul 27, 2026
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
21 changes: 21 additions & 0 deletions .buildkite/test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,27 @@
- KUBERAY_TEST_TIMEOUT_SHORT=1m KUBERAY_TEST_TIMEOUT_MEDIUM=5m KUBERAY_TEST_TIMEOUT_LONG=10m go test -timeout 30m -v ./test/e2erayjobsubmitter 2>&1 | awk -f ../.buildkite/format.awk | tee $$KUBERAY_TEST_OUTPUT_DIR/gotest.log || (kubectl logs --tail -1 -l app.kubernetes.io/name=kuberay | tee $$KUBERAY_TEST_OUTPUT_DIR/kuberay-operator.log && cd $$KUBERAY_TEST_OUTPUT_DIR && find . -name "*.log" | tar -cf /artifact-mount/e2e-log.tar -T - && exit 1)
- echo "--- END:RayJob Light Weight Submitter E2E (nightly operator) tests finished"

- label: 'Test RayCluster mTLS E2E (nightly operator)'
instance_size: large
image: golang:1.26-bookworm
commands:
- source .buildkite/setup-env.sh
- kind create cluster --wait 900s --config ./ci/kind-config-buildkite.yml
- kubectl config set clusters.kind-kind.server https://docker:6443
# Install cert-manager (required for RayClusterMTLS auto-generate e2e tests)
- pushd ray-operator
- make certmanager
- source ../.buildkite/build-start-operator.sh
- kubectl wait --timeout=90s --for=condition=Available=true deployment kuberay-operator
# Run mTLS e2e tests and print KubeRay operator logs if tests fail
- echo "--- START:Running RayCluster mTLS E2E (nightly operator) tests"
- if [ -n "$${KUBERAY_TEST_RAY_IMAGE}" ]; then echo "Using Ray Image $${KUBERAY_TEST_RAY_IMAGE}"; fi
- set -o pipefail
- mkdir -p "$(pwd)/tmp" && export KUBERAY_TEST_OUTPUT_DIR=$(pwd)/tmp
- echo "KUBERAY_TEST_OUTPUT_DIR=$$KUBERAY_TEST_OUTPUT_DIR"
- KUBERAY_TEST_TIMEOUT_SHORT=1m KUBERAY_TEST_TIMEOUT_MEDIUM=5m KUBERAY_TEST_TIMEOUT_LONG=10m go test -timeout 30m -v -run TLS ./test/e2e 2>&1 | awk -f ../.buildkite/format.awk | tee $$KUBERAY_TEST_OUTPUT_DIR/gotest.log || (kubectl logs --tail -1 -l app.kubernetes.io/name=kuberay | tee $$KUBERAY_TEST_OUTPUT_DIR/kuberay-operator.log && cd $$KUBERAY_TEST_OUTPUT_DIR && find . -name "*.log" | tar -cf /artifact-mount/e2e-mtls-log.tar -T - && exit 1)
- echo "--- END:RayCluster mTLS E2E (nightly operator) tests finished"

- label: 'Test RayCronJob E2E (nightly operator)'
instance_size: large
image: golang:1.26-bookworm
Expand Down
2 changes: 2 additions & 0 deletions .buildkite/values-kuberay-operator-override.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ featureGates:
enabled: true
- name: SidecarSubmitterRestart
enabled: true
- name: RayClusterMTLS
enabled: true
21 changes: 21 additions & 0 deletions docs/reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ _Appears in:_
| `enableInTreeAutoscaling` _boolean_ | EnableInTreeAutoscaling indicates whether operator should create in tree autoscaling configs | | |
| `gcsFaultToleranceOptions` _[GcsFaultToleranceOptions](#gcsfaulttoleranceoptions)_ | GcsFaultToleranceOptions for enabling GCS FT | | |
| `networkPolicy` _[NetworkPolicyConfig](#networkpolicyconfig)_ | NetworkPolicy specifies optional configuration for network isolation.<br />When set, separate NetworkPolicies are created for head and worker pods.<br />The reconciler always permits intra-cluster pod-to-pod traffic.<br />Note: under DenyAll/DenyAllEgress, DNS egress is not added<br />automatically; since Ray pods reach the head via its service FQDN, you must<br />allow DNS egress via Head/Worker EgressRules or the cluster will fail to start. | | |
| `tlsOptions` _[TLSOptions](#tlsoptions)_ | TLSOptions specifies optional TLS encryption settings for the RayCluster.<br />If omitted or Enabled is false, TLS is disabled. When Enabled is true,<br />the operator enables mTLS using cert-manager to provision and manage certificates.<br />Requires the RayClusterMTLS feature gate on the operator. | | |
| `headGroupSpec` _[HeadGroupSpec](#headgroupspec)_ | HeadGroupSpec is the spec for the head pod | | |
| `rayVersion` _string_ | RayVersion is used to determine the command for the Kubernetes Job managed by RayJob | | |
| `workerGroupSpecs` _[WorkerGroupSpec](#workergroupspec) array_ | WorkerGroupSpecs are the specs for the worker pods | | |
Expand Down Expand Up @@ -759,6 +760,26 @@ _Appears in:_
| `backoffLimit` _integer_ | BackoffLimit of the submitter. In K8sJobMode, this is the K8s Job backoffLimit.<br />In SidecarMode with SidecarSubmitterRestart enabled, this is the maximum container restart count. | | |


#### TLSOptions



TLSOptions configures TLS encryption for the RayCluster.
When TLSOptions is nil or Enabled is nil/false, TLS is disabled.
When Enabled is true, the operator uses cert-manager to automatically
provision a full PKI (self-signed CA, head and worker leaf certificates)
and keeps certificates up to date as pod IPs change during autoscaling.



_Appears in:_
- [RayClusterSpec](#rayclusterspec)

| Field | Description | Default | Validation |
| --- | --- | --- | --- |
| `enabled` _boolean_ | Enabled controls whether mTLS is active for this RayCluster.<br />Defaults to false when omitted. Set to true to enable mTLS. | | |


#### UpscalingMode

_Underlying type:_ _string_
Expand Down
2 changes: 2 additions & 0 deletions helm-chart/kuberay-operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ spec:
| featureGates[3].enabled | bool | `false` | |
| featureGates[4].name | string | `"RayCronJob"` | |
| featureGates[4].enabled | bool | `false` | |
| featureGates[5].name | string | `"RayClusterMTLS"` | |
| featureGates[5].enabled | bool | `false` | |
| metrics.enabled | bool | `true` | Whether KubeRay operator should emit control plane metrics. |
| metrics.serviceMonitor.enabled | bool | `false` | Enable a prometheus ServiceMonitor |
| metrics.serviceMonitor.interval | string | `"30s"` | Prometheus ServiceMonitor interval |
Expand Down
5 changes: 5 additions & 0 deletions helm-chart/kuberay-operator/crds/ray.io_rayclusters.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions helm-chart/kuberay-operator/crds/ray.io_raycronjobs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5082,6 +5082,11 @@ spec:
type: string
suspend:
type: boolean
tlsOptions:
properties:
enabled:
type: boolean
type: object
upgradeStrategy:
properties:
type:
Expand Down
5 changes: 5 additions & 0 deletions helm-chart/kuberay-operator/crds/ray.io_rayjobs.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions helm-chart/kuberay-operator/crds/ray.io_rayservices.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions helm-chart/kuberay-operator/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,10 @@ rules:
- secrets
verbs:
- create
- delete
- get
- list
- update
- watch
- apiGroups:
- ""
Expand Down Expand Up @@ -229,6 +231,31 @@ rules:
- patch
- update
- watch
- apiGroups:
- cert-manager.io
resources:
- certificates
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- cert-manager.io
resources:
- certificates/status
verbs:
- get
Comment thread
kryanbeane marked this conversation as resolved.
- apiGroups:
- cert-manager.io
resources:
- issuers
verbs:
- create
- get
- list
- watch
- apiGroups:
- coordination.k8s.io
resources:
Expand Down
2 changes: 2 additions & 0 deletions helm-chart/kuberay-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ featureGates:
enabled: false
- name: RayCronJob
enabled: false
- name: RayClusterMTLS
enabled: false
Comment thread
win5923 marked this conversation as resolved.

# Configurations for KubeRay operator metrics.
metrics:
Expand Down
5 changes: 4 additions & 1 deletion ray-operator/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,10 @@ api-docs: crd-ref-docs ## Generate CRD documentation.
--output-path=../docs/reference/api.md

certmanager:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.19.4/cert-manager.yaml
kubectl wait --namespace cert-manager --for=condition=Available deployment/cert-manager --timeout=120s
kubectl wait --namespace cert-manager --for=condition=Available deployment/cert-manager-webhook --timeout=120s
kubectl wait --namespace cert-manager --for=condition=Available deployment/cert-manager-cainjector --timeout=120s

deploy-with-webhooks: manifests kustomize certmanager ## Deploy controller with webhooks to the K8s cluster specified in ~/.kube/config.
cd config/default-with-webhooks && $(KUSTOMIZE) edit set image kuberay/operator=${IMG}
Expand Down
18 changes: 18 additions & 0 deletions ray-operator/apis/ray/v1/raycluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ type RayClusterSpec struct {
// allow DNS egress via Head/Worker EgressRules or the cluster will fail to start.
// +optional
NetworkPolicy *NetworkPolicyConfig `json:"networkPolicy,omitempty"`
// TLSOptions specifies optional TLS encryption settings for the RayCluster.
// If omitted or Enabled is false, TLS is disabled. When Enabled is true,
// the operator enables mTLS using cert-manager to provision and manage certificates.
// Requires the RayClusterMTLS feature gate on the operator.
// +optional
TLSOptions *TLSOptions `json:"tlsOptions,omitempty"`
// HeadGroupSpec is the spec for the head pod
HeadGroupSpec HeadGroupSpec `json:"headGroupSpec"`
// RayVersion is used to determine the command for the Kubernetes Job managed by RayJob
Expand All @@ -61,6 +67,18 @@ type RayClusterSpec struct {
WorkerGroupSpecs []WorkerGroupSpec `json:"workerGroupSpecs,omitempty"`
}

// TLSOptions configures TLS encryption for the RayCluster.
// When TLSOptions is nil or Enabled is nil/false, TLS is disabled.
// When Enabled is true, the operator uses cert-manager to automatically
// provision a full PKI (self-signed CA, head and worker leaf certificates)
// and keeps certificates up to date as pod IPs change during autoscaling.
type TLSOptions struct {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Are there no cert-manager configs we want to expose through this API?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For alpha we're intentionally not exposing cert-manager configs. The only field with real user value would be issuerRef (BYOC CA), but that's blocked by per-pod-IP re-issuance until upstream Ray supports hostname-based identity (related Ray issue). At that point the whole SAN-reconcile loop goes away and we can revisit the API design more broadly. WDYT?

// Enabled controls whether mTLS is active for this RayCluster.
// Defaults to false when omitted. Set to true to enable mTLS.
// +optional
Enabled *bool `json:"enabled,omitempty"`
}

// +kubebuilder:validation:Enum=Recreate;None
type RayClusterUpgradeType string

Expand Down
25 changes: 25 additions & 0 deletions ray-operator/apis/ray/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions ray-operator/config/crd/bases/ray.io_rayclusters.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions ray-operator/config/crd/bases/ray.io_raycronjobs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5082,6 +5082,11 @@ spec:
type: string
suspend:
type: boolean
tlsOptions:
properties:
enabled:
type: boolean
type: object
upgradeStrategy:
properties:
type:
Expand Down
5 changes: 5 additions & 0 deletions ray-operator/config/crd/bases/ray.io_rayjobs.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions ray-operator/config/crd/bases/ray.io_rayservices.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ spec:
containers:
- name: kuberay-operator
args:
- --feature-gates=RayClusterStatusConditions=true,RayJobDeletionPolicy=true,RayMultiHostIndexing=true,RayCronJob=true,RayServiceIncrementalUpgrade=true,SidecarSubmitterRestart=true,GCSFaultToleranceEmbeddedStorage=true
- --feature-gates=RayClusterStatusConditions=true,RayJobDeletionPolicy=true,RayMultiHostIndexing=true,RayCronJob=true,RayServiceIncrementalUpgrade=true,SidecarSubmitterRestart=true,GCSFaultToleranceEmbeddedStorage=true,RayClusterMTLS=true
27 changes: 27 additions & 0 deletions ray-operator/config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ rules:
- secrets
verbs:
- create
- delete
- get
- list
- update
- watch
- apiGroups:
- ""
Comment thread
cursor[bot] marked this conversation as resolved.
Expand Down Expand Up @@ -86,6 +88,31 @@ rules:
- patch
- update
- watch
- apiGroups:
- cert-manager.io
resources:
- certificates
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- cert-manager.io
resources:
- certificates/status
verbs:
- get
- apiGroups:
- cert-manager.io
resources:
- issuers
verbs:
- create
- get
- list
- watch
- apiGroups:
- coordination.k8s.io
resources:
Expand Down
Loading
Loading