Kubeflow是Google推出的基于kubernetes环境下的机器学习组件,通过Kubeflow可以实现对TFJob等资源类型定义,可以像部署应用一样完成在TFJob分布式训练模型的过程。最初的设计是将Kubernetes和Tensorflow结合实现对Tensorflow分布式训练的支持。但是仅仅实现对Tensorflow的支持还是远远不够的,Kubeflow社区又陆续对各种深度学习框架进行支持,例如:MXNet, Caffee, PyTorch等。使得机器学习算法同学只需关心算法实现,而后续的模型训练和服务上线都交给平台来做,解放算法同学使其专做自己擅长的事儿。
目前kubeflow与kubernetes所对应的版本关系如下图:
本文基于k8s
的v1.16
来部署kubeflow
的v1.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
的错误。
有两种原因:
- 镜像无法下载
解决办法:把无法下载的镜像名称添加到上述脚本中重新下载。
- 镜像拉取策略导致每次都重新下载问题
通过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文件所在的本地路径。