Este tutorial muestra cómo usar los componentes de TensorFlow Serving que se ejecutan en contenedores Docker para servir el modelo TensorFlow ResNet y cómo implementar el clúster de servicio con Kubernetes.
Para obtener más información sobre TensorFlow Serving, recomendamos el tutorial básico de TensorFlow Serving y el tutorial avanzado de TensorFlow Serving.
Para obtener más información sobre el modelo TensorFlow ResNet, recomendamos leer ResNet en TensorFlow .
- La parte 1 obtiene la configuración de su entorno
- La parte 2 muestra cómo ejecutar la imagen de servicio local de Docker
- La Parte 3 muestra cómo implementar en Kubernetes.
Parte 1: Configuración
Antes de comenzar, primero instale Docker .
Descargue el modelo guardado de ResNet
Limpiemos nuestro directorio de modelos locales en caso de que ya tengamos uno:
rm -rf /tmp/resnet
Las redes residuales profundas, o ResNets para abreviar, proporcionaron la idea innovadora de los mapeos de identidad para permitir el entrenamiento de redes neuronales convolucionales muy profundas. Para nuestro ejemplo, descargaremos un modelo guardado de TensorFlow de ResNet para el conjunto de datos de 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/
Podemos verificar que tenemos el modelo guardado:
$ ls /tmp/resnet/*
saved_model.pb variables
Parte 2: Ejecutar en Docker
Confirmar imagen para implementación
Ahora queremos tomar una imagen de servicio y confirmar todos los cambios en una nueva imagen $USER/resnet_serving
para la implementación de Kubernetes.
Primero ejecutamos una imagen de servicio como un demonio:
docker run -d --name serving_base tensorflow/serving
A continuación, copiamos los datos del modelo ResNet en la carpeta del modelo del contenedor:
docker cp /tmp/resnet serving_base:/models/resnet
Finalmente, comprometemos el contenedor para servir el modelo ResNet:
docker commit --change "ENV MODEL_NAME resnet" serving_base \
$USER/resnet_serving
Ahora detengamos el contenedor base de servicio.
docker kill serving_base
docker rm serving_base
Inicie el servidor
Ahora comencemos el contenedor con el modelo ResNet para que esté listo para servir, exponiendo el puerto gRPC 8500:
docker run -p 8500:8500 -t $USER/resnet_serving &
consulta el servidor
Para el cliente, necesitaremos clonar el repositorio de GitHub de TensorFlow Serving:
git clone https://github.com/tensorflow/serving
cd serving
Consulta el servidor con resnet_client_grpc.py . El cliente descarga una imagen y la envía a través de gRPC para clasificarla en categorías de ImageNet .
tools/run_in_docker.sh python tensorflow_serving/example/resnet_client_grpc.py
Esto debería dar como resultado una salida como:
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"
}
¡Funciona! ¡El servidor clasifica con éxito una imagen de gato!
Parte 3: Implementar en Kubernetes
En esta sección, usamos la imagen del contenedor creada en la Parte 0 para implementar un clúster de servicio con Kubernetes en Google Cloud Platform .
Iniciar sesión en el proyecto GCloud
Aquí asumimos que ha creado e iniciado sesión en un proyecto de gcloud llamado tensorflow-serving
.
gcloud auth login --project tensorflow-serving
Crear un clúster de contenedores
Primero, creamos un clúster de Google Kubernetes Engine para la implementación del servicio.
$ gcloud container clusters create resnet-serving-cluster --num-nodes 5
Lo que debería generar algo como:
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
Establece el clúster predeterminado para el comando gcloud container y pasa las credenciales del clúster a kubectl .
gcloud config set container/cluster resnet-serving-cluster
gcloud container clusters get-credentials resnet-serving-cluster
lo que debería resultar en:
Fetching cluster endpoint and auth data.
kubeconfig entry generated for resnet-serving-cluster.
Sube la imagen de Docker
Ahora empujemos nuestra imagen a Google Container Registry para que podamos ejecutarla en Google Cloud Platform.
Primero etiquetamos la imagen $USER/resnet_serving
usando el formato de Container Registry y nuestro nombre de proyecto,
docker tag $USER/resnet_serving gcr.io/tensorflow-serving/resnet
A continuación, configuramos Docker para usar gcloud como asistente de credenciales:
gcloud auth configure-docker
A continuación, empujamos la imagen al Registro,
docker push gcr.io/tensorflow-serving/resnet
Crear implementación y servicio de Kubernetes
La implementación consta de 3 réplicas del servidor resnet_inference
controlado por una implementación de Kubernetes . Las réplicas se exponen externamente mediante un servicio de Kubernetes junto con un equilibrador de carga externo .
Los creamos usando el ejemplo Kubernetes config resnet_k8s.yaml .
kubectl create -f tensorflow_serving/example/resnet_k8s.yaml
Con salida:
deployment "resnet-deployment" created
service "resnet-service" created
Para ver el estado de la implementación y los pods:
$ 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
Para ver el estado del servicio:
$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
resnet-service 10.239.240.227 104.155.184.157 8500/TCP 1m
Puede tomar un tiempo para que todo esté en funcionamiento.
$ 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
La dirección IP externa del servicio aparece junto a LoadBalancer Ingress.
consulta el modelo
Ahora podemos consultar el servicio en su dirección externa desde nuestro host local.
$ 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"
}
Ha implementado con éxito el modelo ResNet que actúa como un servicio en Kubernetes.