Repository: kubernetes-sigs/kueue

Issue:
kep-4377: Document how one can implement secure metrics
A user can either enable this with kustomize code or they can use the helm chart.

```yaml
metrics:
  prometheusNamespace: monitoring
# tls configs for serviceMonitor
  serviceMonitor:
    tlsConfig:
      serverName: kueue-controller-manager-metrics-service.kueue-system.svc
      insecureSkipVerify: false
      ca:
        secret:
          name: kueue-metrics-server-cert
          key: ca.crt
      cert:
        secret:
          name: kueue-metrics-server-cert
          key: tls.crt
      keySecret:
        name: kueue-metrics-server-cert
        key: tls.key
```

We should add an example in our installation guide to make it clear that we support secure metrics.

Hints from issue comments:
@kannon92: /assign@tenzen-y: /kind documentation@kannon92: xref: https://github.com/kubernetes-sigs/kueue/issues/4377

Solution patch:
diff --git a/CHANGELOG/CHANGELOG-0.10.md b/CHANGELOG/CHANGELOG-0.10.md
index bf1a4e902..6a2134677 100644
--- a/CHANGELOG/CHANGELOG-0.10.md
+++ b/CHANGELOG/CHANGELOG-0.10.md
@@ -1,3 +1,22 @@
+## v0.10.3
+
+Changes since `v0.10.2`:
+
+## Changes by Kind
+
+### Bug or Regression
+
+- Fixes a bug that would result in default values not being properly set on creation for enabled integrations whose API was not available when the Kueue controller started. (#4557, @dgrove-oss)
+- Helm: Fixed a bug that prometheus namespace is enforced with namespace the same as kueue-controller-manager (#4487, @kannon92)
+- TAS: Do not ignore the TAS annotation if set on the template for the Ray submitter Job. (#4502, @mszadkow)
+- TAS: Fix a bug that TopolologyUngator cound not be triggered the leader change when enabled HA mode (#4656, @tenzen-y)
+- Update FairSharing to be incompatible with ClusterQueue.Preemption.BorrowWithinCohort. Using these parameters together is a no-op, and will be validated against in future releases. This change fixes an edge case which triggered an infinite preemption loop when these two parameters were combined. (#4165, @gabesaba)
+
+### Other (Cleanup or Flake)
+
+- Publish helm charts to the Kueue staging repository `http://us-central1-docker.pkg.dev/k8s-staging-images/kueue/charts`,
+  so that they can be promoted to the permanent location under `registry.k8s.io/kueue/charts`. (#4684, @mimowo)
+
 ## v0.10.2
 
 Changes since `v0.10.1`:
diff --git a/CHANGELOG/CHANGELOG-0.9.md b/CHANGELOG/CHANGELOG-0.9.md
index af0a81442..8b9a0cff3 100644
--- a/CHANGELOG/CHANGELOG-0.9.md
+++ b/CHANGELOG/CHANGELOG-0.9.md
@@ -1,3 +1,21 @@
+## v0.9.5
+
+Changes since `v0.9.4`:
+
+## Changes by Kind
+
+### Bug or Regression
+
+- Fixes a bug that would result in default values not being properly set on creation for enabled integrations whose API was not available when the Kueue controller started. (#4559, @dgrove-oss)
+- Helm: Fixed a bug that prometheus namespace is enforced with namespace the same as kueue-controller-manager (#4488, @kannon92)
+- TAS: Fix a bug that TopolologyUngator cound not be triggered the leader change when enabled HA mode (#4657, @tenzen-y)
+- Update FairSharing to be incompatible with ClusterQueue.Preemption.BorrowWithinCohort. Using these parameters together is a no-op, and will be validated against in future releases. This change fixes an edge case which triggered an infinite preemption loop when these two parameters were combined. (#4165, @gabesaba)
+
+### Other (Cleanup or Flake)
+
+- Publish helm charts to the Kueue staging repository `http://us-central1-docker.pkg.dev/k8s-staging-images/kueue/charts`,
+  so that they can be promoted to the permanent location under `registry.k8s.io/kueue/charts`. (#4685, @mimowo)
+
 ## v0.9.4
 
 Changes since `v0.9.3`:
diff --git a/Makefile b/Makefile
index f949ffe0c..f7aa8f138 100644
--- a/Makefile
+++ b/Makefile
@@ -37,7 +37,7 @@ IMAGE_REGISTRY ?= $(STAGING_IMAGE_REGISTRY)/kueue
 IMAGE_NAME := kueue
 IMAGE_REPO ?= $(IMAGE_REGISTRY)/$(IMAGE_NAME)
 IMAGE_TAG ?= $(IMAGE_REPO):$(GIT_TAG)
-HELM_CHART_REPO := $(STAGING_IMAGE_REGISTRY)/charts
+HELM_CHART_REPO := $(STAGING_IMAGE_REGISTRY)/kueue/charts
 
 ifdef EXTRA_TAG
 IMAGE_EXTRA_TAG ?= $(IMAGE_REPO):$(EXTRA_TAG)
@@ -77,8 +77,10 @@ LD_FLAGS += -X '$(version_pkg).GitCommit=$(shell git rev-parse HEAD)'
 
 # Update these variables when preparing a new release or a release branch.
 # Then run `make prepare-release-branch`
-RELEASE_VERSION=v0.10.2
+RELEASE_VERSION=v0.10.3
 RELEASE_BRANCH=main
+# Version used form Helm which is not using the leading "v"
+CHART_VERSION := $(shell echo $(RELEASE_VERSION) | cut -c2-)
 
 .PHONY: all
 all: generate fmt vet build
@@ -279,9 +281,10 @@ artifacts: kustomize yq helm ## Generate release artifacts.
 
 .PHONY: prepare-release-branch
 prepare-release-branch: yq kustomize ## Prepare the release branch with the release version.
-	$(SED) -r 's/v[0-9]+\.[0-9]+\.[0-9]+/$(RELEASE_VERSION)/g' -i README.md -i site/hugo.toml
-	$(SED) -r 's/--version="v[0-9]+\.[0-9]+\.[0-9]+/--version="$(RELEASE_VERSION)/g' -i charts/kueue/README.md
-	$(YQ) e '.appVersion = "$(RELEASE_VERSION)"' -i charts/kueue/Chart.yaml
+	$(SED) -r 's/version = "v[0-9]+\.[0-9]+\.[0-9]+/version = "$(RELEASE_VERSION)/g' -i README.md -i site/hugo.toml
+	$(SED) -r 's/chart_version = "[0-9]+\.[0-9]+\.[0-9]+/chart_version = "$(CHART_VERSION)/g' -i README.md -i site/hugo.toml
+	$(SED) -r 's/--version="v?[0-9]+\.[0-9]+\.[0-9]+/--version="$(CHART_VERSION)/g' -i charts/kueue/README.md
+	$(YQ) e '.appVersion = "$(CHART_VERSION)"' -i charts/kueue/Chart.yaml
 	@$(call clean-manifests)
 
 .PHONY: update-security-insights
diff --git a/README.md b/README.md
index 0a0774512..ac881630f 100644
--- a/README.md
+++ b/README.md
@@ -58,7 +58,7 @@ Read the [overview](https://kueue.sigs.k8s.io/docs/overview/) and watch the Kueu
 To install the latest release of Kueue in your cluster, run the following command:
 
 ```shell
-kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.10.2/manifests.yaml
+kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.10.3/manifests.yaml
 ```
 
 The controller runs in the `kueue-system` namespace.
diff --git a/SECURITY-INSIGHTS.yaml b/SECURITY-INSIGHTS.yaml
index f3a30d81b..a94c3d2b1 100644
--- a/SECURITY-INSIGHTS.yaml
+++ b/SECURITY-INSIGHTS.yaml
@@ -1,11 +1,11 @@
 header:
   schema-version: 1.0.0
   expiration-date: '2024-09-28T01:00:00.000Z'
-  last-updated: '2025-02-25'
-  last-reviewed: '2025-02-25'
-  commit-hash: bc5b74090af4e54f702c41ffb6971170696f54b2
+  last-updated: '2025-03-19'
+  last-reviewed: '2025-03-19'
+  commit-hash: c79419eb5b3b0021621805a73bec2ff58c398d8b
   project-url: 'https://github.com/kubernetes-sigs/kueue'
-  project-release: 0.10.2
+  project-release: 0.10.3
   changelog: 'https://github.com/kubernetes-sigs/kueue/tree/main/CHANGELOG'
   license: 'https://github.com/kubernetes-sigs/kueue/blob/main/LICENSE'
 project-lifecycle:
@@ -28,7 +28,7 @@ documentation:
   - 'https://kueue.sigs.k8s.io/docs/'
 distribution-points:
   - >-
-    https://github.com/kubernetes-sigs/kueue/releases/download/v0.10.2/manifests.yaml
+    https://github.com/kubernetes-sigs/kueue/releases/download/v0.10.3/manifests.yaml
 security-artifacts:
   threat-model:
     threat-model-created: false
@@ -62,5 +62,5 @@ dependencies:
   dependencies-lists:
     - 'https://github.com/kubernetes-sigs/kueue/blob/main/go.mod'
   sbom:
-    - sbom-file: https://github.com/kubernetes-sigs/kueue/releases/download/v0.10.2/kueue-v0.10.2.spdx.json
+    - sbom-file: https://github.com/kubernetes-sigs/kueue/releases/download/v0.10.3/kueue-v0.10.3.spdx.json
       sbom-format: SPDX
diff --git a/charts/kueue/Chart.yaml b/charts/kueue/Chart.yaml
index da0a3e9c5..c650f7d01 100644
--- a/charts/kueue/Chart.yaml
+++ b/charts/kueue/Chart.yaml
@@ -21,4 +21,4 @@ version: 0.1.0
 # 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: "v0.10.2"
+appVersion: "0.10.3"
diff --git a/charts/kueue/README.md b/charts/kueue/README.md
index d9d9096a0..580471030 100644
--- a/charts/kueue/README.md
+++ b/charts/kueue/README.md
@@ -34,10 +34,10 @@ $ cd kueue/charts
 $ helm install kueue kueue/ --create-namespace --namespace kueue-system
 ```
 
-Or use the charts pushed to `us-central1-docker.pkg.dev/k8s-staging-images/charts/kueue`:
+Or use the charts pushed to `us-central1-docker.pkg.dev/k8s-staging-images/kueue/charts/kueue`:
 
 ```bash
-helm install kueue oci://us-central1-docker.pkg.dev/k8s-staging-images/charts/kueue --version="v0.10.2" --create-namespace --namespace=kueue-system
+helm install kueue oci://us-central1-docker.pkg.dev/k8s-staging-images/kueue/charts/kueue --version="0.10.3" --create-namespace --namespace=kueue-system
 ```
 
 ##### Verify that controller pods are running properly.
@@ -48,6 +48,21 @@ NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
 kueue-controller-manager       1/1     1            1           7s
 ```
 
+##### Cert Manager
+
+Kueue has support for third-party certificates.
+One can enable this by setting `enableCertManager` to true.
+This will use certManager to generate a secret, inject the CABundles and set up the tls.
+
+Check out the [site](https://kueue.sigs.k8s.io/docs/tasks/manage/productization/cert_manager/)
+for more information on installing cert manager with our Helm chart.
+
+##### Prometheus
+
+Kueue supports prometheus metrics.
+Check out the [site](https://kueue.sigs.k8s.io/docs/tasks/manage/productization/prometheus/)
+for more information on installing kueue with metrics using our Helm chart.
+
 ### Configuration
 
 The following table lists the configurable parameters of the kueue chart and their default values.
@@ -82,3 +97,4 @@ The following table lists the configurable parameters of the kueue chart and the
 | `metricsService`                                       | metricsService's ports                                 | abbr.                                       |
 | `webhookService`                                       | webhookService's ports                                 | abbr.                                       |
 | `metrics.prometheusNamespace`                          | prometheus namespace                                   | `monitoring`                                |
+| `metrics.serviceMonitor.tlsConfig`                     | service monitor for prometheus                         | abbr.                                       |
diff --git a/hack/e2e-common.sh b/hack/e2e-common.sh
index 99a4e2156..ef9b01ef3 100644
--- a/hack/e2e-common.sh
+++ b/hack/e2e-common.sh
@@ -49,7 +49,6 @@ if [[ -n ${KUBERAY_VERSION:-} ]]; then
     export KUBERAY_IMAGE=quay.io/kuberay/operator:${KUBERAY_VERSION}
     export KUBERAY_RAY_IMAGE=rayproject/ray:2.9.0
     export KUBERAY_RAY_IMAGE_ARM=rayproject/ray:2.9.0-aarch64
-    export KUBERAY_CRDS=${ROOT_DIR}/dep-crds/ray-operator/crd/bases
 fi
 
 if [[ -n ${LEADERWORKERSET_VERSION:-} ]]; then
diff --git a/hack/multikueue-e2e-test.sh b/hack/multikueue-e2e-test.sh
index d143199e5..8df034dce 100755
--- a/hack/multikueue-e2e-test.sh
+++ b/hack/multikueue-e2e-test.sh
@@ -100,9 +100,7 @@ function kind_load {
     install_mpi "$WORKER2_KIND_CLUSTER_NAME"
 
     ## KUBERAY
-    kubectl config use-context "kind-${MANAGER_KIND_CLUSTER_NAME}"
-    kubectl apply --server-side -f "${KUBERAY_CRDS}"
-
+    install_kuberay "$MANAGER_KIND_CLUSTER_NAME"
     install_kuberay "$WORKER1_KIND_CLUSTER_NAME"
     install_kuberay "$WORKER2_KIND_CLUSTER_NAME"
 }
diff --git a/hack/push-chart.sh b/hack/push-chart.sh
index dee97572a..e69fb2a7a 100755
--- a/hack/push-chart.sh
+++ b/hack/push-chart.sh
@@ -25,7 +25,7 @@ GIT_TAG=${GIT_TAG:-$(git describe --tags --dirty --always)}
 
 STAGING_IMAGE_REGISTRY=${STAGING_IMAGE_REGISTRY:-us-central1-docker.pkg.dev/k8s-staging-images}
 IMAGE_REGISTRY=${IMAGE_REGISTRY:-${STAGING_IMAGE_REGISTRY}/kueue}
-HELM_CHART_REPO=${HELM_CHART_REPO:-${STAGING_IMAGE_REGISTRY}/charts}
+HELM_CHART_REPO=${HELM_CHART_REPO:-${STAGING_IMAGE_REGISTRY}/kueue/charts}
 IMAGE_REPO=${IMAGE_REPO:-${IMAGE_REGISTRY}/kueue}
 
 HELM=${HELM:-./bin/helm}
diff --git a/pkg/controller/jobs/raycluster/raycluster_controller.go b/pkg/controller/jobs/raycluster/raycluster_controller.go
index 00765942f..dbc61b013 100644
--- a/pkg/controller/jobs/raycluster/raycluster_controller.go
+++ b/pkg/controller/jobs/raycluster/raycluster_controller.go
@@ -33,6 +33,7 @@ import (
 
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	"sigs.k8s.io/kueue/pkg/controller/jobframework"
+	"sigs.k8s.io/kueue/pkg/features"
 	"sigs.k8s.io/kueue/pkg/podset"
 )
 
@@ -77,6 +78,7 @@ var NewReconciler = jobframework.NewGenericReconcilerFactory(NewJob)
 type RayCluster rayv1.RayCluster
 
 var _ jobframework.GenericJob = (*RayCluster)(nil)
+var _ jobframework.JobWithManagedBy = (*RayCluster)(nil)
 
 func (j *RayCluster) Object() client.Object {
 	return (*rayv1.RayCluster)(j)
@@ -203,3 +205,17 @@ func isRayCluster(owner *metav1.OwnerReference) bool {
 func fromObject(o runtime.Object) *RayCluster {
 	return (*RayCluster)(o.(*rayv1.RayCluster))
 }
+
+func (j *RayCluster) CanDefaultManagedBy() bool {
+	jobSpecManagedBy := j.Spec.ManagedBy
+	return features.Enabled(features.MultiKueue) &&
+		(jobSpecManagedBy == nil || *jobSpecManagedBy == rayutils.KubeRayController)
+}
+
+func (j *RayCluster) ManagedBy() *string {
+	return j.Spec.ManagedBy
+}
+
+func (j *RayCluster) SetManagedBy(managedBy *string) {
+	j.Spec.ManagedBy = managedBy
+}
diff --git a/pkg/controller/jobs/raycluster/raycluster_multikueue_adapter.go b/pkg/controller/jobs/raycluster/raycluster_multikueue_adapter.go
index 4ad2b19f2..2ba0fe3e8 100644
--- a/pkg/controller/jobs/raycluster/raycluster_multikueue_adapter.go
+++ b/pkg/controller/jobs/raycluster/raycluster_multikueue_adapter.go
@@ -26,6 +26,7 @@ import (
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/klog/v2"
+	"k8s.io/utils/ptr"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
@@ -81,6 +82,9 @@ func (b *multiKueueAdapter) SyncJob(ctx context.Context, localClient client.Clie
 	remoteJob.Labels[constants.PrebuiltWorkloadLabel] = workloadName
 	remoteJob.Labels[kueue.MultiKueueOriginLabel] = origin
 
+	// clear the managedBy enables the controller to take over
+	remoteJob.Spec.ManagedBy = nil
+
 	return remoteClient.Create(ctx, &remoteJob)
 }
 
@@ -96,6 +100,15 @@ func (b *multiKueueAdapter) KeepAdmissionCheckPending() bool {
 }
 
 func (b *multiKueueAdapter) IsJobManagedByKueue(ctx context.Context, c client.Client, key types.NamespacedName) (bool, string, error) {
+	job := rayv1.RayCluster{}
+	err := c.Get(ctx, key, &job)
+	if err != nil {
+		return false, "", err
+	}
+	jobControllerName := ptr.Deref(job.Spec.ManagedBy, "")
+	if jobControllerName != kueue.MultiKueueControllerName {
+		return false, fmt.Sprintf("Expecting spec.managedBy to be %q not %q", kueue.MultiKueueControllerName, jobControllerName), nil
+	}
 	return true, "", nil
 }
 
diff --git a/pkg/controller/jobs/raycluster/raycluster_webhook.go b/pkg/controller/jobs/raycluster/raycluster_webhook.go
index d2201e1be..7df0b0b9a 100644
--- a/pkg/controller/jobs/raycluster/raycluster_webhook.go
+++ b/pkg/controller/jobs/raycluster/raycluster_webhook.go
@@ -29,6 +29,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
+	"sigs.k8s.io/kueue/pkg/cache"
 	"sigs.k8s.io/kueue/pkg/controller/jobframework"
 	"sigs.k8s.io/kueue/pkg/controller/jobframework/webhook"
 	"sigs.k8s.io/kueue/pkg/queue"
@@ -45,6 +46,7 @@ type RayClusterWebhook struct {
 	queues                       *queue.Manager
 	manageJobsWithoutQueueName   bool
 	managedJobsNamespaceSelector labels.Selector
+	cache                        *cache.Cache
 }
 
 // SetupRayClusterWebhook configures the webhook for rayv1 RayCluster.
@@ -58,6 +60,7 @@ func SetupRayClusterWebhook(mgr ctrl.Manager, opts ...jobframework.Option) error
 		queues:                       options.Queues,
 		manageJobsWithoutQueueName:   options.ManageJobsWithoutQueueName,
 		managedJobsNamespaceSelector: options.ManagedJobsNamespaceSelector,
+		cache:                        options.Cache,
 	}
 	obj := &rayv1.RayCluster{}
 	return webhook.WebhookManagedBy(mgr).
@@ -77,7 +80,11 @@ func (w *RayClusterWebhook) Default(ctx context.Context, obj runtime.Object) err
 	log := ctrl.LoggerFrom(ctx).WithName("raycluster-webhook")
 	log.V(10).Info("Applying defaults")
 	jobframework.ApplyDefaultLocalQueue(job.Object(), w.queues.DefaultLocalQueueExist)
-	return jobframework.ApplyDefaultForSuspend(ctx, job, w.client, w.manageJobsWithoutQueueName, w.managedJobsNamespaceSelector)
+	if err := jobframework.ApplyDefaultForSuspend(ctx, job, w.client, w.manageJobsWithoutQueueName, w.managedJobsNamespaceSelector); err != nil {
+		return err
+	}
+	jobframework.ApplyDefaultForManagedBy(job, w.queues, w.cache, log)
+	return nil
 }
 
 // +kubebuilder:webhook:path=/validate-ray-io-v1-raycluster,mutating=false,failurePolicy=fail,sideEffects=None,groups=ray.io,resources=rayclusters,verbs=create;update,versions=v1,name=vraycluster.kb.io,admissionReviewVersions=v1
diff --git a/pkg/controller/jobs/rayjob/rayjob_controller.go b/pkg/controller/jobs/rayjob/rayjob_controller.go
index 9e13fd47b..f29bf452b 100644
--- a/pkg/controller/jobs/rayjob/rayjob_controller.go
+++ b/pkg/controller/jobs/rayjob/rayjob_controller.go
@@ -34,6 +34,7 @@ import (
 
 	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	"sigs.k8s.io/kueue/pkg/controller/jobframework"
+	"sigs.k8s.io/kueue/pkg/features"
 	"sigs.k8s.io/kueue/pkg/podset"
 )
 
@@ -79,6 +80,7 @@ var NewReconciler = jobframework.NewGenericReconcilerFactory(NewJob)
 type RayJob rayv1.RayJob
 
 var _ jobframework.GenericJob = (*RayJob)(nil)
+var _ jobframework.JobWithManagedBy = (*RayJob)(nil)
 
 func (j *RayJob) Object() client.Object {
 	return (*rayv1.RayJob)(j)
@@ -283,3 +285,17 @@ func getSubmitterTemplate(rayJob *RayJob) *corev1.PodTemplateSpec {
 		},
 	}
 }
+
+func (j *RayJob) CanDefaultManagedBy() bool {
+	jobSpecManagedBy := j.Spec.ManagedBy
+	return features.Enabled(features.MultiKueue) &&
+		(jobSpecManagedBy == nil || *jobSpecManagedBy == rayutils.KubeRayController)
+}
+
+func (j *RayJob) ManagedBy() *string {
+	return j.Spec.ManagedBy
+}
+
+func (j *RayJob) SetManagedBy(managedBy *string) {
+	j.Spec.ManagedBy = managedBy
+}
diff --git a/pkg/controller/jobs/rayjob/rayjob_multikueue_adapter.go b/pkg/controller/jobs/rayjob/rayjob_multikueue_adapter.go
index 5b84bea11..cfed41151 100644
--- a/pkg/controller/jobs/rayjob/rayjob_multikueue_adapter.go
+++ b/pkg/controller/jobs/rayjob/rayjob_multikueue_adapter.go
@@ -26,6 +26,7 @@ import (
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/klog/v2"
+	"k8s.io/utils/ptr"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
@@ -80,6 +81,9 @@ func (b *multiKueueAdapter) SyncJob(ctx context.Context, localClient client.Clie
 	remoteJob.Labels[constants.PrebuiltWorkloadLabel] = workloadName
 	remoteJob.Labels[kueue.MultiKueueOriginLabel] = origin
 
+	// clear the managedBy enables the controller to take over
+	remoteJob.Spec.ManagedBy = nil
+
 	return remoteClient.Create(ctx, &remoteJob)
 }
 
@@ -95,6 +99,15 @@ func (b *multiKueueAdapter) KeepAdmissionCheckPending() bool {
 }
 
 func (b *multiKueueAdapter) IsJobManagedByKueue(ctx context.Context, c client.Client, key types.NamespacedName) (bool, string, error) {
+	job := rayv1.RayJob{}
+	err := c.Get(ctx, key, &job)
+	if err != nil {
+		return false, "", err
+	}
+	jobControllerName := ptr.Deref(job.Spec.ManagedBy, "")
+	if jobControllerName != kueue.MultiKueueControllerName {
+		return false, fmt.Sprintf("Expecting spec.managedBy to be %q not %q", kueue.MultiKueueControllerName, jobControllerName), nil
+	}
 	return true, "", nil
 }
 
diff --git a/pkg/controller/jobs/rayjob/rayjob_webhook.go b/pkg/controller/jobs/rayjob/rayjob_webhook.go
index 582202f5b..eeb11107a 100644
--- a/pkg/controller/jobs/rayjob/rayjob_webhook.go
+++ b/pkg/controller/jobs/rayjob/rayjob_webhook.go
@@ -29,6 +29,7 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
+	"sigs.k8s.io/kueue/pkg/cache"
 	"sigs.k8s.io/kueue/pkg/controller/jobframework"
 	"sigs.k8s.io/kueue/pkg/controller/jobframework/webhook"
 	"sigs.k8s.io/kueue/pkg/features"
@@ -46,6 +47,7 @@ type RayJobWebhook struct {
 	queues                       *queue.Manager
 	manageJobsWithoutQueueName   bool
 	managedJobsNamespaceSelector labels.Selector
+	cache                        *cache.Cache
 }
 
 // SetupRayJobWebhook configures the webhook for RayJob.
@@ -56,6 +58,7 @@ func SetupRayJobWebhook(mgr ctrl.Manager, opts ...jobframework.Option) error {
 		queues:                       options.Queues,
 		manageJobsWithoutQueueName:   options.ManageJobsWithoutQueueName,
 		managedJobsNamespaceSelector: options.ManagedJobsNamespaceSelector,
+		cache:                        options.Cache,
 	}
 	obj := &rayv1.RayJob{}
 	return webhook.WebhookManagedBy(mgr).
@@ -71,11 +74,15 @@ var _ admission.CustomDefaulter = &RayJobWebhook{}
 
 // Default implements webhook.CustomDefaulter so a webhook will be registered for the type
 func (w *RayJobWebhook) Default(ctx context.Context, obj runtime.Object) error {
-	job := obj.(*rayv1.RayJob)
+	job := fromObject(obj)
 	log := ctrl.LoggerFrom(ctx).WithName("rayjob-webhook")
 	log.V(5).Info("Applying defaults")
-	jobframework.ApplyDefaultLocalQueue((*RayJob)(job).Object(), w.queues.DefaultLocalQueueExist)
-	return jobframework.ApplyDefaultForSuspend(ctx, (*RayJob)(job), w.client, w.manageJobsWithoutQueueName, w.managedJobsNamespaceSelector)
+	jobframework.ApplyDefaultLocalQueue(job.Object(), w.queues.DefaultLocalQueueExist)
+	if err := jobframework.ApplyDefaultForSuspend(ctx, job, w.client, w.manageJobsWithoutQueueName, w.managedJobsNamespaceSelector); err != nil {
+		return err
+	}
+	jobframework.ApplyDefaultForManagedBy(job, w.queues, w.cache, log)
+	return nil
 }
 
 // +kubebuilder:webhook:path=/validate-ray-io-v1-rayjob,mutating=false,failurePolicy=fail,sideEffects=None,groups=ray.io,resources=rayjobs,verbs=create;update,versions=v1,name=vrayjob.kb.io,admissionReviewVersions=v1
diff --git a/site/content/en/docs/installation/_index.md b/site/content/en/docs/installation/_index.md
index eeeefaed9..798d9dade 100644
--- a/site/content/en/docs/installation/_index.md
+++ b/site/content/en/docs/installation/_index.md
@@ -40,11 +40,7 @@ Use [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus)
 if you don't have your own monitoring system.
 
 The webhook server in kueue uses an internal cert management for provisioning certificates. If you want to use
-  a third-party one, e.g. [cert-manager](https://github.com/cert-manager/cert-manager), follow these steps:
-
-  1. Set `internalCertManagement.enable` to `false` in [config file](#install-a-custom-configured-released-version).
-  2. Comment out the `internalcert` folder in `config/default/kustomization.yaml`.
-  3. Enable `cert-manager` in `config/default/kustomization.yaml` and uncomment all sections with 'CERTMANAGER'.
+  a third-party one, e.g. [cert-manager](https://github.com/cert-manager/cert-manager), follow the [cert manage guide](/docs/tasks/manage/installation).
 
 [feature_gate]: https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/
 
@@ -69,8 +65,8 @@ kubectl wait deploy/kueue-controller-manager -nkueue-system --for=condition=avai
 To install a released version of Kueue in your cluster by [Helm](https://helm.sh/), run the following command:
 
 ```shell
-helm install kueue oci://registry.k8s.io/charts/kueue \
-  --version={{< param "version" >}} \
+helm install kueue oci://registry.k8s.io/kueue/charts/kueue \
+  --version={{< param "chart_version" >}} \
   --namespace  kueue-system \
   --create-namespace \
   --wait --timeout 300s
diff --git a/site/content/en/docs/tasks/_index.md b/site/content/en/docs/tasks/_index.md
index 3813c7eba..8487407b6 100755
--- a/site/content/en/docs/tasks/_index.md
+++ b/site/content/en/docs/tasks/_index.md
@@ -27,6 +27,7 @@ As a batch administrator, you can learn how to:
   [monitor pending workloads](manage/monitor_pending_workloads).
 - As a batch administrator, you can learn how to [run a Kueue managed Jobs with a custom WorkloadPriority](manage/run_job_with_workload_priority).
 - As a batch administrator, you can learn how to [setup a MultiKueue environment](manage/setup_multikueue).
+- As a batch administrator, you can learn how to [use third-party certificate authority with Kueue](manage/cert_manager).
 
 ### Batch user
 
diff --git a/site/content/en/docs/tasks/manage/productization/_index.md b/site/content/en/docs/tasks/manage/productization/_index.md
new file mode 100644
index 000000000..cd7360658
--- /dev/null
+++ b/site/content/en/docs/tasks/manage/productization/_index.md
@@ -0,0 +1,7 @@
+---
+title: "Productionization of Kueue"
+weight: 1
+date: 2024-03-22
+description: >
+  As a _batch administrator_, you may want to configure the installation of Kueue.
+---
\ No newline at end of file
diff --git a/site/content/en/docs/tasks/manage/productization/cert_manager.md b/site/content/en/docs/tasks/manage/productization/cert_manager.md
new file mode 100644
index 000000000..0419f6c73
--- /dev/null
+++ b/site/content/en/docs/tasks/manage/productization/cert_manager.md
@@ -0,0 +1,41 @@
+---
+title: "Configure external cert-manager"
+date: 2025-03-14
+weight: 1
+description: >
+  Cert Manager Support
+---
+
+This page shows how you can a third party certificate authority solution like
+Cert Manager.
+
+The page is intended for a [batch administrator](/docs/tasks#batch-administrator).
+
+## Before you begin
+
+Make sure you the following conditions are set:
+
+- A Kubernetes cluster is running.
+- The kubectl command-line tool has communication with your cluster.
+- [Kueue is installed](/docs/installation).
+- Cert Manager is [installed](https://cert-manager.io/docs/installation/)
+
+Kueue supports either Kustomize or installation via a Helm chart.
+
+### Internal Certificate management
+
+In all cases, Kueue's internal certificate management must be turned off
+if one wants to use CertManager.
+
+### Kustomize Installation
+
+  1. Set `internalCertManagement.enable` to `false` in the kueue configuration.
+  2. Comment out the `internalcert` folder in `config/default/kustomization.yaml`.
+  3. Enable `cert-manager` in `config/default/kustomization.yaml` and uncomment all sections with 'CERTMANAGER'.
+
+### Helm Installation
+
+Kueue can also support optional helm values for Cert Manager enablement.
+
+1. Disable `internalCertManager` in the kueue configuration.
+2. set `enableCertManager` in your values.yaml file to true.
diff --git a/site/content/en/docs/tasks/manage/productization/prometheus.md b/site/content/en/docs/tasks/manage/productization/prometheus.md
new file mode 100644
index 000000000..2577b6ddf
--- /dev/null
+++ b/site/content/en/docs/tasks/manage/productization/prometheus.md
@@ -0,0 +1,78 @@
+---
+title: "Configure Prometheus"
+date: 2025-03-14
+weight: 2
+description: >
+  Prometheus Support
+---
+
+
+This page shows how you configure Kueue to use prometheus metrics.
+
+The page is intended for a [batch administrator](/docs/tasks#batch-administrator).
+
+## Before you begin
+
+Make sure you the following conditions are set:
+
+- A Kubernetes cluster is running.
+- The kubectl command-line tool has communication with your cluster.
+- [Kueue is installed](/docs/installation).
+- Prometheus is [installed](https://prometheus-operator.dev/docs/getting-started/installation/)
+- Cert Manager can be optionally [installed](https://cert-manager.io/docs/installation/)
+
+Kueue supports either Kustomize or installation via a Helm chart.
+
+### Kustomize Installation
+
+1. Enable `prometheus` in `config/default/kustomization.yaml` and uncomment all sections with 'PROMETHEUS'.
+
+#### Kustomize Prometheus with certificates
+
+If one wants to require TLS verification for the metrics endpoint, follow the directions below.
+
+  1. Set `internalCertManagement.enable` to `false` in the kueue configuration.
+  2. Comment out the `internalcert` folder in `config/default/kustomization.yaml`.
+  3. Enable `cert-manager` in `config/default/kustomization.yaml` and uncomment all sections with 'CERTMANAGER'.
+  4. To enable secure metrics with TLS protection, uncomment all sections with 'PROMETHEUS-WITH-CERTS'.
+
+### Helm Installation
+
+#### Prometheus installation
+
+Kueue can also supports helm deployment for Prometheus.
+
+1. Set `enablePrometheus` in your values.yaml file to true.
+
+#### Helm Prometheus with certificates
+
+If one wants to enable secure metrics,
+
+1. Provide values for the tlsConfig. See below for an example.
+2. Disable internal cert management in the kueue configuration.
+3. Set both `enableCertManager` and `enablePrometheus` to true.
+
+An example for your tlsConfig in the helm chart could be as follows:
+
+```yaml
+...
+metrics:
+  prometheusNamespace: monitoring
+# tls configs for serviceMonitor
+  serviceMonitor:
+    tlsConfig:
+      serverName: kueue-controller-manager-metrics-service.kueue-system.svc
+      ca:
+        secret:
+          name: kueue-metrics-server-cert
+          key: ca.crt
+      cert:
+        secret:
+          name: kueue-metrics-server-cert
+          key: tls.crt
+      keySecret:
+        name: kueue-metrics-server-cert
+        key: tls.key
+```
+
+The secrets must reference the cert manager generated secrets.
diff --git a/site/content/en/docs/tasks/run/multikueue/kuberay.md b/site/content/en/docs/tasks/run/multikueue/kuberay.md
new file mode 100644
index 000000000..1494a6327
--- /dev/null
+++ b/site/content/en/docs/tasks/run/multikueue/kuberay.md
@@ -0,0 +1,38 @@
+---
+title: "Run Kuberay Jobs in Multi-Cluster"
+linkTitle: "Kuberay"
+weight: 4
+date: 2025-03-19
+description: >
+  Run a MultiKueue scheduled Kuberay Jobs.
+---
+
+## Before you begin
+
+Check the [MultiKueue installation guide](/docs/tasks/manage/setup_multikueue) on how to properly setup MultiKueue clusters.
+
+For the ease of setup and use we recommend using at least Kueue v0.11.0 and for Kuberay Operator at least v1.3.1.
+
+See [Kuberay Operator Installation](https://docs.ray.io/en/latest/cluster/kubernetes/getting-started/raycluster-quick-start.html#step-2-deploy-a-kuberay-operator) for installation and configuration details of Kuberay Operator.
+
+{{% alert title="Note" color="info" %}}
+Before the [ManagedBy feature](https://github.com/ray-project/kuberay/issues/2544) was supported in Kueue (below v0.11.0), the installation of Kuberay Operator in the <b>Manager Cluster</b> must be limited to CRDs only.
+
+To install the CRDs run:
+```bash
+kubectl create -k "github.com/ray-project/kuberay/ray-operator/config/crd?ref=v1.3.0"
+```
+{{% /alert %}}
+
+## MultiKueue integration
+
+Once the setup is complete you can test it by running a RayJob [`ray-job-sample.yaml`](/docs/tasks/run/rayjobs/#example-rayjob).
+
+{{% alert title="Note" color="primary" %}}
+Note: Kueue defaults the `spec.runPolicy.managedBy` field to `kueue.x-k8s.io/multikueue` on the management cluster for Kuberay Jobs (RayJob, RayCluster, RayService). 
+
+This allows the Kuberay Operator to ignore the Jobs managed by MultiKueue on the management cluster, and in particular skip Pod creation. 
+
+The pods are created and the actual computation will happen on the mirror copy of the Job on the selected worker cluster. 
+The mirror copy of the Job does not have the field set.
+{{% /alert %}}
diff --git a/site/go.sum b/site/go.sum
index caa0a3759..78bc9349c 100644
--- a/site/go.sum
+++ b/site/go.sum
@@ -1,3 +1,4 @@
 github.com/FortAwesome/Font-Awesome v0.0.0-20240402185447-c0f460dca7f7/go.mod h1:IUgezN/MFpCDIlFezw3L8j83oeiIuYoj28Miwr/KUYo=
+github.com/google/docsy v0.10.0 h1:6tMDacPwAyRWNCfvsn/9qGOZDQ8b0aRzjRZvnZPY5dg=
 github.com/google/docsy v0.10.0/go.mod h1:c0nIAqmRTOuJ01F85U/wJPQtc3Zj9N58Kea9bOT2AJc=
 github.com/twbs/bootstrap v5.3.3+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0=
diff --git a/site/hugo.toml b/site/hugo.toml
index ab5f4efba..2fd72af20 100644
--- a/site/hugo.toml
+++ b/site/hugo.toml
@@ -90,7 +90,10 @@ ignoreFiles = []
   # The major.minor version tag for the version of the docs represented in this
   # branch of the repository. Used in the "version-banner" partial to display a
   # version number for this doc set.
-  version = "v0.10.2"
+  version = "v0.10.3"
+
+  # Version of Kueue without the leading "v", as used for Helm charts.
+  chart_version = "0.10.3"
 
   # Flag used in the "version-banner" partial to decide whether to display a
   # banner on every page indicating that this is an archived version of the docs.



Test patch:
diff --git a/pkg/controller/jobs/raycluster/raycluster_multikueue_adapter_test.go b/pkg/controller/jobs/raycluster/raycluster_multikueue_adapter_test.go
index 7b9d23f59..e37ffc1a0 100644
--- a/pkg/controller/jobs/raycluster/raycluster_multikueue_adapter_test.go
+++ b/pkg/controller/jobs/raycluster/raycluster_multikueue_adapter_test.go
@@ -18,6 +18,7 @@ package raycluster
 
 import (
 	"context"
+	"errors"
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
@@ -146,6 +147,51 @@ func TestMultiKueueAdapter(t *testing.T) {
 				return adapter.DeleteRemoteObject(ctx, workerClient, types.NamespacedName{Name: "raycluster1", Namespace: TestNamespace})
 			},
 		},
+		"raycluster with wrong managedBy is not considered managed": {
+			managersRayClusters: []rayv1.RayCluster{
+				*rayClusterBuilder.Clone().
+					ManagedBy("some-other-controller").
+					Obj(),
+			},
+			operation: func(ctx context.Context, adapter *multiKueueAdapter, managerClient, workerClient client.Client) error {
+				if isManged, _, _ := adapter.IsJobManagedByKueue(ctx, managerClient, types.NamespacedName{Name: "raycluster1", Namespace: TestNamespace}); isManged {
+					return errors.New("expecting false")
+				}
+				return nil
+			},
+			wantManagersRayClusters: []rayv1.RayCluster{
+				*rayClusterBuilder.Clone().
+					ManagedBy("some-other-controller").
+					Obj(),
+			},
+		},
+
+		"raycluster managedBy multikueue": {
+			managersRayClusters: []rayv1.RayCluster{
+				*rayClusterBuilder.Clone().
+					ManagedBy(kueue.MultiKueueControllerName).
+					Obj(),
+			},
+			operation: func(ctx context.Context, adapter *multiKueueAdapter, managerClient, workerClient client.Client) error {
+				if isManged, _, _ := adapter.IsJobManagedByKueue(ctx, managerClient, types.NamespacedName{Name: "raycluster1", Namespace: TestNamespace}); !isManged {
+					return errors.New("expecting true")
+				}
+				return nil
+			},
+			wantManagersRayClusters: []rayv1.RayCluster{
+				*rayClusterBuilder.Clone().
+					ManagedBy(kueue.MultiKueueControllerName).
+					Obj(),
+			},
+		},
+		"missing raycluster is not considered managed": {
+			operation: func(ctx context.Context, adapter *multiKueueAdapter, managerClient, workerClient client.Client) error {
+				if isManged, _, _ := adapter.IsJobManagedByKueue(ctx, managerClient, types.NamespacedName{Name: "raycluster1", Namespace: TestNamespace}); isManged {
+					return errors.New("expecting false")
+				}
+				return nil
+			},
+		},
 	}
 	for name, tc := range cases {
 		t.Run(name, func(t *testing.T) {
diff --git a/pkg/controller/jobs/raycluster/raycluster_webhook_test.go b/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
index 2c55411ef..c6f4eda22 100644
--- a/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
+++ b/pkg/controller/jobs/raycluster/raycluster_webhook_test.go
@@ -122,6 +122,7 @@ func TestValidateDefault(t *testing.T) {
 			wh := &RayClusterWebhook{
 				manageJobsWithoutQueueName: tc.manageAll,
 				queues:                     queueManager,
+				cache:                      cqCache,
 			}
 			result := tc.oldJob.DeepCopy()
 			if err := wh.Default(context.Background(), result); err != nil {
diff --git a/pkg/controller/jobs/rayjob/rayjob_multikueue_adapter_test.go b/pkg/controller/jobs/rayjob/rayjob_multikueue_adapter_test.go
index bd01d505e..ef64aaf6c 100644
--- a/pkg/controller/jobs/rayjob/rayjob_multikueue_adapter_test.go
+++ b/pkg/controller/jobs/rayjob/rayjob_multikueue_adapter_test.go
@@ -18,6 +18,7 @@ package rayjob
 
 import (
 	"context"
+	"errors"
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
@@ -145,6 +146,51 @@ func TestMultiKueueAdapter(t *testing.T) {
 				return adapter.DeleteRemoteObject(ctx, workerClient, types.NamespacedName{Name: "rayjob1", Namespace: TestNamespace})
 			},
 		},
+		"job with wrong managedBy is not considered managed": {
+			managersRayJobs: []rayv1.RayJob{
+				*rayJobBuilder.Clone().
+					ManagedBy("some-other-controller").
+					Obj(),
+			},
+			operation: func(ctx context.Context, adapter *multiKueueAdapter, managerClient, workerClient client.Client) error {
+				if isManged, _, _ := adapter.IsJobManagedByKueue(ctx, managerClient, types.NamespacedName{Name: "rayjob1", Namespace: TestNamespace}); isManged {
+					return errors.New("expecting false")
+				}
+				return nil
+			},
+			wantManagersRayJobs: []rayv1.RayJob{
+				*rayJobBuilder.Clone().
+					ManagedBy("some-other-controller").
+					Obj(),
+			},
+		},
+
+		"job managedBy multikueue": {
+			managersRayJobs: []rayv1.RayJob{
+				*rayJobBuilder.Clone().
+					ManagedBy(kueue.MultiKueueControllerName).
+					Obj(),
+			},
+			operation: func(ctx context.Context, adapter *multiKueueAdapter, managerClient, workerClient client.Client) error {
+				if isManged, _, _ := adapter.IsJobManagedByKueue(ctx, managerClient, types.NamespacedName{Name: "rayjob1", Namespace: TestNamespace}); !isManged {
+					return errors.New("expecting true")
+				}
+				return nil
+			},
+			wantManagersRayJobs: []rayv1.RayJob{
+				*rayJobBuilder.Clone().
+					ManagedBy(kueue.MultiKueueControllerName).
+					Obj(),
+			},
+		},
+		"missing job is not considered managed": {
+			operation: func(ctx context.Context, adapter *multiKueueAdapter, managerClient, workerClient client.Client) error {
+				if isManged, _, _ := adapter.IsJobManagedByKueue(ctx, managerClient, types.NamespacedName{Name: "rayjob1", Namespace: TestNamespace}); isManged {
+					return errors.New("expecting false")
+				}
+				return nil
+			},
+		},
 	}
 	for name, tc := range cases {
 		t.Run(name, func(t *testing.T) {
diff --git a/pkg/controller/jobs/rayjob/rayjob_webhook_test.go b/pkg/controller/jobs/rayjob/rayjob_webhook_test.go
index e34c6ac55..d95588642 100644
--- a/pkg/controller/jobs/rayjob/rayjob_webhook_test.go
+++ b/pkg/controller/jobs/rayjob/rayjob_webhook_test.go
@@ -121,6 +121,7 @@ func TestValidateDefault(t *testing.T) {
 			wh := &RayJobWebhook{
 				manageJobsWithoutQueueName: tc.manageAll,
 				queues:                     queueManager,
+				cache:                      cqCache,
 			}
 			result := tc.oldJob.DeepCopy()
 			if err := wh.Default(context.Background(), result); err != nil {
diff --git a/pkg/util/testingjobs/raycluster/wrappers.go b/pkg/util/testingjobs/raycluster/wrappers.go
index e47f73254..088f10263 100644
--- a/pkg/util/testingjobs/raycluster/wrappers.go
+++ b/pkg/util/testingjobs/raycluster/wrappers.go
@@ -195,8 +195,8 @@ func (j *ClusterWrapper) StatusConditions(c metav1.Condition) *ClusterWrapper {
 }
 
 // ManagedBy adds a managedby.
-func (j *ClusterWrapper) ManagedBy(_ string) *ClusterWrapper {
-	// j.Spec.ManagedBy = &c
+func (j *ClusterWrapper) ManagedBy(c string) *ClusterWrapper {
+	j.Spec.ManagedBy = &c
 	return j
 }
 
diff --git a/pkg/util/testingjobs/rayjob/wrappers.go b/pkg/util/testingjobs/rayjob/wrappers.go
index a0f3e0f25..479d1abbb 100644
--- a/pkg/util/testingjobs/rayjob/wrappers.go
+++ b/pkg/util/testingjobs/rayjob/wrappers.go
@@ -279,3 +279,8 @@ func (j *JobWrapper) Env(rayType rayv1.RayNodeType, name, value string) *JobWrap
 	}
 	return j
 }
+
+func (j *JobWrapper) ManagedBy(c string) *JobWrapper {
+	j.Spec.ManagedBy = &c
+	return j
+}
diff --git a/test/e2e/multikueue/suite_test.go b/test/e2e/multikueue/suite_test.go
index 273cef599..5c1344562 100644
--- a/test/e2e/multikueue/suite_test.go
+++ b/test/e2e/multikueue/suite_test.go
@@ -297,6 +297,7 @@ var _ = ginkgo.BeforeSuite(func() {
 	util.WaitForAppWrapperAvailability(ctx, k8sWorker1Client)
 	util.WaitForAppWrapperAvailability(ctx, k8sWorker2Client)
 
+	util.WaitForKubeRayOperatorAvailability(ctx, k8sManagerClient)
 	util.WaitForKubeRayOperatorAvailability(ctx, k8sWorker1Client)
 	util.WaitForKubeRayOperatorAvailability(ctx, k8sWorker2Client)
 
diff --git a/test/util/constants.go b/test/util/constants.go
index 61c6934d9..b2f3a883b 100644
--- a/test/util/constants.go
+++ b/test/util/constants.go
@@ -64,7 +64,15 @@ var (
 )
 
 var (
-	BehaviorWaitForDeletion           = []string{"netexec"}
+	// For full documentation on agnhost subcommands see the following documentation:
+	// https://pkg.go.dev/k8s.io/kubernetes/test/images/agnhost#section-readme
+
+	// Starts a simple HTTP(S) with a few endpoints, one of which is the /exit endpoint which exits with `exit 0`
+	BehaviorWaitForDeletion = []string{"netexec"}
+
+	// Starts a container which will remain paused and therefore must be deleted resulting in `exit 1`
 	BehaviorWaitForDeletionFailOnExit = []string{"pause"}
-	BehaviorExitFast                  = []string{"entrypoint-tester"}
+
+	// The agnhost container will print args passed and `exit 0`
+	BehaviorExitFast = []string{"entrypoint-tester"}
 )