Kubernetes ile TensorFlow Hizmetini Kullanın

Bu eğitimde, TensorFlow ResNet modeline hizmet vermek için Docker kapsayıcılarında çalışan TensorFlow Hizmet bileşenlerinin nasıl kullanılacağı ve hizmet kümesinin Kubernetes ile nasıl dağıtılacağı gösterilmektedir.

TensorFlow Sunumu hakkında daha fazla bilgi edinmek için TensorFlow Sunumu temel eğitimini ve TensorFlow Sunumu gelişmiş eğitimini öneriyoruz.

TensorFlow ResNet modeli hakkında daha fazla bilgi edinmek için TensorFlow'daki ResNet'i okumanızı öneririz.

  • Bölüm 1, ortam kurulumunuzu alır
  • Bölüm 2, yerel Docker sunum görüntüsünün nasıl çalıştırılacağını gösterir
  • Bölüm 3, Kubernetes'te nasıl dağıtılacağını gösterir.

Bölüm 1: Kurulum

Başlamadan önce Docker'ı yükleyin .

ResNet SavedModel'i indirin

Zaten bir tane varsa, yerel modeller dizinimizi temizleyelim:

rm -rf /tmp/resnet

Derin artık ağlar veya kısaca ResNet'ler, çok derin evrişimli sinir ağlarının eğitilmesine olanak sağlamak için kimlik eşlemeleri konusunda çığır açan bir fikir sağladı. Örneğimiz için, ImageNet veri kümesi için ResNet'in TensorFlow SavedModel'ini indireceğiz.

# 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'e sahip olduğumuzu doğrulayabiliriz:

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

Bölüm 2: Docker'da Çalıştırma

Dağıtım için görüntüyü kaydet

Şimdi bir sunum görüntüsü almak ve tüm değişiklikleri Kubernetes dağıtımı için yeni bir $USER/resnet_serving görüntüsüne uygulamak istiyoruz.

İlk önce hizmet veren bir imajı daemon olarak çalıştırıyoruz:

docker run -d --name serving_base tensorflow/serving

Daha sonra ResNet model verilerini konteynerin model klasörüne kopyalıyoruz:

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

Son olarak konteyneri ResNet modeline hizmet etmeye adadık:

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

Şimdi servis tabanı kabını durduralım

docker kill serving_base
docker rm serving_base

Sunucuyu başlat

Şimdi kapsayıcıyı ResNet modeliyle başlatalım, böylece hizmete hazır olsun ve gRPC bağlantı noktası 8500'ü açığa çıkaralım:

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

Sunucuyu sorgula

Müşteri için TensorFlow Serving GitHub deposunu klonlamamız gerekecek:

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

Sunucuyu resnet_client_grpc.py ile sorgulayın. İstemci bir görüntüyü indirir ve bunu ImageNet kategorilerine göre sınıflandırılmak üzere gRPC üzerinden gönderir.

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

Bu, aşağıdaki gibi bir çıktıyla sonuçlanmalıdır:

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

İşe yarıyor! Sunucu bir kedi görüntüsünü başarıyla sınıflandırıyor!

Bölüm 3: Kubernetes'te Dağıtım

Bu bölümde , Google Cloud Platform'da Kubernetes ile bir sunum kümesi dağıtmak için Bölüm 0'da yerleşik konteyner görüntüsünü kullanıyoruz.

GCloud projesine giriş

Burada tensorflow-serving adında bir gcloud projesi oluşturup oturum açtığınızı varsayıyoruz.

gcloud auth login --project tensorflow-serving

Kapsayıcı kümesi oluşturma

Öncelikle hizmet dağıtımı için bir Google Kubernetes Engine kümesi oluşturuyoruz.

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

Hangisi şöyle bir çıktı vermelidir:

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 kapsayıcı komutu için varsayılan kümeyi ayarlayın ve küme kimlik bilgilerini kubectl'e iletin.

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

bunun sonucunda:

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

Docker görüntüsünü yükleyin

Şimdi görselimizi Google Cloud Platform'da çalıştırabilmek için Google Container Registry'ye aktaralım.

Öncelikle $USER/resnet_serving imajını Container Registry formatını ve proje ismimizi kullanarak etiketliyoruz,

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

Daha sonra Docker'ı gcloud'u kimlik bilgisi yardımcısı olarak kullanacak şekilde yapılandırıyoruz:

gcloud auth configure-docker

Daha sonra görüntüyü Kayıt Defterine gönderiyoruz,

docker push gcr.io/tensorflow-serving/resnet

Kubernetes Dağıtımı ve Hizmeti Oluşturun

Dağıtım, bir Kubernetes Dağıtımı tarafından kontrol edilen resnet_inference sunucusunun 3 kopyasından oluşur. Replikalar, Harici Yük Dengeleyici ile birlikte bir Kubernetes Hizmeti tarafından harici olarak kullanıma sunulur.

Bunları Kubernetes config resnet_k8s.yaml örneğini kullanarak oluşturuyoruz.

kubectl create -f tensorflow_serving/example/resnet_k8s.yaml

Çıkış ile:

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

Dağıtımın ve bölmelerin durumunu görüntülemek için:

$ 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

Hizmetin durumunu görüntülemek için:

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

Her şeyin çalışır duruma gelmesi biraz zaman alabilir.

$ 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

Hizmetin harici IP adresi LoadBalancer Girişi'nin yanında listelenir.

Modeli sorgula

Artık hizmeti yerel ana makinemizden harici adresinde sorgulayabiliriz.

$ 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'te hizmet olarak hizmet veren ResNet modelini başarıyla devreye aldınız!