Skip to content

Commit

Permalink
update istio example
Browse files Browse the repository at this point in the history
  • Loading branch information
ukclivecox committed Jul 11, 2018
1 parent 41569bd commit 473b30a
Show file tree
Hide file tree
Showing 13 changed files with 550 additions and 15 deletions.
94 changes: 89 additions & 5 deletions examples/istio/canary_update/canary.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -264,14 +264,16 @@
"source": [
"%matplotlib inline\n",
"import utils\n",
"from visualizer import get_graph\n",
"mnist = utils.download_mnist()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Launch Version 1 Model"
"# Launch Version 1 Model\n",
"A sklearn MNIST model."
]
},
{
Expand All @@ -283,6 +285,15 @@
"!pygmentize mnist_v1.json"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"get_graph(\"mnist_v1.json\")"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down Expand Up @@ -360,7 +371,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Setup Version 1 Istio Routing"
"# Setup Version 1 Istio Routing\n",
"Just route to version 1 of our model"
]
},
{
Expand All @@ -385,7 +397,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Launch Version 2 of Model"
"# Launch Version 2 of Model\n",
"Version 2 is a Tensorflow Deep Learning Model for MNIST. Hopefully, better..."
]
},
{
Expand All @@ -397,6 +410,15 @@
"!pygmentize mnist_v2.json"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"get_graph(\"mnist_v2.json\")"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down Expand Up @@ -435,7 +457,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Setup Canary Routing"
"# Setup Canary Routing\n",
"Let's be cautious and route 30% of traffic to version 2"
]
},
{
Expand All @@ -460,7 +483,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Setup Routing to Version 2"
"# Setup Routing to Version 2\n",
"After testing we are happy and want to switch 100% of traffic to version 2 our Tensorflow model."
]
},
{
Expand Down Expand Up @@ -490,6 +514,66 @@
"utils.predict_rest_mnist(mnist,\"mnist-classifier\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Switch to final model\n",
"Finally, lets save resources and remove version 1 of our model"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pygmentize mnist_v3.json"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"get_graph(\"mnist_v3.json\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl apply -f mnist_v3.json"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"** Wait until pods ready**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl get pods"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"utils.predict_rest_mnist(mnist,\"mnist-classifier\")"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down
4 changes: 2 additions & 2 deletions examples/istio/canary_update/istio_canary_v2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ spec:
- destination:
host: mnist-deployment
subset: v1
weight: 80
weight: 70
- destination:
host: mnist-deployment
subset: v2
weight: 20
weight: 30
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
Expand Down
8 changes: 4 additions & 4 deletions examples/istio/canary_update/mnist_v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
"spec": {
"containers": [
{
"image": "seldonio/r-mnist:0.1",
"image": "seldonio/sk-mnist:0.1",
"imagePullPolicy": "IfNotPresent",
"name": "r-mnist-classifier",
"name": "sk-mnist-classifier",
"resources": {
"requests": {
"memory": "1Mi"
Expand All @@ -35,13 +35,13 @@
}],
"graph": {
"children": [],
"name": "r-mnist-classifier",
"name": "sk-mnist-classifier",
"endpoint": {
"type" : "REST"
},
"type": "MODEL"
},
"name": "r-mnist-predictor",
"name": "sk-mnist-predictor",
"replicas": 1,
"labels":{
"version":"v1"
Expand Down
8 changes: 4 additions & 4 deletions examples/istio/canary_update/mnist_v2.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
"spec": {
"containers": [
{
"image": "seldonio/r-mnist:0.1",
"image": "seldonio/sk-mnist:0.1",
"imagePullPolicy": "IfNotPresent",
"name": "r-mnist-classifier",
"name": "sk-mnist-classifier",
"resources": {
"requests": {
"memory": "1Mi"
Expand All @@ -35,13 +35,13 @@
}],
"graph": {
"children": [],
"name": "r-mnist-classifier",
"name": "sk-mnist-classifier",
"endpoint": {
"type" : "REST"
},
"type": "MODEL"
},
"name": "r-mnist-predictor",
"name": "sk-mnist-predictor",
"replicas": 1,
"labels":{
"version":"v1"
Expand Down
53 changes: 53 additions & 0 deletions examples/istio/canary_update/mnist_v3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"apiVersion": "machinelearning.seldon.io/v1alpha2",
"kind": "SeldonDeployment",
"metadata": {
"labels": {
"app": "seldon"
},
"name": "mnist-classifier"
},
"spec": {
"annotations": {
"project_name": "Mnist classification"
},
"name": "mnist-deployment",
"oauth_key": "oauth-key",
"oauth_secret": "oauth-secret",
"predictors": [
{
"componentSpecs": [{
"spec": {
"containers": [
{
"image": "seldonio/deep-mnist:0.1",
"imagePullPolicy": "IfNotPresent",
"name": "tf-mnist-classifier",
"resources": {
"requests": {
"memory": "1Mi"
}
}
}
],
"terminationGracePeriodSeconds": 20
}
}],
"graph": {
"children": [],
"name": "tf-mnist-classifier",
"endpoint": {
"type" : "REST"
},
"type": "MODEL"
},
"name": "tf-mnist-predictor",
"replicas": 1,
"labels":{
"version":"v2"
}
}

]
}
}
8 changes: 8 additions & 0 deletions examples/istio/canary_update/setup_port_forwards.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#Ambassador
kubectl port-forward $(kubectl get pods -n seldon -l service=ambassador -o jsonpath='{.items[0].metadata.name}') -n seldon 8002:8080 &

#Seldon Grafana
kubectl port-forward $(kubectl get pods -n seldon -l app=grafana-prom-server -o jsonpath='{.items[0].metadata.name}') -n seldon 3001:3000 &

#Istio grafana
kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 3000:3000 &
36 changes: 36 additions & 0 deletions examples/istio/canary_update/visualizer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import graphviz
import json

def _populate_graph(dot, root, suffix=''):
name = root.get("name")
id = name+suffix
if root.get("implementation"):
dot.node(id, label=name, shape="box", style="filled", color="lightgrey")
else:
dot.node(id, label=name, shape="box")
endpoint_type = root.get("endpoint",{}).get("type")
if endpoint_type is not None:
dot.node(id+'endpoint', label=endpoint_type)
dot.edge(id,id+'endpoint')
for child in root.get("children",[]):
child_id = _populate_graph(dot,child)
dot.edge(id, child_id)
return id

def get_graph(filename,predictor=0):
deployment = json.load(open(filename,'r'))
predictors = deployment.get("spec").get("predictors")
dot = graphviz.Digraph()

with dot.subgraph(name="cluster_0") as pdot:
graph = predictors[0].get("graph")
_populate_graph(pdot, graph, suffix='0')
pdot.attr(label="predictor")

if len(predictors)>1:
with dot.subgraph(name="cluster_1") as cdot:
graph = predictors[1].get("graph")
_populate_graph(cdot, graph, suffix='1')
cdot.attr(label="canary")

return dot
4 changes: 4 additions & 0 deletions examples/models/sk_mnist/.s2i/environment
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
MODEL_NAME=SkMnist
API_TYPE=REST
SERVICE_TYPE=MODEL
PERSISTENCE=0
12 changes: 12 additions & 0 deletions examples/models/sk_mnist/SkMnist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from sklearn.externals import joblib

class SkMnist(object):
def __init__(self):
self.class_names = ["class:{}".format(str(i)) for i in range(10)]
self.clf = joblib.load('sk.pkl')

def predict(self,X,feature_names):
predictions = self.clf.predict_proba(X)
return predictions


22 changes: 22 additions & 0 deletions examples/models/sk_mnist/contract.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"features":[
{
"name":"x",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,1],
"repeat":784
}
],
"targets":[
{
"name":"class",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,1],
"repeat":10
}
]
}


2 changes: 2 additions & 0 deletions examples/models/sk_mnist/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
scipy>= 0.13.3
scikit-learn>=0.18
Loading

0 comments on commit 473b30a

Please sign in to comment.