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

add tls to kserve-router and add certs to ig service and always mount… #502

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 1 addition & 2 deletions cmd/router/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (

"github.com/kserve/kserve/pkg/constants"
"github.com/pkg/errors"

"github.com/tidwall/gjson"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
Expand Down Expand Up @@ -368,8 +367,8 @@ func main() {
WriteTimeout: time.Minute, // set the maximum duration before timing out writes of the response
IdleTimeout: 3 * time.Minute, // set the maximum amount of time to wait for the next request when keep-alives are enabled
}
err = server.ListenAndServe()

err = server.ListenAndServeTLS("/etc/tls/private/tls.crt", "/etc/tls/private/tls.key")
if err != nil {
log.Error(err, "failed to listen on 8080")
os.Exit(1)
Expand Down
24 changes: 16 additions & 8 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,15 @@ var (

// kserve networking constants
const (
NetworkVisibility = "networking.kserve.io/visibility"
ClusterLocalVisibility = "cluster-local"
ClusterLocalDomain = "svc.cluster.local"
IsvcNameHeader = "KServe-Isvc-Name"
IsvcNamespaceHeader = "KServe-Isvc-Namespace"
ODHKserveRawAuth = "security.opendatahub.io/enable-auth"
ODHRouteEnabled = "exposed"
ServingCertSecretSuffix = "-serving-cert"
NetworkVisibility = "networking.kserve.io/visibility"
ClusterLocalVisibility = "cluster-local"
ClusterLocalDomain = "svc.cluster.local"
IsvcNameHeader = "KServe-Isvc-Name"
IsvcNamespaceHeader = "KServe-Isvc-Namespace"
ODHKserveRawAuth = "security.opendatahub.io/enable-auth"
ODHRouteEnabled = "exposed"
ServingCertSecretSuffix = "-serving-cert"
OpenshiftServingCertAnnotation = "service.beta.openshift.io/serving-cert-secret-name"
)

// StorageSpec Constants
Expand Down Expand Up @@ -518,6 +519,13 @@ const (
OpenShiftServiceCaConfigMapName = "openshift-service-ca.crt"
)

type ResourceType string

const (
InferenceServiceResource ResourceType = "InferenceService"
InferenceGraphResource ResourceType = "InferenceGraph"
)

// GetRawServiceLabel generate native service label
func GetRawServiceLabel(service string) string {
return "isvc." + service
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/v1alpha1/inferencegraph/raw_ig.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ func createInferenceGraphPodSpec(graph *v1alpha1api.InferenceGraph, config *Rout
},
}
}

return podSpec
}

Expand Down Expand Up @@ -145,7 +144,7 @@ func handleInferenceGraphRawDeployment(cl client.Client, clientset kubernetes.In
objectMeta, componentExtSpec := constructForRawDeployment(graph)

// create the reconciler
reconciler, err := raw.NewRawKubeReconciler(cl, clientset, scheme, objectMeta, metav1.ObjectMeta{}, &componentExtSpec, desiredSvc, nil)
reconciler, err := raw.NewRawKubeReconciler(cl, clientset, scheme, constants.InferenceGraphResource, objectMeta, metav1.ObjectMeta{}, &componentExtSpec, desiredSvc, nil)

if err != nil {
return nil, reconciler.URL, errors.Wrapf(err, "fails to create NewRawKubeReconciler for inference graph")
Expand All @@ -158,6 +157,7 @@ func handleInferenceGraphRawDeployment(cl client.Client, clientset kubernetes.In
}
// set Service Controller
for _, svc := range reconciler.Service.ServiceList {
svc.ObjectMeta.Annotations[constants.OpenshiftServingCertAnnotation] = graph.Name + constants.ServingCertSecretSuffix
if err := controllerutil.SetControllerReference(graph, svc, scheme); err != nil {
return nil, reconciler.URL, errors.Wrapf(err, "fails to set service owner reference for inference graph")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func (e *Explainer) Reconcile(isvc *v1beta1.InferenceService) (ctrl.Result, erro

// Here we allow switch between knative and vanilla deployment
if e.deploymentMode == constants.RawDeployment {
r, err := raw.NewRawKubeReconciler(e.client, e.clientset, e.scheme, objectMeta, metav1.ObjectMeta{},
r, err := raw.NewRawKubeReconciler(e.client, e.clientset, e.scheme, constants.InferenceServiceResource, objectMeta, metav1.ObjectMeta{},
&isvc.Spec.Explainer.ComponentExtensionSpec, &podSpec, nil)
if err != nil {
return ctrl.Result{}, errors.Wrapf(err, "fails to create NewRawKubeReconciler for explainer")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ func (p *Predictor) Reconcile(isvc *v1beta1.InferenceService) (ctrl.Result, erro
rawDeployment = true
podLabelKey = constants.RawDeploymentAppLabel
// This is main RawKubeReconciler to create objects (deployment, svc, scaler)
r, err := raw.NewRawKubeReconciler(p.client, p.clientset, p.scheme, objectMeta, workerObjectMeta, &isvc.Spec.Predictor.ComponentExtensionSpec,
r, err := raw.NewRawKubeReconciler(p.client, p.clientset, p.scheme, constants.InferenceServiceResource, objectMeta, workerObjectMeta, &isvc.Spec.Predictor.ComponentExtensionSpec,
&podSpec, workerPodSpec)
if err != nil {
return ctrl.Result{}, errors.Wrapf(err, "fails to create NewRawKubeReconciler for predictor")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ func (p *Transformer) Reconcile(isvc *v1beta1.InferenceService) (ctrl.Result, er

// Here we allow switch between knative and vanilla deployment
if p.deploymentMode == constants.RawDeployment {
r, err := raw.NewRawKubeReconciler(p.client, p.clientset, p.scheme, objectMeta, metav1.ObjectMeta{},
r, err := raw.NewRawKubeReconciler(p.client, p.clientset, p.scheme, constants.InferenceServiceResource, objectMeta, metav1.ObjectMeta{},
&isvc.Spec.Transformer.ComponentExtensionSpec, &podSpec, nil)
if err != nil {
return ctrl.Result{}, errors.Wrapf(err, "fails to create NewRawKubeReconciler for transformer")
Expand Down
13 changes: 13 additions & 0 deletions pkg/controller/v1beta1/inferenceservice/rawkube_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"fmt"
"time"

"github.com/onsi/gomega/format"
apierr "k8s.io/apimachinery/pkg/api/errors"

"github.com/kserve/kserve/pkg/apis/serving/v1alpha1"
Expand Down Expand Up @@ -100,6 +101,7 @@ var _ = Describe("v1beta1 inference service controller", func() {

It("Should have ingress/service/deployment/hpa created", func() {
By("By creating a new InferenceService")
format.MaxLength = 1000000
// Create configmap
var configMap = &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -229,6 +231,7 @@ var _ = Describe("v1beta1 inference service controller", func() {
"serving.kserve.io/autoscalerClass": "hpa",
"serving.kserve.io/metrics": "cpu",
"serving.kserve.io/targetUtilizationPercentage": "75",
constants.OpenshiftServingCertAnnotation: predictorDeploymentKey.Name + constants.ServingCertSecretSuffix,
},
},
Spec: v1.PodSpec{
Expand Down Expand Up @@ -648,6 +651,7 @@ var _ = Describe("v1beta1 inference service controller", func() {
"serving.kserve.io/autoscalerClass": "hpa",
"serving.kserve.io/metrics": "cpu",
"serving.kserve.io/targetUtilizationPercentage": "75",
constants.OpenshiftServingCertAnnotation: "raw-foo-customized-predictor-serving-cert",
},
},
Spec: v1.PodSpec{
Expand Down Expand Up @@ -1052,6 +1056,7 @@ var _ = Describe("v1beta1 inference service controller", func() {
constants.StorageInitializerSourceUriInternalAnnotationKey: *isvc.Spec.Predictor.Model.StorageURI,
"serving.kserve.io/deploymentMode": "RawDeployment",
"serving.kserve.io/autoscalerClass": "external",
constants.OpenshiftServingCertAnnotation: predictorDeploymentKey.Name + constants.ServingCertSecretSuffix,
},
},
Spec: v1.PodSpec{
Expand Down Expand Up @@ -1723,6 +1728,7 @@ var _ = Describe("v1beta1 inference service controller", func() {
"serving.kserve.io/autoscalerClass": "hpa",
"serving.kserve.io/metrics": "cpu",
"serving.kserve.io/targetUtilizationPercentage": "75",
constants.OpenshiftServingCertAnnotation: predictorDeploymentKey.Name + constants.ServingCertSecretSuffix,
},
},
Spec: v1.PodSpec{
Expand Down Expand Up @@ -2157,6 +2163,7 @@ var _ = Describe("v1beta1 inference service controller", func() {
"serving.kserve.io/autoscalerClass": "hpa",
"serving.kserve.io/metrics": "cpu",
"serving.kserve.io/targetUtilizationPercentage": "75",
constants.OpenshiftServingCertAnnotation: predictorDeploymentKey.Name + constants.ServingCertSecretSuffix,
},
},
Spec: v1.PodSpec{
Expand Down Expand Up @@ -2597,6 +2604,12 @@ var _ = Describe("v1beta1 inference service controller", func() {
"--model_base_path=" + constants.DefaultModelLocalMountPath,
"--rest_api_timeout_in_ms=60000",
},
VolumeMounts: []v1.VolumeMount{
{
Name: "proxy-tls",
MountPath: "/etc/tls/private",
},
},
Resources: defaultResource,
ReadinessProbe: &v1.Probe{
ProbeHandler: v1.ProbeHandler{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"strings"

"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/client-go/kubernetes"

"github.com/google/go-cmp/cmp/cmpopts"
Expand All @@ -41,6 +40,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"knative.dev/pkg/kmp"
kclient "sigs.k8s.io/controller-runtime/pkg/client"
logf "sigs.k8s.io/controller-runtime/pkg/log"
Expand All @@ -64,11 +64,12 @@ const (
func NewDeploymentReconciler(client kclient.Client,
clientset kubernetes.Interface,
scheme *runtime.Scheme,
resourceType constants.ResourceType,
componentMeta metav1.ObjectMeta,
workerComponentMeta metav1.ObjectMeta,
componentExt *v1beta1.ComponentExtensionSpec,
podSpec *corev1.PodSpec, workerPodSpec *corev1.PodSpec) (*DeploymentReconciler, error) {
deploymentList, err := createRawDeploymentODH(clientset, componentMeta, workerComponentMeta, componentExt, podSpec, workerPodSpec)
deploymentList, err := createRawDeploymentODH(clientset, resourceType, componentMeta, workerComponentMeta, componentExt, podSpec, workerPodSpec)
if err != nil {
return nil, err
}
Expand All @@ -80,21 +81,26 @@ func NewDeploymentReconciler(client kclient.Client,
}, nil
}

func createRawDeploymentODH(clientset kubernetes.Interface, componentMeta metav1.ObjectMeta, workerComponentMeta metav1.ObjectMeta,
func createRawDeploymentODH(clientset kubernetes.Interface, resourceType constants.ResourceType, componentMeta metav1.ObjectMeta, workerComponentMeta metav1.ObjectMeta,
componentExt *v1beta1.ComponentExtensionSpec,
podSpec *corev1.PodSpec, workerPodSpec *corev1.PodSpec) ([]*appsv1.Deployment, error) {
deploymentList, err := createRawDeployment(componentMeta, workerComponentMeta, componentExt, podSpec, workerPodSpec)
if err != nil {
return nil, err
}
enableAuth := false
// Deployment list is for multi-node, we only need to add oauth proxy and serving sercret certs to the head deployment
headDeployment := deploymentList[0]
if val, ok := componentMeta.Annotations[constants.ODHKserveRawAuth]; ok && strings.EqualFold(val, "true") {
for _, deployment := range deploymentList {
err := addOauthContainerToDeployment(clientset, deployment, componentMeta, componentExt, podSpec)
if err != nil {
return nil, err
}
enableAuth = true
err := addOauthContainerToDeployment(clientset, headDeployment, componentMeta, componentExt, podSpec)
if err != nil {
return nil, err
}
}
if (resourceType == constants.InferenceServiceResource && enableAuth) || resourceType == constants.InferenceGraphResource {
mountServingSecretVolumeToDeployment(headDeployment, componentMeta, resourceType)
}
return deploymentList, nil
}

Expand Down Expand Up @@ -187,6 +193,36 @@ func createRawDefaultDeployment(componentMeta metav1.ObjectMeta,
return deployment, nil
}

func mountServingSecretVolumeToDeployment(deployment *appsv1.Deployment, componentMeta metav1.ObjectMeta, resourceType constants.ResourceType) {
updatedPodSpec := deployment.Spec.Template.Spec.DeepCopy()
tlsSecretVolume := corev1.Volume{
Name: tlsVolumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: componentMeta.Name + constants.ServingCertSecretSuffix,
DefaultMode: func(i int32) *int32 { return &i }(420),
},
},
}

updatedPodSpec.Volumes = append(updatedPodSpec.Volumes, tlsSecretVolume)

containerName := "kserve-container"
if resourceType == constants.InferenceGraphResource {
containerName = componentMeta.Name
}
for i, container := range updatedPodSpec.Containers {
if container.Name == containerName {
updatedPodSpec.Containers[i].VolumeMounts = append(updatedPodSpec.Containers[i].VolumeMounts, corev1.VolumeMount{
Name: tlsVolumeName,
MountPath: "/etc/tls/private",
})
}
}

deployment.Spec.Template.Spec = *updatedPodSpec
}

func addOauthContainerToDeployment(clientset kubernetes.Interface, deployment *appsv1.Deployment, componentMeta metav1.ObjectMeta, componentExt *v1beta1.ComponentExtensionSpec,
podSpec *corev1.PodSpec) error {
var isvcname string
Expand Down Expand Up @@ -223,16 +259,6 @@ func addOauthContainerToDeployment(clientset kubernetes.Interface, deployment *a
updatedPodSpec := deployment.Spec.Template.Spec.DeepCopy()
// updatedPodSpec := podSpec.DeepCopy()
updatedPodSpec.Containers = append(updatedPodSpec.Containers, *oauthProxyContainer)
tlsSecretVolume := corev1.Volume{
Name: tlsVolumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: componentMeta.Name + constants.ServingCertSecretSuffix,
DefaultMode: func(i int32) *int32 { return &i }(420),
},
},
}
updatedPodSpec.Volumes = append(updatedPodSpec.Volumes, tlsSecretVolume)
deployment.Spec.Template.Spec = *updatedPodSpec
}
return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"

"github.com/kserve/kserve/pkg/apis/serving/v1beta1"
"github.com/kserve/kserve/pkg/constants"
autoscaler "github.com/kserve/kserve/pkg/controller/v1beta1/inferenceservice/reconcilers/autoscaler"
deployment "github.com/kserve/kserve/pkg/controller/v1beta1/inferenceservice/reconcilers/deployment"
"github.com/kserve/kserve/pkg/controller/v1beta1/inferenceservice/reconcilers/ingress"
Expand Down Expand Up @@ -51,6 +52,7 @@ type RawKubeReconciler struct {
func NewRawKubeReconciler(client client.Client,
clientset kubernetes.Interface,
scheme *runtime.Scheme,
resourceType constants.ResourceType,
componentMeta metav1.ObjectMeta,
workerComponentMeta metav1.ObjectMeta,
componentExt *v1beta1.ComponentExtensionSpec,
Expand All @@ -76,7 +78,7 @@ func NewRawKubeReconciler(client client.Client,
log.Error(err1, "failed to get service config")
}

depl, err := deployment.NewDeploymentReconciler(client, clientset, scheme, componentMeta, workerComponentMeta, componentExt, podSpec, workerPodSpec)
depl, err := deployment.NewDeploymentReconciler(client, clientset, scheme, resourceType, componentMeta, workerComponentMeta, componentExt, podSpec, workerPodSpec)
if err != nil {
return nil, err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,12 @@ func createDefaultSvc(componentMeta metav1.ObjectMeta, componentExt *v1beta1.Com
},
}

if service.ObjectMeta.Annotations == nil {
service.ObjectMeta.Annotations = make(map[string]string)
}
service.ObjectMeta.Annotations[constants.OpenshiftServingCertAnnotation] = componentMeta.Name + constants.ServingCertSecretSuffix

if val, ok := componentMeta.Annotations[constants.ODHKserveRawAuth]; ok && strings.EqualFold(val, "true") {
if service.ObjectMeta.Annotations == nil {
service.ObjectMeta.Annotations = make(map[string]string)
}
service.ObjectMeta.Annotations["service.beta.openshift.io/serving-cert-secret-name"] = componentMeta.Name + constants.ServingCertSecretSuffix
httpsPort := corev1.ServicePort{
Name: "https",
Port: constants.OauthProxyPort,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ func TestCreateDefaultDeployment(t *testing.T) {
constants.DeploymentMode: string(constants.RawDeployment),
},
Annotations: map[string]string{
"annotation": "annotation-value",
"annotation": "annotation-value",
constants.OpenshiftServingCertAnnotation: "default-predictor-serving-cert",
},
},
Spec: corev1.ServiceSpec{
Expand Down Expand Up @@ -149,7 +150,8 @@ func TestCreateDefaultDeployment(t *testing.T) {
constants.InferenceServiceGenerationPodLabelKey: "1",
},
Annotations: map[string]string{
"annotation": "annotation-value",
"annotation": "annotation-value",
constants.OpenshiftServingCertAnnotation: "default-predictor-serving-cert",
},
},
Spec: corev1.ServiceSpec{
Expand Down Expand Up @@ -178,7 +180,8 @@ func TestCreateDefaultDeployment(t *testing.T) {
constants.MultiNodeRoleLabelKey: constants.MultiNodeHead,
},
Annotations: map[string]string{
"annotation": "annotation-value",
"annotation": "annotation-value",
constants.OpenshiftServingCertAnnotation: "default-predictor-serving-cert",
},
},
Spec: corev1.ServiceSpec{
Expand Down Expand Up @@ -268,9 +271,13 @@ func TestCreateServiceRawTrueAndConfigNil(t *testing.T) {
}

func runTestServiceCreate(serviceConfig *v1beta1.ServiceConfig, expectedClusterIP string, t *testing.T) {
// Adding the annotation here as the test it is expected that this annotation is injected automatically for all services
componentMeta := metav1.ObjectMeta{
Name: "test-service",
Namespace: "default",
Annotations: map[string]string{
constants.OpenshiftServingCertAnnotation: "default-predictor-serving-cert",
},
}
componentExt := &v1beta1.ComponentExtensionSpec{}
podSpec := &corev1.PodSpec{}
Expand Down
Loading