Ubuntu Serveräžã®MicroK8sã«KubeflowãšMLflowãã€ã³ã¹ããŒã«ããæ¹æ³
ã¯ããã«
Kubeflow 㯠Google ã瀟å ã§äœ¿ã£ãŠãã MLOps åºç€ã OSS ãšããŠå ¬éãããã®ã§ãKubernetes äžã§åäœãããããšãåæã«éçºãããŠããããŸããMLflow 㯠Databricks ã OSS ã§éçºããŠããæ©æ¢°åŠç¿ã¢ãã«éçºã®å®éšç®¡çããŒã«ã§ãããMLflow ã¯ãµãŒããŒãç«ãŠãã«åäœãããããšãã§ããããMinIO(OSS ã® S3 äºæãªããžã§ã¯ãã¹ãã¬ãŒãž)ãšé£æºãããããšã§ãå®éšçµæãããŒã ã§å ±æããããšãã§ããããããã®ããŒã«ãçµã¿åããããšãç¡æã§èªåã®ãµãŒããŒäžã« MLOps åºç€ãæ§ç¯ããããšãã§ããã
ãã®èšäºã§ã¯ Canonical 瀟ã®ãã¥ãŒããªã¢ã«ã«åŸããMicrok8s äžã« Kubeflow ãš MLflow ã®ç°å¢æ§ç¯ãè¡ãããã®èšäºã®å 容ã¯ããŒã«ã«ãããã¯ãŒã¯äžã§å®éšçã«åäœãããããšãæ³å®ããŠããããµãŒããŒã«ã°ããŒãã« IP ãå²ãåœãŠãŠåäœãããããšã¯åæãšããŠããªãããã®ç¹ã¯æ³šæããŠã»ããã
Kubeflow ã®ã€ã³ã¹ããŒã«
ãã®ç« ã§ã¯ã以äžã®èšäºã«åŸã Kubeflow ãã€ã³ã¹ããŒã«ãè¡ããèšäºå·çæç¹ã® Kubeflow ã®ææ°ããŒãžã§ã³ã¯ 1.7 ã§ããã
ã¯ããã«ãmicrok8s ãã€ã³ã¹ããŒã«ããã
$ sudo snap install microk8s --classic --channel=1.25/stable
$ sudo snap alias microk8s.kubectl kubectl
Kubeflow 1.7 㯠k8s version 1.24/1.25 äžã§ã®åäœããµããŒãããŠãã[1]ããã®ãããä»å㯠microk8s 1.25 ãã€ã³ã¹ããŒã«ããã
次ã«ãmicrok8s ã® addons ãæå¹åããã
$ microk8s enable dns storage hostpath-storage ingress metallb:10.64.140.43-10.64.140.49
$ microk8s enable gpu dashboard
gpu 㯠microk8s äžã®ã³ã³ããã GPU ãèªèã§ããããã«ããããã® addon ã§ãããdashboard 㯠microk8s ã®éçšç£èŠçšã® addon ã§ããã
以äžã®ã³ãã³ãã§ dashboard ã«ã¢ã¯ã»ã¹ã§ããã
$ microk8s dashboard-proxy
ãã®æãchrome ã«ããã®æ¥ç¶ã¯ãã©ã€ãã·ãŒãä¿è·ãããŸããããšè¡šç€ºããããšãããããã®ãšã©ãŒã¯thisisunsafeãšæã€ãšè§£æ±ºã§ãã[2]ã

次㫠juju ãã€ã³ã¹ããŒã«ãããjuju 㯠canonical ãéçºããŠãããããã€èªååããŒã«ã§ãããk8s ããããªã¯ã¯ã©ãŠãäžã«æ§ã ãªãœãããŠã§ã¢ãç°¡åã«ã€ã³ã¹ããŒã«ã§ãã[3]ã
sudo snap install juju --classic --channel=2.9/stable
juju v3 以éã§ bootstrap ã§ microk8s ãéžæã§ããªããªã£ãããã®ãã 2.9 ãéžæããã
以äžãã³ãã³ãã§ MicroK8s äžã« Kubeflow ãã€ã³ã¹ããŒã«ããããšã宣èšã§ããã
juju bootstrap microk8s
juju add-model kubeflow
å®éã«ãããã€ããåã«ãsysctl.conf ã®èšå®ã以äžã®ããã«æžãæããã
$ cat /etc/sysctl.conf
fs.inotify.max_user_instances=1280
fs.inotify.max_user_watches=655360
ãããããªããš Linux ã®ç£èŠãã¡ã€ã«å¯Ÿè±¡ã®äžéã«éãã³ã³ãããç«ã¡äžãããªããªã[4]ã
å®éã«ãããã€ããã
$ juju deploy kubeflow --trust
kubectl get po -n kubeflowã§ pods ã®ã¹ããŒã¿ã¹ã確èªããistio é¢é£ã§ãšã©ãŒã«ãªã£ãŠããå Žåã以äžã®ã³ãã³ãã§è§£æ±ºããå Žåãããã
$ juju run --unit istio-pilot/0 -- "export JUJU_DISPATCH_PATH=hooks/config-changed; ./dispatch"
æåŸã«ãèªèšŒã®èšå®ãè¡ãã
$ juju config dex-auth public-url=http://10.64.140.43.nip.io
$ juju config oidc-gatekeeper public-url=http://10.64.140.43.nip.io
$ juju config dex-auth static-username=admin
$ juju config dex-auth static-password=admin
dex 㯠k8s äžã§èªèšŒãå®çŸããæ©èœã§ãããpublic-url ã§ã¢ã¯ã»ã¹ãããã¡ã€ã³ãæå®ããŠãããããã¯ããã®èšäºã®æåŸã§ ingress ãèšå®ããéã«æžãæããããŸããdex-auth ã§ãŠãŒã¶ãŒåãšãã¹ã¯ãŒããèšå®ãããadmin 㯠Kubeflow ãã jupyter notebook ã® pods ãç«ãŠãæã® namespace ãšããŠçšããããã
ããã§ Kubeflow ã®æ§ç¯ã¯å®äºã§ãããssh -D 9999 <server>ã§ãµãŒããŒã« ssh ããç¶æ
ã§ããã©ãŠã¶ã§ socks ãããã·ãšã㊠127.0.0.1:9999 ãèšå®ããhttp://10.64.140.43.nip.ioã«ã¢ã¯ã»ã¹ããã° Kubeflow ãæ±ããã

MLflow ã®ã€ã³ã¹ããŒã«
ãã®ç« ã§ã¯ã以äžã®èšäºã« MLflow ã®ã€ã³ã¹ããŒã«ãè¡ãã
以äžã®ã³ãã³ãã§ãMLflow ãã€ã³ã¹ããŒã«ã§ããã
$ juju deploy mlflow-server
$ juju deploy charmed-osm-mariadb-k8s mlflow-db
ããã§ãjuju statusã§ mlflow-server ã wait ç¶æ
ã«ãªãã®ãåŸ
ã€ããã®åŸã以äžã³ãã³ãã§ mlflow ã« kubeflow ã®ããŒã¿ããŒã¹çãé¢é£ä»ããã
$ juju relate minio mlflow-server
$ juju relate istio-pilot mlflow-server
$ juju relate mlflow-db mlflow-server
$ juju relate mlflow-server admission-webhook
Kubeflow ãšåæ§ã« socks ãããã·ãèšå®ããŠãhttp://10.64.140.43.nip.io/mlflow/ã«ã¢ã¯ã»ã¹ããã° mlflow ã«ã¢ã¯ã»ã¹ã§ããã

MinIO ã®èšå®
Charmed Kubeflow ã«ã¯ MinIO ãå«ãŸããŠãããMinIO ã® WebUI ã®ç®¡çç»é¢ã«ãã¢ã¯ã»ã¹ã§ããããã«ããã
以äžã³ãã³ãã§ãã¹ã¯ãŒããèšå®ããã
juju config minio secret-key=<password>
ãã¹ã¯ãŒã㯠8 æå以äžã§ããå¿ èŠããããMinIO ã®ç®¡çç»é¢ã«ã¯ Ingress ãèšå®ãããšã¢ã¯ã»ã¹ã§ããããã«ãªãã
ã¢ã³ã€ã³ã¹ããŒã«æ¹æ³
äžèšã®æé ã§å€±æããå Žåã¯ã以äžã®æé ã«åŸã£ãŠã¢ã³ã€ã³ã¹ããŒã«ãå¯èœã§ããã
juju destroy-model kubeflow --yes --destroy-storage --force
juju destroy-controller microk8s-localhost
ãŸããmicrok8s ããªã»ãããããå Žåã¯ãmicrok8s resetã䜿ããã
Ingress ã®èšå®
MicroK8s 㯠Ingress ããµããŒãããŠãã[5]ããã®ãã以äžã®ããã«ããŠãIngress ãäœæããã°ãLAN å ã®å¥ã®ããœã³ã³ãã Kubeflow ã MinIO ã«ã¢ã¯ã»ã¹å¯èœã§ããã
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubeflow-ingress
namespace: kubeflow
spec:
rules:
- host: "192.168.0.5.nip.io"
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: istio-ingressgateway-workload
port:
number: 80
- host: "minio.192.168.0.5.nip.io"
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: minio
port:
number: 9001
kubectl apply -f kubeflow-ingress.yamlã§ Ingress ãæå¹åã§ããããã®åŸã以äžã®èšå®ãè¡ãã
$ juju config dex-auth public-url=http://<server ip>.nip.io
$ juju config oidc-gatekeeper public-url=http://<server ip>.nip.io
ããã§ãLAN å
ããhttp://<server ip>.nip.ioã§ Kubeflow ã«ã¢ã¯ã»ã¹å¯èœãšãªããããã«ãhttp://minio.<server ip>.nip.ioã§ MinIO ã«ã¢ã¯ã»ã¹å¯èœã§ããã
MinIO ã®ç»é¢ã¯ä»¥äžã®ããã«ãªãã

ãããã«
MicroK8s äžã« Kubeflow ãš MLflow ã®ç°å¢æ§ç¯ãè¡ã£ããCanonical 瀟ã®ãšã³ã·ã¹ãã ã䜿ãã°ç°¡åã«æ¬æ Œç㪠Kubeflow ç°å¢ãäœæã§ããããšãããã£ããMicroK8s ã¯è€æ°ããŒãã«ããããšãå¯èœ[6]ã§ãããNVIDIA DGX ã«ã€ã³ã¹ããŒã«ããããšãå¯èœ[7]ã§ããããããã®èšäºã§ç€ºããã€ã³ã¹ããŒã«æ¹æ³ã¯ãã³ãã£ãŒäŒæ¥ã倧åŠç 究宀ã®ãªã³ãã¬æ©æ¢°åŠç¿ç°å¢ããããŸã§ã¯ã¹ã±ãŒã«ãããšæãã
ãŸããæè¿ã® Canonical 瀟ã¯ããŒã¿ã»ã³ã¿ãŒããããªãã¯ã¯ã©ãŠãã®ãããªæ©èœãæããã OSS ãç©æ¥µçã«éçºããŠãããæ¬æ Œçãªç°å¢ãšããŠãMAAS ãš Charmed OpenStack ãš Charmed Kubernetes ãçµã¿åãããŠåºç€ãäœã£ãäžã«ãKubeflow ãªã©ã® OSS ããããã€ããããšãå¯èœã§ãããAI ãçºå±ãäžè¬ã®äŒæ¥ã䜿ãããŒã¿éãèšç®ãªãœãŒã¹ãä»ã®äœåã«ãèšãäžãã£ãæãã¯ã©ãŠãäžã®ã³ã¹ãããããéšåããªã³ãã¬ååž°ãããŠãããšã«ãªã£ããããããã䜿ãããšã«ãªããšæãã
Kubeflow ã MLflow ã®äœ¿ãæ¹ã«ã€ããŠã¯ãŸã ããã£ãŠããªãéšåãå€ãããããã¯äœ¿ãããªããããã«ãªãããã
é¢é£èšäº
远èš
Nvidia Driver ãã¢ããããŒããããCan't run container using nvidia-docker - libnvidia-ml.so.1ãšãããšã©ãŒãåºãŠå£ããŠããŸã£ãã
å šãŠã®ã³ã³ãããåé€ã snap remove microk8s ãå®è¡ã㊠microk8s ãåé€ããŠãªã»ããããŠãããäžèšã®ã€ã³ã¹ããŒã«ãåå®è¡ããã解決ãããçµå±åå ã¯ããããããªãã£ããmicrok8s ã® gpu addon ã®ããã¥ã¡ã³ã[8]ãåèã« nvidia-container ã®èšå®ãããã°æ²»ã£ãã®ãããããªããæ¬¡ãšã©ãŒã«ãªã£ãããã®ããã¥ã¡ã³ãã詊ããŠã¿ãã
Discussion