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 configura 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 TensorFlow SavedModel de ResNet para el conjunto de datos 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 SavedModel:
$ ls /tmp/resnet/*
saved_model.pb variables
Parte 2: Ejecutar en Docker
Confirmar imagen para implementación
Ahora queremos tomar una imagen de publicación 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 demonio:
docker run -d --name serving_base tensorflow/serving
A continuación, copiamos los datos del modelo ResNet a la carpeta del modelo del contenedor:
docker cp /tmp/resnet serving_base:/models/resnet
Finalmente comprometemos el contenedor para que sirva el modelo ResNet:
docker commit --change "ENV MODEL_NAME resnet" serving_base \
$USER/resnet_serving
Ahora detengamos el recipiente base para servir.
docker kill serving_base
docker rm serving_base
Iniciar el servidor
Ahora iniciemos 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 &
Consultar el servidor
Para el cliente, necesitaremos clonar el repositorio de TensorFlow Serving GitHub:
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 un resultado 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: Implementación en Kubernetes
En esta sección utilizamos la imagen del contenedor creada en la Parte 0 para implementar un clúster de servicio con Kubernetes en Google Cloud Platform .
Inicio de sesión del proyecto GCloud
Aquí asumimos que creó e inició 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
Configure el clúster predeterminado para el comando del contenedor gcloud y pase 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 envíemos nuestra imagen al Registro de contenedores de Google para que podamos ejecutarla en Google Cloud Platform.
Primero etiquetamos la imagen $USER/resnet_serving
usando el formato Container Registry y el nombre de nuestro 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 enviamos 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 Kubernetes junto con un balanceador de carga externo .
Los creamos usando el ejemplo de configuración de Kubernetes 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 hasta 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.
Consultar 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 sirve como servicio en Kubernetes!