Skip to content

Commit

Permalink
KEP: 2170: Adding cel validations on TrainingRuntime/ClusterTrainingR…
Browse files Browse the repository at this point in the history
…untime CRDs (#2313)

Signed-off-by: Akshay Chitneni <achitneni@apple.com>
Co-authored-by: Akshay Chitneni <achitneni@apple.com>
  • Loading branch information
akshaychitneni and Akshay Chitneni authored Feb 14, 2025
1 parent 3f3a8d3 commit 9b3b1de
Show file tree
Hide file tree
Showing 10 changed files with 246 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ spec:
description: Configuration for the MPI Runtime.
properties:
mpiImplementation:
default: OpenMPI
description: |-
Implementation name for the MPI to create the appropriate hostfile.
Defaults to OpenMPI.
Expand All @@ -61,6 +62,7 @@ spec:
format: int32
type: integer
runLauncherAsNode:
default: false
description: |-
Whether to run training process on the launcher Job.
Defaults to false.
Expand Down Expand Up @@ -585,14 +587,24 @@ spec:
type: integer
type: object
numProcPerNode:
default: auto
description: |-
Number of processes per node.
This value is inserted into the `--nproc-per-node` argument of the `torchrun` CLI.
Supported values: `auto`, `cpu`, `gpu`, or int value.
Defaults to `auto`.
type: string
x-kubernetes-validations:
- message: NumProcPerNode must be equal to auto, cpu, gpu,
or int value
rule: self in ['auto', 'cpu', 'gpu'] || type(self) == int
type: object
type: object
x-kubernetes-validations:
- message: numNodes should not be set if torch.elasticPolicy is configured
rule: '!(has(self.numNodes) && (has(self.torch) && has(self.torch.elasticPolicy)))'
- message: Only one of the policy can be configured
rule: '!(has(self.torch) && has(self.mpi))'
podGroupPolicy:
description: Configuration for the PodGroup to enable gang-scheduling
via supported plugins.
Expand All @@ -602,6 +614,7 @@ spec:
for gang-scheduling.
properties:
scheduleTimeoutSeconds:
default: 60
description: |-
Time threshold to schedule PodGroup for gang-scheduling.
If the scheduling timeout is equal to 0, the default value is used.
Expand Down
13 changes: 13 additions & 0 deletions manifests/base/crds/trainer.kubeflow.org_trainingruntimes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ spec:
description: Configuration for the MPI Runtime.
properties:
mpiImplementation:
default: OpenMPI
description: |-
Implementation name for the MPI to create the appropriate hostfile.
Defaults to OpenMPI.
Expand All @@ -61,6 +62,7 @@ spec:
format: int32
type: integer
runLauncherAsNode:
default: false
description: |-
Whether to run training process on the launcher Job.
Defaults to false.
Expand Down Expand Up @@ -585,14 +587,24 @@ spec:
type: integer
type: object
numProcPerNode:
default: auto
description: |-
Number of processes per node.
This value is inserted into the `--nproc-per-node` argument of the `torchrun` CLI.
Supported values: `auto`, `cpu`, `gpu`, or int value.
Defaults to `auto`.
type: string
x-kubernetes-validations:
- message: NumProcPerNode must be equal to auto, cpu, gpu,
or int value
rule: self in ['auto', 'cpu', 'gpu'] || type(self) == int
type: object
type: object
x-kubernetes-validations:
- message: numNodes should not be set if torch.elasticPolicy is configured
rule: '!(has(self.numNodes) && (has(self.torch) && has(self.torch.elasticPolicy)))'
- message: Only one of the policy can be configured
rule: '!(has(self.torch) && has(self.mpi))'
podGroupPolicy:
description: Configuration for the PodGroup to enable gang-scheduling
via supported plugins.
Expand All @@ -602,6 +614,7 @@ spec:
for gang-scheduling.
properties:
scheduleTimeoutSeconds:
default: 60
description: |-
Time threshold to schedule PodGroup for gang-scheduling.
If the scheduling timeout is equal to 0, the default value is used.
Expand Down
7 changes: 7 additions & 0 deletions pkg/apis/trainer/v1alpha1/trainingruntime_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,13 @@ type CoschedulingPodGroupPolicySource struct {
// Time threshold to schedule PodGroup for gang-scheduling.
// If the scheduling timeout is equal to 0, the default value is used.
// Defaults to 60 seconds.
// +kubebuilder:default=60
ScheduleTimeoutSeconds *int32 `json:"scheduleTimeoutSeconds,omitempty"`
}

// MLPolicy represents configuration for the model trining with ML-specific parameters.
// +kubebuilder:validation:XValidation:rule="!(has(self.numNodes) && (has(self.torch) && has(self.torch.elasticPolicy)))", message="numNodes should not be set if torch.elasticPolicy is configured"
// +kubebuilder:validation:XValidation:rule="!(has(self.torch) && has(self.mpi))", message="Only one of the policy can be configured"
type MLPolicy struct {
// Number of training nodes.
// Defaults to 1.
Expand Down Expand Up @@ -173,6 +176,8 @@ type TorchMLPolicySource struct {
// Supported values: `auto`, `cpu`, `gpu`, or int value.
// TODO (andreyvelich): Add kubebuilder validation.
// Defaults to `auto`.
// +kubebuilder:default="auto"
// +kubebuilder:validation:XValidation:rule="self in ['auto', 'cpu', 'gpu'] || type(self) == int", message="NumProcPerNode must be equal to auto, cpu, gpu, or int value"
NumProcPerNode *string `json:"numProcPerNode,omitempty"`

// Elastic policy for the PyTorch training.
Expand Down Expand Up @@ -210,6 +215,7 @@ type MPIMLPolicySource struct {

// Implementation name for the MPI to create the appropriate hostfile.
// Defaults to OpenMPI.
// +kubebuilder:default=OpenMPI
MPIImplementation MPIImplementation `json:"mpiImplementation,omitempty"`

// Directory where SSH keys are mounted.
Expand All @@ -218,6 +224,7 @@ type MPIMLPolicySource struct {

// Whether to run training process on the launcher Job.
// Defaults to false.
// +kubebuilder:default=false
RunLauncherAsNode *bool `json:"runLauncherAsNode,omitempty"`
}

Expand Down
7 changes: 4 additions & 3 deletions pkg/runtime/core/trainingruntime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package core
import (
"context"
"fmt"
"k8s.io/utils/ptr"
"testing"

"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -263,7 +264,7 @@ func TestTrainingRuntimeNewObjects(t *testing.T) {
"succeeded to build JobSet with Torch values from the TrainJob": {
trainingRuntime: testingutil.MakeTrainingRuntimeWrapper(metav1.NamespaceDefault, "test-runtime").RuntimeSpec(
testingutil.MakeTrainingRuntimeSpecWrapper(testingutil.MakeTrainingRuntimeWrapper(metav1.NamespaceDefault, "test-runtime").Spec).
TorchPolicy(100, "auto").
TorchPolicy(100, ptr.To("auto")).
ContainerTrainer("test:runtime", []string{"runtime"}, []string{"runtime"}, resRequests).
Obj(),
).Obj(),
Expand All @@ -273,7 +274,7 @@ func TestTrainingRuntimeNewObjects(t *testing.T) {
Trainer(
testingutil.MakeTrainJobTrainerWrapper().
NumNodes(30).
NumProcPerNode("3").
NumProcPerNode(ptr.To("3")).
Obj(),
).
Obj(),
Expand Down Expand Up @@ -317,7 +318,7 @@ func TestTrainingRuntimeNewObjects(t *testing.T) {
"succeeded to build JobSet with Torch values from the Runtime and envs.": {
trainingRuntime: testingutil.MakeTrainingRuntimeWrapper(metav1.NamespaceDefault, "test-runtime").RuntimeSpec(
testingutil.MakeTrainingRuntimeSpecWrapper(testingutil.MakeTrainingRuntimeWrapper(metav1.NamespaceDefault, "test-runtime").Spec).
TorchPolicy(100, "auto").
TorchPolicy(100, ptr.To("auto")).
ContainerTrainer("test:runtime", []string{"runtime"}, []string{"runtime"}, resRequests).
ContainerTrainerEnv(
[]corev1.EnvVar{
Expand Down
1 change: 1 addition & 0 deletions pkg/runtime/framework/plugins/torch/torch.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func (t *Torch) EnforceMLPolicy(info *runtime.Info, trainJob *trainer.TrainJob)
// TODO (andreyvelich): Add validation to check that TrainJob doesn't have "PET_" envs.
// TODO (andreyvelich): We should validate that envs from different plugins don't conflict with each other.
// Ref: https://github.com/kubeflow/trainer/pull/2308#discussion_r1823229940

infoEnvs := []corev1.EnvVar{
{
Name: constants.TorchEnvNumNodes,
Expand Down
8 changes: 4 additions & 4 deletions pkg/util/testing/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@ func (t *TrainJobTrainerWrapper) NumNodes(numNodes int32) *TrainJobTrainerWrappe
return t
}

func (t *TrainJobTrainerWrapper) NumProcPerNode(numProcPerNode string) *TrainJobTrainerWrapper {
t.Trainer.NumProcPerNode = &numProcPerNode
func (t *TrainJobTrainerWrapper) NumProcPerNode(numProcPerNode *string) *TrainJobTrainerWrapper {
t.Trainer.NumProcPerNode = numProcPerNode
return t
}

Expand Down Expand Up @@ -689,12 +689,12 @@ func (s *TrainingRuntimeSpecWrapper) NumNodes(numNodes int32) *TrainingRuntimeSp
return s
}

func (s *TrainingRuntimeSpecWrapper) TorchPolicy(numNodes int32, numProcPerNode string) *TrainingRuntimeSpecWrapper {
func (s *TrainingRuntimeSpecWrapper) TorchPolicy(numNodes int32, numProcPerNode *string) *TrainingRuntimeSpecWrapper {
s.MLPolicy = &trainer.MLPolicy{
NumNodes: &numNodes,
MLPolicySource: trainer.MLPolicySource{
Torch: &trainer.TorchMLPolicySource{
NumProcPerNode: &numProcPerNode,
NumProcPerNode: numProcPerNode,
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion test/integration/controller/trainjob_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ var _ = ginkgo.Describe("TrainJob controller", ginkgo.Ordered, func() {
trainingRuntime = testingutil.MakeTrainingRuntimeWrapper(ns.Name, "alpha").
RuntimeSpec(
testingutil.MakeTrainingRuntimeSpecWrapper(testingutil.MakeTrainingRuntimeWrapper(metav1.NamespaceDefault, "alpha").Spec).
TorchPolicy(100, "auto").
TorchPolicy(100, ptr.To("auto")).
ContainerTrainer("test:runtime", []string{"runtime"}, []string{"runtime"}, resRequests).
Obj()).
Obj()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2024 The Kubeflow Authors.
Copyright 2025 The Kubeflow Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
77 changes: 0 additions & 77 deletions test/integration/webhooks/trainingruntime_test.go

This file was deleted.

Loading

0 comments on commit 9b3b1de

Please sign in to comment.