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

Example of TF Serving with GPU #154

Merged
merged 14 commits into from
Jul 25, 2018
Merged
Show file tree
Hide file tree
Changes from 11 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
3 changes: 2 additions & 1 deletion object_detection/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ This example is based on the TensorFlow [Pets tutorial](https://github.com/tenso
1. [Setup a Kubeflow cluster](setup.md)
2. [Submit a distributed object detection training job](submit_job.md)
3. [Monitor your training job](monitor_job.md)
4. [Serve your model with TensorFlow serving](export_tf_graph.md)
4. [Export model](export_tf_graph.md)
5. [Serve the model with GPU](tf_serving_gpu.md)
27 changes: 0 additions & 27 deletions object_detection/export_tf_graph.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,30 +33,3 @@ kubectl -n kubeflow exec -it pets-training-master-r1hv-0-i6k7c sh
mkdir /pets_data/exported_graphs/saved_model/1
cp /pets_data/exported_graphs/saved_model/* /pets_data/exported_graphs/saved_model/1
```

## Serve the model using TF-Serving

Apply the manifest file under [tf-serving](./tf-serving) directory:
```
kubectl -n kubeflow apply -f ./tf-serving/tf-serving.yaml
```

After that you should see pets-model pod. Run:
```
kubectl -n kubeflow get pods | grep pets-model
```
That will output something like this:
```
pets-model-v1-57674c8f76-4qrqp 1/1 Running 0 4h
```
Take a look at the logs:
```
kubectl -n kubeflow logs pets-model-v1-57674c8f76-4qrqp
```
And you should see:
```
2018-06-21 19:20:32.325406: I tensorflow_serving/core/loader_harness.cc:86] Successfully loaded servable version {name: pets-model version: 1}
E0621 19:20:34.134165172 7 ev_epoll1_linux.c:1051] grpc epoll fd: 3
2018-06-21 19:20:34.135354: I tensorflow_serving/model_servers/main.cc:288] Running ModelServer at 0.0.0.0:9000 ...
```
Now you can use a gRPC client to run inference using your trained model!
5 changes: 5 additions & 0 deletions object_detection/ks-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/lib
/.ksonnet/registries
/app.override.yaml
/.ks_environment
/environments
37 changes: 37 additions & 0 deletions object_detection/ks-app/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
apiVersion: 0.1.0
environments:
default:
destination:
namespace: kubeflow
server: https://35.193.147.35
k8sVersion: v1.9.6
path: default
kai4:
destination:
namespace: kubeflow
server: https://35.227.118.244
k8sVersion: v1.9.6
path: kai4
kind: ksonnet.io/app
libraries:
tf-serving:
gitVersion:
commitSha: 430d4f7ae16af389ac570182af519f6571f160cf
refSpec: master
name: tf-serving
registry: kubeflow
name: object-detection-app
registries:
incubator:
gitVersion:
commitSha: 40285d8a14f1ac5787e405e1023cf0c07f6aa28c
refSpec: master
protocol: github
uri: github.com/ksonnet/parts/tree/master/incubator
kubeflow:
gitVersion:
commitSha: 430d4f7ae16af389ac570182af519f6571f160cf
refSpec: master
protocol: github
uri: github.com/kubeflow/kubeflow/tree/master/kubeflow
version: 0.0.1
21 changes: 21 additions & 0 deletions object_detection/ks-app/components/model1.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
local env = std.extVar("__ksonnet/environments");
local params = std.extVar("__ksonnet/params").components["model1"];

local k = import "k.libsonnet";

// ksonnet appears to require name be a parameter of the prototype which is why we handle it differently.
local name = params.name;

// updatedParams includes the namespace from env by default.
// We can override namespace in params if needed
local updatedParams = env + params;

local tfServingBase = import "kubeflow/tf-serving/tf-serving.libsonnet";
local tfServing = tfServingBase {
// Override parameters with user supplied parameters.
params+: updatedParams {
name: name,
},
};

std.prune(k.core.v1.list.new(tfServing.components))
16 changes: 16 additions & 0 deletions object_detection/ks-app/components/params.libsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
global: {},
components: {
// Component-level parameters, defined initially from 'ks prototype use ...'
// Each object below should correspond to a component in the components/ directory
model1: {
cloud: 'gcp',
deployHttpProxy: true,
gcpCredentialSecretName: 'user-sa',
modelPath: 'gs://kai-test2-models/object-detection',
modelServerImage: 'gcr.io/kubeflow-images-public/tensorflow-serving-1.8gpu:latest',
name: 'coco',
numGpus: 1,
},
},
}
73 changes: 73 additions & 0 deletions object_detection/ks-app/vendor/kubeflow/tf-serving/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*

- [tf-serving](#tf-serving)
- [Quickstart](#quickstart)
- [Using the library](#using-the-library)
- [io.ksonnet.pkg.tf-serving](#ioksonnetpkgtf-serving)
- [Example](#example)
- [Parameters](#parameters)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

# tf-serving

> TensorFlow serving is a server for TensorFlow models.


* [Quickstart](#quickstart)
* [Using Prototypes](#using-prototypes)
* [io.ksonnet.pkg.tf-serving](#io.ksonnet.pkg.tf-serving)

## Quickstart

*The following commands use the `io.ksonnet.pkg.tf-serving` prototype to generate Kubernetes YAML for tf-serving, and then deploys it to your Kubernetes cluster.*

First, create a cluster and install the ksonnet CLI (see root-level [README.md](rootReadme)).

If you haven't yet created a [ksonnet application](linkToSomewhere), do so using `ks init <app-name>`.

Finally, in the ksonnet application directory, run the following:

```shell
# Expand prototype as a Jsonnet file, place in a file in the
# `components/` directory. (YAML and JSON are also available.)
$ ks prototype use io.ksonnet.pkg.tf-serving tf-serving \
--name tf-serving \
--namespace default

# Apply to server.
$ ks apply -f tf-serving.jsonnet
```

## Using the library

The library files for tf-serving define a set of relevant *parts* (_e.g._, deployments, services, secrets, and so on) that can be combined to configure tf-serving for a wide variety of scenarios. For example, a database like Redis may need a secret to hold the user password, or it may have no password if it's acting as a cache.

This library provides a set of pre-fabricated "flavors" (or "distributions") of tf-serving, each of which is configured for a different use case. These are captured as ksonnet *prototypes*, which allow users to interactively customize these distributions for their specific needs.

These prototypes, as well as how to use them, are enumerated below.

### io.ksonnet.pkg.tf-serving

TensorFlow serving
#### Example

```shell
# Expand prototype as a Jsonnet file, place in a file in the
# `components/` directory. (YAML and JSON are also available.)
$ ks prototype use io.ksonnet.pkg.tf-serving tf-serving \
--name YOUR_NAME_HERE \
--model_path YOUR_MODEL_PATH_HERE
```

#### Parameters

The available options to pass prototype are:

* `--name=<name>`: Name to give to each of the components [string]
* `--model_path=<model_path>`: Path to the model. This can be a GCS path. [string]


[rootReadme]: https://github.com/ksonnet/mixins
35 changes: 35 additions & 0 deletions object_detection/ks-app/vendor/kubeflow/tf-serving/parts.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "tf-serving",
"apiVersion": "0.0.1",
"kind": "ksonnet.io/parts",
"description": "TensorFlow serving is a server for TensorFlow models.\n",
"author": "kubeflow team <kubeflow-team@google.com>",
"contributors": [
{
"name": "Jeremy Lewi",
"email": "jlewi@google.com"
}
],
"repository": {
"type": "git",
"url": "https://github.com/kubeflow/kubeflow"
},
"bugs": {
"url": "https://github.com/kubeflow/kubeflow/issues"
},
"keywords": [
"kubeflow",
"tensorflow",
"database"
],
"quickStart": {
"prototype": "io.ksonnet.pkg.tf-serving",
"componentName": "tf-serving",
"flags": {
"name": "tf-serving",
"namespace": "default"
},
"comment": "Run TensorFlow Serving"
},
"license": "Apache 2.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// @apiVersion 0.1
// @name io.ksonnet.pkg.tf-serving
// @description TensorFlow serving
// @shortDescription A TensorFlow serving deployment
// @param name string Name to give to each of the components

local k = import "k.libsonnet";

// ksonnet appears to require name be a parameter of the prototype which is why we handle it differently.
local name = import "param://name";

// updatedParams includes the namespace from env by default.
// We can override namespace in params if needed
local updatedParams = env + params;

local tfServingBase = import "kubeflow/tf-serving/tf-serving.libsonnet";
local tfServing = tfServingBase {
// Override parameters with user supplied parameters.
params+: updatedParams {
name: name,
},
};

std.prune(k.core.v1.list.new(tfServing.components))
Loading