Skip to content
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

Expose generic OpenShift routes for KServe InferenceServices #84

Merged
merged 8 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
9 changes: 9 additions & 0 deletions controllers/comparators/resourcecomparator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package comparators

import (
"sigs.k8s.io/controller-runtime/pkg/client"
)

type ResourceComparator interface {
Compare(deployed client.Object, requested client.Object) bool
}
18 changes: 18 additions & 0 deletions controllers/comparators/route_comparator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package comparators

import (
v1 "github.com/openshift/api/route/v1"
"k8s.io/apimachinery/pkg/api/equality"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type RouteComparator struct {
}

func (c *RouteComparator) Compare(deployed client.Object, requested client.Object) bool {
deployedRoute := deployed.(*v1.Route)
requestedRoute := requested.(*v1.Route)
return equality.Semantic.DeepEqual(deployedRoute.Spec, requestedRoute.Spec) &&
equality.Semantic.DeepEqual(deployedRoute.Annotations, requestedRoute.Annotations) &&
equality.Semantic.DeepEqual(deployedRoute.Labels, requestedRoute.Labels)
}
47 changes: 47 additions & 0 deletions controllers/components/route.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package components

import (
"context"
"github.com/go-logr/logr"
"github.com/opendatahub-io/odh-model-controller/controllers/comparators"
v1 "github.com/openshift/api/route/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type RouteHandler interface {
FetchRoute(key types.NamespacedName) (*v1.Route, error)
GetComparator() comparators.ResourceComparator
}

type routeHandler struct {
client.Client
ctx context.Context
log logr.Logger
}

func NewRouteHandler(client client.Client, ctx context.Context, log logr.Logger) RouteHandler {
return &routeHandler{
Client: client,
ctx: ctx,
log: log,
}
}

func (o *routeHandler) FetchRoute(key types.NamespacedName) (*v1.Route, error) {
route := &v1.Route{}
err := o.Get(o.ctx, key, route)
if err != nil && errors.IsNotFound(err) {
o.log.Info("Openshift Route not found.")
return nil, nil
} else if err != nil {
return nil, err
}
o.log.Info("Successfully fetch deployed Openshift Route")
return route, nil
}

func (o *routeHandler) GetComparator() comparators.ResourceComparator {
return &comparators.RouteComparator{}
}
26 changes: 16 additions & 10 deletions controllers/inferenceservice_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,24 +82,20 @@ func (r *OpenshiftInferenceServiceReconciler) Reconcile(ctx context.Context, req
return ctrl.Result{}, err
}

if inferenceservice.GetDeletionTimestamp() != nil {
return reconcile.Result{}, r.delete(ctx, inferenceservice)
}

// Check what deployment mode is used by the InferenceService. We have differing reconciliation logic for Kserve and ModelMesh
if r.isDeploymentModeForIsvcModelMesh(inferenceservice) {
log.Info("Reconciling InferenceService for ModelMesh")
err = r.ReconcileRoute(inferenceservice, ctx)
if err != nil {
return ctrl.Result{}, err
}

err = r.ReconcileSA(inferenceservice, ctx)
if err != nil {
return ctrl.Result{}, err
}
err = r.ReconcileModelMeshInference(ctx, req, inferenceservice)
} else {
log.Info("Reconciling InferenceService for Kserve")
err = r.ReconcileKserveInference(ctx, req, inferenceservice)
}

return ctrl.Result{}, nil
return ctrl.Result{}, err
}

// SetupWithManager sets up the controller with the Manager.
Expand Down Expand Up @@ -152,3 +148,13 @@ func (r *OpenshiftInferenceServiceReconciler) SetupWithManager(mgr ctrl.Manager)

return nil
}

// general clean-up, mostly resources in different namespaces from kservev1beta1.InferenceService
func (r *OpenshiftInferenceServiceReconciler) delete(ctx context.Context, inferenceService *kservev1beta1.InferenceService) error {
log := r.Log.WithValues("InferenceService", inferenceService.Name, "namespace", inferenceService.Namespace)

log.Info("Running cleanup logic")
vaibhavjainwiz marked this conversation as resolved.
Show resolved Hide resolved

log.Info("Deleting kserve inference route")
return r.DeleteKserveInferenceServiceRoute(ctx, inferenceService)
}
31 changes: 30 additions & 1 deletion controllers/kserve_inferenceservice_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ package controllers

import (
"context"

"fmt"
kservev1beta1 "github.com/kserve/kserve/pkg/apis/serving/v1beta1"
"github.com/opendatahub-io/odh-model-controller/controllers/reconcilers"
v1 "github.com/openshift/api/route/v1"
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
"istio.io/api/security/v1beta1"
"istio.io/api/telemetry/v1alpha1"
Expand Down Expand Up @@ -468,6 +470,25 @@ func (r *OpenshiftInferenceServiceReconciler) createOrUpdateMetricsServiceMonito
return nil
}

func (r *OpenshiftInferenceServiceReconciler) DeleteKserveInferenceServiceRoute(ctx context.Context, inferenceService *kservev1beta1.InferenceService) error {
israel-hdez marked this conversation as resolved.
Show resolved Hide resolved
if r.isDeploymentModeForIsvcModelMesh(inferenceService) {
return nil
}
vaibhavjainwiz marked this conversation as resolved.
Show resolved Hide resolved
route := &v1.Route{}
err := r.Get(ctx, types.NamespacedName{Name: inferenceService.Name, Namespace: reconcilers.IstioNamespace}, route)
if err != nil {
if errors.IsNotFound(err) {
return nil
}
return err
}
if err = r.Delete(ctx, route); err != nil {
return fmt.Errorf("failed to delete Kserve Inference route: %w", err)
}

return nil
}

func (r *OpenshiftInferenceServiceReconciler) DeleteKserveMetricsResourcesIfNoKserveIsvcExists(ctx context.Context, req ctrl.Request, ns string) error {
// Initialize logger format
log := r.Log.WithValues("namespace", ns)
Expand Down Expand Up @@ -644,5 +665,13 @@ func (r *OpenshiftInferenceServiceReconciler) ReconcileKserveInference(ctx conte
if err != nil {
return err
}

log.Info("Reconciling Generic Route for Kserve InferenceService")
kisvcRouteReconciler := reconcilers.NewKserveInferenceServiceRouteReconciler(r.Client, r.Scheme, ctx, log, inferenceService)
err = kisvcRouteReconciler.Reconcile()
israel-hdez marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
}

return nil
}
25 changes: 25 additions & 0 deletions controllers/mm_inferenceservice_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package controllers

import (
"context"
kservev1beta1 "github.com/kserve/kserve/pkg/apis/serving/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
)

func (r *OpenshiftInferenceServiceReconciler) ReconcileModelMeshInference(ctx context.Context, req ctrl.Request, inferenceService *kservev1beta1.InferenceService) error {
// Initialize logger format
log := r.Log.WithValues("InferenceService", inferenceService.Name, "namespace", inferenceService.Namespace)

log.Info("Reconciling Route for InferenceService")
err := r.ReconcileRoute(inferenceService, ctx)
if err != nil {
return err
}

log.Info("Reconciling ServiceAccount for InferenceSercvice")
err = r.ReconcileSA(inferenceService, ctx)
if err != nil {
return err
}
return nil
}
67 changes: 67 additions & 0 deletions controllers/processors/deltaProcessor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package processors
vaibhavjainwiz marked this conversation as resolved.
Show resolved Hide resolved

import (
"github.com/opendatahub-io/odh-model-controller/controllers/comparators"
"github.com/opendatahub-io/odh-model-controller/controllers/utils"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type DeltaProcessor interface {
ComputeDelta(comparator comparators.ResourceComparator, requestedResource client.Object, deployedResource client.Object) ResourceDelta
}

type deltaProcessor struct {
}

func NewDeltaProcessor() DeltaProcessor {
return &deltaProcessor{}
}

func (d *deltaProcessor) ComputeDelta(comparator comparators.ResourceComparator, requestedResource client.Object, deployedResource client.Object) ResourceDelta {
var added bool
var updated bool
var removed bool

if utils.IsNotNil(requestedResource) && utils.IsNil(deployedResource) {
added = true
} else if utils.IsNil(requestedResource) && utils.IsNotNil(deployedResource) {
removed = true
} else if !comparator.Compare(deployedResource, requestedResource) {
updated = true
}

return &resourceDelta{
Added: added,
Updated: updated,
Removed: removed,
}
}

type ResourceDelta interface {
HasChanges() bool
IsAdded() bool
IsUpdated() bool
IsRemoved() bool
}

type resourceDelta struct {
Added bool
Updated bool
Removed bool
}

func (delta *resourceDelta) HasChanges() bool {
return delta.Added || delta.Updated || delta.Removed
}

func (delta *resourceDelta) IsAdded() bool {
return delta.Added
}

func (delta *resourceDelta) IsUpdated() bool {
return delta.Updated
}

func (delta *resourceDelta) IsRemoved() bool {
return delta.Removed
}
Loading