-
Notifications
You must be signed in to change notification settings - Fork 835
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/master'
- Loading branch information
Showing
21 changed files
with
9,651 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# Install Seldon-Core | ||
|
||
To install seldon-core on a Kubernetes cluster you have several choices: | ||
|
||
* Decide on which package manager to use, we support: | ||
* Helm | ||
* Ksonnet | ||
* Decide on how you wish APIs to be exposed, we support: | ||
* Ambassador reverse proxy | ||
* Seldon's builtin OAuth API Gateway | ||
* Decide on whether you wish to contribute anonymous usage metrics. We encourage you to allow anonymous usage metrics to help us improve the project by understanding the deployment environments. More details can be found [here](/docs/developer/readme.md#usage-reporting) | ||
* Does your kubernetes cluster have RBAC enabled? | ||
* If not then disable seldon RBAC setup | ||
|
||
Follow one of the methods below: | ||
|
||
## With Helm | ||
|
||
* [Install Helm](https://docs.helm.sh) | ||
* [Optionally, Install Ambassador](https://www.getambassador.io) | ||
* Install Seldon CRD. Set: | ||
* ```usage_metrics.enabled``` as appropriate. | ||
|
||
``` | ||
helm install seldon-core-crd --name seldon-core-crd --repo https://storage.googleapis.com/seldon-charts \ | ||
--set usage_metrics.enabled=true | ||
``` | ||
* Install seldon-core components. Set | ||
* ```apife.enabled``` : (default true) set to ```false``` if you have installed Ambassador. | ||
* ```rbac.enabled``` : (default true) set to ```false``` if running an old Kubernetes cluster without RBAC. | ||
``` | ||
helm install seldon-core --name seldon-core --repo https://storage.googleapis.com/seldon-charts \ | ||
--set apife.enabled=<true|false> \ | ||
--set rbac.enabled=<true|false> | ||
``` | ||
|
||
Notes | ||
|
||
* You can use ```--namespace``` to install seldon-core to a particular namespace | ||
|
||
## With Ksonnet | ||
|
||
* [install Ksonnet](https://ksonnet.io/) | ||
* [Optionally, Install Ambassador](https://www.getambassador.io) | ||
* Create a seldon ksonnet app | ||
``` | ||
ks init my-ml-deployment --api-spec=version:v1.8.0 | ||
``` | ||
* Install seldon-core. Set: | ||
* ```withApife``` set to ```false``` if you are using Ambassador | ||
* ```withRbac``` set to ```true``` if your cluster has RBAC enabled | ||
``` | ||
cd my-ml-deployment && \ | ||
ks registry add seldon-core github.com/SeldonIO/seldon-core/tree/master/seldon-core && \ | ||
ks pkg install seldon-core/seldon-core@master && \ | ||
ks generate seldon-core seldon-core \ | ||
--withApife=<true|false> \ | ||
--withRbac=<true|false> | ||
``` | ||
* Launch components onto cluster | ||
``` | ||
ks apply default | ||
``` | ||
Notes | ||
|
||
* You can use ```--namespace``` to install seldon-core to a particular namespace | ||
|
||
## Other Options | ||
|
||
### Install with kubeflow | ||
|
||
* [Install Seldon as part of kubeflow.](https://github.com/kubeflow/kubeflow/blob/master/user_guide.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
API_TYPE=REST | ||
SERVICE_TYPE=MODEL |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"features":[ | ||
{ | ||
"name":"_c", | ||
"dtype":"INT", | ||
"ftype":"continuous", | ||
"range":[0,255], | ||
"repeat":784 | ||
} | ||
], | ||
"targets":[ | ||
{ | ||
"name":"class", | ||
"dtype":"FLOAT", | ||
"ftype":"continuous", | ||
"range":[0,1], | ||
"repeat":10 | ||
} | ||
] | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,282 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# PySpark and PMML Example\n", | ||
"In this example we train an MNIST model using pySpark, export the model to PMML and then wrap it using Seldon's S2I interface so we can run predictions against it using seldon-core.\n", | ||
"\n", | ||
"## Dependencies\n", | ||
"\n", | ||
"To run this notebook you will need to set up pySpark and JPMML's spark export.\n", | ||
"\n", | ||
" * [Install pySpark along with Spark](http://spark.apache.org/downloads.html)\n", | ||
" * [Install JPMML Spark Package](https://github.com/jpmml/jpmml-sparkml-package)\n", | ||
" \n", | ||
" Following the above instruction you should add a set of environment variables of the form shown below to your shell:\n", | ||
"\n", | ||
"```\n", | ||
"export SPARK_HOME=<MY SPARK INSTALL FOLDER>/spark-2.3.0-bin-hadoop2.7\n", | ||
"export PATH=$SPARK_HOME/bin:$PATH\n", | ||
"export PYSPARK_DRIVER_PYTHON=jupyter\n", | ||
"export PYSPARK_DRIVER_PYTHON_OPTS='notebook'\n", | ||
"export PYTHONPATH=<MY JPPML FOLDER>/jpmml-sparkml-package/target/jpmml_sparkml-1.4rc0-py3.6.egg\n", | ||
"```\n", | ||
"\n", | ||
"Then when you run pyspark from the folder of this notebook it should start Jupyter running with a Spark context and the JPMML libraries availble, e.g.\n", | ||
"\n", | ||
"```\n", | ||
"pyspark --jars <MY JPPML FOLDER>/jpmml-sparkml-package/target/jpmml-sparkml-package-1.4-SNAPSHOT.jar\n", | ||
"```" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Train MNIST Model using pySpark" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from tensorflow.examples.tutorials.mnist import input_data\n", | ||
"import numpy as np\n", | ||
"\n", | ||
"mnist = input_data.read_data_sets('data/MNIST_data', one_hot=False)\n", | ||
"X = (mnist.train.images * 225).astype(int)\n", | ||
"X_y = np.concatenate((X,np.expand_dims(mnist.train.labels,1)),axis=1)\n", | ||
"np.savetxt(\"mnist_train.csv\", X_y, fmt='%i', delimiter=\",\")\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from pyspark.ml import Pipeline\n", | ||
"from pyspark.ml.classification import LogisticRegression, LogisticRegressionModel\n", | ||
"from pyspark.ml.feature import VectorAssembler\n", | ||
"\n", | ||
"df = sqlContext.read.csv(\"./mnist_train.csv\",inferSchema=True)\n", | ||
"\n", | ||
"df = df.withColumnRenamed(\"_c784\",\"label\")\n", | ||
"\n", | ||
"assembler = (VectorAssembler()\n", | ||
" .setInputCols(df.columns[0:784])\n", | ||
" .setOutputCol(\"features\"))\n", | ||
"\n", | ||
"lr = LogisticRegression(maxIter=10, regParam=0.01)\n", | ||
"\n", | ||
"pipeline = Pipeline(stages=[assembler, lr])\n", | ||
"model = pipeline.fit(df)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from jpmml_sparkml import toPMMLBytes\n", | ||
"\n", | ||
"pmmlBytes = toPMMLBytes(sc, df, model)\n", | ||
"f = open('model.pmml', 'wb')\n", | ||
"f.write(pmmlBytes)\n", | ||
"f.close()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!mv model.pmml src/main/resources" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Build Image with S2I" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!s2i build . seldonio/seldon-core-s2i-java-build pyspark-test:0.1 --runtime-image seldonio/seldon-core-s2i-java-runtime" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Test with Docker" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!docker run --name \"pyspark_predictor\" -d --rm -p 5000:5000 pyspark-test:0.1" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!cd ../../../wrappers/testing && make build_protos" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!python ../../../wrappers/testing/tester.py contract.json 0.0.0.0 5000 -p -t" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!docker rm pyspark_predictor --force" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Test in Minikube" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!minikube start --memory 4096 --feature-gates=CustomResourceValidation=true --extra-config=apiserver.Authorization.Mode=RBAC" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!kubectl create clusterrolebinding kube-system-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!helm init" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!helm install ../../../helm-charts/seldon-core-crd --name seldon-core-crd --set usage_metrics.enabled=true\n", | ||
"!helm install ../../../helm-charts/seldon-core --name seldon-core" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!eval $(minikube docker-env) && s2i build . seldonio/seldon-core-s2i-java-build pyspark-test:0.1 --runtime-image seldonio/seldon-core-s2i-java-runtime" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!kubectl create -f mnist_deployment.json" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Wait until ready (replicas == replicasAvailable)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!kubectl get seldondeployments seldon-deployment-example -o jsonpath='{.status}'" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!python ../../../util/api_tester/api-tester.py contract.json \\\n", | ||
" `minikube ip` `kubectl get svc -l app=seldon-apiserver-container-app -o jsonpath='{.items[0].spec.ports[0].nodePort}'` \\\n", | ||
" --oauth-key oauth-key --oauth-secret oauth-secret -p" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"!minikube delete" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.6.4" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
Oops, something went wrong.