KFServing – 클라우드 저장소를 이용하여 InferenceService 배포와 예측

S3에 저장된 모델로 InferenceService 배포와 예측하기

S3에 저장된 모델을 이용하여 InferenceService 를 생성해 보겠습니다.

S3 Secret 을 샐성하고 서비스 계정에 추가하기

InferenceService 에서 S3에 접속하여 모델을 가져오려면 접속 정보가 필요합니다. KFServing은 InferenceService에 정의된 서비스 계정의 Secret을 이용하여 접속 정보를 가져옵니다. 그래서 S3 접속 정보를 쿠버테티스 Secret 으로 저장해야합니다. Secret 에는 기본적으로 awsAccessKeyIDawsSecretAccessKey 가 포함되어야 합니다. KFServing은 S3 엔드포인트와 https 사용 여부 등의 S3 옵션을 Secret의 어노테이션으로 설정할 수 있는 기능을 제공합니다. 그래서 변경이 필요한 S3 옵션이 있을 경우에는 어노테이션을 추가 하면 됩니다.

다음은 Kubeflow에서 제공하는 minio를 s3 저장소로 사용하는 Secret 매니페스트 입니다. data 섹션에 있는 awsAccessKeyIDawsSecretAccessKey 필드의 값은 BASE64 로 인코딩 된 값을 사용해야합니다.

apiVersion: v1
kind: Secret
metadata:
  name: s3-secret
  annotations:
     serving.kubeflow.org/s3-endpoint: minio-service.kubeflow:9000 # replace with your s3 endpoint
     serving.kubeflow.org/s3-usehttps: "0" # by default 1, for testing with minio you need to set to 0
     serving.kubeflow.org/s3-verifyssl: "0" # by default 1, for testing with minio you need to set to 0
type: Opaque
data:
  awsAccessKeyID: bWluaW8=
  awsSecretAccessKey: bWluaW8xMjM=

맥이나 리눅스를 사용하고 있다면, 다음 명령어로 BASE64 인코딩을 할 수 있습니다.

echo -n 'minio' | base64

KFServing은 서비스 계정에서 Secret을 가져옵니다. 그렇기 때문에, 생성한 Secret 을 서비스 계정의 secrets 필드에 추가해야 합니다. 만약 기존에 생성했던 Secret 이 있다면, 기존것을 사용해도 됩니다. KFServing은 기본적으로 default 서비스 계정을 사용합니다. 예제에서는 새로운 서비스 계정을 생성한 후, InferenceService 매니페스트에 사용할 서비스 계정을 지정해 주겠습니다.

다음은 서비스 계정을 만드는 매니페스트입니다. 앞서 생성한 s3-secret 을 추가하였습니다.

s3-sa.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: s3-sa
secrets:
- name: s3-secret

admin 네임스페이스에 서비스 계정을 생성하겠습니다.

kubectl -n admin apply -f s3-sa.yaml

텐서플로우 mnist 모델을 학습하고 S3에 저장하기

InferenceService에서 사용할 mnist 모델을 S3에 저장하겠습니다. 코드는 앞서 사용한 Tensorflow 코드와 동일하기 때문에 자세한 설명은 생략하겠습니다.

tensorflow_mnist.py

from __future__ import absolute_import, division, print_function, unicode_literals

import argparse
import os

import tensorflow as tf


def train():
    print("TensorFlow version: ", tf.__version__)

    parser = argparse.ArgumentParser()
    parser.add_argument('--model_path', default='s3://tensorflow/mnist/model', type=str)
    args = parser.parse_args()

    version = 1
    export_path = os.path.join(args.model_path, str(version))

    (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
    x_train, x_test = x_train / 255.0, x_test / 255.0

    model = tf.keras.models.Sequential([
        tf.keras.layers.Flatten(input_shape=(28, 28)),
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.Dense(10, activation='softmax')
    ])

    model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.01),
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])

    print("Training...")
    training_history = model.fit(x_train, y_train, batch_size=64, epochs=10,
                                 validation_split=0.2)

    print('\\nEvaluate on test data')
    results = model.evaluate(x_test, y_test, batch_size=128)
    print('test loss, test acc:', results)

    model.save(export_path)
    print('"Saved model to {}'.format(export_path))


if __name__ == '__main__':
    train()

컨테이너 이미지를 만들기

컨테이너 이미지를 만들기 위한 Dockerfile 입니다. 텐서플로우를 기본 이미지로 사용합니다.

Dockerfile

FROM tensorflow/tensorflow:2.1.0-py3

RUN mkdir -p /app
ADD tensorflow_mnist.py /app/

쿠버네티스 잡 실행하기

컨테이너 이미지를 빌드하고, 컨테이너 이미지 레지스트리에 푸시 한 다음, 쿠버네티스 잡(Job)을 생성하겠습니다.

Job을 생성할 때는 학습한 모델을 S3에 저장하기 위해서 S3 접속 정보를 추가해줍니다. 이 일련의 작업들은 직접 실행 할 수 있습니다. 하지만 좀 더 편하게 하기 위해서 앞서 배운 Kubeflow Fairing을 사용하겠습니다.

InferneceService 에서 학습한 모델을 가져올 때 S3 접속 정보가 필요한 것 처럼, Job을 실행해서 S3로 모델을 저장할 때도 S3 접속 정보가 필요합니다. S3 접속 정보는 Job의 환경 정보(Environment)로 추가해 줄 수 있습니다. 현재 Fairing 에는 Job의 환경 정보를 추가할 수 있는 손 쉬운 방법이 없기때문에, pod_spec_mutator

를 이용하여, 환경 정보를 추가하겠습니다.

다음은 S3 접속 정보를 환경 정보로 추가하는 pod_spec_mutator 코드입니다. 접속 정보를 별도로 입력 받는 것이 번거로워서, 앞서 생성한 s3-secret 에서 정보를 가져와서 환경 변수로 설정해 줍니다. 이 코드는 예외 처리가 안되어 있기 때문에 참고만 하시기 바랍니다.

s3_utils.py

from kubeflow.fairing.constants import constants
from kubernetes import client


def aws_credentials(secret_name=constants.AWS_CREDS_SECRET_NAME):
    def _add_aws_credentials(kube_manager, pod_spec, namespace):
        """add AWS credential

        :param kube_manager: kube manager for handles communication with Kubernetes' client
        :param pod_spec: pod spec like volumes and security context
        :param namespace: The custom resource

        """
        if not kube_manager.secret_exists(secret_name, namespace):
            raise ValueError('Unable to mount credentials: Secret {}} not found in namespace {}'
                             .format(secret_name, namespace))

        secret = client.CoreV1Api().read_namespaced_secret(secret_name, namespace)
        annotations = secret.metadata.annotations
        s3_endpoint = annotations['serving.kubeflow.org/s3-endpoint']
        s3_use_https = annotations['serving.kubeflow.org/s3-usehttps']
        s3_verify_ssl = annotations['serving.kubeflow.org/s3-verifyssl']

        env = [
            client.V1EnvVar(
                name='AWS_ACCESS_KEY_ID',
                value_from=client.V1EnvVarSource(
                    secret_key_ref=client.V1SecretKeySelector(
                        name=secret_name,
                        key='awsAccessKeyID'
                    )
                )
            ),
            client.V1EnvVar(
                name='AWS_SECRET_ACCESS_KEY',
                value_from=client.V1EnvVarSource(
                    secret_key_ref=client.V1SecretKeySelector(
                        name=secret_name,
                        key='awsSecretAccessKey'
                    )
                )
            ),
            client.V1EnvVar(name='S3_ENDPOINT', value=s3_endpoint),
            client.V1EnvVar(name='S3_USE_HTTPS', value=s3_use_https),
            client.V1EnvVar(name='S3_VERIFY_SSL', value=s3_verify_ssl),

        ]

        if pod_spec.containers[0].env:
            pod_spec.containers[0].env.extend(env)
        else:
            pod_spec.containers[0].env = env

    return _add_aws_credentials

다음은 로컬 개발 환경에서 Fairing을 사용하여 컨테이너 이미지를 만들고, 쿠버네티스 잡을 실행하는 예제입니다.

fairing-local-docker.py

import uuid

import s3_utils

from kubeflow import fairing
from kubeflow.fairing.kubernetes import utils as k8s_utils



CONTAINER_REGISTRY = 'kangwoo'

namespace = 'admin'
job_name = f'tensorflow-mnist-s3-job-{uuid.uuid4().hex[:4]}'

command = ["python", "tensorflow_mnist.py", "--model_path", "s3://tensorflow/mnist/model"]
output_map = {
    "Dockerfile": "Dockerfile",
    "tensorflow_mnist.py": "tensorflow_mnist.py"
}
fairing.config.set_preprocessor('python', command=command, path_prefix="/app", output_map=output_map)

fairing.config.set_builder('docker', registry=CONTAINER_REGISTRY, image_name="tensorflow-mnist",
                           dockerfile_path="Dockerfile")

fairing.config.set_deployer('job', namespace=namespace, job_name=job_name,
                            pod_spec_mutators=[
                                s3_utils.aws_credentials(secret_name='s3-secret')
                            ],
                            cleanup=False, stream_log=True)

fairing.config.run()

fairing을 실행하면 쿠버네티스 잡이 생성되고, 학습이 완료된 모델이 지정한 경로에 저장됩니다.

S3을 사용하는 InferenceService 로 예측 하기

InferenceService 생성

InferenceService 매니페스트를 작성합니다. predictor로 tensorflow 를 사용합니다. storageUri 필드로 모델 저장 위치인 s3://tensorflow/mnist/model 를 지정해 줍니다. 그리고 serviceAccountName 필드를 이용하여, S3 접근 권한 정보를 가지고 있는 서비스 계정을 지정해 줍니다.

mnist-s3.yaml

apiVersion: "serving.kubeflow.org/v1alpha2"
kind: "InferenceService"
metadata:
  name: "mnist-s3"
spec:
  default:
    predictor:
      serviceAccountName: s3-sa
      tensorflow:
        storageUri: "s3://tensorflow/fashion-mnist/model"

InferenceService 를 생성합니다.

다음은 admin 네임스페이스 InferenceService 를 생성하는 예제입니다.

kubectl -n admin apply -f mnist-s3.yaml

생성한 InferenceService를 조회해 보겠습니다.

kubectl -n admin get inferenceservice

InferenceService 가 정상적으로 생성되면 다음과 같은 응답 결과를 확인할 수 있습니다.

NAME                  URL                                                                          READY   DEFAULT TRAFFIC   CANARY TRAFFIC   AGE
mnist-s3              <http://mnist-s3.admin.example.com/v1/models/mnist-s3>                         True    100                                20s

예측 실행하기

예측을 요청하기 위해서는 모델 서버에 접근해야 합니다. 모델 서버는 ingressgateway 를 통해서 접근할 수 있습니다. ingressgateway 는 모델 서버들을 구분하기 위해서 호스트 이름을 사용합니다. ingressgateway에 접근하 기 위한 주소는 앞서 정의한 CLUSTER_IP 를 사용하겠습니다.

예측을 요청할 데이터를 json 파일로 작성합니다.

데이터의 크기가 크기 때문에 git 에 있는 파일을 다운받아서 사용해주세요.

mnist-input.json

{
  "instances": [
    [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
...
  ]
}

다음은 admin 네임스페이스의 tensorflow-mnist InferenceService 에 예측을 요청하는 예제입니다.

MODEL_NAME=mnist-s3
SERVICE_HOSTNAME=$(kubectl -n admin get inferenceservice mnist-s3 -o jsonpath='{.status.url}' | cut -d "/" -f 3)

INPUT_PATH=@./mnist-input.json
curl -v -H "Host: ${SERVICE_HOSTNAME}" http://$CLUSTER_IP/v1/models/${MODEL_NAME}:predict -d ${INPUT_PATH}

정상적으로 실행되면 다음과 같은 응답 결과를 확인 할 수 있습니다.

*   Trying 192.168.21.38...
* TCP_NODELAY set
* Connected to 192.168.21.38 (192.168.21.38) port 32380 (#0)
> POST /v1/models/mnist-s3:predict HTTP/1.1
> Host: mnist-s3.admin.example.com
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 9866
> Content-Type: application/x-www-form-urlencoded
> Expect: 100-continue
> 
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< content-length: 183
< content-type: application/json
< date: Sat, 04 Apr 2020 03:43:16 GMT
< server: istio-envoy
< x-envoy-upstream-service-time: 29
< 
{
    "predictions": [[0.000134299538, 1.87837134e-06, 0.000226354547, 0.00111765205, 1.1317371e-05, 3.8724811e-05, 3.75441829e-07, 0.997255147, 3.78830955e-05, 0.00117637496]
    ]
}

GCS에 저장된 모델로 InferenceService 배포와 예측하기

GCS에 저장된 모델을 이용하여 InferenceService 를 생성해 보겠습니다.

(현재 KFServing의 버그로 인해 아래 방법은 정상 작동하지 않습니다.)

GCS Secret 을 생성하고 서비스 계정에 추가하기

InferenceService 에서 GCS에 접속하여 모델을 가져오려면 접속 정보가 필요합니다. KFServing은 InferenceService에 정의된 서비스 계정의 Secret을 이용하여 접속 정보를 가져옵니다. 그래서 GCS 접속 정보를 쿠버테티스 Secret 으로 저장해야합니다. Secret 에는 기본적으로 awsAccessKeyIDawsSecretAccessKey 가 포함되어야 합니다. KFServing은 S3 엔드포인트와 https 사용 여부 등의 S3 옵션을 Secret의 어노테이션으로 설정할 수 있는 기능을 제공합니다. 그래서 변경이 필요한 S3 옵션이 있을 경우에는 어노테이션을 추가 하면 됩니다.

구글 클라우드의 JSON 서비스 계정 키를 다운로드 합니다. 이 서비스 계정은 사용할 GCS에 접근할 권한이 부여되어 있어야합니다.

다음은 서비스 계정 키를 gcp-sa-credentials.json 파일로 다운로드 하는 명령어 입니다. [SA-NAME] 에는 서비스 계정의 아이디를, [PROJECT-ID] 에는 프로젝트 아이디를 입력하면 됩니다.

gcloud iam service-accounts keys create gcp-sa-credentials.json \\
  --iam-account [SA-NAME]@[PROJECT-ID].iam.gserviceaccount.com

다운로드 받은 구글 클라우드의 서비스 계정 키를, 쿠버네티스 Secret 에 등록합니다.

다음은 admin 네임스페이스 Secret 을 생성하는 명령어 입니다. KFServing의 설정 값을 변경하지 않았다면, Secretdata에 저장되는 파일명은 gcloud-application-credentials.json 을 반드시 사용해야합니다.

kubectl -n admin create secret generic user-gcp-sa \\
  --from-file=gcloud-application-credentials.json=gcp-sa-credentials.json

KFServing은 서비스 계정에서 Secret을 가져옵니다. 그렇기 때문에, 생성한 Secret 을 서비스 계정의 secrets 필드에 추가해야 합니다. 만약 기존에 생성했던 Secret 이 있다면, 기존것을 사용해도 됩니다. KFServing은 기본적으로 default 서비스 계정을 사용합니다. 예제에서는 새로운 서비스 계정을 생성한 후, InferenceService 매니페스트에 사용할 서비스 계정을 지정해 주겠습니다.

다음은 서비스 계정을 만드는 매니페스트입니다. 앞서 생성한 s3-secret 을 추가하였습니다.

gcs-sa.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: gcs-sa
secrets:
- name: user-gcp-sa

admin 네임스페이스에 서비스 계정을 생성하겠습니다.

kubectl -n admin apply -f gcs-sa.yaml

텐서플로우 mnist 모델을 학습하고 GCS에 저장하기

InferenceService에서 사용할 mnist 모델을 GCS에 저장하겠습니다. 코드는 앞서 사용한 Tensorflow 코드와 동일하기 때문에 자세한 설명은 생략하겠습니다.

tensorflow_mnist.py

from __future__ import absolute_import, division, print_function, unicode_literals

import argparse
import os

import tensorflow as tf


def train():
    print("TensorFlow version: ", tf.__version__)

    parser = argparse.ArgumentParser()
    parser.add_argument('--model_path', default='gcs://tensorflow/fashion-mnist/model', type=str)
    args = parser.parse_args()

    version = 1
    export_path = os.path.join(args.model_path, str(version))

    (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
    x_train, x_test = x_train / 255.0, x_test / 255.0

    model = tf.keras.models.Sequential([
        tf.keras.layers.Flatten(input_shape=(28, 28)),
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.Dense(10, activation='softmax')
    ])

    model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.01),
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])

    print("Training...")
    training_history = model.fit(x_train, y_train, batch_size=64, epochs=10,
                                 validation_split=0.2)

    print('\\nEvaluate on test data')
    results = model.evaluate(x_test, y_test, batch_size=128)
    print('test loss, test acc:', results)

    model.save(export_path)
    print('"Saved model to {}'.format(export_path))


if __name__ == '__main__':
    train()

컨테이너 이미지를 만들기

컨테이너 이미지를 만들기 위한 Dockerfile 입니다. 텐서플로우를 기본 이미지로 사용합니다.

Dockerfile

FROM tensorflow/tensorflow:2.1.0-py3

RUN mkdir -p /app
ADD tensorflow_mnist.py /app/

쿠버네티스 잡 실행하기

컨테이너 이미지를 빌드하고, 컨테이너 이미지 레지스트리에 푸시 한 다음, 쿠버네티스 잡(Job)을 생성하겠습니다.

Job을 생성할 때는 학습한 모델을 GCS에 저장하기 위해서 GCS 접속 정보를 추가해줍니다. 이 일련의 작업들은 직접 실행 할 수 있습니다. 하지만 좀 더 편하게 하기 위해서 앞서 배운 Kubeflow Fairing을 사용하겠습니다.

InferneceService 에서 학습한 모델을 가져올 때 GCS 접속 정보가 필요한 것 처럼, Job을 실행해서 GCS로 모델을 저장할 때도 GCS 접속 정보가 필요합니다. GCS 접속 정보는 Job의 환경 정보(Environment)로 추가해 줄 수 있습니다. 현재 Fairing 에는 Job의 환경 정보를 추가할 수 있는 손 쉬운 방법이 없기때문에, pod_spec_mutator

를 이용하여, 환경 정보를 추가하겠습니다.

다음은 GCS 접속 정보를 환경 정보로 추가하는 pod_spec_mutator 코드입니다. 접속 정보를 별도로 입력 받는 것이 번거로워서, 앞서 생성한 user-gcp-sa 를 볼륨 마운트 한 다음, GOOGLE_APPLICATION_CREDENTIALS 라는 환경 변수에 인증 정보가 들어 있는 json 파일의 위치를 설정해 줍니다. 이 코드는 예외 처리가 안되어 있기 때문에 참고만 하시기 바랍니다.

gcs_utils.py

import os

from kubernetes import client

GCSCredentialFileName = "gcloud-application-credentials.json"
GCSCredentialVolumeName = "user-gcp-sa"
GCSCredentialVolumeMountPath = "/var/secrets/"
GCSCredentialEnvKey = "GOOGLE_APPLICATION_CREDENTIALS"


def gcp_credentials(secret_name='user-gcp-sa', credential_file_name=GCSCredentialFileName):
    def _add_gcp_credentials(kube_manager, pod_spec, namespace):
        """add GCP credential

        :param kube_manager: kube manager for handles communication with Kubernetes' client
        :param pod_spec: pod spec like volumes and security context
        :param namespace: The custom resource

        """
        if not kube_manager.secret_exists(secret_name, namespace):
            raise ValueError('Unable to mount credentials: Secret {}} not found in namespace {}'
                             .format(secret_name, namespace))

        # volume_mount
        volume_mount = client.V1VolumeMount(
            name=GCSCredentialVolumeName, mount_path=GCSCredentialVolumeMountPath)
        if pod_spec.containers[0].volume_mounts:
            pod_spec.containers[0].volume_mounts.append(volume_mount)
        else:
            pod_spec.containers[0].volume_mounts = [volume_mount]

        volume = client.V1Volume(
            name=GCSCredentialVolumeName,
            secret=client.V1SecretVolumeSource(secret_name=secret_name))
        if pod_spec.volumes:
            pod_spec.volumes.append(volume)
        else:
            pod_spec.volumes = [volume]

        # environment
        credential_file_path = os.path.join(GCSCredentialVolumeMountPath, GCSCredentialFileName)
        env = [
            client.V1EnvVar(name=GCSCredentialEnvKey, value=credential_file_path),
        ]

        if pod_spec.containers[0].env:
            pod_spec.containers[0].env.extend(env)
        else:
            pod_spec.containers[0].env = env

    return _add_gcp_credentials

다음은 로컬 개발 환경에서 Fairing을 사용하여 컨테이너 이미지를 만들고, 쿠버네티스 잡을 실행하는 예제입니다.

fairing-local-docker.py

import uuid

import gcs_utils
from kubeflow import fairing

CONTAINER_REGISTRY = 'kangwoo'

namespace = 'admin'
job_name = f'tensorflow-mnist-gcs-job-{uuid.uuid4().hex[:4]}'

command = ["python", "tensorflow_mnist.py", "--model_path", "gs://kfp-bucket/mnist/model"]
output_map = {
    "Dockerfile": "Dockerfile",
    "tensorflow_mnist.py": "tensorflow_mnist.py"
}
fairing.config.set_preprocessor('python', command=command, path_prefix="/app", output_map=output_map)

fairing.config.set_builder('docker', registry=CONTAINER_REGISTRY, image_name="tensorflow-mnist",
                           dockerfile_path="Dockerfile")

fairing.config.set_deployer('job', namespace=namespace, job_name=job_name,
                            pod_spec_mutators=[
                                gcs_utils.gcp_credentials(secret_name='user-gcp-sa')
                            ],
                            cleanup=False, stream_log=True)

fairing.config.run()

fairing을 실행하면 쿠버네티스 잡이 생성되고, 학습이 완료된 모델이 지정한 경로에 저장됩니다.

GCS을 사용하는 InferenceService 로 예측 하기

InferenceService 생성

InferenceService 매니페스트를 작성합니다. predictor로 tensorflow 를 사용합니다. storageUri 필드로 모델 저장 위치인 gs://kfp-bucket/mnist/model 를 지정해 줍니다. 그리고 serviceAccountName 필드를 이용하여, GCS 접근 권한 정보를 가지고 있는 서비스 계정을 지정해 줍니다.

mnist-gcs.yaml

apiVersion: "serving.kubeflow.org/v1alpha2"
kind: "InferenceService"
metadata:
  name: "mnist-gcs"
spec:
  default:
    predictor:
      serviceAccountName: gcs-sa
      tensorflow:
        storageUri: "gs://kfp-bucket/mnist/model"

InferenceService 를 생성합니다.

다음은 admin 네임스페이스 InferenceService 를 생성하는 예제입니다.

kubectl -n admin apply -f mnist-gcs.yaml

생성한 InferenceService를 조회해 보겠습니다.

kubectl -n admin get inferenceservice

InferenceService 가 정상적으로 생성되면 다음과 같은 응답 결과를 확인할 수 있습니다.

NAME                  URL                                                                          READY   DEFAULT TRAFFIC   CANARY TRAFFIC   AGE
mnist-gcs             <http://mnist-gcs.admin.example.com/v1/models/mnist-gcs>                      True    100                                20s

예측 실행하기

예측을 요청하기 위해서는 모델 서버에 접근해야 합니다. 모델 서버는 ingressgateway 를 통해서 접근할 수 있습니다. ingressgateway 는 모델 서버들을 구분하기 위해서 호스트 이름을 사용합니다. ingressgateway에 접근하 기 위한 주소는 앞서 정의한 CLUSTER_IP 를 사용하겠습니다.

예측을 요청할 데이터를 json 파일로 작성합니다.

데이터의 크기가 크기 때문에 git 에 있는 파일을 다운받아서 사용해주세요.

mnist-input.json

{
  "instances": [
    [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
...
  ]
}

다음은 admin 네임스페이스의 tensorflow-mnist InferenceService 에 예측을 요청하는 예제입니다.

MODEL_NAME=mnist-gcs
SERVICE_HOSTNAME=$(kubectl -n admin get inferenceservice mnist-gcs -o jsonpath='{.status.url}' | cut -d "/" -f 3)

INPUT_PATH=@./mnist-input.json
curl -v -H "Host: ${SERVICE_HOSTNAME}" http://$CLUSTER_IP/v1/models/${MODEL_NAME}:predict -d ${INPUT_PATH}

정상적으로 실행되면 다음과 같은 응답 결과를 확인 할 수 있습니다.

*   Trying 192.168.21.38...
* TCP_NODELAY set
* Connected to 192.168.21.38 (192.168.21.38) port 32380 (#0)
> POST /v1/models/mnist-gcs:predict HTTP/1.1
> Host: mnist-gcs.admin.example.com
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 9866
> Content-Type: application/x-www-form-urlencoded
> Expect: 100-continue
> 
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< content-length: 183
< content-type: application/json
< date: Sat, 04 Apr 2020 11:43:16 GMT
< server: istio-envoy
< x-envoy-upstream-service-time: 29
< 
{
    "predictions": [[0.000134299538, 1.87837134e-06, 0.000226354547, 0.00111765205, 1.1317371e-05, 3.8724811e-05, 3.75441829e-07, 0.997255147, 3.78830955e-05, 0.00117637496]
    ]
}

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다