מדריך זה מראה כיצד להשתמש ברכיבי TensorFlow Serving הפועלים בקונטיינרים של Docker כדי לשרת את מודל TensorFlow ResNet וכיצד לפרוס את אשכול ההגשה עם Kubernetes.
למידע נוסף על TensorFlow Serving, אנו ממליצים על הדרכה בסיסית של TensorFlow Serving ועל הדרכה מתקדמת של TensorFlow Serving .
כדי ללמוד עוד על מודל TensorFlow ResNet, אנו ממליצים לקרוא את ResNet ב-TensorFlow .
- חלק 1 מקבל את הגדרת הסביבה שלך
- חלק 2 מראה כיצד להפעיל את תמונת ההגשה המקומית של Docker
- חלק 3 מראה כיצד לפרוס ב- Kubernetes.
חלק 1: התקנה
לפני שמתחילים, התקן תחילה את Docker .
הורד את ResNet SavedModel
בואו ננקה את ספריית הדגמים המקומית שלנו למקרה שכבר יש לנו אחד:
rm -rf /tmp/resnet
רשתות שיוריות עמוקות, או בקיצור ResNets, סיפקו את רעיון פריצת הדרך של מיפוי זהויות על מנת לאפשר אימון של רשתות עצביות קונבולוציוניות עמוקות מאוד. לדוגמה שלנו, נוריד TensorFlow SavedModel של ResNet עבור מערך הנתונים של 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/
אנחנו יכולים לוודא שיש לנו את SavedModel:
$ ls /tmp/resnet/*
saved_model.pb variables
חלק 2: פועל ב-Docker
קבע תמונה לפריסה
כעת אנו רוצים לקחת תמונת הגשה ולבצע את כל השינויים לתמונה חדשה $USER/resnet_serving
עבור פריסת Kubernetes.
ראשית אנו מריצים תמונת הגשה בתור דמון:
docker run -d --name serving_base tensorflow/serving
לאחר מכן, אנו מעתיקים את נתוני הדגם של ResNet לתיקיית הדגם של המכולה:
docker cp /tmp/resnet serving_base:/models/resnet
לבסוף אנו מתחייבים למכולה לשרת את מודל ResNet:
docker commit --change "ENV MODEL_NAME resnet" serving_base \
$USER/resnet_serving
עכשיו בואו נעצור את מיכל בסיס ההגשה
docker kill serving_base
docker rm serving_base
הפעל את השרת
עכשיו בואו נתחיל את המיכל עם דגם ResNet כך שהוא מוכן להגשה, ונחשוף את יציאת gRPC 8500:
docker run -p 8500:8500 -t $USER/resnet_serving &
שאל את השרת
עבור הלקוח, נצטרך לשכפל את ריפו TensorFlow Serving GitHub:
git clone https://github.com/tensorflow/serving
cd serving
שאל את השרת באמצעות resnet_client_grpc.py . הלקוח מוריד תמונה ושולח אותה דרך gRPC לסיווג לקטגוריות ImageNet .
tools/run_in_docker.sh python tensorflow_serving/example/resnet_client_grpc.py
זה אמור לגרום לפלט כמו:
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"
}
זה עובד! השרת מסווג בהצלחה תמונת חתול!
חלק 3: פריסה ב-Kubernetes
בסעיף זה אנו משתמשים בתמונת המכולה שנבנתה בחלק 0 כדי לפרוס אשכול הגשה עם Kubernetes ב- Google Cloud Platform .
התחברות לפרויקט GCloud
כאן אנו מניחים שיצרת ונכנסת לפרויקט gcloud בשם tensorflow-serving
.
gcloud auth login --project tensorflow-serving
צור אשכול מיכל
ראשית אנו יוצרים אשכול Google Kubernetes Engine עבור פריסת שירות.
$ gcloud container clusters create resnet-serving-cluster --num-nodes 5
מה שאמור להוציא משהו כמו:
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
הגדר את אשכול ברירת המחדל עבור פקודת מיכל gcloud והעבר את אישורי האשכול ל- kubectl .
gcloud config set container/cluster resnet-serving-cluster
gcloud container clusters get-credentials resnet-serving-cluster
מה שאמור להביא ל:
Fetching cluster endpoint and auth data.
kubeconfig entry generated for resnet-serving-cluster.
העלה את תמונת Docker
כעת נדחוף את התמונה שלנו ל- Google Container Registry כדי שנוכל להפעיל אותה ב-Google Cloud Platform.
ראשית אנו מתייגים את תמונת $USER/resnet_serving
באמצעות פורמט Container Registry ושם הפרויקט שלנו,
docker tag $USER/resnet_serving gcr.io/tensorflow-serving/resnet
לאחר מכן, אנו מגדירים את Docker להשתמש ב-gcloud כעוזר אישורים:
gcloud auth configure-docker
לאחר מכן אנו דוחפים את התמונה לרישום,
docker push gcr.io/tensorflow-serving/resnet
צור פריסה ושירות של Kubernetes
הפריסה מורכבת מ-3 העתקים של שרת resnet_inference
הנשלט על ידי פריסת Kubernetes . ההעתקים נחשפים חיצונית על ידי שירות Kubernetes יחד עם מאזן עומסים חיצוני .
אנו יוצרים אותם באמצעות הדוגמה של Kubernetes config resnet_k8s.yaml .
kubectl create -f tensorflow_serving/example/resnet_k8s.yaml
עם פלט:
deployment "resnet-deployment" created
service "resnet-service" created
כדי להציג את הסטטוס של הפריסה והתרמילים:
$ 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
לצפייה בסטטוס השירות:
$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
resnet-service 10.239.240.227 104.155.184.157 8500/TCP 1m
זה יכול לקחת זמן עד שהכל יפעל.
$ 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
כתובת ה-IP החיצונית של השירות מופיעה ליד LoadBalancer Ingress.
שאל את הדגם
כעת אנו יכולים לשאול את השירות בכתובת החיצונית שלו מהמארח המקומי שלנו.
$ 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"
}
פרסתם בהצלחה את מודל ResNet המשמש כשירות ב-Kubernetes!