-
Notifications
You must be signed in to change notification settings - Fork 134
add HPA feature/unit/fvt/docs/script #342
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
dcf8fd9
add HPA feature/unit/fvt/docs/script
Jooho 2cc2cff
Merge branch 'main' into kserve-hpa
Jooho 30e7e78
fix hpa fvt
Jooho 4f1b941
Fix HPA related issues
Jooho c966cf1
Merge branch 'main' into kserve-hpa
Jooho 2b1abb4
delete namespace:system from manifests
Jooho ed58fda
delete modelmesh.yaml release artifact from doc
Jooho File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,14 +20,16 @@ jobs: | |
- uses: actions/checkout@v2 | ||
- uses: actions/setup-go@v2 | ||
with: | ||
go-version: '1.18.7' | ||
- name: Setup Minikube | ||
run: | | ||
wget --no-verbose https://github.com/kubernetes/minikube/releases/download/v1.25.1/minikube-linux-amd64 | ||
sudo cp minikube-linux-amd64 /usr/local/bin/minikube | ||
sudo chmod 755 /usr/local/bin/minikube | ||
sudo apt-get install -y conntrack socat | ||
minikube start --driver=none --kubernetes-version v1.22.10 | ||
go-version: '1.18.7' | ||
- name: Start Minikube | ||
uses: medyagh/[email protected] | ||
id: minikube | ||
with: | ||
minikube-version: 1.27.1 | ||
container-runtime: docker | ||
kubernetes-version: v1.25.2 | ||
cpus: max | ||
memory: max | ||
- name: Check pods | ||
run: | | ||
sleep 30 | ||
|
@@ -55,6 +57,7 @@ jobs: | |
echo -e '\n disabled: true' >> config/runtimes/torchserve-0.x.yaml | ||
- name: Build Controller image | ||
run: | | ||
eval $(minikube -p minikube docker-env) | ||
make build.develop | ||
./scripts/build_docker.sh --target runtime --tag ${{ env.IMAGE_TAG }} | ||
- name: Install ModelMesh Serving | ||
|
@@ -63,12 +66,14 @@ jobs: | |
./scripts/install.sh --namespace modelmesh-serving --fvt --dev-mode-logging | ||
- name: Free up disk space | ||
run: | | ||
eval $(minikube -p minikube docker-env) | ||
echo "Pruning images" | ||
docker image prune -a -f | ||
docker system df | ||
df -h | ||
- name: Pre-pull runtime images | ||
run: | | ||
eval $(minikube -p minikube docker-env) | ||
docker pull nvcr.io/nvidia/tritonserver:21.06.1-py3 | ||
docker pull seldonio/mlserver:0.5.2 | ||
docker pull openvino/model_server:2022.2 | ||
|
@@ -78,6 +83,7 @@ jobs: | |
docker pull kserve/modelmesh | ||
- name: Check installation | ||
run: | | ||
eval $(minikube -p minikube docker-env) | ||
docker images | ||
kubectl get pods | ||
kubectl get clusterservingruntimes | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
|
||
public/ | ||
target/ | ||
vendor/ | ||
|
||
# Binaries for programs and plugins | ||
*.exe | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,7 @@ RUN microdnf install \ | |
tar \ | ||
vim \ | ||
git \ | ||
jq \ | ||
python38 \ | ||
nodejs && \ | ||
pip3 install pre-commit && \ | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
//Copyright 2021 IBM Corporation | ||
// | ||
//Licensed under the Apache License, Version 2.0 (the "License"); | ||
//you may not use this file except in compliance with the License. | ||
//You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
//Unless required by applicable law or agreed to in writing, software | ||
//distributed under the License is distributed on an "AS IS" BASIS, | ||
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
//See the License for the specific language governing permissions and | ||
//limitations under the License. | ||
// | ||
package v1alpha1 | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"math" | ||
"net/http" | ||
"strconv" | ||
|
||
kservev1alpha "github.com/kserve/kserve/pkg/apis/serving/v1alpha1" | ||
"github.com/kserve/kserve/pkg/constants" | ||
"github.com/kserve/modelmesh-serving/controllers/autoscaler" | ||
mmcontstant "github.com/kserve/modelmesh-serving/pkg/constants" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission" | ||
) | ||
|
||
//+kubebuilder:webhook:path=/validate-serving-modelmesh-io-v1alpha1-servingruntime,mutating=false,failurePolicy=fail,sideEffects=None,groups=serving.kserve.io,resources=servingruntimes;clusterservingruntimes,verbs=create;update,versions=v1alpha1,name=servingruntime.modelmesh-webhook-server.default,admissionReviewVersions=v1 | ||
type ServingRuntimeWebhook struct { | ||
Client client.Client | ||
decoder *admission.Decoder | ||
} | ||
|
||
func (s *ServingRuntimeWebhook) Handle(ctx context.Context, req admission.Request) admission.Response { | ||
tjohnson31415 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var srAnnotations map[string]string | ||
srReplicas := uint16(math.MaxUint16) | ||
multiModel := false | ||
|
||
if req.Kind.Kind == "ServingRuntime" { | ||
Jooho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
servingRuntime := &kservev1alpha.ServingRuntime{} | ||
err := s.decoder.Decode(req, servingRuntime) | ||
if err != nil { | ||
return admission.Errored(http.StatusBadRequest, err) | ||
} | ||
srAnnotations = servingRuntime.ObjectMeta.Annotations | ||
|
||
if (*servingRuntime).Spec.Replicas != nil { | ||
srReplicas = uint16(*servingRuntime.Spec.Replicas) | ||
} | ||
|
||
if (*servingRuntime).Spec.MultiModel != nil { | ||
multiModel = *servingRuntime.Spec.MultiModel | ||
} | ||
|
||
} else { | ||
clusterServingRuntime := &kservev1alpha.ClusterServingRuntime{} | ||
err := s.decoder.Decode(req, clusterServingRuntime) | ||
if err != nil { | ||
return admission.Errored(http.StatusBadRequest, err) | ||
} | ||
srAnnotations = clusterServingRuntime.ObjectMeta.Annotations | ||
|
||
if (*clusterServingRuntime).Spec.Replicas != nil { | ||
srReplicas = uint16(*clusterServingRuntime.Spec.Replicas) | ||
} | ||
|
||
if (*clusterServingRuntime).Spec.MultiModel != nil { | ||
multiModel = *clusterServingRuntime.Spec.MultiModel | ||
} | ||
} | ||
|
||
if !multiModel { | ||
return admission.Allowed("Not validating ServingRuntime because it is not ModelMesh compatible") | ||
} | ||
Jooho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if err := validateServingRuntimeAutoscaler(srAnnotations); err != nil { | ||
return admission.Denied(err.Error()) | ||
} | ||
|
||
if err := validateAutoscalerTargetUtilizationPercentage(srAnnotations); err != nil { | ||
return admission.Denied(err.Error()) | ||
} | ||
|
||
if err := validateAutoScalingReplicas(srAnnotations, srReplicas); err != nil { | ||
return admission.Denied(err.Error()) | ||
} | ||
|
||
return admission.Allowed("Passed all validation checks for ServingRuntime") | ||
} | ||
|
||
// InjectDecoder injects the decoder. | ||
func (s *ServingRuntimeWebhook) InjectDecoder(d *admission.Decoder) error { | ||
s.decoder = d | ||
return nil | ||
} | ||
|
||
// Validation of servingruntime autoscaler class | ||
func validateServingRuntimeAutoscaler(annotations map[string]string) error { | ||
value, ok := annotations[constants.AutoscalerClass] | ||
class := constants.AutoscalerClassType(value) | ||
if ok { | ||
for _, item := range constants.AutoscalerAllowedClassList { | ||
if class == item { | ||
switch class { | ||
case constants.AutoscalerClassHPA: | ||
if metric, ok := annotations[constants.AutoscalerMetrics]; ok { | ||
return validateHPAMetrics(constants.AutoscalerMetricsType(metric)) | ||
} else { | ||
return nil | ||
} | ||
default: | ||
return fmt.Errorf("unknown autoscaler class [%s]", class) | ||
} | ||
} | ||
} | ||
return fmt.Errorf("[%s] is not a supported autoscaler class type.\n", value) | ||
Jooho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
return nil | ||
} | ||
|
||
// Validate of autoscaler targetUtilizationPercentage | ||
func validateAutoscalerTargetUtilizationPercentage(annotations map[string]string) error { | ||
if value, ok := annotations[constants.TargetUtilizationPercentage]; ok { | ||
t, err := strconv.Atoi(value) | ||
if err != nil { | ||
return fmt.Errorf("The target utilization percentage should be a [1-100] integer.") | ||
} else { | ||
if t < 1 || t > 100 { | ||
return fmt.Errorf("The target utilization percentage should be a [1-100] integer.") | ||
} | ||
Jooho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Validate scaling options | ||
func validateAutoScalingReplicas(annotations map[string]string, srReplicas uint16) error { | ||
autoscalerClassType := autoscaler.AutoscalerClassNone | ||
if value, ok := annotations[constants.AutoscalerClass]; ok { | ||
autoscalerClassType = value | ||
} | ||
|
||
switch autoscalerClassType { | ||
case string(constants.AutoscalerClassHPA): | ||
if srReplicas != math.MaxUint16 { | ||
return fmt.Errorf("Autoscaler is enabled and also replicas variable set. You can not set both.") | ||
} | ||
return validateScalingHPA(annotations) | ||
default: | ||
return nil | ||
} | ||
} | ||
|
||
func validateScalingHPA(annotations map[string]string) error { | ||
metric := constants.AutoScalerMetricsCPU | ||
if value, ok := annotations[constants.AutoscalerMetrics]; ok { | ||
metric = constants.AutoscalerMetricsType(value) | ||
} | ||
|
||
minReplicas := 1 | ||
if value, ok := annotations[mmcontstant.MinScaleAnnotationKey]; ok { | ||
if valueInt, err := strconv.Atoi(value); err != nil { | ||
return fmt.Errorf("The min replicas should be a integer.") | ||
} else if valueInt < 1 { | ||
return fmt.Errorf("The min replicas should be more than 0") | ||
} else { | ||
minReplicas = valueInt | ||
} | ||
} | ||
|
||
maxReplicas := 1 | ||
if value, ok := annotations[mmcontstant.MaxScaleAnnotationKey]; ok { | ||
if valueInt, err := strconv.Atoi(value); err != nil { | ||
return fmt.Errorf("The max replicas should be a integer.") | ||
} else { | ||
maxReplicas = valueInt | ||
} | ||
} | ||
|
||
if minReplicas > maxReplicas { | ||
return fmt.Errorf("The max replicas should be same or bigger than min replicas.") | ||
} | ||
|
||
err := validateHPAMetrics(metric) | ||
if err != nil { | ||
return err | ||
} | ||
Jooho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if value, ok := annotations[constants.TargetUtilizationPercentage]; ok { | ||
t, err := strconv.Atoi(value) | ||
if err != nil { | ||
return fmt.Errorf("The target utilization percentage should be a [1-100] integer.") | ||
} else if metric == constants.AutoScalerMetricsMemory && t < 1 { | ||
return fmt.Errorf("The target memory should be greater than 1 MiB") | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Validate of autoscaler HPA metrics | ||
func validateHPAMetrics(metric constants.AutoscalerMetricsType) error { | ||
for _, item := range constants.AutoscalerAllowedMetricsList { | ||
if item == metric { | ||
return nil | ||
} | ||
} | ||
return fmt.Errorf("[%s] is not a supported metric.\n", metric) | ||
|
||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.