Kubeflow安装

安装、避坑指南

Posted by LANY on November 10, 2020

Kubeflow是Google推出的基于kubernetes环境下的机器学习组件,通过Kubeflow可以实现对TFJob等资源类型定义,可以像部署应用一样完成在TFJob分布式训练模型的过程。最初的设计是将Kubernetes和Tensorflow结合实现对Tensorflow分布式训练的支持。但是仅仅实现对Tensorflow的支持还是远远不够的,Kubeflow社区又陆续对各种深度学习框架进行支持,例如:MXNet, Caffee, PyTorch等。使得机器学习算法同学只需关心算法实现,而后续的模型训练和服务上线都交给平台来做,解放算法同学使其专做自己擅长的事儿。

目前kubeflow与kubernetes所对应的版本关系如下图:

版本关系对应图

本文基于k8sv1.16来部署kubeflowv1.0

安装kubeflow

安装kfctl脚本

kubeflow release page下载对应kubeflow版本的kfctl脚本

解压安装包并添加到执行目录

tar -xvf kfctl_v1.0-0-g94c35cf_linux.tar.gz
sudo cp kfctl /usr/bin

设置安装环境变量

export BASE_DIR=/data/
export KF_NAME=my-kubeflow
export KF_DIR=${BASE_DIR}/${KF_NAME}
export CONFIG_URI="https://raw.githubusercontent.com/kubeflow/manifests/v1.0-branch/kfdef/kfctl_k8s_istio.v1.0.1.yaml"

部署kubeflow

mkdir -p ${KF_DIR}
cd ${KF_DIR}
kfctl apply -V -f ${CONFIG_URI}
kubectl -n kubeflow get all

输出如下日志即安装成功:

可以通过如下命令查看kubeflow是否部署成功:

kubectl get pods --namespace kubeflow

执行一下命令来进行端口映射访问kubeflow ui:

nohup kubectl port-forward -n istio-system svc/istio-ingressgateway 8088:80 &

闭坑指南

kubeflow大部分pod没有启动成功

检查原因发现由于网络问题,需要访问gcr.io下载镜像,但是由于这个地址因为内外网原因下载不了,所以只能通过自己构建然后保存到阿里云或者dockerhub镜像,可以使用一位博主提供的构建好的镜像,执行下面脚本即可,也可以自己构建,具体构建流程参考

执行一下脚本:

#!/usr/bin/env bash

echo ""
echo "=========================================================="
echo "pull kubeflow  v1.0 images from dockerhub ..."
echo "=========================================================="
echo ""

# registry.cn-hangzhou.aliyuncs.com/smartliby

gcr_imgs=(
    "smartliby/kfserving-controller:0.2.2,gcr.io/kfserving/kfserving-controller:0.2.2"
    "smartliby/api-server:0.2.0,gcr.io/ml-pipeline/api-server:0.2.0"
    "smartliby/kfam:v1.0.0-gf3e09203,gcr.io/kubeflow-images-public/kfam:v1.0.0-gf3e09203"
    "smartliby/ingress-setup:latest,gcr.io/kubeflow-images-public/ingress-setup:latest"
    "smartliby/application:1.0-beta,gcr.io/kubeflow-images-public/kubernetes-sigs/application:1.0-beta"
    "smartliby/centraldashboard:v1.0.0-g3ec0de71,gcr.io/kubeflow-images-public/centraldashboard:v1.0.0-g3ec0de71"
    "smartliby/jupyter-web-app:v1.0.0-g2bd63238,gcr.io/kubeflow-images-public/jupyter-web-app:v1.0.0-g2bd63238"
    "smartliby/katib-controller:v0.8.0,gcr.io/kubeflow-images-public/katib/v1alpha3/katib-controller:v0.8.0"
    "smartliby/katib-db-manager:v0.8.0,gcr.io/kubeflow-images-public/katib/v1alpha3/katib-db-manager:v0.8.0"
    "smartliby/katib-ui:v0.8.0,gcr.io/kubeflow-images-public/katib/v1alpha3/katib-ui:v0.8.0"
    "smartliby/kube-rbac-proxy:v0.4.0,gcr.io/kubebuilder/kube-rbac-proxy:v0.4.0"
    "smartliby/metacontroller:v0.3.0,gcr.io/metacontroller/metacontroller:v0.3.0"
    "smartliby/metadata:v0.1.11,gcr.io/kubeflow-images-public/metadata:v0.1.11"
    "smartliby/envoy:metadata-grpc,gcr.io/ml-pipeline/envoy:metadata-grpc"
    "smartliby/ml_metadata_store_server:v0.21.1,gcr.io/tfx-oss-public/ml_metadata_store_server:v0.21.1"
    "smartliby/metadata-frontend:v0.1.8,gcr.io/kubeflow-images-public/metadata-frontend:v0.1.8"
    "smartliby/visualization-server:0.2.0,gcr.io/ml-pipeline/visualization-server:0.2.0"
    "smartliby/persistenceagent:0.2.0,gcr.io/ml-pipeline/persistenceagent:0.2.0"
    "smartliby/scheduledworkflow:0.2.0,gcr.io/ml-pipeline/scheduledworkflow:0.2.0"
    "smartliby/frontend:0.2.0,gcr.io/ml-pipeline/frontend:0.2.0"
    "smartliby/viewer-crd-controller:0.2.0,gcr.io/ml-pipeline/viewer-crd-controller:0.2.0"
    "smartliby/notebook-controller:v1.0.0-gcd65ce25,gcr.io/kubeflow-images-public/notebook-controller:v1.0.0-gcd65ce25"
    "smartliby/profile-controller:v1.0.0-ge50a8531,gcr.io/kubeflow-images-public/profile-controller:v1.0.0-ge50a8531"
    "smartliby/pytorch-operator:v1.0.0-g047cf0f,gcr.io/kubeflow-images-public/pytorch-operator:v1.0.0-g047cf0f"
    "smartliby/spark-operator:v1beta2-1.0.0-2.4.4,gcr.io/spark-operator/spark-operator:v1beta2-1.0.0-2.4.4"
    "smartliby/spartakus-amd64:v1.1.0,gcr.io/google_containers/spartakus-amd64:v1.1.0"
    "smartliby/tf_operator:v1.0.0-g92389064,gcr.io/kubeflow-images-public/tf_operator:v1.0.0-g92389064"
    "smartliby/admission-webhook:v1.0.0-gaf96e4e3,gcr.io/kubeflow-images-public/admission-webhook:v1.0.0-gaf96e4e3"
    "smartliby/kfam:v1.0.0-gf3e09203,gcr.io/kubeflow-images-public/kfam:v1.0.0-gf3e09203"
)

for img in ${gcr_imgs[@]}
do
    img_array=(${img//,/ })
    # 拉取镜像
    docker pull ${img_array[0]}
    # 添加Tag
    image_name=${img_array[1]}
    image_name=${image_name%@*}
    docker tag ${img_array[0]} ${image_name}
    # 输出
    docker save -o /data/k8s_img/kubeflow/${image_name##*/}.tar ${image_name}
    # 删除Tag
    docker rmi ${img_array[0]} ${image_name}
done

echo ""
echo "=========================================================="
echo "pull kubeflow  v1.0 images from dockerhub finished."
echo "=========================================================="
echo ""

knative-serving服务没有启动成功

原因是因为knative镜像使用的是sha256,没有使用具体版本号,而镜像下载到阿里云之后sha256就变更了,所以无法下载,只能通过修改配置文件更改下载地址了。

vim /data/my-kubeflow/kustomize/knative-install/base/deployment.yaml

镜像地址如下格式:

gcr.io/knative-releases/knative.dev/serving/cmd/activator@sha256:8e606671215cc029683e8cd633ec5de9eabeaa6e9a4392ff289883304be1f418
gcr.io/knative-releases/knative.dev/serving/cmd/autoscaler-hpa@sha256:5e0fadf574e66fb1c893806b5c5e5f19139cc476ebf1dff9860789fe4ac5f545
gcr.io/knative-releases/knative.dev/serving/cmd/autoscaler@sha256:ef1f01b5fb3886d4c488a219687aac72d28e72f808691132f658259e4e02bb27
gcr.io/knative-releases/knative.dev/serving/cmd/networking/istio@sha256:727a623ccb17676fae8058cb1691207a9658a8d71bc7603d701e23b1a6037e6c
gcr.io/knative-releases/knative.dev/serving/cmd/webhook@sha256:1ef3328282f31704b5802c1136bd117e8598fd9f437df8209ca87366c5ce9fcb
gcr.io/knative-releases/knative.dev/serving/cmd/controller@sha256:5ca13e5b3ce5e2819c4567b75c0984650a57272ece44bc1dabf930f9fe1e19a1

修改后:

smartliby/activator:latest
smartliby/autoscaler-hpa:latest
smartliby/autoscaler:latest
smartliby/istio:latest
smartliby/webhook:latest
smartliby/controller:latest

最后执行kfctl apply -V -f ${CONFIG_URI}重新安装即可。

镜像下载失败

重新安装之后发现仍然有一些pod出现pullEmgError的错误。

有两种原因:

  1. 镜像无法下载

解决办法:把无法下载的镜像名称添加到上述脚本中重新下载。

  1. 镜像拉取策略导致每次都重新下载问题

通过kubectl edit pod <pod_name> -n kubeflow编辑镜像拉取策略为IfNotPresent

由于有些pod是由deployment控制的,通过上述命令修改可能会出现invalid错误。所以可以直接修改对应服务的deployment中的镜像拉取策略为IfNotPresent

数据库相关pod一直处于pending状态

通过kubectl describe <pod_name> -n kubeflow查看event发现该pod在挂载pvc卷的时候出现错误。

随后通过kubectl get pvc -n kubeflow发现所有pvc卷处于pending状态

通过kubectl describe pvc <pvc_name> -n kubeflow随机查看一个pvc的event发现是没有发现可用的pv。

通过kubectl get pv发现目前k8s集群确实不存在pv。

创建pv

我们通过搭建nfs server后来创建pv。

通过lstio的ingressgateway访问kubeflow服务

首先通过以下命令来查看目前运行中的k8s集群是否支持external load balancer

kubectl get svc istio-ingressgateway -n istio-system

如果发现external-ip<none>,那么代表当前k8s集群环境不支持ingress gateway的负载均衡,所以我们可以通过服务的node port来访问路由。 具体操作详见lstio官网

kfctl_k8s_istio.v1.0.1.yaml下载不下来

可以在mainfests页面下载,然后上传到服务器,并修改环境变量CONFIG_URI参数为该yaml文件所在的本地路径。