Skip to content

Commit 208ee45

Browse files
committed
feat: Add TLS certificate mount on ModelMesh
1 parent 4c8550e commit 208ee45

File tree

4 files changed

+95
-5
lines changed

4 files changed

+95
-5
lines changed

controllers/certificates.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,41 @@ package controllers
33
import (
44
"context"
55
trustyaiopendatahubiov1alpha1 "github.com/trustyai-explainability/trustyai-service-operator/api/v1alpha1"
6+
corev1 "k8s.io/api/core/v1"
67
"sigs.k8s.io/controller-runtime/pkg/client"
78
"sigs.k8s.io/controller-runtime/pkg/log"
89
)
910

11+
const (
12+
tlsMountPath = "/etc/trustyai/tls"
13+
)
14+
15+
// TLSCertVolumes holds the volume and volume mount for the TLS certificates
16+
type TLSCertVolumes struct {
17+
volume corev1.Volume
18+
volumeMount corev1.VolumeMount
19+
}
20+
21+
// createFor creates the required volumes and volume mount for the TLS certificates for a specific Kubernetes secret
22+
func (cert *TLSCertVolumes) createFor(instance *trustyaiopendatahubiov1alpha1.TrustyAIService) {
23+
volume := corev1.Volume{
24+
Name: instance.Name + "-internal",
25+
VolumeSource: corev1.VolumeSource{
26+
Secret: &corev1.SecretVolumeSource{
27+
SecretName: instance.Name + "-internal",
28+
},
29+
},
30+
}
31+
32+
volumeMount := corev1.VolumeMount{
33+
Name: instance.Name + "-internal",
34+
MountPath: tlsMountPath,
35+
ReadOnly: true,
36+
}
37+
cert.volume = volume
38+
cert.volumeMount = volumeMount
39+
}
40+
1041
func (r *TrustyAIServiceReconciler) GetCustomCertificatesBundle(ctx context.Context, instance *trustyaiopendatahubiov1alpha1.TrustyAIService) CustomCertificatesBundle {
1142

1243
var customCertificatesBundle CustomCertificatesBundle

controllers/constants.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ const (
99
serviceMonitorName = "trustyai-metrics"
1010
finalizerName = "trustyai.opendatahub.io/finalizer"
1111
payloadProcessorName = "MM_PAYLOAD_PROCESSORS"
12+
tlsKeyCertPathName = "MM_TLS_KEY_CERT_PATH"
13+
mmContainerName = "mm"
1214
modelMeshLabelKey = "modelmesh-service"
1315
modelMeshLabelValue = "modelmesh-serving"
1416
volumeMountName = "volume"

controllers/inference_services.go

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import (
1313
)
1414

1515
func (r *TrustyAIServiceReconciler) patchEnvVarsForDeployments(ctx context.Context, instance *trustyaiopendatahubiov1alpha1.TrustyAIService, deployments []appsv1.Deployment, envVarName string, url string, remove bool) (bool, error) {
16+
// Create volume and volume mount for this intance's TLS secrets
17+
certVolumes := TLSCertVolumes{}
18+
certVolumes.createFor(instance)
19+
1620
// Loop over the Deployments
1721
for _, deployment := range deployments {
1822

@@ -23,8 +27,31 @@ func (r *TrustyAIServiceReconciler) patchEnvVarsForDeployments(ctx context.Conte
2327
return false, nil
2428
}
2529

30+
// If the secret volume doesn't exist, add it
31+
volumeExists := false
32+
for _, vol := range deployment.Spec.Template.Spec.Volumes {
33+
if vol.Name == instance.Name+"-internal" {
34+
volumeExists = true
35+
break
36+
}
37+
}
38+
if !volumeExists {
39+
deployment.Spec.Template.Spec.Volumes = append(deployment.Spec.Template.Spec.Volumes, certVolumes.volume)
40+
}
41+
2642
// Loop over all containers in the Deployment's Pod template
2743
for i := range deployment.Spec.Template.Spec.Containers {
44+
mountExists := false
45+
for _, mount := range deployment.Spec.Template.Spec.Containers[i].VolumeMounts {
46+
if mount.Name == instance.Name+"-internal" {
47+
mountExists = true
48+
break
49+
}
50+
}
51+
if !mountExists {
52+
deployment.Spec.Template.Spec.Containers[i].VolumeMounts = append(deployment.Spec.Template.Spec.Containers[i].VolumeMounts, certVolumes.volumeMount)
53+
}
54+
2855
// Store the original environment variable list
2956
// Get the existing env var
3057
var envVar *corev1.EnvVar
@@ -50,14 +77,17 @@ func (r *TrustyAIServiceReconciler) patchEnvVarsForDeployments(ctx context.Conte
5077
} else if envVar != nil {
5178
// If the env var exists and already contains the value, don't do anything
5279
existingValues := strings.Split(envVar.Value, " ")
80+
valueExists := false
5381
for _, v := range existingValues {
5482
if v == url {
55-
continue
83+
valueExists = true
84+
break
5685
}
5786
}
5887

59-
// Modify the existing env var based on the remove flag and current value
60-
envVar.Value = generateEnvVarValue(envVar.Value, url, remove)
88+
if !valueExists {
89+
envVar.Value = generateEnvVarValue(envVar.Value, url, remove)
90+
}
6191
}
6292

6393
// Only update the deployment if the var value has to change, or we are removing it
@@ -70,6 +100,32 @@ func (r *TrustyAIServiceReconciler) patchEnvVarsForDeployments(ctx context.Conte
70100
r.eventModelMeshConfigured(instance)
71101
log.FromContext(ctx).Info("Updating Deployment " + deployment.Name + ", container spec " + deployment.Spec.Template.Spec.Containers[i].Name + ", env var " + envVarName + " to " + url)
72102
}
103+
104+
// Check TLS environment variable on ModelMesh
105+
if deployment.Spec.Template.Spec.Containers[i].Name == mmContainerName {
106+
tlsKeyCertPathEnvValue := tlsMountPath + "/tls.crt"
107+
tlsKeyCertPathExists := false
108+
for _, envVar := range deployment.Spec.Template.Spec.Containers[i].Env {
109+
if envVar.Name == tlsKeyCertPathName {
110+
tlsKeyCertPathExists = true
111+
break
112+
}
113+
}
114+
115+
// Doesn't exist, so we can add
116+
if !tlsKeyCertPathExists {
117+
deployment.Spec.Template.Spec.Containers[i].Env = append(deployment.Spec.Template.Spec.Containers[i].Env, corev1.EnvVar{
118+
Name: tlsKeyCertPathName,
119+
Value: tlsKeyCertPathEnvValue,
120+
})
121+
122+
if err := r.Update(ctx, &deployment); err != nil {
123+
log.FromContext(ctx).Error(err, "Could not update Deployment", "Deployment", deployment.Name)
124+
return false, err
125+
}
126+
log.FromContext(ctx).Info("Added environment variable " + tlsKeyCertPathName + " to deployment " + deployment.Name + " for container " + mmContainerName)
127+
}
128+
}
73129
}
74130
}
75131

controllers/utils.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ package controllers
22

33
import (
44
"context"
5+
"os"
6+
57
appsv1 "k8s.io/api/apps/v1"
68
"k8s.io/apimachinery/pkg/labels"
7-
"os"
89
"sigs.k8s.io/controller-runtime/pkg/client"
910
"sigs.k8s.io/controller-runtime/pkg/log"
1011
)
@@ -63,5 +64,5 @@ func (r *TrustyAIServiceReconciler) GetDeploymentsByLabel(ctx context.Context, n
6364

6465
// generateServiceURL generates an internal URL for a TrustyAI service
6566
func generateServiceURL(crName string, namespace string) string {
66-
return "http://" + crName + "." + namespace + ".svc.cluster.local"
67+
return "https://" + crName + "." + namespace + ".svc"
6768
}

0 commit comments

Comments
 (0)