历经千辛万苦,终于把kubeflow安装成功了,不把安装过程记录下来都对不起自己!

kubeflow与kubernetes版本对应

要在现有 kubernetes 集群的基础上安装 kubeflow,那么首先要确定是的 kubeflow 的版本!

版本查看地址:

Overview of Deployment on an Existing Kubernetes Cluster | Kubeflow

很显然,只支持 k8s 1.11 之后的版本,标有 compatible 的是经历过完整测试的版本。

写这篇文章的时候,我的 kubernetes 集群版本是 1.20,kubeflow 也选了 1.2,虽然这个版本没有在 kubernetes 1.20 上经历过完整测试,但也没办法,毕竟集群版本不可能更改。

常规安装

1)下载必要的文件

需要两个东西:kfctl 以及 kfctl_k8s_istio.v1.2.0.yaml

kfctl下载地址

Releases · kubeflow/kfctl · GitHub

yaml 下载地址https://github.com/kubeflow/manifests/blob/v1.2-branch/kfdef/kfctl_k8s_istio.v1.2.0.yaml

2)解压 kfctl 

tar -xvf kfctl_v1.2.0-0-gbc038f9_linux.tar.gz

3)将 kfctl 移到 /usr/bin 目录中,这样就不用配置环境变量了

mv kfctl /usr/bin

4)查看 kfctl 

5)配置环境变量 

vi /etc/profile

增加如下三个配置

export KF_NAME=<自己起一个Kubeflow应用名称> 
export BASE_DIR=<自己设一个根目录>
export KF_DIR=${BASE_DIR}/${KF_NAME}  # kubeflow应用存放路径

至于官方教程中的 CONFIG_URI,我就不设了,因为我是把 yaml 下载到本地直接执行的。

 6)刷新环境变量

source /etc/profile

7)创建${KF_DIR}目录

mkdir -p ${KF_DIR}

8)执行部署 kubeflow

将 kfctl_k8s_istio.v1.2.0.yaml 放到 ${KF_DIR} 目录中,进入此目录

注意:下面这一步正常来讲在国内是不会成功的,所以先别执行,看看就好!

然后执行 yaml 进行部署

kfctl apply -V -f kfctl_k8s_istio.v1.2.0.yaml

9)查看结果

会自动创建 kubeflow 命名空间,所有资源都在此命名空间下。

kubectl -n kubeflow get all

到了这一步,安装过程就结束了。但是很遗憾,在国内,正常来讲是不可能成功的,很多镜像都是谷歌的,没法这么顺利地下载成功。

自定义安装

kubeflow 1.2.0 版本是没有经过官方完全测试的,所以安装过程中可能会遇到意想不到的问题,需要改很多地方,甚至要修改源码!

注意:常规安装中的第1到第7个步骤,还是需要的,在此基础上进行自定义!

镜像下载

这一步最为麻烦,有五六十个镜像需要下载,其中四十多个是谷歌gcr.io的镜像,这在国内正常是没法下载的。所以需要自己想办法手动下载下来。

关于下载谷歌gcr.io镜像,需要翻墙,如果不能翻墙的话,可以借助于阿里云的容器镜像服务,

我写了一篇教程:通过阿里云容器镜像服务下载谷歌gcr.io镜像_修理男爵的博客-CSDN博客

python:3.7
mysql:8.0.3
metacontroller/metacontroller:v0.3.0
mpioperator/mpi-operator:v0.2.3
kubeflow/mxnet-operator:v1.0.0-20200625
argoproj/workflow-controller:v2.3.0
docker.io/seldonio/seldon-core-operator:1.4.0
quay.io/jetstack/cert-manager-cainjector:v0.11.0
quay.io/jetstack/cert-manager-webhook:v0.11.0
quay.io/jetstack/cert-manager-controller:v0.11.0
gcr.io/kubebuilder/kube-rbac-proxy:v0.4.0
gcr.io/kfserving/kfserving-controller:v0.4.1
gcr.io/tfx-oss-public/ml_metadata_store_server:v0.21.1
gcr.io/google_containers/spartakus-amd64:v1.1.0
gcr.io/spark-operator/spark-operator:v1beta2-1.1.0-2.4.5
gcr.io/istio-release/proxy_init:release-1.3-latest-daily
gcr.io/istio-release/citadel:release-1.3-latest-daily
gcr.io/istio-release/proxyv2:release-1.3-latest-daily
gcr.io/istio-release/node-agent-k8s:release-1.3-latest-daily
gcr.io/istio-release/pilot:release-1.3-latest-daily
gcr.io/istio-release/mixer:release-1.3-latest-daily
gcr.io/istio-release/galley:release-1.3-latest-daily
gcr.io/istio-release/sidecar_injector:release-1.3-latest-daily
gcr.io/ml-pipeline/api-server:1.0.4
gcr.io/ml-pipeline/cache-deployer:1.0.4
gcr.io/ml-pipeline/viewer-crd-controller:1.0.4
gcr.io/ml-pipeline/envoy:metadata-grpc
gcr.io/ml-pipeline/persistenceagent:1.0.4
gcr.io/ml-pipeline/scheduledworkflow:1.0.4
gcr.io/ml-pipeline/frontend:1.0.4
gcr.io/ml-pipeline/metadata-writer:1.0.4
gcr.io/ml-pipeline/visualization-server:1.0.4
gcr.io/ml-pipeline/cache-server:1.0.4
gcr.io/ml-pipeline/minio:RELEASE.2019-08-14T20-37-41Z-license-compliance
gcr.io/ml-pipeline/mysql:5.6
gcr.io/kubeflow-images-public/notebook-controller:vmaster-g6eb007d0
gcr.io/kubeflow-images-public/pytorch-operator:vmaster-g518f9c76
gcr.io/kubeflow-images-public/tf_operator:vmaster-gda226016
gcr.io/kubeflow-images-public/admission-webhook:v20190520-v0-139-gcee39dbc-dirty-0d8f4c
gcr.io/kubeflow-images-public/profile-controller:vmaster-ga49f658f
gcr.io/kubeflow-images-public/kfam:vmaster-g9f3bfd00
gcr.io/kubeflow-images-public/ingress-setup:latest
gcr.io/kubeflow-images-public/centraldashboard:vmaster-g8097cfeb
gcr.io/kubeflow-images-public/jupyter-web-app:vmaster-g845af298
gcr.io/kubeflow-images-public/admission-webhook:v20190520-v0-139-gcee39dbc-dirty-0d8f4c
gcr.io/knative-releases/knative.dev/serving/cmd/activator@sha256:ffa3d72ee6c2eeb2357999248191a643405288061b7080381f22875cb703e929
gcr.io/knative-releases/knative.dev/serving/cmd/autoscaler@sha256:f89fd23889c3e0ca3d8e42c9b189dc2f93aa5b3a91c64e8aab75e952a210eeb3
gcr.io/knative-releases/knative.dev/serving/cmd/controller@sha256:b86ac8ecc6b2688a0e0b9cb68298220a752125d0a048b8edf2cf42403224393c
gcr.io/knative-releases/knative.dev/serving/cmd/webhook@sha256:7e6df0fda229a13219bbc90ff72a10434a0c64cd7fe13dc534b914247d1087f4
gcr.io/knative-releases/knative.dev/net-istio/cmd/webhook@sha256:e6b142c0f82e0e0b8cb670c11eb4eef6ded827f98761bbf4bea7bdb777b80092
gcr.io/knative-releases/knative.dev/net-istio/cmd/controller@sha256:75c7918ca887622e7242ec1965f87036db1dc462464810b72735a8e64111f6f7

这里列举了50多个1.2.0 kubeflow 中需要用到的镜像,需要手动下载下来,最好放到自己的镜像仓库中,比如aihub。因为如果不改镜像名的话,镜像名还是谷歌gcr.io的,当创建pod的时候,如果节点上还没有镜像,会去拉取镜像,那显然拉取不到。

当然,还不止这些个镜像,有些pod在创建时,可能还有下载其他的镜像,不过都是些开了外网就能下载到的,并不是gcr.io的镜像。如果服务器没开外网,那还是要自己手动下载。

自定义manifests

默认 manifests 是在 kfctl_k8s_istio.v1.2.0.yaml 的最后引入的

需要创建的资源对象,都是在 manifests 中定义的。所以说,既然自己下载了镜像,然后放到自己的镜像仓库中,那么镜像名显然跟之前不一样了,所以需要下载 manifests 源码,然后修改里面的代码,比如各种镜像名,还有镜像拉取策略等,然后再重新打包,放到自己的 ftp 服务器上,然后在 kfctl_k8s_istio.v1.2.0.yaml 中引入自己打的 manifests 包!

manifests 源码下载地址:https://github.com/kubeflow/manifests/tree/v1.2.0

1)镜像名替换

首先就是镜像名称的替换。

这一步真的很烦,四五十个镜像需要替换。替换成自己的镜像仓库中的镜像名:

记得不带上 tag 也搜下,有几个地方需要不带 tag 才能搜到,例如:

2)镜像拉取策略替换

默认都是每次都替换的:imagePullPolicy: Always

需要改成当镜像不存在时才替换:imagePullPolicy: IfNotPresent

3)修改mpioperator/mpi-operator:latest镜像

这个是kubeflow安装过程中最最坑的地方之一!

如果直接部署,会发现 mpi-operator 容器永远无法正常运行起来!结果是因为镜像是错的!

所以,需要修改镜像。将代码中 mpioperator/mpi-operator:latest 镜像修改为 mpioperator/mpi-operator:v0.2.3。

4)修改tag为dummy的镜像

部署的时候,会用到9个tag为dummy的镜像:

gcr.io/ml-pipeline/cache-deployer:dummy
gcr.io/ml-pipeline/metadata-writer:dummy
gcr.io/ml-pipeline/api-server:dummy
gcr.io/ml-pipeline/persistenceagent:dummy
gcr.io/ml-pipeline/scheduledworkflow:dummy
gcr.io/ml-pipeline/frontend:dummy
gcr.io/ml-pipeline/cache-server:dummy
gcr.io/ml-pipeline/viewer-crd-controller:dummy
gcr.io/ml-pipeline/visualization-server:dummy

但是特别坑的是:这几个镜像有压根就不存在!不管是通过阿里云容器镜像服务,还是翻墙,发现都下载不到,因为根本就没有这几个镜像,非常得坑。

然后我发现,部署的时候还会用到几个相似的镜像:

gcr.io/ml-pipeline/cache-deployer:1.0.4
gcr.io/ml-pipeline/metadata-writer:1.0.4
gcr.io/ml-pipeline/api-server:1.0.4
gcr.io/ml-pipeline/persistenceagent:1.0.4
gcr.io/ml-pipeline/scheduledworkflow:1.0.4
gcr.io/ml-pipeline/frontend:1.0.4
gcr.io/ml-pipeline/cache-server:1.0.4
gcr.io/ml-pipeline/viewer-crd-controller:1.0.4
gcr.io/ml-pipeline/visualization-server:1.0.4

所以我试着把 dummy 改成 1.0.4,然后重新部署,发现可行!

5)修改proxy_init

有一个镜像很特殊:gcr.io/istio-release/proxy_init:release-1.3-latest-daily 

有很多个容器,在创建之前,有一个 initContaniers 的操作,这个 init 过程就会用到 proxy_init 镜像,但是在代码中,直接根据名字压根搜不到这个镜像,后来我发现,写法不相同:

{{- if contains "/" .Values.global.proxy_init.image }}
    image: "{{ .Values.global.proxy_init.image }}"
{{- else }}
    image: "{{ .Values.global.hub }}/{{ .Values.global.proxy_init.image }}:{{ .Values.global.tag }}"

这个镜像在代码中是这么引用到的。所以根据 proxy_init.image 搜索,在搜到的结果中,将如下的代码全都改成自己的proxy_init镜像名:

"{{ .Values.global.proxy_init.image }}" 
"{{ .Values.global.hub }}/{{ .Values.global.proxy_init.image }}:{{ .Values.global.tag }}"

6)存储不够的话适当调整storage大小

storage: 10Gi
storage: 20Gi

这是创建pvc时用到的,需要有相应pv资源才能创建pvc。如果存储比较小,pv资源不足,就调小storage的值。

7)重新打包

使用工具 7z 将 manifests-1.2.0 工程打包为 manifests-1.2.0.tar.gz,或者放到 linux 服务器上去打包也行。

8)放到自己的 ftp 服务器上

9)修改yaml,引入自己的 manifests 包

创建PV

几个 Mysql 相关的容器会用到 PVC,不创建的话会报错。容器会一直处于 Pending 状态。

PVC 在执行部署时会自动创建,但是前提是要有一个 PV,所以现在要做的工作是创建一个 PV !

但是要创建 PV,最好有个 NFS(网络存储),所以得提前准备好 NFS 服务器!

不过我为了省事起见,用的是本地存储:

首先在 /etc/kubeflow/data 目录下创建4个目录:pv1, pv2, pv3, pv4;

然后创建 pv.yaml,之后运行此 yaml。

注意:这里  storage 我填的 25Gi,因为默认创建 pvc 的 yaml 中,storage 是 20Gi 或者 10Gi,如果这边想设得小一点,需要在 manifents 源码中将 20Gi 和 10Gi 统一替换得小一点再打包!我自己改成了 2Gi。总之这边设的要比 manifents 源码中的要大点,不然 pvc 是没法创建的!

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-mysql
spec:
  capacity:
    storage: 25Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/etc/kubeflow/data/pv1"

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-katib-mysql
spec:
  capacity:
    storage: 25Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/etc/kubeflow/data/pv2"

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-minio
spec:
  capacity:
    storage: 25Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/etc/kubeflow/data/pv3"

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-metadata-db
spec:
  capacity:
    storage: 25Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/etc/kubeflow/data/pv4"

查看创建出来的 PV :

proxyv2镜像

gcr.io/istio-release/proxyv2:release-1.3-latest-daily 这个镜像很奇怪,在 manifests 源码中找不到用这个镜像的地方,所以没办法改源码。

但是从部署的结果来看,很多个容器用到了这个镜像,所以没办法,我只能下载下来放到自己的镜像仓库,然后手动拉取到服务器上,然后打 tag 为 gcr.io/istio-release/proxyv2:release-1.3-latest-daily。

注意:需要所有可能分配到Pod的机器上都有这个镜像!

可能遇到的问题

我遇到了一个问题,iptables相关的,导致初始化容器启动失败,所有涉及使用proxy_init镜像做初始化的容器,都会受到影响,所以需要自己解决iptables的问题。

当然,这个问题不一定会遇到。

执行部署

准备工作都做好之后,可以开始进行部署了!

kfctl apply -V -f kfctl_k8s_istio.v1.2.0.yaml

执行完毕后,会生成kustomize目录:

预期效果

kubeflow涉及4个namespace:

cert-manager
istio-system
knative-serving
kubeflow

需要确保这四个命名空间下的资源都正常启动。主要看pod就行:

namespace: cert-manager

namespace: istio-system

namespace: knative-serving

namespace: kubeflow

当然,可能还有各种各样预想不到的问题,需要自己根据容器的状态与报错,自己解决。

页面访问

首先通过命令查询端口:

kubectl get svc/istio-ingressgateway -n istio-system

然后通过url在浏览器上访问:http://<ip>:31380/

页面我暂时用不到,就没有过多研究。 

异常处理方法

显然,需要安装的东西特别多,总会出现点情况。比如我一开始镜像替换得不够完全,导致很多容器报错。当然,还有其他原因,比如没有创建 pv,pvc 等。

这个时候就要将这些容器先清理掉(需要删除deployment或者statefulsets这种,只删除 pod 没用,因为还会自动创建出来)

举个例子:
kubectl delete deploy cache-deployer-deployment -n kubeflow              
kubectl delete deploy cache-server -n kubeflow                            
kubectl delete deploy metadata-writer -n kubeflow   

然后删掉manifests包的缓存(.cache目录),以及生成的kustomize目录

然后修改 manifests 源码,重新打包并上传,然后再次执行部署:

kfctl apply -V -f kfctl_k8s_istio.v1.2.0.yaml

创建pytorch训练任务测试

这个直接参考github上的教程吧:https://github.com/kubeflow/pytorch-operator

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐