GitHub
쿠브플로우 관련 코드 내용은 GitHub에서 관리하고 있습니다.
https://github.com/Seokii/Study-MLOps
쿠브플로우 페어링에 대한 개념과 설치 방법은 이전 게시글을 참고해주세요.
https://seokii.tistory.com/206
1. 로컬 환경에서 사용하기(실패)
수 많은 에러 발생을 해결하고 해결했지만, 마지막 오류 해결을 못하겠습니다..ㅠㅠ
1.4. 부분 참고바랍니다.
1.1. 페어링, 도커 설치 확인
pip3 show kubeflow-fairing
저는 fairing-test 이름으로 파이썬 가상환경을 만들고 페어링을 설치했습니다.
docker version
sudo systemctl status docker
또한, 로컬에서 페어링을 사용하기 위해서는 도커 엔진이 필요합니다.
1.2. 도커, 쿠버네티스 설정
docker login
도커 허브에 대한 로그인을 진행합니다.
계정이 없다면, 도커 허브에서 회원 가입을 진행할 수 있습니다.
Docker Hub : https://hub.docker.com/
로그인이 성공적으로 진행된다면, 아래와 같이 ~/.docker/config.json 파일이 생성됩니다.
kubectl create secret generic regcred \
--from-file=.dockerconfigjson=~/.docker/config.json \
--type=kubernetes.io/dockerconfigjson
쿠버네티스 클러스터에서는 개인 컨테이너 저장소에 접근하기 위해서, 도커 config 파일을 이용해 secret 리소스를 생성합니다. 공식 문서의 내용은 여기를 참고해주세요.
(config 파일을 찾을 수 없다는 오류 발생시!)
--from-file의 경로를 ~/.docker/config.json이 아닌 절대경로로 입력해주세요.
1.3. kubeconfig 설정
쿠브플로우 페어링에서 쿠버네티스 클러스터에 작업을 배포하려면, 클러스터 접근 권한이 필요합니다.
설정이 되어 있지 않다면, 쿠버네티스 클러스터의 .kube/config 파일을 로컬 환경의 ~/.kube/config 파일로 만들어줘야 합니다. 쿠버네티스를 설치하면서 해당 과정을 진행했었습니다.
1.4. docker 빌더로 모델 학습
mnist_tf.py
# mnist_tf.py
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
import numpy as np
def train():
print("TensorFlow version: ", tf.__version__)
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = 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='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
print("Training...")
training_history = model.fit(x_train, y_train, epochs=5)
print("Average test loss: ", np.average(training_history.history['loss']))
if __name__ == '__main__':
train()
로컬에서 pycharm으로 프로젝트를 만들고, 텐서플로우를 통해 mnist를 학습시키는 간단한 코드를 작성했습다.
dockerfile
#dockerfile
FROM tensorflow/tensorflow:2.11.0
RUN mkdir -p /app
ADD mnist_tf.py /app/
간단한 도커 파일을 작성했습니다.
fairing-docker.py
# fairing-docker.py
import uuid
from kubeflow import fairing
CONTAINER_REGISTRY = 'seokii'
namespace = 'kubeflow-user-example-com'
job_name = f'mnist-job-{uuid.uuid4().hex[:4]}'
command={"python", "mnist_tf.py"}
output_map = {
"dockerfile": "dockerfile",
"mnist_tf.py": "mnist_tf.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="mnist-job", dockerfile_path="dockerfile")
fairing.config.set_deployer('job', namespace=namespace, job_name=job_name,
cleanup=False, stream_log=False)
fairing.config.run()
컨테이너 이미지(도커 이미지)를 빌드, 배포하기 위해서 faring 코드 파일을 작성했습니다.
- CONTAINER_REGISTRY : 도커 허브 유저네임
- namespace : 쿠브플로우 namespace 이름
- job_name : job 이름
- fairing.config.set_preprocessor : 페어링 전처리기 부분
- fairing.config.set_builder : 페어링 빌더 부분
- fairing.config.set_deployer : 페어링 배포 부분
(네임스페이스 부분은 kubectl get namespace 명령어로 확인할 수 있습니다.)
- 전처리기
파이썬 파일을 사용하기 때문에 'python'으로 지정했습니다.
빌드하기 위한 파일을 빌더로 넘겨주기 위해 ouput_map을 지정했습니다.
학습 작업을 실행하기 위한 명령어를 command로 지정했습니다.
- 빌더
도커 엔진을 사용하기 위해 도커 빌더를 사용했습니다.
이미지 레지스트리 주소를 지정하고,이름, 도커파일 경로를 설정했습니다.
- 배포
job 배포로 설정하고 배포되는 네임스페이스를 지정했습니다.
기본값이 True인 cleanup, stream_log를 False로 지정했습니다.
python fairing-docker.py
결과: 실패 ㅠㅠ
(경험한 에러들 시간순으로 나열)
ModuleNotFoundError: No module named 'ray.serve.utils'
: 해당 오류가 발생하여 pip uninstall kfserving 이후 0.5.1로 다시 pip3 install을 진행했습니다.
AttributeError: module 'numpy' has no attribute 'float'
: numpy 1.24 이후 버전에서 발생하는 에러인 것 같습니다.
pip3 install numpy==1.22.4로 해결했습니다.
ImportError: cannot import name 'PROTOCOL_TLS' from 'urllib3.util.ssl_'
: urllib3 버전을 1.24.2에서 1.25.4로 변경했습니다.
ModuleNotFoundError: No module named 'msrestazure'
: pip3 install msrestazure 명령어로 0.6.4버전을 설치했습니다.
ImportError: cannot import name 'V1alpha2TensorRTSpec' from 'kfserving'
: kubeflow-fairing 버전이 0.7.1로 되어 있어서 1.0.1로 다시 설치했습니다.
그랬더니, urllib3 버전이 낮아져 다시 1.25.4로 설치했습니다.
수 많은 에러들을 해결하고 진행이 되길래 정상 작동하는 줄 알았으나,
AttributeError: 'set' object has no attribute 'swagger_types' 에러 발생..
fairing github도 뒤져보고, 구글링도 진행했으나 해결 방법을 모르겠습니다.
2. Kubeflow 주피터 노트북 서버에서 사용하기
로컬 환경에서 페어링을 사용하는 것에 실패하고, 쿠브플로우에서 주피터 노트북 환경을 구성하고 다시 한 번 진행했습니다.
이상하게도 구글링, 책, 공식 docs에서는 kubeflow에서 주피터 노트북 환경을 구성할 경우 페어링을 바로 사용할 수 있다고 했습니다. 그러나, 제가 구성한 환경에서는 주피터 노트북 서버를 만들어도 바로 쿠브 플로우 페어링을 사용할 수 없었고, 서버의 런처에서 터미널을 열어 pip install kubeflow-fairing 명령어를 통해 따로 설치했습니다. 설치 도중 의존성 패키지를 찾는 과정으로 인해 시간이 매우 오래 걸렸습니다.
또한, kubeflow를 끄고 다시 켜면 설치한 패키지의 내용이 초기화되었습니다.
주피터 노트북 서버를 만들 때, custom image를 통해 생성한다면 해결할 수 있을 것으로 보입니다.
2.1. 주피터 노트북 환경 구성
kubectl port-forward svc/istio-ingressgateway -n istio-system 8080:80
포트 포워딩을 통해 쿠브플로우 대시보드에 접속하고 Notebooks > New Notebook > 기본 제공하는 주피터 노트북 이미지(텐서플로우)를 사용했습니다. 그 후, 환경 구성이 완료되면 connect를 눌러 런처에 접속한 후 새로운 주피터 노트북 파일을 생성합니다.
주피터 노트북 서버에 대한 개념과 생성 방법은 예전 글을 참고바랍니다.
https://seokii.tistory.com/205
2.2. cluster 빌더로 모델 학습
이미 비슷한 방식으로 주피터 노트북 환경에서 다시 시도해봤지만 실패했습니다.
그래서 새로운 방식을 찾기 위해 구글링 및 kubeflow 공식 docs에서 연결된 예제 github를 참고해 진행했습니다.
https://github.com/kubeflow/examples
cluster 빌더는 예전 글에서 설명했던 바와 같이 컨테이너 이미지 빌드 작업이 쿠버네티스 클러스터에서 진행됩니다. 구글 컨테이너 툴인 Kaniko를 사용합니다.
아무래도 작업 자체가 쿠버네티스 클러스터 안에서 진행되다 보니 좀 더 안정적이지 않을까는 생각으로 시도해봤습니다.
docker-config 생성하기
kubectl -n kubeflow-example-user-com create configmap docker-config \
--from-file=/home/seokii/.docker/config.json
명령어를 통해 kubeflow-example-user-com 네임스페이스에 도커 configmap을 생성합니다.
저는 이미 입력한 상태이기 때문에, 이미 존재한다는 문구가 출력되었습니다.
ContextSource
cluster 빌더를 사용하기 위해서는 ContextSource 정의가 필요합니다.
github에서는 minio을 통한 예제가 있었기에 해당 코드를 참고했습니다.
minio외에도 azurestorage, gcs, s3도 지원하는 것으로 보입니다.
train.py
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
import numpy as np
def train():
print("TensorFlow version: ", tf.__version__)
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = 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='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
print("Training...")
training_history = model.fit(x_train, y_train, epochs=5)
print("Average test loss: ", np.average(training_history.history['loss']))
if __name__ == '__main__':
train()
주피터 노트북 서버 런처에서 파이썬 파일을 만들어 train.py를 작성합니다.
dockerfile
FROM tensorflow/tensorflow:2.1.0-py3
RUN mkdir -p /app
ADD train.py /app/
도커 파일 또한 작성합니다.
주피터 노트북파일
import uuid
from kubeflow import fairing
# docker hub username
CONTAINER_REGISTRY = 'seokii'
# kubectl get namespace로 확인가능
namespace = 'kubeflow-user-example-com'
# job이름 지정
job_name = f'mnist-job-{uuid.uuid4().hex[:4]}'
# command 정의
command=["python", "train.py"]
# output_map 정의
output_map = {
"dockerfile": "dockerfile",
"train.py": "train.py"
}
# 페어링 전처리기 정의
fairing.config.set_preprocessor('python', command=command, path_prefix="/app", output_map=output_map)
# cluster builder ContextSource를 minio로 정의
s3_endpoint = 'minio-service.kubeflow.svc.cluster.local:9000'
minio_endpoint = "http://"+s3_endpoint
minio_username = "minio"
minio_key = "minio123"
minio_region = "us-east-1"
# minio_context사용
from kubeflow.fairing.builders.cluster.minio_context import MinioContextSource
minio_context_source = MinioContextSource(endpoint_url=minio_endpoint, minio_secret=minio_username, minio_secret_key=minio_key, region_name=minio_region)
# 페어링 빌더 정의
fairing.config.set_builder('cluster', registry=CONTAINER_REGISTRY, image_name="train", dockerfile_path="dockerfile",
context_source=minio_context_source)
# 페어링 배포 정의
fairing.config.set_deployer('job', namespace=namespace, job_name=job_name, cleanup=False, stream_log=True)
# 페어링 실행
fairing.config.run()
코드가 정상적으로 작동하는 것을 확인했습니다.
kubectl -n kubeflow-user-example-com get job
터미널에서 명령어를 통해 네임스페이스의 job을 확인할 수 있습니다.
# 네임스페이스 job 개별 삭제
kubectl -n kubeflow-user-example-com delete job fairing-builder-zdq7g
kubectl -n kubeflow-user-example-com delete job mnist-job-b53b
# 네임스페이스 job 전체 삭제
kubectl -n kubeflow-user-example-com delete job --all
도커 허브 레파지토리에 잘 배포된 것을 확인할 수 있었습니다.
모델을 저장하려면 pvc를 생성하여 저장하는 등의 과정을 진행할 수도 있습니다.
'MLOps' 카테고리의 다른 글
[MLOps] 쿠브플로우 카티브(Katib) 하이퍼파라미터 튜닝(1) (0) | 2023.01.09 |
---|---|
[MLOps] 쿠브플로우 카티브(Katib) 개념 이해와 설치하기 (0) | 2023.01.08 |
[MLOps] 쿠브플로우 페어링(Fairing) 개념 이해와 설치하기 (1) | 2023.01.05 |
[MLOps] 쿠브플로우 주피터 노트북 서버 만들기 (0) | 2023.01.02 |
[MLOps] Ubuntu 20.04에서 docker 및 쿠버네티스와 kubeflow 설치하기 (0) | 2023.01.01 |
댓글