В этом руководстве показано, как использовать компоненты обслуживания TensorFlow, работающие в контейнерах Docker, для обслуживания модели TensorFlow ResNet и как развернуть обслуживающий кластер с помощью Kubernetes.
Чтобы узнать больше о обслуживании TensorFlow, мы рекомендуем базовое руководство по обслуживанию TensorFlow и расширенное руководство по обслуживанию TensorFlow .
Чтобы узнать больше о модели TensorFlow ResNet, мы рекомендуем прочитать ResNet в TensorFlow .
- Часть 1 посвящена настройке вашей среды.
- В части 2 показано, как запустить локальный образ обслуживания Docker.
- В части 3 показано, как развертывать в Kubernetes.
Часть 1: Настройка
Прежде чем приступить к работе, сначала установите Docker .
Загрузите сохраненную модель ResNet.
Давайте очистим наш локальный каталог моделей, если он у нас уже есть:
rm -rf /tmp/resnet
Глубокие остаточные сети, или сокращенно ResNet, предоставили революционную идею сопоставления идентичности, позволяющую обучать очень глубокие сверточные нейронные сети. В нашем примере мы загрузим сохраненную модель TensorFlow ResNet для набора данных ImageNet.
# Download Resnet model from TF Hub
wget https://tfhub.dev/tensorflow/resnet_50/classification/1?tf-hub-format=compressed -o resnet.tar.gz
# Extract SavedModel into a versioned subfolder ‘123’
mkdir -p /tmp/resnet/123
tar xvfz resnet.tar.gz -C /tmp/resnet/123/
Мы можем убедиться, что у нас есть SavedModel:
$ ls /tmp/resnet/*
saved_model.pb variables
Часть 2. Запуск в Docker
Зафиксировать образ для развертывания
Теперь мы хотим взять обслуживающий образ и зафиксировать все изменения в новом образе $USER/resnet_serving
для развертывания Kubernetes.
Сначала мы запускаем обслуживающий образ в качестве демона:
docker run -d --name serving_base tensorflow/serving
Затем мы копируем данные модели ResNet в папку модели контейнера:
docker cp /tmp/resnet serving_base:/models/resnet
Наконец, мы передаем контейнер для обслуживания модели ResNet:
docker commit --change "ENV MODEL_NAME resnet" serving_base \
$USER/resnet_serving
Теперь давайте остановим обслуживающий базовый контейнер.
docker kill serving_base
docker rm serving_base
Запустить сервер
Теперь давайте запустим контейнер с моделью ResNet, чтобы он был готов к обслуживанию, открыв порт gRPC 8500:
docker run -p 8500:8500 -t $USER/resnet_serving &
Запросить сервер
Для клиента нам нужно будет клонировать репозиторий TensorFlow Serving GitHub:
git clone https://github.com/tensorflow/serving
cd serving
Опросите сервер с помощью resnet_client_grpc.py . Клиент загружает изображение и отправляет его через gRPC для классификации по категориям ImageNet .
tools/run_in_docker.sh python tensorflow_serving/example/resnet_client_grpc.py
Это должно привести к выводу вроде:
outputs {
key: "classes"
value {
dtype: DT_INT64
tensor_shape {
dim {
size: 1
}
}
int64_val: 286
}
}
outputs {
key: "probabilities"
value {
dtype: DT_FLOAT
tensor_shape {
dim {
size: 1
}
dim {
size: 1001
}
}
float_val: 2.41628322328e-06
float_val: 1.90121829746e-06
float_val: 2.72477100225e-05
float_val: 4.42638565801e-07
float_val: 8.98362372936e-07
float_val: 6.84421956976e-06
float_val: 1.66555237229e-05
...
float_val: 1.59407863976e-06
float_val: 1.2315689446e-06
float_val: 1.17812135159e-06
float_val: 1.46365800902e-05
float_val: 5.81210713335e-07
float_val: 6.59980651108e-05
float_val: 0.00129527016543
}
}
model_spec {
name: "resnet"
version {
value: 123
}
signature_name: "serving_default"
}
Оно работает! Сервер успешно классифицирует изображение кота!
Часть 3. Развертывание в Kubernetes
В этом разделе мы используем образ контейнера, созданный в части 0, для развертывания обслуживающего кластера с Kubernetes в Google Cloud Platform .
Вход в проект GCloud
Здесь мы предполагаем, что вы создали и вошли в систему проект gcloud с именем tensorflow-serving
.
gcloud auth login --project tensorflow-serving
Создать кластер контейнеров
Сначала мы создаем кластер Google Kubernetes Engine для развертывания службы.
$ gcloud container clusters create resnet-serving-cluster --num-nodes 5
Что должно вывести что-то вроде:
Creating cluster resnet-serving-cluster...done.
Created [https://container.googleapis.com/v1/projects/tensorflow-serving/zones/us-central1-f/clusters/resnet-serving-cluster].
kubeconfig entry generated for resnet-serving-cluster.
NAME ZONE MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
resnet-serving-cluster us-central1-f 1.1.8 104.197.163.119 n1-standard-1 1.1.8 5 RUNNING
Установите кластер по умолчанию для команды контейнера gcloud и передайте учетные данные кластера в kubectl .
gcloud config set container/cluster resnet-serving-cluster
gcloud container clusters get-credentials resnet-serving-cluster
что должно привести к:
Fetching cluster endpoint and auth data.
kubeconfig entry generated for resnet-serving-cluster.
Загрузите образ Docker
Давайте теперь отправим наш образ в реестр контейнеров Google , чтобы мы могли запустить его на Google Cloud Platform.
Сначала мы помечаем образ $USER/resnet_serving
используя формат реестра контейнеров и имя нашего проекта:
docker tag $USER/resnet_serving gcr.io/tensorflow-serving/resnet
Далее мы настраиваем Docker для использования gcloud в качестве помощника по учетным данным:
gcloud auth configure-docker
Далее мы помещаем образ в реестр,
docker push gcr.io/tensorflow-serving/resnet
Создание развертывания и обслуживания Kubernetes
Развертывание состоит из трех реплик сервера resnet_inference
, управляемых развертыванием Kubernetes . Реплики предоставляются извне службой Kubernetes вместе с внешним балансировщиком нагрузки .
Создаём их на примере конфига Kubernetes resnet_k8s.yaml .
kubectl create -f tensorflow_serving/example/resnet_k8s.yaml
С выводом:
deployment "resnet-deployment" created
service "resnet-service" created
Чтобы просмотреть состояние развертывания и модулей:
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
resnet-deployment 3 3 3 3 5s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
resnet-deployment-bbcbc 1/1 Running 0 10s
resnet-deployment-cj6l2 1/1 Running 0 10s
resnet-deployment-t1uep 1/1 Running 0 10s
Чтобы просмотреть статус услуги:
$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
resnet-service 10.239.240.227 104.155.184.157 8500/TCP 1m
Чтобы все заработало, может потребоваться некоторое время.
$ kubectl describe service resnet-service
Name: resnet-service
Namespace: default
Labels: run=resnet-service
Selector: run=resnet-service
Type: LoadBalancer
IP: 10.239.240.227
LoadBalancer Ingress: 104.155.184.157
Port: <unset> 8500/TCP
NodePort: <unset> 30334/TCP
Endpoints: <none>
Session Affinity: None
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {service-controller } Normal CreatingLoadBalancer Creating load balancer
1m 1m 1 {service-controller } Normal CreatedLoadBalancer Created load balancer
Внешний IP-адрес службы указан рядом с входом LoadBalancer.
Запросить модель
Теперь мы можем запросить службу по ее внешнему адресу с нашего локального хоста.
$ tools/run_in_docker.sh python \
tensorflow_serving/example/resnet_client_grpc.py \
--server=104.155.184.157:8500
outputs {
key: "classes"
value {
dtype: DT_INT64
tensor_shape {
dim {
size: 1
}
}
int64_val: 286
}
}
outputs {
key: "probabilities"
value {
dtype: DT_FLOAT
tensor_shape {
dim {
size: 1
}
dim {
size: 1001
}
}
float_val: 2.41628322328e-06
float_val: 1.90121829746e-06
float_val: 2.72477100225e-05
float_val: 4.42638565801e-07
float_val: 8.98362372936e-07
float_val: 6.84421956976e-06
float_val: 1.66555237229e-05
...
float_val: 1.59407863976e-06
float_val: 1.2315689446e-06
float_val: 1.17812135159e-06
float_val: 1.46365800902e-05
float_val: 5.81210713335e-07
float_val: 6.59980651108e-05
float_val: 0.00129527016543
}
}
model_spec {
name: "resnet"
version {
value: 1538687457
}
signature_name: "serving_default"
}
Вы успешно развернули модель ResNet, работающую в качестве службы в Kubernetes!