Rejoignez la communauté SIG TFX-Addons et aidez à rendre TFX encore meilleur!
Cette page a été traduite par l'API Cloud Translation.
Switch to English

Utiliser TensorFlow Serving avec Kubernetes

Ce didacticiel montre comment utiliser les composants de serveur TensorFlow s'exécutant dans des conteneurs Docker pour servir le modèle TensorFlow ResNet et comment déployer le cluster de serveur avec Kubernetes.

Pour en savoir plus sur TensorFlow Serving, nous vous recommandons le didacticiel de base TensorFlow Serving et le didacticiel avancé TensorFlow Serving .

Pour en savoir plus sur le modèle TensorFlow ResNet, nous vous recommandons de lire ResNet dans TensorFlow .

  • La partie 1 obtient la configuration de votre environnement
  • La partie 2 montre comment exécuter l'image de diffusion Docker locale
  • La partie 3 montre comment déployer dans Kubernetes.

Partie 1: Configuration

Avant de commencer, installez d' abord Docker .

Téléchargez le ResNet SavedModel

Effaçons notre répertoire de modèles locaux au cas où nous en aurions déjà un:

rm -rf /tmp/resnet

Les réseaux résiduels profonds, ou ResNets en abrégé, ont fourni l'idée révolutionnaire des mappages d'identité afin de permettre la formation de réseaux de neurones convolutifs très profonds. Pour notre exemple, nous allons télécharger un TensorFlow SavedModel de ResNet pour l'ensemble de données ImageNet.

mkdir /tmp/resnet
curl -s http://download.tensorflow.org/models/official/20181001_resnet/savedmodels/resnet_v2_fp32_savedmodel_NHWC_jpg.tar.gz | \
tar --strip-components=2 -C /tmp/resnet -xvz

Nous pouvons vérifier que nous avons le SavedModel:

$ ls /tmp/resnet/*
saved_model.pb  variables

Partie 2: Exécution dans Docker

Valider l'image pour le déploiement

Nous voulons maintenant prendre une image de diffusion et valider toutes les modifications dans une nouvelle image $USER/resnet_serving pour le déploiement de Kubernetes.

Nous exécutons d'abord une image de diffusion en tant que démon:

docker run -d --name serving_base tensorflow/serving

Ensuite, nous copions les données du modèle ResNet dans le dossier du modèle du conteneur:

docker cp /tmp/resnet serving_base:/models/resnet

Enfin, nous engageons le conteneur à servir le modèle ResNet:

docker commit --change "ENV MODEL_NAME resnet" serving_base \
  $USER/resnet_serving

Arrêtons maintenant le conteneur de base de service

docker kill serving_base
docker rm serving_base

Démarrez le serveur

Maintenant, commençons le conteneur avec le modèle ResNet afin qu'il soit prêt à être diffusé, en exposant le port gRPC 8500:

docker run -p 8500:8500 -t $USER/resnet_serving &

Interroger le serveur

Pour le client, nous aurons besoin de cloner le dépôt TensorFlow Serving GitHub:

git clone https://github.com/tensorflow/serving
cd serving

Interrogez le serveur avec resnet_client_grpc.py . Le client télécharge une image et l'envoie via gRPC pour la classification en catégories ImageNet .

tools/run_in_docker.sh python tensorflow_serving/example/resnet_client_grpc.py

Cela devrait aboutir à une sortie comme:

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"
}

Ça marche! Le serveur classe avec succès une image de chat!

Partie 3: Déployer dans Kubernetes

Dans cette section, nous utilisons l'image de conteneur créée dans la partie 0 pour déployer un cluster de diffusion avec Kubernetes dans Google Cloud Platform .

Connexion au projet GCloud

Ici , nous supposons que vous avez créé et connecté dans un gcloud projet nommé tensorflow-serving .

gcloud auth login --project tensorflow-serving

Créer un cluster de conteneurs

Nous créons d'abord un cluster Google Kubernetes Engine pour le déploiement de services.

$ gcloud container clusters create resnet-serving-cluster --num-nodes 5

Ce qui devrait générer quelque chose comme:

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

Définissez le cluster par défaut pour la commande de conteneur gcloud et transmettez les informations d'identification du cluster à kubectl .

gcloud config set container/cluster resnet-serving-cluster
gcloud container clusters get-credentials resnet-serving-cluster

ce qui devrait se traduire par:

Fetching cluster endpoint and auth data.
kubeconfig entry generated for resnet-serving-cluster.

Télécharger l'image Docker

Poussons maintenant notre image vers Google Container Registry afin que nous puissions l'exécuter sur Google Cloud Platform.

Nous $USER/resnet_serving image $USER/resnet_serving utilisant le format Container Registry et le nom de notre projet,

docker tag $USER/resnet_serving gcr.io/tensorflow-serving/resnet

Ensuite, nous configurons Docker pour utiliser gcloud comme assistant d'identification:

gcloud auth configure-docker

Ensuite, nous poussons l'image vers le registre,

docker push gcr.io/tensorflow-serving/resnet

Créer un déploiement et un service Kubernetes

Le déploiement se compose de 3 répliques du serveur resnet_inference contrôlées par un déploiement Kubernetes . Les réplicas sont exposés en externe par un service Kubernetes avec un équilibreur de charge externe .

Nous les créons en utilisant l'exemple Kubernetes config resnet_k8s.yaml .

kubectl create -f tensorflow_serving/example/resnet_k8s.yaml

Avec sortie:

deployment "resnet-deployment" created
service "resnet-service" created

Pour afficher l'état du déploiement et des 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

Pour afficher l'état du service:

$ kubectl get services
NAME                    CLUSTER-IP       EXTERNAL-IP       PORT(S)     AGE
resnet-service       10.239.240.227   104.155.184.157   8500/TCP    1m

Cela peut prendre un certain temps pour que tout soit opérationnel.

$ 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

L'adresse IP externe du service est répertoriée à côté de LoadBalancer Ingress.

Interroger le modèle

Nous pouvons maintenant interroger le service à son adresse externe à partir de notre hôte 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"
}

Vous avez déployé avec succès le modèle ResNet servant de service dans Kubernetes!