From be2fcaf190c5626888c404918ed517f86fa0ba77 Mon Sep 17 00:00:00 2001 From: Gurminder Sunner Date: Mon, 9 Apr 2018 11:25:36 +0100 Subject: [PATCH] add notebook for azure demo --- notebooks/kubectl_demo_azure.ipynb | 386 +++++++++++++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 notebooks/kubectl_demo_azure.ipynb diff --git a/notebooks/kubectl_demo_azure.ipynb b/notebooks/kubectl_demo_azure.ipynb new file mode 100644 index 0000000000..ead4974fa1 --- /dev/null +++ b/notebooks/kubectl_demo_azure.ipynb @@ -0,0 +1,386 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Deploying Machine Learning Models on Azure Kubernetes\n", + "\n", + "\"predictor" + ] + }, + { + "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 +}