Sử dụng TensorFlow Phục vụ với Kubernetes

Hướng dẫn này trình bày cách sử dụng các thành phần Phục vụ TensorFlow chạy trong bộ chứa Docker để phục vụ mô hình TensorFlow ResNet và cách triển khai cụm phân phối với Kubernetes.

Để tìm hiểu thêm về Dịch vụ TensorFlow, chúng tôi khuyên bạn nên sử dụng hướng dẫn cơ bản về Dịch vụ TensorFlowhướng dẫn nâng cao về Dịch vụ TensorFlow .

Để tìm hiểu thêm về mô hình TensorFlow ResNet, chúng tôi khuyên bạn nên đọc ResNet trong TensorFlow .

  • Phần 1 thiết lập môi trường của bạn
  • Phần 2 hướng dẫn cách chạy image phục vụ Docker cục bộ
  • Phần 3 trình bày cách triển khai trong Kubernetes.

Phần 1: Thiết lập

Trước khi bắt đầu, trước tiên hãy cài đặt Docker .

Tải xuống ResNet SavingModel

Hãy xóa thư mục mô hình cục bộ của chúng tôi trong trường hợp chúng tôi đã có:

rm -rf /tmp/resnet

Mạng dư sâu, hay gọi tắt là ResNet, đã cung cấp ý tưởng đột phá về ánh xạ nhận dạng để cho phép đào tạo các mạng thần kinh tích chập rất sâu. Trong ví dụ của chúng tôi, chúng tôi sẽ tải xuống TensorFlow SavingModel của ResNet cho tập dữ liệu 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/

Chúng tôi có thể xác minh rằng chúng tôi có SavingModel:

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

Phần 2: Chạy trong Docker

Cam kết hình ảnh để triển khai

Bây giờ chúng tôi muốn chụp một hình ảnh phục vụ và cam kết tất cả các thay đổi đối với một hình ảnh mới $USER/resnet_serving để triển khai Kubernetes.

Đầu tiên chúng tôi chạy một hình ảnh phục vụ dưới dạng daemon:

docker run -d --name serving_base tensorflow/serving

Tiếp theo, chúng tôi sao chép dữ liệu mô hình ResNet vào thư mục mô hình của vùng chứa:

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

Cuối cùng, chúng tôi cam kết vùng chứa sẽ phục vụ mô hình ResNet:

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

Bây giờ hãy dừng container cơ sở phục vụ

docker kill serving_base
docker rm serving_base

Khởi động máy chủ

Bây giờ, hãy khởi động vùng chứa với mô hình ResNet để nó sẵn sàng phân phát, hiển thị cổng gRPC 8500:

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

Truy vấn máy chủ

Đối với máy khách, chúng tôi sẽ cần sao chép repo GitHub của TensorFlow Serve:

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

Truy vấn máy chủ bằng resnet_client_grpc.py . Máy khách tải xuống một hình ảnh và gửi nó qua gRPC để phân loại thành các danh mục ImageNet .

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

Điều này sẽ dẫn đến kết quả đầu ra như:

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

Nó hoạt động! Máy chủ phân loại thành công hình ảnh con mèo!

Phần 3: Triển khai trong Kubernetes

Trong phần này, chúng tôi sử dụng container image được xây dựng trong Phần 0 để triển khai cụm phân phối với Kubernetes trong Google Cloud Platform .

Đăng nhập dự án GCloud

Ở đây, chúng tôi giả sử bạn đã tạo và đăng nhập vào dự án gcloud có tên tensorflow-serving .

gcloud auth login --project tensorflow-serving

Tạo một cụm vùng chứa

Đầu tiên, chúng tôi tạo cụm Google Kubernetes Engine để triển khai dịch vụ.

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

Cái nào sẽ xuất ra cái gì đó như:

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

Đặt cụm mặc định cho lệnh vùng chứa gcloud và chuyển thông tin xác thực cụm cho kubectl .

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

điều này sẽ dẫn đến:

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

Tải lên hình ảnh Docker

Bây giờ chúng ta hãy đẩy hình ảnh của chúng ta lên Google Container Register để có thể chạy nó trên Google Cloud Platform.

Đầu tiên, chúng tôi gắn thẻ hình ảnh $USER/resnet_serving bằng cách sử dụng định dạng Đăng ký vùng chứa và tên dự án của chúng tôi,

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

Tiếp theo, chúng tôi định cấu hình Docker để sử dụng gcloud làm trình trợ giúp thông tin xác thực:

gcloud auth configure-docker

Tiếp theo chúng ta đẩy image vào Sổ đăng ký,

docker push gcr.io/tensorflow-serving/resnet

Tạo triển khai và dịch vụ Kubernetes

Việc triển khai bao gồm 3 bản sao của máy chủ resnet_inference được kiểm soát bởi Triển khai Kubernetes . Các bản sao được hiển thị bên ngoài bởi Dịch vụ Kubernetes cùng với Bộ cân bằng tải bên ngoài .

Chúng tôi tạo chúng bằng ví dụ Kubernetes config resnet_k8s.yaml .

kubectl create -f tensorflow_serving/example/resnet_k8s.yaml

Với đầu ra:

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

Để xem trạng thái triển khai và nhóm:

$ 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

Để xem trạng thái của dịch vụ:

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

Có thể mất một thời gian để mọi thứ được thiết lập và hoạt động.

$ 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

Địa chỉ IP bên ngoài của dịch vụ được liệt kê bên cạnh LoadBalancer Ingress.

Truy vấn mô hình

Bây giờ chúng ta có thể truy vấn dịch vụ tại địa chỉ bên ngoài của nó từ máy chủ cục bộ của chúng ta.

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

Bạn đã triển khai thành công mô hình ResNet phục vụ như một dịch vụ trong Kubernetes!