[MLOps] M1/M2 Apple Silicon Mac에 Kubeflow v1.7.0 설치하기

김선주·2023년 7월 13일
1

MLOps

목록 보기
1/1

0. Kubeflow 설치 실패...

나는 Data Science를 전공했기 때문에 사실 Kubernetes와는 아예 남남 사이였다. 그런데 최근 MLOps의 필요성을 느끼게 되었고 결국 이 친구들을 다뤄야 한다는 사실을 알게 되었다. 잘 모르지만 천천히 docker와 kubernetes를 찾아보며 활용법을 중심으로 찾아보고 있었고 그 중 가장 흥미로웠던 부분이 바로 kubeflow였는데... 나에게 한 가지 큰 문제가 생겼다. 바로, 아무리 시도해도 kubeflow가 설치되지 않는 것이다.

찾아보다보니 내가 얼마 전에 M1 Macbook Pro로 노트북을 바꾸었다는 점이 문제가 됐던 것 같다.이게 왜 문제가 되냐면, 나와 같은 apple silicon 동지들은 보편적으로 알려져있는 linux/amd64 기준 설치 방법을 따르면 안 되기 때문이다...^^ 아마 이 글을 찾아오신 분들은 이미 알고 계시겠지만 우리는 linux/arm64를 키워드로 하는 설치 방법을 따라야 한다. 이 말을 믿기 어렵다면 Terminal에 아래와 같은 명령을 실행해볼 수 있다.

$ uname
Darwin

$ uname -m
arm64

이 글은 위와 같은 환경에서, kubeflow 최신 버전(2023.07 기준) 설치에 애를 먹고 있는 동지들을 위한 글이다. 나 또한 매우 애를 먹었던 부분이었기 때문에, 누구 한 명이라도 도움을 받았으면 좋겠다는 생각에 정리해보았다.

본 글을 시작하기에 앞서 나는 본 글 작성일자를 기준으로 docker, kubernetes, kubeflow 전문가가 전-혀 아니며 완전 뉴비임을 밝힌다.

1. 설치 시도: Manifest repository

우선 내 환경은 다음과 같다.

kubernetes version: v1.23.1 Single node deployment
minikube version: v1.30.1
kustomize version: v5.0.0

kubeflow를 설치할 수 있는 방법에는 굉장히 여러 가지가 있었는데, manifests repository를 통해서 설치하는 방법이 제일 정석이라고 해서 그대로 README.md의 안내를 따라봤다.
Kubeflow가 정상적으로 잘 설치되었다!라고 말하려면 모든 pod가 running이어야 하는데 나는 일부 pod에서 ErrImagePull가 발생했다.

첫 번째 탈출 시도: kustomize 버전 바꾸기

가장 먼저 했던 시도는 Mac에서 kubeflow를 설치한 사례를 찾는 것이었다. 다들 kustomize를 downgrade해서 설치하길래 나도 따라해보고 싶었는데 많이들 쓰는 kustomize 3.2.0은 linux/arm64를 지원하지 않는다. 어느 블로그 글에서 M1에 저 버전으로 설치해서 kubeflow를 사용하신 분을 봤는데, 어떻게 한 건지.. 잘 모르겠다. 그리고 내가 간과하고 있었던 게, kubeflow v1.7.0은 kustomize 5.0.0을 지원한다. 그러니까 새삥 버전을 쓰고 싶었던 나한테는 해당되지 않는 문제였다. ^^^

두 번째 탈출 시도, Ubuntu 가상 환경 생성

가장 첫 시도는 바로, ubuntu 가상 환경 생성이었다. VirtualBox를 이용하고 싶었는데 아직까지 apple silicon에 대해서 beta 버전을 지원하고 있고, 내 생각대로 설치가 안 되어서 UTM이라는 앱을 설치해보았다.
가상 환경을 생성하기 위해 Ubuntu에서 이미지를 가져왔는데, 사실 이때도 고민이 되었다. 나는 amd64 가상환경이 필요한데, 내 노트북은 arm64니까 이미지는 어떤 걸 가져와야 하지...? 그래서 먼저 arm64를 시도해보았다. 지금 생각해보면 바보같은 생각인데 당연히 내 맥북과 동일한 환경에서 설치를 시도하였기 때문에 안 됐다. 그래서 linux/amd64를 가져와서 에뮬레이션(Emulation)을 시도해보았다. 에뮬레이션의 경우 cpu architecture가 다를 경우 속도가 느릴 수 있다는 단점이 있다는 것은 알고 있었는데, 실제로 시도해보니 정말정말정말정말정말정말 많이 느렸다.. 굳이 시도해보지 않는 것을 추천드릴 정도이다.
실패한 시도였지만, 하나 확실히 알게 된 것은 다음과 같았다.

  1. 내가 다른 블로그 환경을 맞추는 것이 아니라, kubeflow에서 arm을 지원하는지부터 확인해보아야 함.
    -> 아니면 애초에 내가 쓸 수 없는 운명인 것...
  2. kubeflow와 연계되는 kustomize의 버전 또한 살펴볼 것.
  3. kubeflow 설치 과정에서나타나는 log를 좀 더 면밀하게 살펴보자.
+) 기타 등등

Reddit에서 multipass라는 걸 설치해서 하라는 말을 들어봤는데 이것도 잘 안 됐다. ㅋ minikube 버전도 바꿔보고 했는데 결국 아키텍쳐와 관련한 접근이 필요하다는 결론에 도달했다.

2. 해결 과정: pod의 로그를 살펴보자!!

ErrImagePull이 발생한 로그의 pod 기록을 살펴보면 대략 다음과 같이 나온다.

(중략)
Events: 
  Type     Reason     Age                From               Message 
  ----     ------     ----               ----               ------- 
  Normal   Scheduled  22s                default-scheduler  Successfully assigned kubeflow/profiles-deployment-54f457d59d-d44ts to minikube 
  Normal   Pulled     21s                kubelet            Container image "docker.io/istio/proxyv2:1.16.0" already present on machine 
  Normal   Created    21s                kubelet            Created container istio-init 
  Normal   Started    21s                kubelet            Started container istio-init 
  Normal   Pulling    21s                kubelet            Pulling image "docker.io/kubeflownotebookswg/kfam:v1.7.0-rc.0" 
  Normal   Created    18s (x2 over 18s)  kubelet            Created container manager 
  Warning  Failed     18s                kubelet            Error: ErrImagePull 
  Normal   Pulled     18s (x2 over 18s)  kubelet            Container image "docker.io/vinaychandran/profile-controller:v1.7.0" already present on machine 
  Warning  Failed     18s                kubelet            Failed to pull image "docker.io/kubeflownotebookswg/kfam:v1.7.0-rc.0": rpc error: code = Unknown desc = no matching manifest for linux/arm64/v8 in the manifest list entries 
  Normal   Started    18s (x2 over 18s)  kubelet            Started container manager 
  Normal   Pulled     18s                kubelet            Container image "docker.io/istio/proxyv2:1.16.0" already present on machine 
  Normal   Created    18s                kubelet            Created container istio-proxy 
  Normal   Started    18s                kubelet            Started container istio-proxy 
  Warning  BackOff    16s (x2 over 17s)  kubelet            Back-off restarting failed container 
  Normal   BackOff    15s (x4 over 18s)  kubelet            Back-off pulling image "docker.io/kubeflownotebookswg/kfam:v1.7.0-rc.0" 
  Warning  Failed     15s (x4 over 18s)  kubelet            Error: ImagePullBackOff 

나는 사실 docker에 대해서 아직 잘 모르지만 여기서 대략 답을 알 수 있었다.

"docker.io/kubeflownotebookswg/kfam:v1.7.0-rc.0": rpc error: code = Unknown desc = no matching manifest for linux/arm64/v8 in the manifest list entries Normal Started 18s (x2 over 18s) kubelet Started container manager
한 마디로 나의 환경인 linux/arm64와 일치하는 docker image를 찾을 수 없다는 것이었다. 그러니까 이제 해결 방법은, linux/arm64를 지원하는 docker image를 찾던지(없으면 만들던지...^^)해서 manifests 설치 과정에서 반영해주어야 한다는 것이다.

Docker hub를 찾아보니, 아무래도 나와 같은 문제를 겪었던 유저가 있었던듯 하다. 오류가난 pod에 대한 linux/arm64 image들을 여기서 확인할 수 있었다. https://hub.docker.com/u/vinaychandran

3. 해결: Manifests 변경

근데 도대체 manifests 코드 중에서 이걸 어디에 반영해야할지 모르겠던 나는 이리저리 헤매였다. 진짜 뭐가 뭔지 하나도 모르겠지만 오랜 삽질 끝에 아무튼 Repo의 docker image 주소를 변경해야지만 한다는 결론을 내린 나를 믿어보기로 했다. docker를 잘 몰라서 망가뜨릴까봐 좀 겁나긴 했지만(잘못되면 다시 clone 해오면 되니까 ㅎㅎ), 우선 Kustomization.yaml 파일들을 열어보기 시작했고 찾을 수 없는 docker image 주소가 적힌 것을 위에서 언급한 linux/arm64 이미지 주소로 아래와 같이 변경해두었다.

그리고 다음처럼 pod들을 삭제해준 뒤 (pod만 삭제하면 깔끔하게 안 지워지니까 다음과 같은 명령어로 수행하시길 권장한다.)

$ kustomize build apps/profiles/upstream/overlays/kubeflow | kubectl delete -f 

다시 설치했다.

$ kustomize build apps/profiles/upstream/overlays/kubeflow | kubectl apply -f - 

그랬더니 비로소 광명을 찾았다^^^^^^^^^^

$ kubectl get pod -A
NAMESPACE                   NAME                                                     READY   STATUS    RESTARTS        AGE
auth                        dex-64775f9cf6-jtgnq                                     1/1     Running   0               10m
cert-manager                cert-manager-b4b465456-f6vks                             1/1     Running   0               10m
cert-manager                cert-manager-cainjector-64d74f9c8f-k26pg                 1/1     Running   0               10m
cert-manager                cert-manager-webhook-66fff58cdf-zk59s                    1/1     Running   0               10m
istio-system                authservice-0                                            1/1     Running   0               10m
istio-system                cluster-local-gateway-7f55dcfff7-hx5vm                   1/1     Running   0               10m
istio-system                istio-ingressgateway-869ccf7495-ddxmb                    1/1     Running   0               10m
istio-system                istiod-69d59d9787-kh6zp                                  1/1     Running   0               10m
knative-eventing            eventing-controller-59f4b748d5-nrk49                     1/1     Running   0               10m
knative-eventing            eventing-webhook-d85c57bb4-2bdqv                         1/1     Running   0               10m
knative-serving             activator-866846c6d5-n2ngv                               2/2     Running   0               9m14s
knative-serving             autoscaler-7654f76758-zhvpr                              2/2     Running   0               9m12s
knative-serving             controller-756f7689b7-hjwvn                              2/2     Running   0               9m11s
knative-serving             domain-mapping-59c548885b-v4zr5                          2/2     Running   0               9m11s
knative-serving             domainmapping-webhook-77d7fcdd89-2p75m                   2/2     Running   0               9m10s
knative-serving             net-istio-controller-59cfff6cb6-tbtjz                    2/2     Running   0               9m10s
knative-serving             net-istio-webhook-55c7fbc94d-h668d                       2/2     Running   0               9m9s
knative-serving             webhook-6d7b7f6b54-6n7sc                                 2/2     Running   0               9m9s
kube-system                 coredns-64897985d-cvphm                                  1/1     Running   1 (12m ago)     13m
kube-system                 etcd-minikube                                            1/1     Running   1 (12m ago)     13m
kube-system                 kube-apiserver-minikube                                  1/1     Running   1 (12m ago)     13m
kube-system                 kube-controller-manager-minikube                         1/1     Running   1 (12m ago)     13m
kube-system                 kube-proxy-8hvw4                                         1/1     Running   1 (12m ago)     13m
kube-system                 kube-scheduler-minikube                                  1/1     Running   1 (12m ago)     13m
kube-system                 storage-provisioner                                      1/1     Running   1 (12m ago)     13m
kubeflow-user-example-com   ml-pipeline-ui-artifact-569fc96b97-m92hv                 2/2     Running   0               20s
kubeflow-user-example-com   ml-pipeline-visualizationserver-989cc86c9-qhghz          2/2     Running   0               20s
kubeflow                    admission-webhook-deployment-75d8f74f49-nq7xq            1/1     Running   0               9m29s
kubeflow                    cache-server-94888747d-fbftm                             2/2     Running   0               9m28s
kubeflow                    centraldashboard-5454d95d5-8f8c4                         2/2     Running   0               9m28s
kubeflow                    jupyter-web-app-deployment-694b9f69cc-rm4b6              2/2     Running   0               9m28s
kubeflow                    katib-controller-64877b975b-xlv5l                        1/1     Running   0               9m28s
kubeflow                    katib-db-manager-5f69cfc55d-fvlp9                        1/1     Running   0               9m27s
kubeflow                    katib-mysql-6975d6c6c4-8hbfl                             1/1     Running   0               9m27s
kubeflow                    katib-ui-5cc65f6464-pgn79                                2/2     Running   1 (2m13s ago)   9m27s
kubeflow                    kserve-controller-manager-574f455cd9-4gbw4               2/2     Running   0               9m27s
kubeflow                    kserve-models-web-app-85ccc875dd-4mx6m                   2/2     Running   0               9m26s
kubeflow                    kubeflow-pipelines-profile-controller-6dc4ff7ffd-zpqwp   1/1     Running   0               9m26s
kubeflow                    metacontroller-0                                         1/1     Running   0               9m27s
kubeflow                    metadata-envoy-deployment-b58cd84bf-gf6ws                1/1     Running   0               9m26s
kubeflow                    metadata-grpc-deployment-679b49cc95-kk2fn                2/2     Running   5 (81s ago)     9m26s
kubeflow                    metadata-writer-b89f875db-kd2mk                          2/2     Running   2 (107s ago)    9m26s
kubeflow                    minio-7955cfc9fc-q9dc5                                   2/2     Running   0               9m25s
kubeflow                    ml-pipeline-fd97b696-knj8x                               2/2     Running   0               9m25s
kubeflow                    ml-pipeline-persistenceagent-76dd4f5778-dr5j8            2/2     Running   0               9m25s
kubeflow                    ml-pipeline-scheduledworkflow-5866bf76d7-pq7rp           2/2     Running   0               9m25s
kubeflow                    ml-pipeline-ui-c58ddcd6b-plg84                           2/2     Running   0               9m25s
kubeflow                    ml-pipeline-viewer-crd-67f66b9746-dzw7h                  2/2     Running   0               9m25s
kubeflow                    ml-pipeline-visualizationserver-8656969c7f-v266l         2/2     Running   0               9m24s
kubeflow                    mysql-8456ccf979-sb67g                                   2/2     Running   0               9m24s
kubeflow                    notebook-controller-deployment-579f9cd658-6ffg4          2/2     Running   2 (115s ago)    9m24s
kubeflow                    profiles-deployment-6cc58bc769-s4pj5                     3/3     Running   1 (29s ago)     9m24s
kubeflow                    tensorboard-controller-deployment-787ddd8b77-g7g2m       3/3     Running   1 (3m ago)      9m24s
kubeflow                    tensorboards-web-app-deployment-5586dd9bf8-fkm49         2/2     Running   0               9m23s
kubeflow                    training-operator-55d56885cb-k5fvv                       1/1     Running   0               9m23s
kubeflow                    volumes-web-app-deployment-7c8b56d8d7-7x5q2              2/2     Running   0               9m23s
kubeflow                    workflow-controller-555f64865-gvzxb                      2/2     Running   1 (94s ago)     9m23s

4. 이제 잘 수 있나 했는데 Katib가 안 된다고..^^?

이제 포트포워딩을 해주고

$ kubectl port-forward svc/istio-ingressgateway -n istio-system 8080:80

localhost에 들어갔는데, 또 하나의 문제가 생겼다. 바로 Katib 설치가 안 되는 것. 이것도 docker image 주소를 바꾸면 되지 않을까? 역시 image 버전 문제였다. 바로 upstream으로 받아오는 부분에서 katib 최신 버전으로 pull이 안 돼서 생긴 문제였던 것 같다. 그래서 다음과같이 upstream에 해당하는 부분에서 image를 최신 버전으로 변경해주었다.

5. 진짜 진짜 해결

다시 한 번 포트포워딩을 하고 localhost를 통해 들어가보면 해결이 되어있다.

6. GitHub Issue로 문제 상황 공유

공식 repo issue에 현재 문제 상황을 공유하였다.
내 시간은 못 지켰지만 누군가의 시간을 지켰다면 넘나 뿌듯할 것 같다. ㅎㅎ

https://github.com/kubeflow/manifests/issues/2472

위에서 언급한 문제가 수정된 manifests는 아래의 repo에서 확인할 수 있다.
https://github.com/hwang9u/manifests

마치며

확실히 개발 쪽은 변화가 빨라서 버전 문제에 민감한 것 같다. 특히 MLOps라고 하는 분야는 아직까지 정립되어있다고 볼 수 없는 것 같기도 하다. 나는 데이터사이언티스트인데 이런 부분에서 난관에 부딪혀야 하나 싶기도 했지만 맞닥뜨려야 하나 싶지만, 아직까지 이런 도구들을 활용할 수 있으려면 공부해야 하는 게 현실인 것 같다. 내가 못하는 것에 대해 언제까지고 툴툴댈 수는 없는 노릇임을 다시금 되새기는 날이었다.

profile
황구는 멍멍

0개의 댓글