บทช่วยสอนนี้แสดงวิธีใช้ส่วนประกอบ 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
Deep Residual Network หรือเรียกสั้นๆ ว่า ResNets ทำให้เกิดแนวคิดที่ก้าวหน้าในการแมปข้อมูลประจำตัว เพื่อให้สามารถฝึกอบรมโครงข่ายประสาทเทียมแบบ Convolutional ที่ลึกมากได้ สำหรับตัวอย่างของเรา เราจะดาวน์โหลด 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
ขั้นแรกเราเรียกใช้อิมเมจที่ให้บริการเป็น daemon:
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 &
สอบถามเซิร์ฟเวอร์
สำหรับลูกค้า เราจะต้องโคลน repo 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.
อัปโหลดภาพนักเทียบท่า
ตอนนี้เรามาส่งอิมเมจของเราไปที่ 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
ต่อไปเราจะพุชอิมเมจไปที่ Registry
docker push gcr.io/tensorflow-serving/resnet
สร้างการปรับใช้และบริการ Kubernetes
การปรับใช้ประกอบด้วย 3 เรพลิกาของเซิร์ฟเวอร์ resnet_inference
ที่ควบคุมโดย Kubernetes Deployment แบบจำลองจะถูกเปิดเผยภายนอกโดย บริการ Kubernetes พร้อมด้วย External Load Balancer
เราสร้างมันขึ้นมาโดยใช้ตัวอย่าง 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 สำเร็จแล้ว!