이 튜토리얼에서는 Docker 컨테이너에서 실행되는 TensorFlow Serving 구성 요소를 사용하여 TensorFlow ResNet 모델을 제공하는 방법과 Kubernetes를 사용하여 제공 클러스터를 배포하는 방법을 보여줍니다.
TensorFlow Serving에 대해 자세히 알아보려면 TensorFlow Serving 기본 자습서 및 TensorFlow Serving 고급 자습서를 권장합니다.
TensorFlow ResNet 모델에 대해 자세히 알아보려면 TensorFlow의 ResNet을 읽어 보시기 바랍니다.
파트 1: 설정
시작하기 전에 먼저 Docker를 설치하세요 .
ResNet 저장된 모델 다운로드
이미 로컬 모델 디렉토리가 있는 경우 로컬 모델 디렉토리를 삭제해 보겠습니다.
rm -rf /tmp/resnet
심층 잔차 네트워크(Deep Residual Networks, 줄여서 ResNets)는 매우 심층적인 컨벌루션 신경망을 훈련할 수 있도록 ID 매핑이라는 획기적인 아이디어를 제공했습니다. 이 예에서는 ImageNet 데이터 세트에 대한 ResNet의 TensorFlow SavedModel을 다운로드합니다.
# 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/
저장된 모델이 있는지 확인할 수 있습니다.
$ ls /tmp/resnet/*
saved_model.pb variables
2부: Docker에서 실행
배포용 이미지 커밋
이제 제공 이미지를 가져와 Kubernetes 배포를 위한 새 이미지 $USER/resnet_serving
에 대한 모든 변경 사항을 커밋 하려고 합니다.
먼저 제공 이미지를 데몬으로 실행합니다.
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 로 서버를 쿼리합니다. 클라이언트는 이미지를 다운로드하고 ImageNet 범주로 분류하기 위해 gRPC를 통해 보냅니다.
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부에서 구축한 컨테이너 이미지를 사용하여 Google Cloud Platform 에 Kubernetes 가 포함된 제공 클러스터를 배포합니다.
GCloud 프로젝트 로그인
여기서는 tensorflow-serving
이라는 gcloud 프로젝트를 만들고 로그인했다고 가정합니다.
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 Cloud Platform에서 실행할 수 있도록 이미지를 Google Container Registry 에 푸시하겠습니다.
먼저 Container Registry 형식과 프로젝트 이름을 사용하여 $USER/resnet_serving
이미지에 태그를 지정합니다.
docker tag $USER/resnet_serving gcr.io/tensorflow-serving/resnet
다음으로 gcloud를 사용자 인증 정보 도우미로 사용하도록 Docker를 구성합니다.
gcloud auth configure-docker
다음으로 이미지를 레지스트리에 푸시합니다.
docker push gcr.io/tensorflow-serving/resnet
Kubernetes 배포 및 서비스 생성
배포는 Kubernetes 배포 에 의해 제어되는 resnet_inference
서버의 복제본 3개로 구성됩니다. 복제본은 외부 로드 밸런서 와 함께 Kubernetes 서비스 에 의해 외부에 노출됩니다.
예제 Kubernetes 구성 resnet_k8s.yaml을 사용하여 이를 생성합니다.
kubectl create -f tensorflow_serving/example/resnet_k8s.yaml
출력:
deployment "resnet-deployment" created
service "resnet-service" created
배포 및 Pod 상태를 보려면 다음 안내를 따르세요.
$ 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"
}
Kubernetes에서 서비스 역할을 하는 ResNet 모델을 성공적으로 배포했습니다!