Treten Sie der SIG TFX-Addons-Community bei und helfen Sie mit, TFX noch besser zu machen! SIG TFX-Addons beitreten

Verwenden Sie TensorFlow Serving mit Kubernetes

Dieses Tutorial zeigt, wie TensorFlow Serving-Komponenten, die in Docker-Containern ausgeführt werden, für das TensorFlow ResNet-Modell verwendet werden und wie der Serving-Cluster mit Kubernetes bereitgestellt wird.

Um mehr über TensorFlow Serving zu erfahren, empfehlen wir das grundlegende Tutorial zu TensorFlow Serving und das erweiterte Tutorial zu TensorFlow Serving .

Um mehr über das TensorFlow ResNet-Modell zu erfahren, empfehlen wir, ResNet in TensorFlow zu lesen.

  • Teil 1 richtet Ihre Umgebung ein
  • Teil 2 zeigt, wie das lokale Docker-Serving-Image ausgeführt wird
  • Teil 3 zeigt, wie in Kubernetes bereitgestellt wird.

Teil 1: Einrichtung

Bevor Sie beginnen, installieren Sie zuerst Docker .

Laden Sie das ResNet SavedModel herunter

Löschen wir unser lokales Modellverzeichnis, falls wir bereits eines haben:

rm -rf /tmp/resnet

Tiefe Restnetzwerke, kurz ResNets, lieferten die bahnbrechende Idee von Identitätszuordnungen, um das Training sehr tiefer neuronaler Faltungsnetzwerke zu ermöglichen. In unserem Beispiel laden wir ein TensorFlow SavedModel von ResNet für das ImageNet-Dataset herunter.

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

Wir können überprüfen, ob wir das SavedModel haben:

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

Teil 2: Ausführen in Docker

Übertragen Sie das Image für die Bereitstellung

Jetzt wollen wir eine Portion Bild nehmen und verpflichten alle Änderungen an einem neuen Bild $USER/resnet_serving für Kubernetes Einsatz.

Zuerst führen wir ein Serving-Image als Daemon aus:

docker run -d --name serving_base tensorflow/serving

Als Nächstes kopieren wir die ResNet-Modelldaten in den Modellordner des Containers:

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

Schließlich verpflichten wir den Container, das ResNet-Modell zu bedienen:

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

Lassen Sie uns nun den Servierbodenbehälter stoppen

docker kill serving_base
docker rm serving_base

Starten Sie den Server

Beginnen wir den Container nun mit dem ResNet-Modell, damit er für die Bereitstellung bereit ist, und legen den gRPC-Port 8500 frei:

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

Fragen Sie den Server ab

Für den Client müssen wir das TensorFlow Serving GitHub-Repo klonen:

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

Fragen Sie den Server mit resnet_client_grpc.py ab . Der Client lädt ein Bild herunter und sendet es über gRPC zur Klassifizierung in ImageNet- Kategorien.

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

Dies sollte zu einer Ausgabe führen wie:

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

Es klappt! Der Server klassifiziert erfolgreich ein Katzenbild!

Teil 3: Bereitstellung in Kubernetes

In diesem Abschnitt verwenden wir das in Teil 0 erstellte Container-Image, um einen Serving-Cluster mit Kubernetes in der Google Cloud Platform bereitzustellen .

GCloud-Projekt-Login

Hier nehmen wir an, dass Sie ein gcloud- Projekt mit dem Namen tensorflow-serving erstellt und angemeldet haben.

gcloud auth login --project tensorflow-serving

Erstellen Sie einen Containercluster

Zuerst erstellen wir einen Google Kubernetes Engine- Cluster für die Dienstbereitstellung.

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

Welches sollte etwas ausgeben wie:

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

Legen Sie den Standardcluster für den Befehl gcloud container fest und übergeben Sie die Clusteranmeldeinformationen an kubectl .

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

was dazu führen sollte:

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

Laden Sie das Docker-Image hoch

Lassen Sie uns unser Bild jetzt in die Google Container-Registrierung verschieben, damit wir es auf der Google Cloud Platform ausführen können.

Zuerst markieren wir das Image $USER/resnet_serving mit dem Container Registry-Format und unserem Projektnamen.

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

Als Nächstes konfigurieren wir Docker so, dass gcloud als Helfer für Anmeldeinformationen verwendet wird:

gcloud auth configure-docker

Als nächstes schieben wir das Bild in die Registrierung,

docker push gcr.io/tensorflow-serving/resnet

Erstellen Sie die Bereitstellung und den Service von Kubernetes

Die Bereitstellung besteht aus 3 Replikaten des resnet_inference Servers, die von einer Kubernetes-Bereitstellung gesteuert werden. Die Replikate werden extern von einem Kubernetes-Dienst zusammen mit einem externen Load Balancer verfügbar gemacht .

Wir erstellen sie am Beispiel der Kubernetes-Konfiguration resnet_k8s.yaml .

kubectl create -f tensorflow_serving/example/resnet_k8s.yaml

Mit Ausgabe:

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

So zeigen Sie den Status der Bereitstellung und der Pods an:

$ 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

So zeigen Sie den Status des Dienstes an:

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

Es kann eine Weile dauern, bis alles funktioniert.

$ 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

Die externe IP-Adresse des Dienstes wird neben LoadBalancer Ingress aufgeführt.

Fragen Sie das Modell ab

Wir können den Dienst jetzt an seiner externen Adresse von unserem lokalen Host abfragen.

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

Sie haben das ResNet-Modell, das als Dienst in Kubernetes dient, erfolgreich bereitgestellt!