diff --git a/controllers/inferenceservice_route.go b/controllers/inferenceservice_route.go index 7103a083..7c636559 100644 --- a/controllers/inferenceservice_route.go +++ b/controllers/inferenceservice_route.go @@ -38,11 +38,13 @@ const ( modelmeshServiceName = "modelmesh-serving" modelmeshAuthServicePort = 8443 modelmeshServicePort = 8008 + modelmeshGrpcPort = 8033 ) // NewInferenceServiceRoute defines the desired route object -func NewInferenceServiceRoute(inferenceservice *inferenceservicev1.InferenceService, enableAuth bool) *routev1.Route { +func NewInferenceServiceRoute(inferenceservice *inferenceservicev1.InferenceService, enableAuth bool, enableGrpc bool) *routev1.Route { + // create a http route finalRoute := &routev1.Route{ ObjectMeta: metav1.ObjectMeta{ Name: inferenceservice.Name, @@ -62,12 +64,17 @@ func NewInferenceServiceRoute(inferenceservice *inferenceservicev1.InferenceServ }, WildcardPolicy: routev1.WildcardPolicyNone, Path: "/v2/models/" + inferenceservice.Name, + TLS: &routev1.TLSConfig{ + Termination: routev1.TLSTerminationEdge, + InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect, + }, }, Status: routev1.RouteStatus{ Ingress: []routev1.RouteIngress{}, }, } + // if secure route is selected, create the https route if enableAuth { finalRoute.Spec.Port = &routev1.RoutePort{ TargetPort: intstr.FromInt(modelmeshAuthServicePort), @@ -76,9 +83,17 @@ func NewInferenceServiceRoute(inferenceservice *inferenceservicev1.InferenceServ Termination: routev1.TLSTerminationReencrypt, InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect, } - } else { + } + + // if grpc is selected, create a grpc route + if enableGrpc { + finalRoute.ObjectMeta.Name = inferenceservice.Name + "-grpc" + finalRoute.Spec.Port = &routev1.RoutePort{ + TargetPort: intstr.FromInt(modelmeshGrpcPort), + } + finalRoute.Spec.Path = "" finalRoute.Spec.TLS = &routev1.TLSConfig{ - Termination: routev1.TLSTerminationEdge, + Termination: routev1.TLSTerminationPassthrough, InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect, } } @@ -157,83 +172,107 @@ func (r *OpenshiftInferenceServiceReconciler) findSupportingRuntimeForISvc(ctx c // Reconcile will manage the creation, update and deletion of the route returned // by the newRoute function func (r *OpenshiftInferenceServiceReconciler) reconcileRoute(inferenceservice *inferenceservicev1.InferenceService, - ctx context.Context, newRoute func(service *inferenceservicev1.InferenceService, enableAuth bool) *routev1.Route) error { + ctx context.Context, newRoute func(service *inferenceservicev1.InferenceService, enableAuth bool, enableGrpc bool) *routev1.Route) error { // Initialize logger format log := r.Log.WithValues("inferenceservice", inferenceservice.Name, "namespace", inferenceservice.Namespace) desiredServingRuntime := r.findSupportingRuntimeForISvc(ctx, log, inferenceservice) - enableAuth := true - if desiredServingRuntime.Annotations["enable-auth"] != "true" { - enableAuth = false - } - createRoute := true - if desiredServingRuntime.Annotations["enable-route"] != "true" { - createRoute = false + // optionsList allows for creation of both grpc and http/s routes as desired + var optionsList [2]string + + createRoute, enableAuth, enableGrpc := false, false, false + + // If routes need to be exposed, then enable both grpc and http/s + if desiredServingRuntime.Annotations["enable-route"] == "true" { + createRoute = true + enableGrpc = true + optionsList[1] = "grpc" + + if desiredServingRuntime.Annotations["enable-auth"] == "true" { + enableAuth = true + optionsList[0] = "https" + } else { + optionsList[0] = "http" + } } - // Generate the desired route - desiredRoute := newRoute(inferenceservice, enableAuth) - - // Create the route if it does not already exist - foundRoute := &routev1.Route{} - justCreated := false - err := r.Get(ctx, types.NamespacedName{ - Name: desiredRoute.Name, - Namespace: inferenceservice.Namespace, - }, foundRoute) - if err != nil { - if !createRoute { - log.Info("Serving runtime does not have 'enable-route' annotation set to 'True'. Skipping route creation") - return nil + for _, v := range optionsList { + + // Check which route to create + if v == "http" || v == "https" { + enableGrpc = false + } else if v == "grpc" { + enableAuth, enableGrpc = false, true + } else { + continue } - if apierrs.IsNotFound(err) { - log.Info("Creating Route") - // Add .metatada.ownerReferences to the route to be deleted by the - // Kubernetes garbage collector if the predictor is deleted - err = ctrl.SetControllerReference(inferenceservice, desiredRoute, r.Scheme) - if err != nil { - log.Error(err, "Unable to add OwnerReference to the Route") - return err + + // Generate the desired routes + desiredRoute := newRoute(inferenceservice, enableAuth, enableGrpc) + + // Create the route if it does not already exist + foundRoute := &routev1.Route{} + justCreated := false + err := r.Get(ctx, types.NamespacedName{ + Name: desiredRoute.Name, + Namespace: inferenceservice.Namespace, + }, foundRoute) + + if err != nil { + if !createRoute { + log.Info("Serving runtime does not have 'enable-route' annotation set to 'True'. Skipping route creation") + return nil } - // Create the route in the Openshift cluster - err = r.Create(ctx, desiredRoute) - if err != nil && !apierrs.IsAlreadyExists(err) { - log.Error(err, "Unable to create the Route") + if apierrs.IsNotFound(err) { + log.Info("Creating Route") + // Add .metatada.ownerReferences to the route to be deleted by the + // Kubernetes garbage collector if the predictor is deleted + err = ctrl.SetControllerReference(inferenceservice, desiredRoute, r.Scheme) + if err != nil { + log.Error(err, "Unable to add OwnerReference to the Route") + return err + } + // Create the route in the Openshift cluster + err = r.Create(ctx, desiredRoute) + if err != nil && !apierrs.IsAlreadyExists(err) { + log.Error(err, "Unable to create the Route") + return err + } + justCreated = true + } else { + log.Error(err, "Unable to fetch the Route") return err } - justCreated = true - } else { - log.Error(err, "Unable to fetch the Route") - return err } - } - if !createRoute { - log.Info("Serving Runtime does not have 'enable-route' annotation set to 'True'. Deleting existing route") - return r.Delete(ctx, foundRoute) - } - // Reconcile the route spec if it has been manually modified - if !justCreated && !CompareInferenceServiceRoutes(*desiredRoute, *foundRoute) { - log.Info("Reconciling Route") - // Retry the update operation when the ingress controller eventually - // updates the resource version field - err := retry.RetryOnConflict(retry.DefaultRetry, func() error { - // Get the last route revision - if err := r.Get(ctx, types.NamespacedName{ - Name: desiredRoute.Name, - Namespace: inferenceservice.Namespace, - }, foundRoute); err != nil { + if !createRoute { + log.Info("Serving Runtime does not have 'enable-route' annotation set to 'True'. Deleting existing route") + return r.Delete(ctx, foundRoute) + } + + // Reconcile the route spec if it has been manually modified + if !justCreated && !CompareInferenceServiceRoutes(*desiredRoute, *foundRoute) { + log.Info("Reconciling Route") + // Retry the update operation when the ingress controller eventually + // updates the resource version field + err := retry.RetryOnConflict(retry.DefaultRetry, func() error { + // Get the last route revision + if err := r.Get(ctx, types.NamespacedName{ + Name: desiredRoute.Name, + Namespace: inferenceservice.Namespace, + }, foundRoute); err != nil { + return err + } + // Reconcile labels and spec field + foundRoute.Spec = desiredRoute.Spec + foundRoute.ObjectMeta.Labels = desiredRoute.ObjectMeta.Labels + return r.Update(ctx, foundRoute) + }) + if err != nil { + log.Error(err, "Unable to reconcile the Route") return err } - // Reconcile labels and spec field - foundRoute.Spec = desiredRoute.Spec - foundRoute.ObjectMeta.Labels = desiredRoute.ObjectMeta.Labels - return r.Update(ctx, foundRoute) - }) - if err != nil { - log.Error(err, "Unable to reconcile the Route") - return err } } @@ -241,7 +280,7 @@ func (r *OpenshiftInferenceServiceReconciler) reconcileRoute(inferenceservice *i } // ReconcileRoute will manage the creation, update and deletion of the -// TLS route when the predictor is reconciled +// TLS route wheoptionsList[v]n the predictor is reconciled func (r *OpenshiftInferenceServiceReconciler) ReconcileRoute( inferenceservice *inferenceservicev1.InferenceService, ctx context.Context) error { return r.reconcileRoute(inferenceservice, ctx, NewInferenceServiceRoute)