회사에서 모델을 개발하니 Production을 해야하고 이를 실제 배포까지 진행한다면 많은 단계를 거쳐야하고 모니터링 및 복구가 가능해야 합니다.
이에따라 MLOps가 필요해졌고 고객요구에 따라 Sagemaker를 활용하여 MLOps를 구축하게 되었습니다.
사실 MLOps에 대한 개념도 없이 Sagemaker로 구축을하니 너무 불편하고 번거로운 작업을 초반에 진행해야하는 문제가 있었고 이게 좋은게 맞나 ? 라는 생각이 들어 on-premise mlops를 구축하여 모르고 욕하는 것보다 알고 욕하고 싶었고 그 결과는 Sagemaker가 맞구나 라는 결론이었습니다.
on-premise로 Kubeflow를 구축하며 많은 자료가 있었지만 너무나 구버전이고 GPU 자원 활용에 대한 정보가 부족하여 누군가에게 도움되길 바라며 공유합니다.
업데이트는 첫번째 출처 깃허브에서 진행됩니다
원본 깃허브
# /etc/docker/daemon.json
{
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
}
}
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
minikube start --driver=docker --disk-size=100g --kubernetes-version=1.21.0 --memory=4g --cpus=4
(optional)minikube config set profile test
kubeflow가 kubernetes 위에서 작동하므로 minikube에 cuda 환경이 배포되어야 사용 가능
sudo apt install conntrack
sudo apt install socat
minikube start --driver=none --kubernetes-version=1.21.0
kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/master/nvidia-device-plugin.yml
kubectl get pod -A | grep nvidia
kubectl get nodes "-o=custom-columns=NAME:.metadata.name,GPU:.status.allocatable.nvidia\.com/gpu"
vim gpu.yaml
# in gpu.yaml
# caution cuda version
# 이미지가 본인의 환경에 맞는 cuda 환경을 설정해 주어야 합니다.
apiVersion: v1
kind: Pod
metadata:
name: gpu
spec:
containers:
- name: gpu-container
image: nvidia/cuda:11.4.2-runtime-ubuntu18.04
command:
- "/bin/sh"
- "-c"
args:
- nvidia-smi && tail -f /dev/null
resources:
requests:
nvidia.com/gpu: 1
limits:
nvidia.com/gpu: 1
#
kubectl create -f gpu.yaml
kubectl logs gpu
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
kubectl version --client
wget https://github.com/kubernetes-sigs/kustomize/releases/download/v3.2.0/kustomize_3.2.0_linux_amd64
chmod +x kustomize_3.2.0_linux_amd64
sudo mv kustomize_3.2.0_linux_amd64 /usr/local/bin/kustomize
manifests/common/user-namespace/base/params.env
manifests/common/dex/base/config-map.yaml
kubectl -n auth rollout restart deployment dex
git clone https://github.com/kubeflow/manifests.git
cd manifests
git checkout v1.4-branch(kubeflow 버전 변경)
# 아래 명령어는 작동 순서에 예민하므로 성공할 때까지 기다린다
while ! kustomize build example | kubectl apply -f -; do echo "Retrying to apply resources"; sleep 10; done
# 이유를 모르겠으나 이렇게 설치하면 파드가 잘 생성이 안됩니다.
# 아래 참조처럼 한개씩 설치합시다
# (참조)[https://mlops-for-all.github.io/docs/setup-components/install-components-kf/#cert-manager]
kubectl port-forward svc/istio-ingressgateway -n istio-system 8080:80
# Login
user@example.com
12341234
# manifests/common/dex/base/comnfig-map.yaml
# hash는 접속시 비밀번호인데 Bcrypt를 통해 암호화 시킨 값을 넣어야 한다.
apiVersion: v1
kind: ConfigMap
metadata:
name: dex
data:
config.yaml: |
issuer: http://dex.auth.svc.cluster.local:5556/dex
storage:
type: kubernetes
config:
inCluster: true
web:
http: 0.0.0.0:5556
logger:
level: "debug"
format: text
oauth2:
skipApprovalScreen: true
enablePasswordDB: true
staticPasswords:
- email: user@example.com
hash: $2y$12$4K/VkmDd1q1Orb3xAt82zu8gk7Ad6ReFR4LCP9UeYE90NLiN9Df72
# https://github.com/dexidp/dex/pull/1601/commits
# FIXME: Use hashFromEnv instead
username: user
userID: "15841185641784"
- email: dev7halo@gmail.com
hash: $2a$12$pnfKk2PSRTyM8Wm3jrEkKuM339fgBqWcFPrHbcsEHGhzDmH/pm/Uy
username: krkim
userID: krkim
staticClients:
# https://github.com/dexidp/dex/pull/1664
- idEnv: OIDC_CLIENT_ID
redirectURIs: ["/login/oidc"]
name: 'Dex Login Application'
secretEnv: OIDC_CLIENT_SECRET
# manifests/common/user-namespace/base/params.env
user=dev7halo@gmail.com
profile-name=krkim
import kfp
import requests
USERNAME = "dev7halo@gmail.com"
PASSWORD = " "
NAMESPACE = "krkim"
HOST = "http://10.23.13.113:31265" # istio-ingressgateway's external-ip created by the load balancer.
session = requests.Session()
response = session.get(HOST)
headers = {
"Content-Type": "application/x-www-form-urlencoded",
}
data = {"login": USERNAME, "password": PASSWORD}
session.post(response.url, headers=headers, data=data)
session_cookie = session.cookies.get_dict()["authservice_session"]
client = kfp.Client(
host=f"{HOST}/pipeline",
namespace=f"{NAMESPACE}",
cookies=f"authservice_session={session_cookie}",
)
print(client.list_pipelines())
# 쿠버네티스 파드 확인
kubectl get pods -A
watch kubectl get pods -A
kubectl get po -A -w
# namespace별 pod 확인
kubectl get po -n {namespace}
# pod 재생성
kubectl get pod <pod_name> -n <namespace> -o yaml | kubectl replace --force -f-
# pod 삭제
kubectl delete pod <pod_name> -n <namespace>
# 강제종료
kubectl delete pod <pod_name> -n <namespace> --grace-period 0 --force
# namespace 삭제
kubectl delete namespace {삭제할 namespace}
# minikube service list
minikube service list -n istio-system
Tool | Version |
---|---|
Ubuntu | 22.04 |
minikube | v1.26.0 |
kubernetes | v1.21.0 |
kustomize | v3.2.0 |
cuda | 11.4 |
https://github.com/kubeflow/manifests
https://velog.io/@moey920/Minikube-Nvidia-GPU-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0