diff --git a/pkg/backends/k8s.go b/pkg/backends/k8s.go index 4d89e38c..d583e0da 100644 --- a/pkg/backends/k8s.go +++ b/pkg/backends/k8s.go @@ -127,6 +127,7 @@ func (k *KubeBackend) CreateService(service types.Service) error { MaxScale: service.Expose.MaxScale, MinScale: service.Expose.MinScale, CpuThreshold: service.Expose.CpuThreshold, + EnableSGX: service.EnableSGX, } utils.CreateExpose(exposeConf, k.kubeClientset, *k.config) } @@ -216,6 +217,7 @@ func (k *KubeBackend) UpdateService(service types.Service) error { MaxScale: service.Expose.MaxScale, MinScale: service.Expose.MinScale, CpuThreshold: service.Expose.CpuThreshold, + EnableSGX: service.EnableSGX, } utils.UpdateExpose(exposeConf, k.kubeClientset, *k.config) diff --git a/pkg/backends/knative.go b/pkg/backends/knative.go index 49d06447..3a5800fe 100644 --- a/pkg/backends/knative.go +++ b/pkg/backends/knative.go @@ -133,6 +133,7 @@ func (kn *KnativeBackend) CreateService(service types.Service) error { MaxScale: service.Expose.MaxScale, MinScale: service.Expose.MinScale, CpuThreshold: service.Expose.CpuThreshold, + EnableSGX: service.EnableSGX, } utils.CreateExpose(exposeConf, kn.kubeClientset, *kn.config) @@ -224,6 +225,7 @@ func (kn *KnativeBackend) UpdateService(service types.Service) error { MaxScale: service.Expose.MaxScale, MinScale: service.Expose.MinScale, CpuThreshold: service.Expose.CpuThreshold, + EnableSGX: service.EnableSGX, } utils.UpdateExpose(exposeConf, kn.kubeClientset, *kn.config) @@ -310,6 +312,11 @@ func (kn *KnativeBackend) createKNServiceDefinition(service *types.Service) (*kn }, } + if service.EnableSGX { + knSvc.Spec.ConfigurationSpec.Template.ObjectMeta.Annotations["kubernetes.podspec-securitycontext"] = "enabled" + knSvc.Spec.ConfigurationSpec.Template.ObjectMeta.Annotations["kubernetes.containerspec-addcapabilities"] = "enabled" + } + return knSvc, nil } diff --git a/pkg/types/service.go b/pkg/types/service.go index be4d99c6..13f83180 100644 --- a/pkg/types/service.go +++ b/pkg/types/service.go @@ -143,6 +143,10 @@ type Service struct { // Optional. (default: false) EnableGPU bool `json:"enable_gpu"` + // EnableSGX parameter to use the SCONE k8s plugin + // Optional. (default: false) + EnableSGX bool `json:"enable_sgx"` + // ImagePrefetch parameter to enable the image cache functionality // Optional. (default: false) ImagePrefetch bool `json:"image_prefetch"` @@ -289,6 +293,10 @@ func (service *Service) ToPodSpec(cfg *Config) (*v1.PodSpec, error) { // Add the required environment variables for the watchdog addWatchdogEnvVars(podSpec, cfg, service) + if service.EnableSGX { + SetSecurityContext(podSpec) + } + return podSpec, nil } @@ -327,6 +335,16 @@ func SetImagePullSecrets(secrets []string) []v1.LocalObjectReference { return objects } +func SetSecurityContext(podSpec *v1.PodSpec) { + ctx := v1.SecurityContext{ + Capabilities: &v1.Capabilities{ + Add: []v1.Capability{"SYS_RAWIO"}, + }, + } + + podSpec.Containers[0].SecurityContext = &ctx +} + func createResources(service *Service) (v1.ResourceRequirements, error) { resources := v1.ResourceRequirements{ Limits: v1.ResourceList{}, @@ -356,6 +374,14 @@ func createResources(service *Service) (v1.ResourceRequirements, error) { resources.Limits["nvidia.com/gpu"] = gpu } + if service.EnableSGX { + sgx, err := resource.ParseQuantity("1") + if err != nil { + return resources, err + } + resources.Limits["sgx.intel.com/enclave"] = sgx + } + return resources, nil } diff --git a/pkg/types/service_test.go b/pkg/types/service_test.go index 05f2bcc4..20b5242a 100644 --- a/pkg/types/service_test.go +++ b/pkg/types/service_test.go @@ -215,6 +215,7 @@ cpu: "1.0" total_memory: "" total_cpu: "" enable_gpu: false +enable_sgx: false image_prefetch: false synchronous: min_scale: 0 diff --git a/pkg/utils/expose.go b/pkg/utils/expose.go index 8bb14cf5..6bdecf33 100644 --- a/pkg/utils/expose.go +++ b/pkg/utils/expose.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "log" + "os" "github.com/grycap/oscar/v2/pkg/types" apps "k8s.io/api/apps/v1" @@ -41,23 +42,28 @@ type Expose struct { MinScale int32 `default:"1"` Port int ` binding:"required" default:"80"` CpuThreshold int32 `default:"80"` + EnableSGX bool } +// Custom logger +var ExposeLogger = log.New(os.Stdout, "[EXPOSED-SERVICE] ", log.Flags()) + // / Main function that creates all the kubernetes components func CreateExpose(expose Expose, kubeClientset kubernetes.Interface, cfg types.Config) error { + ExposeLogger.Printf("DEBUG: Creating exposed service: \n%v\n", expose) err := createDeployment(expose, kubeClientset) if err != nil { - log.Printf("WARNING: %v\n", err) + ExposeLogger.Printf("WARNING: %v\n", err) return err } err = createService(expose, kubeClientset) if err != nil { - log.Printf("WARNING: %v\n", err) + ExposeLogger.Printf("WARNING: %v\n", err) return err } err = createIngress(expose, kubeClientset, cfg) if err != nil { - log.Printf("WARNING: %v\n", err) + ExposeLogger.Printf("WARNING: %v\n", err) return err } return nil @@ -67,17 +73,17 @@ func CreateExpose(expose Expose, kubeClientset kubernetes.Interface, cfg types.C func DeleteExpose(expose Expose, kubeClientset kubernetes.Interface) error { err := deleteDeployment(expose, kubeClientset) if err != nil { - log.Printf("WARNING: %v\n", err) + ExposeLogger.Printf("WARNING: %v\n", err) return err } err = deleteService(expose, kubeClientset) if err != nil { - log.Printf("WARNING: %v\n", err) + ExposeLogger.Printf("WARNING: %v\n", err) return err } err = deleteIngress(expose, kubeClientset) if err != nil { - log.Printf("WARNING: %v\n", err) + ExposeLogger.Printf("WARNING: %v\n", err) return err } return nil @@ -100,12 +106,12 @@ func UpdateExpose(expose Expose, kubeClientset kubernetes.Interface, cfg types.C } err := updateDeployment(expose, kubeClientset) if err != nil { - log.Printf("WARNING: %v\n", err) + ExposeLogger.Printf("WARNING: %v\n", err) return err } err2 := updateService(expose, kubeClientset) if err2 != nil { - log.Printf("WARNING: %v\n", err2) + ExposeLogger.Printf("WARNING: %v\n", err2) return err2 } return nil @@ -119,15 +125,15 @@ func ListExpose(expose Expose, kubeClientset kubernetes.Interface) error { services, err2 := listServices(expose, kubeClientset) ingress, err3 := listIngress(expose, kubeClientset) if err != nil { - log.Printf("WARNING: %v\n", err) + ExposeLogger.Printf("WARNING: %v\n", err) return err } if err2 != nil { - log.Printf("WARNING: %v\n", err2) + ExposeLogger.Printf("WARNING: %v\n", err2) return err } if err3 != nil { - log.Printf("WARNING: %v\n", err3) + ExposeLogger.Printf("WARNING: %v\n", err3) return err } fmt.Println(deploy, hpa, services, ingress) @@ -173,6 +179,7 @@ func getDeployment(e Expose) *apps.Deployment { }, Status: apps.DeploymentStatus{}, } + return deployment } @@ -208,17 +215,7 @@ func getPodTemplateSpec(e Expose) v1.PodTemplateSpec { ContainerPort: int32(e.Port), } cores := resource.NewMilliQuantity(500, resource.DecimalSI) - var container v1.Container = v1.Container{ - Name: e.Name, - Image: e.Image, - Env: types.ConvertEnvVars(e.Variables), - Ports: []v1.ContainerPort{ports}, - Resources: v1.ResourceRequirements{ - Requests: v1.ResourceList{ - "cpu": *cores, - }, - }, - } + template := v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Name: e.Name, @@ -229,9 +226,31 @@ func getPodTemplateSpec(e Expose) v1.PodTemplateSpec { }, Spec: v1.PodSpec{ InitContainers: []v1.Container{}, - Containers: []v1.Container{container}, + Containers: []v1.Container{ + { + Name: e.Name, + Image: e.Image, + Env: types.ConvertEnvVars(e.Variables), + Ports: []v1.ContainerPort{ports}, + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + "cpu": *cores, + }, + // Empty Limits list initialized in case enabling SGX is needed + Limits: v1.ResourceList{}, + }, + }, + }, }, } + + if e.EnableSGX { + ExposeLogger.Printf("DEBUG: Enabling components to use SGX plugin\n") + types.SetSecurityContext(&template.Spec) + sgx, _ := resource.ParseQuantity("1") + template.Spec.Containers[0].Resources.Limits["sgx.intel.com/enclave"] = sgx + } + return template }