Skip to content

Commit

Permalink
feat(sherlock): Added support for model reuse
Browse files Browse the repository at this point in the history
  • Loading branch information
isala404 committed Mar 13, 2022
1 parent e97157f commit 3f5f223
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 53 deletions.
3 changes: 2 additions & 1 deletion control-plane/api/v1alpha1/inspector_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type InspectorSpec struct {
DeploymentRef string `json:"deploymentRef"`
ServiceRef string `json:"serviceRef"`
Namespace string `json:"namespace"`
ModelName string `json:"modelName"`
}

type Status string
Expand All @@ -64,7 +65,7 @@ type InspectorStatus struct {
//+kubebuilder:printcolumn:JSONPath=".spec.namespace",name="Namespace",type="string"
//+kubebuilder:printcolumn:JSONPath=".spec.deploymentRef",name="Target Deployment",type="string"
//+kubebuilder:printcolumn:JSONPath=".spec.serviceRef",name="Target ClusterIP",type="string"
//+kubebuilder:printcolumn:JSONPath=".spec.modelURI",name="Model URI",type="string"
//+kubebuilder:printcolumn:JSONPath=".spec.modelName",name="Model Name",type="string"
//+kubebuilder:printcolumn:JSONPath=".status.status",name="Status",type="string"

// Inspector is the Schema for the inspectors API
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ spec:
- jsonPath: .spec.serviceRef
name: Target ClusterIP
type: string
- jsonPath: .spec.modelURI
name: Model URI
- jsonPath: .spec.modelName
name: Model Name
type: string
- jsonPath: .status.status
name: Status
Expand Down Expand Up @@ -55,12 +55,15 @@ spec:
description: Foo is an example field of Inspector. Edit inspector_types.go
to remove/update
type: string
modelName:
type: string
namespace:
type: string
serviceRef:
type: string
required:
- deploymentRef
- modelName
- namespace
- serviceRef
type: object
Expand Down
10 changes: 10 additions & 0 deletions control-plane/config/manager/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,13 @@ metadata:
namespace: lazy-koala
data:
config.yaml: |
---
apiVersion: v1
kind: ConfigMap
metadata:
name: sherlock-config
namespace: lazy-koala
data:
models.config: |
services.yaml: |
48 changes: 21 additions & 27 deletions control-plane/controllers/inspector_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ type ScrapePoint struct {
IsService bool `yaml:"isService"`
}

type InferenceData struct {
ModelName string `yaml:"modelName"`
Namespace string `yaml:"namespace"`
}

//+kubebuilder:rbac:groups=lazykoala.isala.me,resources=inspectors,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=lazykoala.isala.me,resources=inspectors/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=lazykoala.isala.me,resources=inspectors/finalizers,verbs=update
Expand Down Expand Up @@ -285,19 +290,26 @@ func (r *InspectorReconciler) configureSherlock(ctx context.Context, inspector *
}

// Phase the services.yaml
var sherlockServiceList []string
sherlockServiceList := make(map[string]InferenceData)
modelsList := make(map[string]bool)
if err := yaml.Unmarshal([]byte(sherlockConfigMap.Data["services.yaml"]), &sherlockServiceList); err != nil {
return err
}

if append {
sherlockServiceList = AppendIfMissing(sherlockServiceList, inspector.Spec.DeploymentRef)
sherlockServiceList[inspector.Spec.DeploymentRef] = InferenceData{
ModelName: inspector.Spec.ModelName,
Namespace: inspector.Spec.Namespace,
}
} else {
sherlockServiceList = RemoveIfExists(sherlockServiceList, inspector.Spec.DeploymentRef)
if _, ok := sherlockServiceList[inspector.Spec.DeploymentRef]; ok {
delete(sherlockServiceList, inspector.Spec.DeploymentRef)
delete(modelsList, inspector.Spec.DeploymentRef)
}
}

// Generate the Servings Config
servingsConfig, err := createServingsConfig(sherlockServiceList)
servingsConfig, err := createServingsConfig(modelsList)
if err != nil {
return err
}
Expand Down Expand Up @@ -338,32 +350,14 @@ func eventFilter() predicate.Predicate {
}
}

func AppendIfMissing(slice []string, item string) []string {
for _, ele := range slice {
if ele == item {
return slice
}
}
return append(slice, item)
}

func RemoveIfExists(slice []string, item string) []string {
for i, other := range slice {
if other == item {
return append(slice[:i], slice[i+1:]...)
}
}
return slice
}

func createServingsConfig(service []string) (string, error) {
func createServingsConfig(service map[string]bool) (string, error) {
tmpl := template.New("config")

tmpl, err := tmpl.Parse(`model_config_list {
{{range .}}
{{ range $key, $value := . }}
config {
name: '{{.}}'
base_path: '/models/{{.}}/'
name: '{{$key}}'
base_path: '/models/{{$key}}/'
model_platform: 'tensorflow'
}
{{end}}
Expand All @@ -376,5 +370,5 @@ func createServingsConfig(service []string) (string, error) {
if err != nil {
return "", err
}
return fmt.Sprintf("%+v", buf), nil
return fmt.Sprintf("%v", buf), nil
}
2 changes: 1 addition & 1 deletion sherlock/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ lazy_static = "1.4.0"
hyper = { version = "0.14.17", features = ["full"] }
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.11", features = ["blocking", "json"] }
serde = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.8"
20 changes: 9 additions & 11 deletions sherlock/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,15 @@ spec:
name: sherlock-config
- name: model-files
emptyDir: {}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: sherlock-config
namespace: lazy-koala
data:
models.config: |
services.yaml: |
# ---
# apiVersion: v1
# kind: ConfigMap
# metadata:
# name: sherlock-config
# namespace: lazy-koala
# data:
# models.config: |
# services.yaml: |
# ---
## https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity
# apiVersion: v1
Expand Down
31 changes: 20 additions & 11 deletions sherlock/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ use hyper::{
Body, Request, Response, Server,
};
use prometheus::{Encoder, GaugeVec, TextEncoder};
use std::{env::var, thread, time::Duration};
use std::{env::var, thread, time::Duration, collections::HashMap};
use lazy_static::lazy_static;
use prometheus::{opts, register_gauge_vec};
use std::collections::HashMap;
use serde_yaml;
use serde::{Serialize, Deserialize};

lazy_static! {
static ref END_POINT: String = var("END_POINT").unwrap_or("http://localhost:8501/v1/models".to_string());
Expand All @@ -18,11 +17,18 @@ lazy_static! {
"anomaly_score",
"Reconstruction loss of the autoencoder"
),
&["serviceName"]
&["serviceName", "namespace"]
)
.unwrap();
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct InferenceData {
model_name : String,
namespace: String,
}


async fn serve_req(_req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
let encoder = TextEncoder::new();
Expand Down Expand Up @@ -52,10 +58,13 @@ fn poll_anomaly_scores(delay: u64) {
loop {
match read_config() {
Ok(services) => {
for service in services.iter(){
match query_model(service) {
Ok(score) => ANOMLAY_GAUGE.with_label_values(&[service]).set(score),
Err(e) => eprintln!("Error while querying model: {}", e),
for (service, args) in services.iter() {
match query_model(&args.model_name) {
Ok(score) => ANOMLAY_GAUGE.with_label_values(&[service, &args.namespace]).set(score),
Err(e) => {
eprintln!("Error while querying model: {}", e);
ANOMLAY_GAUGE.with_label_values(&[service, &args.namespace]).set(-1.0)
},
}
}
},
Expand All @@ -65,15 +74,15 @@ fn poll_anomaly_scores(delay: u64) {
}
}

fn read_config() -> Result<Vec<String>, Box<dyn std::error::Error>> {
fn read_config() -> Result<HashMap<String, InferenceData>, Box<dyn std::error::Error>> {
let f = std::fs::File::open("config/services.yaml")?;
let services: Vec<String> = serde_yaml::from_reader(f)?;
let services: HashMap<String, InferenceData> = serde_yaml::from_reader(f)?;
Ok(services)
}

#[tokio::main]
async fn main() {

thread::spawn(|| poll_anomaly_scores(POOL_DURATION.as_str().parse::<u64>().unwrap()));

let addr = ([0, 0, 0, 0], 9898).into();
Expand Down

0 comments on commit 3f5f223

Please sign in to comment.