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 notebook for azure demo #135

Merged
merged 1 commit into from
Apr 10, 2018
Merged
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
386 changes: 386 additions & 0 deletions notebooks/kubectl_demo_azure.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,386 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Deploying Machine Learning Models on Azure Kubernetes\n",
"\n",
"<img src=\"images/deploy-graph.png\" alt=\"predictor with canary\" title=\"ml graph\"/>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Prerequisites\n",
" - You need a running AKS cluster with kubernetes>1.8 with kubectl configured to use.\n",
" - [Git clone of Seldon Core](https://github.com/SeldonIO/seldon-core)\n",
" - [Helm](https://github.com/kubernetes/helm)\n",
" - [python grpc tools](https://grpc.io/docs/quickstart/python.html)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install helm"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!helm init"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Start Seldon-Core"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!helm install ../helm-charts/seldon-core-crd --name seldon-core-crd \\\n",
" --set rbac.enabled=false \\\n",
" --set usage_metrics.enabled=true"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl create namespace seldon"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!helm install ../helm-charts/seldon-core --name seldon-core \\\n",
" --set rbac.enabled=false \\\n",
" --set apife_service_type=LoadBalancer \\\n",
" --namespace seldon"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Set up REST and GRPC methods"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Wait for API server to be given an external IP"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl get svc -n seldon seldon-apiserver"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"!cp ../proto/prediction.proto ./proto\n",
"!python -m grpc.tools.protoc -I. --python_out=. --grpc_python_out=. ./proto/prediction.proto"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Setup python code to do REST and gRPC requests. **Only run this when the LoadBalancer created by GCP for the seldon-apife is running**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import requests\n",
"from requests.auth import HTTPBasicAuth\n",
"from proto import prediction_pb2\n",
"from proto import prediction_pb2_grpc\n",
"import grpc\n",
"try:\n",
" from commands import getoutput # python 2\n",
"except ImportError:\n",
" from subprocess import getoutput # python 3\n",
"\n",
"NAMESPACE=\"seldon\"\n",
"SELDON_API_IP=getoutput(\"kubectl get svc -n \"+NAMESPACE+\" seldon-apiserver -o jsonpath='{.status.loadBalancer.ingress[0].ip}'\")\n",
"\n",
"def get_token():\n",
" payload = {'grant_type': 'client_credentials'}\n",
" response = requests.post(\n",
" \"http://{}:8080/oauth/token\".format(SELDON_API_IP),\n",
" auth=HTTPBasicAuth('oauth-key', 'oauth-secret'),\n",
" data=payload)\n",
" token = response.json()[\"access_token\"]\n",
" return token\n",
"\n",
"def rest_request():\n",
" token = get_token()\n",
" headers = {'Authorization': 'Bearer '+token}\n",
" payload = {\"data\":{\"names\":[\"a\",\"b\"],\"tensor\":{\"shape\":[2,2],\"values\":[0,0,1,1]}}}\n",
" response = requests.post(\n",
" \"http://{}:8080/api/v0.1/predictions\".format(SELDON_API_IP),\n",
" headers=headers,\n",
" json=payload)\n",
" print(response.text)\n",
" \n",
"def grpc_request():\n",
" token = get_token()\n",
" datadef = prediction_pb2.DefaultData(\n",
" names = [\"a\",\"b\"],\n",
" tensor = prediction_pb2.Tensor(\n",
" shape = [3,2],\n",
" values = [1.0,1.0,2.0,3.0,4.0,5.0]\n",
" )\n",
" )\n",
" request = prediction_pb2.SeldonMessage(data = datadef)\n",
" channel = grpc.insecure_channel(\"{}:5000\".format(SELDON_API_IP))\n",
" stub = prediction_pb2_grpc.SeldonStub(channel)\n",
" metadata = [('oauth_token', token)]\n",
" response = stub.Predict(request=request,metadata=metadata)\n",
" print(response)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Normal Operation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Create Seldon Deployment"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl create -f resources/model.json -n seldon"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl get seldondeployments -n seldon"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"!kubectl describe seldondeployments seldon-deployment-example -n seldon"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Get the status of the SeldonDeployment. **When ready the replicasAvailable should be 1**."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl get seldondeployments seldon-deployment-example -o jsonpath='{.status}' -n seldon"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Get Predictions"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# REST Request\n",
"rest_request()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# GRPC Request\n",
"grpc_request()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Update Deployment with Canary"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl apply -f resources/model_with_canary.json -n seldon"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Check the status of the deployments. Note: **Might need to run several times until replicasAvailable is 1 for both predictors**."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl get seldondeployments seldon-deployment-example -o jsonpath='{.status}' -n seldon"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"rest_request()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"grpc_request()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Tear Down"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl delete -f resources/model.json -n seldon"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!helm delete seldon-core --purge"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!helm delete seldon-core-crd --purge"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.13"
}
},
"nbformat": 4,
"nbformat_minor": 1
}