2.5.14.TrafficPeriodicTrainAndK8sServingExample.md 15.8 KB
Newer Older
HooYoungAhn's avatar
HooYoungAhn committed
---
html:
  toc: true
  offline: true
export_on_save:
  html: true
---
# 쿠버네티스를 이용한 주기적인 모델학습 및 예측모델 서빙하기 (TrafficPeriodicTrainAndK8sServingExample)
---
교통센서 데이터 파일을 이용하여 주기적으로 텐서플로우 모델을 학습한 후, 쿠버네티스를 이용해 최신 모델을 서빙하는 예제를 설명합니다.

## 쿠버네티스와 연동 환경 준비하기
쿠버네티스 클러스터 설치하기 매뉴얼을 참고하여 쿠버네티스 클러스터를 구성합니다.
HooYoungAhn's avatar
HooYoungAhn committed

## 입력 데이터 준비하기
본 예제에서는 KSB 프레임워크 웹툴킷 화면에서 Repository 탭을 클릭하여 dataset/input 디렉토리를 선택합니다. 해당 디렉토리에 traffic_processing.csv 파일이 있는지 확인합니다.

만약 없다면 /home/csle/ksb-csle/examples/input 폴더에 존재하는 traffic_processing.csv 파일을 사용자 HDFS repository dataset/input 폴더에 등록하여 사용합니다.

![파일 업로드](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_01.png)

## 사용자 파이썬 코드 준비하기
텐서플로우 기반 딥러닝 모델이 구현된 사용자 파이썬 코드가 있어야 합니다. 사용자 파이썬 코드는 프레임워크와 연동하기 위해 프레임워크에서 전달하는 파라미터를 받는 부분, 학습된 모델을 텐서플로우 서빙용으로 export 하는 부분 등이 구현되어야 합니다. 자세한 내용은 <a href="https://etrioss.kr/thkimetri/ksb19.03-manual/blob/master/manual1903/2.7.2.KSB_TfPyCoding_Guide.md">KSB 프레임워크와 연동을 위한 tensorflow 학습코드 작성하기</a> 를 참고합니다.
HooYoungAhn's avatar
HooYoungAhn committed
main 함수를 포함한 사용자 파이썬 코드에서 사용하는 라이브러리 파일 등은 동일한 폴더에 위치 시키거나 1 depth의 하위 폴더까지 작성 가능합니다.

## 워크플로우 생성하기
HooYoungAhn's avatar
HooYoungAhn committed
워크플로우 편집화면에서 워크플로우를 작성합니다. 본 예제에서는 두 개의 엔진을 생성합니다.

- 워크플로우 속성

속성  | 값  | 비고
--|---|--
name  | TrafficPeriodicTrainAndK8sServingExample |  워크플로우 이름  
description  | 강남교통데이터에 대한 주기적 학습 및 쿠버네티스를 이용한 서빙 예제  | 워크플로우를 설명하는 글
isBatch  | true | 배치 처리를 하는 워크플로우이므로, true 로 지정
verbose  | false | 디버깅을 위해 로그정보를 보고자할 경우, true 로 지정

- 엔진 속성

순번  | 엔진 Type | NickName  | RunType | 설명
--|---|---|---|--
1  | Batch  | TrainEngine  | 반복실행 | 딥러닝 모델 학습
2  | OnDemandServing  | K8sServingEngine  | 반복실행 | 최신 모델을 이용한 쿠버네티스 서빙

### 첫 번째 엔진 생성하기

텐서플로우를 이용하여 딥러닝 학습을 위해 Batch 엔진을 선택합니다.

HooYoungAhn's avatar
HooYoungAhn committed
FileReader를 선택하고 아래표와 같은 속성을 지정합니다. filePath 에 입력 파일의 경로 및 파일명을 지정합니다. 이 값은 사용자 파이썬 코드(텐서플로우 모델을 정의하고 학습하는 코드)의 `--input` 파라미터로 전달됩니다.

field  |value   | 설명
--|---|--
filePath|  dataset/input/traffic/traffic_processing.csv |  파일 경로  
fileType  |  CSV |  파일 형태


filePath의 경로 입력창 옆의 "File" 버튼을 클릭하여 HDFS repository 탐색창을 통해 파일을 선택하여 업로드할 수 있습니다. 아래의 그림은 업로드된 후 결과 화면을 나타냅니다.

![학습 데이터셋 파일 위치 및 선택하기  ](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_02.png)

HooYoungAhn's avatar
HooYoungAhn committed
처리 결과를 파일 형태로 저장할 것이므로 FileWriter를 선택합니다. filePath 에 학습한 딥러닝 모델이 최종 저장될 폴더를 지정합니다. 해당 폴더에 자동으로 최신버전의 폴더를 생성한 후 모델이 저장됩니다. 모델의 버전은 0000 부터 시작하여 1씩 증가합니다. filePath 에 입력한 값은 사용자 파이썬 코드(텐서플로우 모델을 정의하고 학습하는 코드)의 `--output` 파라미터로 전달됩니다.

본 예제에서는 두번째 엔진인 OnDemandServing 엔진에서 쿠버네티스를 이용한 모델 서빙을 하기 위해 HDFS 절대경로를 지정합니다. 상대경로를 지정할 경우, 동적으로 생성한 **사용자 기본 파일경로** 가 앞에 추가되므로 OnDemandServing 엔진에서 정확한 파일 경로를 지정하는 것이 어렵습니다.   

field  |value   | 설명
--|---|--
filePath  |  hdfs://csle1:9000/user/ksbuser_etri_re_kr/model/kangnam |  모델 저장 경로
fileType  |  CSV |  파일 타입
delimeter  |  , |  구분자  
header  |  false |  header 포함 여부
saveMode  |   | 사용하지 않음

HooYoungAhn's avatar
HooYoungAhn committed
본 예제에서 Controller는 텐서플로우와 같은 외부시스템를 제어하기 위한 ExternalAnalysisController를 선택합니다.

HooYoungAhn's avatar
HooYoungAhn committed
tensorflowRunner 를 선택합니다. pyEntryPath 에 main 함수를 포함하는 사용자 파이썬 코드(강남 교통 데이터를 학습하기 위한 코드)의 경로 및 파일명을 지정합니다.

field  |value   | 설명
--|---|--
pyEntryPath  |  file:///home/csle/ksb-csle/components/src/main/python/kangnam/tensorflow_train.py |  텐서플로우 모델 학습을 위한 파이썬 코드 경로
cluster  |  false |  cluster 환경 실행 여부  
inJson  |  false |  Json 형태 파라미터 전달 여부
tfVersion  |  r1.6 |  텐서플로우의 버전


pyEntryPath 에는 아래와 같이 3가지 경로가 입력 가능합니다.

1. 로컬 파일시스템 절대경로 지정
   file:///home/csle/ksb-csle/components/src/main/python/kangnam/tensorflow_train.py
2. hdfs 절대경로 지정
   hdfs://csle1:9000/user/ksbuser_etri_re_kr/dataset/tensorflowTrainSource/kangnam/tensorflow_train.py
3. hdfs 상대경로 지정
   dataset/tensorflowTrainSource/kangnam/tensorflow_train.py

사용자는 로컬 파일시스템에 원하는 이름(예: kangnam) 폴더를 생성하고 해당 폴더 내에 main 함수를 포함하는 사용자 python 파일(예:tensorflow_train.py)을 작성합니다.
그리고, 관련된 라이브러리 파일 등은 동일한 폴더에 위치 시키거나 1 depth의 하위 폴더까지 작성 가능합니다.

이렇게 작성된 kangnam 폴더를 KSB 웹툴킷 repository내 dataset/tensorflowTrainSource 폴더내에 업로드합니다.

![](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_20.png)

![](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_19.png)

결과적으로 KSB 인공지능 프레임워크는 엔진 실행시, 로컬 파일시스템의 사용자 repository에 있는 kangnam 폴더 및 하위 1 depth 폴더를 file:///home/csle/ksb-csle/components/src/main/python/로 copy 후 tensorflow를 실행합니다.

HooYoungAhn's avatar
HooYoungAhn committed
DLTrainOperator를 선택하고 아래표와 같은 속성을 지정합니다. modelPath 에 내부적으로 학습된 모델을 저장할 경로를 지정합니다. 이 값은 사용자 파이썬 코드(텐서플로우 모델을 정의하고 학습하는 코드)의 `--modelPath` 파라미터로 전달됩니다. 로컬 파일시스템 절대경로로 입력합니다.
또한, modelPath를 기준으로 최신버전의 폴더를 자동으로 생성하여 사용자 파이썬 코드의 `--model` 파라미터로 전달합니다. 모델의 버전은 0000 부터 시작하여 1씩 증가합니다. 따라서 예를 들면:

- (modelPath) file:///home/csle/ksb-csle/models/kangnam/model
- (자동생성되는 model) file:///home/csle/ksb-csle/models/kangnam/model/0000

field  |value   | 설명
--|---|--
modelPath  | file:///home/csle/ksb-csle/models/kangnam/model |  학습모델 저장 경로
addtionalParams  | 아래 설정 참고  |

addtionalParams 를 클릭하여 아래의 값을 추가 설정합니다. 사용자가 필요한 파라미터의 이름과 값을 세팅하여 사용자 파이썬 코드로 전달합니다.

field  |value   | 설명
--|---|--
isTrain  | True  |  새롭게 학습할 경우에는 True, 그 외의 경우에는 False.
num_epochs  | 1  | 학습 반복 횟수

HooYoungAhn's avatar
HooYoungAhn committed
매분 주기적으로 실행하기 위해 해당 파라미터를 설정하고 Apply를 누릅니다. 현재 테스트를 위해 주기 : '매분' 설정은 내부적으로 5분 단위의 주기적 실행을 하게 설정되어 있습니다.

![](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_15.png)

<br>

### 두 번째 엔진 생성하기
두번째 엔진은 강남교통속도 예측모델을 이용하여 텐서플로우 서빙을 동작하기 위한 엔진입니다. 또한 쿠버네티스를 이용하여 온디맨드 서비스를 제공하기 위해 OnDemandServing 엔진을 선택합니다.
OnDemandServing 엔진에서는 데이터를 입출력하기 위한 Reader 와 Writer를 사용하지 않습니다. 데이터는 request 에 실어서 보냅니다.

#### Controller
본 예제의 Controller는 TensorflowServingController를 사용합니다.

#### Runner
본 예제의 Runner는 TensorflowServingRunner를 사용합니다.

field  |value   | 설명
--|---|--
modelBasePath | hdfs://csle1:9000/user/ksbuser_etri_re_kr/model/kangnam| 학습 모델 경로
port | 8001 | 교통속도 예측 RESTful 서비스 포트번호
modelName | kangnam| 교통속도 예측 모델의 이름

쿠버네티스를 이용하여 엔진을 구동하는 경우, 8001번 포트는 쿠버네티스 동작에 의해 외부로 노출되지 않으며, 외부에서 엔진에 접속하기 위해서는 쿠버네티스 마스터에 ingress에 할당된 30100번 포트를 이용합니다.

#### Operator
본 예제의 Operator는 TensorflowServingOperator를 사용합니다.

![워크플로우 완성 화면](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_04.png)

ksbuser@etri.re.kr 계정으로 접속하면 예제 워크플로우가 만들어져있습니다. 불러오기해서도 돌려볼 수 있습니다.

HooYoungAhn's avatar
HooYoungAhn committed

매분 주기적으로 실행하기 위해 해당 파라미터를 설정하고 Apply를 누릅니다. 단, 첫번째 엔진에서 생성된 모델을 이용하여 서빙을 하기 때문에 첫번째 엔진의 시작시간에서 5분 후에 tensorflow 서빙 엔진을 시작하도록 설정합니다.
![](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_18.png)


## 워크플로우 실행 및 모니터링하기

### ksb.conf 수정하기
쿠버네티스를 이용하기 위해 ksb.conf 파일에 쿠버네티스 환경설정 정보를 수정합니다. 그리고 enable을 true로 설정한 후, ./startKsbApiServing.sh 를 실행합니다.

```sh
vi /home/csle/ksb-csle/conf/ksb.conf
```
```
kubernetes {
    enable = "true"   # 수정필요
    baseUrl = "http://SERVICENAME.ksb.local:30100"
    imgRepositoryUrl = "docker.io"
    kubernetes_yaml_path = "/kubernetes"
    masterIp = "csle1"
    masterPort = "2243"
    nodesIp = "csle2,csle3"
    user = "csle"
    externalKafka {
        brokerHostName = "csle1"
        brokerHostIp = "192.168.0.5"          
      }
```

### 워크플로우 실행하기
위에서 작성한 워크플로우를 실행하기 위해서는 워크플로우 편집기 상단의 실행 버튼을 누릅니다. 주기적으로 엔진을  배치방식으로 처리하므로 Batch 체크 박스는 체크하고 워크플로우를 제출합니다.

![워크플로우 제출](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_05.png)

### 워크플로우 모니터링 하기

KSB 웹툴킷 상단 메뉴의 Monitoring 탭을 클릭하면 Workflow 탭이 선택되어있습니다. Workflow 탭에는 위에서 실행한 두 엔진들의 동작 상태 (status) 가 실행 중(Inprogress)인 것을 확인 할 수 있습니다. Batch엔진은 주기적으로 동작하는 시점에만 Ingress 상태를 확인할 수 있으며 OnDemandServing 엔진인 경우 항상 Ingress 상태에서 주기적으로 서빙모델을 업데이트 합니다.

![워크플로우 동작 상태 확인](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_06.png)

### 주기적으로 학습한 모델 확인하기  
첫 번째 엔진의 FileWriter 에서 지정한 위치에 학습된 모델이 생성된 것을 확인합니다. 첫 번째 엔진이 5분 마다 실행되어 모델을 주기적으로 생성하는 것을 확인할 수 있습니다. 모델의 버전은 0000 부터 자동으로 1씩 증가합니다.

![학습 모델 저장 위치 설정하기  ](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_03.png)

![학습된 모델 확인](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_07.png)

### 쿠버네티스 서빙엔진 동작 확인하기

쿠버네티스 Dashboard에 접속하여 서빙 엔진 pod들이 동작하는지 확인합니다. Dashboad에 접속하는 방법은 <a href="http://csleoss.etri.re.kr:8088/images/contents/manual_1.0/1.6.KSB_K8s_install_Guide.html"> Kubernetes 클러스터 설치하기</a>를 참고합니다.
Dashboaddml Pod 부분에 kangnam-server의 pod가 2개 생성되는지 확인합니다.
![](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_10.png)
또한, Pode의 로그 아이콘을 콜릭하여 현재 쿠버네티스가 서빙하고 있는 모델의 버전을 확인합니다. 그림에서는 0010 폴더의 모델을 이용해서 텐서플로우 서빙을 하고 있는 것을 확인합니다.
![](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_08.png)

5분 후 자동적으로 OnDemandServing 엔진을 다시 실행하게 되므로 기존은 pod들은 점차 삭제되고 새로 생기는 pod들은 다시 새로운 모델 버전을 이용해서 서빙을 하게 됩니다.
![](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_11.png)
아래 그림과 같이 0011 폴더의 새로운 모델을 이용해서 서빙을 하는 것을 확인할 수 있습니다.
![](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_12.png)


### 결과 확인하기

#### /etc/hosts 에 dns 이름 등록하기
쿠버네티스의 ingress는 도메인 주소와 포트를 이용해 쿠버네티스 내부의 pod로 데이터를 전달합니다.
OnDemandServing 엔진 생성시, TensorflowServingRunner에서 지정한 modelname : "kangnam" 정보를 이용하여 kangnam.ksb.local 주소로 자동 proxy 되도록 설정됩니다.
따라서, host pc의 /etc/hosts를 아래와 같이 수정한 후, 쿠버네티스에서 동작하는 tensorflow 서빙에게 query를 전달하여야 합니다. (쿠버네티스 마스터의 IP는 192.168.0.5로 가정합니다. 자신의 쿠버네티스 클러스터 IP에 맞게 설정합니다.)

```sh
sudo vi /etc/hosts

127.0.0.1       localhost
# 아래 주석처리. Hdfs 연동시 문제가 생김.
#127.0.1.1      csle1

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

# 쿠버네티스 master, node1, node2 정보
192.168.0.5 csle1 master
192.168.0.6 csle2
192.168.0.7 csle3
# 쿠버네티스 kangnam 서빙 주소 설정
192.168.0.5 kangnam.ksb.local
```

#### 교통속도 예측 질의 및 서비스 결과 보기
클라이언트 SDK 내의 아래의 디렉터리로 이동합니다. 테스트 스트립트를 실행하여 교통속도 예측 질의를 요청합니다.

```sh
cd /home/csle/ksb-csle/examples/models/kangnam/client/rest-csv
./predict-speed.sh kangnam.ksb.local:30100 in1.csv
```

![](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_09.png)

테스트 스크립트를 실행한 결과로 교통속도 예측값을 확인할 수 있습니다.

## 워크플로우 종료하기
KSB 웹툴킷 상단 "Monitoring" 메뉴의 "Workflow" 탭에서 실행 중인 TrafficPeriodicTrainAndK8sServingExample 워크플로우를 종료(<span style="color:red">&#9724;</span>)할 수 있습니다.

![](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_16.png)

![](./images/2.5.14.TrafficPeriodicTrainAndK8sServingExample_17.png)