W tym samouczku pokazano, jak używać komponentów TensorFlow Serving działających w kontenerach platformy Docker do obsługi modelu TensorFlow ResNet oraz jak wdrożyć klaster obsługujący za pomocą Kubernetes.
Aby dowiedzieć się więcej na temat udostępniania TensorFlow, zalecamy podstawowy samouczek TensorFlow Serving i zaawansowany samouczek TensorFlow Serving .
Aby dowiedzieć się więcej o modelu TensorFlow ResNet, zalecamy przeczytanie ResNet w TensorFlow .
- Część 1 zawiera konfigurację środowiska
- Część 2 pokazuje, jak uruchomić lokalny obraz obsługujący platformę Docker
- Część 3 pokazuje, jak wdrożyć w Kubernetes.
Część 1: Konfiguracja
Zanim zaczniesz, najpierw zainstaluj Docker .
Pobierz zapisany model ResNet
Wyczyśćmy nasz lokalny katalog modeli, na wypadek, gdybyśmy już go posiadali:
rm -rf /tmp/resnet
Głębokie sieci resztkowe, w skrócie ResNets, dostarczyły przełomowej koncepcji mapowania tożsamości umożliwiającej szkolenie bardzo głębokich splotowych sieci neuronowych. W naszym przykładzie pobierzemy zapisany model TensorFlow z ResNet dla zestawu danych 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/
Możemy sprawdzić, czy mamy SavedModel:
$ ls /tmp/resnet/*
saved_model.pb variables
Część 2: Uruchamianie w Dockerze
Zatwierdź obraz do wdrożenia
Teraz chcemy pobrać obraz do obsługi i zatwierdzić wszystkie zmiany w nowym obrazie $USER/resnet_serving
na potrzeby wdrożenia Kubernetes.
Najpierw uruchamiamy obraz obsługujący jako demon:
docker run -d --name serving_base tensorflow/serving
Następnie kopiujemy dane modelu ResNet do folderu modelu kontenera:
docker cp /tmp/resnet serving_base:/models/resnet
Na koniec angażujemy kontener do obsługi modelu ResNet:
docker commit --change "ENV MODEL_NAME resnet" serving_base \
$USER/resnet_serving
Zatrzymajmy teraz podstawowy pojemnik do serwowania
docker kill serving_base
docker rm serving_base
Uruchom serwer
Teraz uruchommy kontener z modelem ResNet, aby był gotowy do udostępnienia, odsłaniając port gRPC 8500:
docker run -p 8500:8500 -t $USER/resnet_serving &
Zapytaj serwer
W przypadku klienta będziemy musieli sklonować repozytorium TensorFlow Serving GitHub:
git clone https://github.com/tensorflow/serving
cd serving
Wyślij zapytanie do serwera za pomocą resnet_client_grpc.py . Klient pobiera obraz i wysyła go przez gRPC w celu klasyfikacji w kategoriach ImageNet .
tools/run_in_docker.sh python tensorflow_serving/example/resnet_client_grpc.py
Powinno to dać wynik taki jak:
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"
}
To działa! Serwer pomyślnie klasyfikuje zdjęcie kota!
Część 3: Wdrażanie w Kubernetes
W tej sekcji używamy obrazu kontenera utworzonego w części 0, aby wdrożyć klaster obsługujący z Kubernetesem w Google Cloud Platform .
Logowanie do projektu GCloud
Zakładamy, że utworzyłeś i zalogowałeś się do projektu gcloud o nazwie tensorflow-serving
.
gcloud auth login --project tensorflow-serving
Utwórz klaster kontenerów
Najpierw tworzymy klaster Google Kubernetes Engine na potrzeby wdrożenia usługi.
$ gcloud container clusters create resnet-serving-cluster --num-nodes 5
Który powinien wypisać coś takiego:
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
Ustaw domyślny klaster dla polecenia kontenera gcloud i przekaż poświadczenia klastra do kubectl .
gcloud config set container/cluster resnet-serving-cluster
gcloud container clusters get-credentials resnet-serving-cluster
co powinno skutkować:
Fetching cluster endpoint and auth data.
kubeconfig entry generated for resnet-serving-cluster.
Prześlij obraz platformy Docker
Prześlijmy teraz nasz obraz do Google Container Registry , abyśmy mogli go uruchomić na Google Cloud Platform.
Najpierw tagujemy obraz $USER/resnet_serving
przy użyciu formatu Container Registry i nazwy naszego projektu,
docker tag $USER/resnet_serving gcr.io/tensorflow-serving/resnet
Następnie konfigurujemy Dockera tak, aby używał gcloud jako pomocnika poświadczeń:
gcloud auth configure-docker
Następnie wrzucamy obraz do Rejestru,
docker push gcr.io/tensorflow-serving/resnet
Utwórz wdrożenie i usługę Kubernetes
Wdrożenie składa się z 3 replik serwera resnet_inference
kontrolowanych przez wdrożenie Kubernetes . Repliki są udostępniane zewnętrznie przez usługę Kubernetes wraz z zewnętrznym modułem równoważenia obciążenia .
Tworzymy je korzystając z przykładowej konfiguracji Kubernetesa resnet_k8s.yaml .
kubectl create -f tensorflow_serving/example/resnet_k8s.yaml
Z wyjściem:
deployment "resnet-deployment" created
service "resnet-service" created
Aby wyświetlić stan wdrożenia i podów:
$ 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
Aby wyświetlić status usługi:
$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
resnet-service 10.239.240.227 104.155.184.157 8500/TCP 1m
Zanim wszystko zacznie działać, może minąć trochę czasu.
$ 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
Zewnętrzny adres IP usługi jest wyświetlany obok elementu Ingress LoadBalancer.
Zapytaj o model
Możemy teraz wysyłać zapytania do usługi pod jej adresem zewnętrznym z naszego lokalnego hosta.
$ 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"
}
Pomyślnie wdrożyłeś model ResNet służący jako usługa w Kubernetesie!