Seldon Core
1. Install Seldon Core with Kubeflow
1.1 Uninstall Existing Seldon Core
먼저 namespace 삭제해줍니다.
$ kubectl get ns seldon-system -o json | jq '.spec.finalizers'=null | kubectl apply -f -
$ kubectl delete ns/seldon-system
Custom Resources Definitions 삭제는 다음과 같이 합니다.
$ kubectl get crd | grep seldon
NAME CREATED AT
.. 생략
seldondeployments.machinelearning.seldon.io 2020-10-05T13:49:42Z
$ kubectl delete crd/seldondeployments.machinelearning.seldon.io
1.2 Install Seldon Core with Helm
먼저 dependencies를 설치합니다.
# Ubuntu
$ sudo snap install helm --classic
$ sudo snap install kustomize
$ helm version --short # 3.x 버젼을 확인합니다.
v3.3.4+ga61ce56
이후에 Seldon Core를 helm으로 설치 합니다.
$ kubectl create namespace seldon-system
$ helm install seldon-core seldon-core-operator \
--repo https://storage.googleapis.com/seldon-charts \
--set usageMetrics.enabled=true \
--namespace seldon-system \
--set istio.enabled=true \
--set certManager.enabled=true
그외에 몇가지 옵션을 더 추가 할 수 있습니다.
--set ambassador.enabled=true
: Ambassador 사용시 해당 옵션을 추가 합니다.--set istio.enabled=true
: Istio 사용시 해당 옵션을 추가 합니다.--set certManager.enabled=true
: cert manager를 통해서 certificate 사용
rollout 잘되었는지 확인해 봅니다.
$ kubectl rollout status deploy/seldon-controller-manager -n seldon-system
deployment "seldon-controller-manager" successfully rolled out
Seldon Namespace 를 생성
$ kubectl create namespace seldon
1.3 Install Source to Image
Source to Image는 RedHat에서 지원하는 툴로서 코드를 빠르게 docker 로 만들어 줍니다.
https://github.com/openshift/source-to-image/releases 들어가서 다운로드 받습니다.
$ wget https://github.com/openshift/source-to-image/releases/download/v1.3.1/source-to-image-v1.3.1-a5a77147-linux-amd64.tar.gz
$ tar -xvf source-to-image-*.tar.gz
$ sudo cp ./s2i /usr/local/bin/
1.3 Ingress with Istio
설치는 istio.enabled=true 로 설치되어 있어야 합니다.
$ cat <<EOF > gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: seldon-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
EOF
$ kubectl apply -f gateway.yaml
1.5 Namespace Labeling
serving.kubeflow.org/inferenceservice=enabled
하면..
deploy시에 x509 certificate signed by unknown authority 에러 나옴
이유는 kubeflow의 apiserver 에 없는 뭔가를 호출하면서 발생.. 즉 kubeflow의 에러
아래 Namespace는 사용하고 있는 namespace 이름으로 변경하고,
serving.kubeflow.org/inferenceservice=enabled
로 label 을 지정합니다.
$ kubectl create namespace seldon
$ kubectl label namespace seldon serving.kubeflow.org/inferenceservice=enabled
$ kubectl get ns seldon --show-labels
NAME STATUS AGE LABELS
seldon Active 26s serving.kubeflow.org/inferenceservice=enabled
2. Getting Started
2.1 Pre-packaged Scikit-Learn Serving
$ cat <<EOF > sklearn.yaml
apiVersion: machinelearning.seldon.io/v1
kind: SeldonDeployment
metadata:
name: sklearn
namespace: seldon
spec:
name: iris
predictors:
- componentSpecs:
- spec:
containers:
- name: classifier
resources:
requests:
memory: 50Mi
graph:
children: []
implementation: SKLEARN_SERVER
modelUri: gs://seldon-models/sklearn/iris
name: classifier
name: anderson
replicas: 1
EOF
$ kubectl apply -f sklearn.yaml
확인은 다음과 같이 합니다.
sdep는 seldondeployments 의 약자입니다.
$ kubectl get sdep -n seldon
NAME AGE
iris-model 70m
Prediction Request는 다음과 같이 합니다.
$ INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
$ curl -X POST http://${INGRESS_HOST}/seldon/seldon/sklearn/api/v1.0/predictions \
-H 'Content-Type: application/json' \
-d '{ "data": { "ndarray": [[1,2,3,4]] } }' \
--silent | jq
{
"data": {
"names": [
"t:0",
"t:1",
"t:2"
],
"ndarray": [
[
0.0006985194531162841,
0.003668039039435755,
0.9956334415074478
]
]
},
"meta": {}
}
Seldon External API를 통해서도 확인을 할 수 있습니다.
아래 주소에서 반드시 끝에 슬래쉬까지 붙여줘야 합니다.
- 형식:
http://<ingress_url>/seldon/<namespace>/<model-name>/api/v1.0/doc/
- 예제: http://{INGRESS_HOST}/seldon/seldon/sklearn/api/v1.0/doc/
$ kubectl get svc istio-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP
istio-ingressgateway LoadBalancer 10.100.223.12 abcd-12345.ap-northeast-2.elb.amazonaws.com
삭제는 다음과 같이 합니다.
$ kubectl delete sdep iris-model -n seldon
$ kubectl delete deployments/iris-model-default-0-classifier -n seldon
2.2 Custom Model
아래 예제는 예제 에서 가져왔습니다.
파일이름은 MyModel.py 이고 클래스 이름도 동일하게 MyModel 로 가져갑니다.
$ cat <<EOF > MyModel.py
import json
class MyModel:
def __init__(self):
print("MyModel 초기화됨 v0.0.11")
def predict(self, data, names=None):
print("predict함수 실행됨")
print('data:', data, 'type:', type(data))
print('names:', names, 'type:', type(names))
return data
def transform_input(self, X, names, meta=None):
print('transform_input')
return X, names, meta
EOF
$ cat <<EOF > requirements.txt
scikit-learn
EOF
Local 환경에서 테스트를 합니다.
$ seldon-core-microservice MyModel REST --service-type MODEL
[2020-09-25 23:49:13 +0900] [16097] [INFO] Listening at: http://0.0.0.0:5000 (16097)
$ curl -X POST http://localhost:5000/api/v1.0/predictions \
-H 'Content-Type: application/json' \
-d '{"data": {"names":["f1", "f2"], "ndarray": [[1,2,3,4], [1,2,3,4]]}}' --silent | jq
{
"jsonData": {
"data": [
[
1,
2,
3,
4
],
[
1,
2,
3,
4
]
],
"names": [
"f1",
"f2"
]
},
"meta": {}
}
Docker build가 필요합니다.
./s2i/environment
라는 파일을 만들고 다음 내용을 넣습니다.
$ mkdir .s2i
$ cat <<EOF > .s2i/environment
MODEL_NAME=MyModel
API_TYPE=REST
SERVICE_TYPE=MODEL
PERSISTENCE=0
EOF
$ s2i build . seldonio/seldon-core-s2i-python3 sklearn_iris:v0.0.12
$ docker tag sklearn_iris:v0.0.12 andersonjo/sklearn_iris:v0.0.12
$ docker push andersonjo/sklearn_iris:v0.0.12
배포합니다.
$ kubectl apply -f - << END
apiVersion: machinelearning.seldon.io/v1
kind: SeldonDeployment
metadata:
name: iris-model
namespace: seldon
spec:
name: iris
predictors:
- componentSpecs:
- spec:
containers:
- name: classifier
image: andersonjo/sklearn_iris:v0.0.12
resources:
requests:
memory: 50Mi
env:
- name: PAYLOAD_PASSTHROUGH
value: "false"
- name: SELDON_DEBUG
value: "true"
graph:
name: classifier
name: default
replicas: 1
END
$ INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
$ echo ${INGRESS_HOST}/seldon/seldon/iris-model/api/v1.0/doc/
아래 링크에서 확인합니다.
http://{INGRESS_HOST}.us-east-2.elb.amazonaws.com/seldon/seldon/iris-model/api/v1.0/doc/
$ INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
$ curl -X POST http://${INGRESS_HOST}/seldon/seldon/iris-model/api/v1.0/predictions \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{"data": {"names":["f1", "f2"], "ndarray": [[1,2,3,4], [1,2,3,4]]}}' --silent | jq
{
"data": {
"names": [
"t:0",
"t:1",
"t:2"
],
"ndarray": [
[
0.0006985194531162841,
0.003668039039435755,
0.9956334415074478
]
]
},
"meta": {}
}
Python에서 호출
import requests
import json
test_url = 'http://****.us-east-2.elb.amazonaws.com/seldon/seldon/iris-model/api/v1.0/predictions'
jsonData = {
"data": {
"names": ["text"],
"ndarray": [[1,2,3,4]]
}
}
print(requests.post(test_url, data={'json': json.dumps(jsonData)}).text)
Quick References
상태 확인
Seldon Models 리스트
kubectl get sdep -n seldon
Troubleshooting
Pods 이 계속 Restarting 될때
$ kubectl get events -n seldon