在最近的一段时间,主要投入到“分布式机器学习平台” 的技术选型和搭建过程,今天对前段时间的工作进行下总结。
这项工作主要的主要出发点有两点,第一是将现有的服务器资源充分利用,达到分布式训练,提高训练速度。第二是将原有基于Spark的计算集群整合到k8s上,统一集群架构,统一使用容器来进行管理。
本篇文章主要记录了第一部分工作完成的过程和相关经验,第二部分的工作可以查看博主的另一篇文章:。

技术选型

K8s是google开源的容器编排系统,在云原生架构中处于Pass层面,能够管理容器的整个生命周期。随着时间的发展,其优势地位逐渐显现,已经有逐渐成为统一容器编排领域的趋势。而且,一开始k8s主要被用于微服务领域,利用k8s来管理容器,而微服务运行在容器中,这样的架构方便服务弹性伸缩,带来了很多好处。现在,k8s越来越被作为一种底层设施,负责支撑无状态应用、有状态应用、大数据应用等多种类型的服务。
在分布式机器学习方面,有很多种方式,包括“数据并行”,“模型并行”等等,Pytorch、Tensorflow等框架其本身提供了分布式训练的能力,但是这种分布式只是在计算层次,我们需要手动构建“多机多卡”等分布式训练环境,保证各个节点之间能够进行通讯,所以,我们还需要“控制、调度”的能力。
Spark、K8s都能够支持GPU的管理,而且提供应用分布式调度的能力。现有的平台架构大多基于k8s,而且在k8s生态中,kubeflow是被很多厂商采用的分布式机器学习套件。

K8s集群搭建

kubeflow是在k8s之上运行的一组服务,对k8s有很强的依赖性。因此,在选择k8s版本时,首先要根据kubeflow的版本要求,选择合适的k8s版本。

Centos 裸机装机笔记

  1. centos 实体机安装的时候,遇见 /dev/root can't find 的问题,其问题原因是,设置的u盘地址错误,引导启动后,没有找到系统的位置,因此报错。
  1. 静态网址配置 https://my.oschina.net/calmsnow/blog/3002952
  2. 国内源配置 Yum换源的坑,你踩了吗? - 知乎 yum更新之前需要先设置 https://blog.csdn.net/wanormi/article/details/82900137
  3. Nvidia 和 Cuda 安装
    参考博客:https://www.techgrow.cn/posts/3a164cac.html 先装cuda,再安装显卡驱动
    yum install "kernel-devel-uname-r == $(uname -r)"
    
  4. 安装docker。
    k8s提供gpu资源的管理和调度,其能力目前还处于实验的状态。对于 NVIDIA GPU 的支持在 v1.6 中加入,对 AMD GPU 的支持则在 v1.9 中通过 设备插件加入。其实现方式主要依赖于各个gpu厂家提供的插件和各厂家对docker容器的支持。对于Navida的显卡,如果我们想要k8s能够调度gpu资源,我们必须在各个节点安装nvidia-docker,并将其设置为默认的容器运行时,详细内容可以参考其github地址。
  5. 集群扩容,在虚拟机使用过程中,如果磁盘不够,使用的方法。 https://blog.csdn.net/sirchenhua/article/details/106493812https://blog.csdn.net/sirchenhua/article/details/106493812

集群搭建笔记

集群搭建中主要参考下面这篇博客: https://juejin.im/post/5e550b3ff265da57570476db

Istio

在微服务架构下,单个服务承载一定的功能,服务与服务之间相互依赖,需要进行通讯。如何控制服务于服务之间的通讯的方式?同时所有的服务构成服务集群,如何将服务集群暴露出来,供用户访问?istio给出了解决方案。
https://istio.io/latest/docs/ops/common-problems/validation/

在Istio中集成了grafana、kiali、promtheus等多种套件,能够很好的监控整个微服务集群。在kubeflow中会使用istio的相关功能,在kubeflow 安装资源清单kfctl_k8s_istio.v1.0.2.yaml 中,使用istio 1.1.3的版本,该版本太低。笔者想采用较高的版本,但是istio的版本和kubeflow的版本适配也是很大的问题,经过采坑和实践后,推荐搭建使用isito 1.4.3的版本配合kfctl_k8s_istio.v1.0.2.yaml

安装步骤

  1. 首先安装isitoctl 的安装包,早期istio提供helm的安装方式,现在,统一到istioctl之中。
 curl -L https://git.io/getLatestIstio | ISTIO_VERSION=0.3.6 sh -
 通过ISTIO_VERSION 可以指定下载安装的istio的版本

istioctl manifest apply \
    --set profile=demo \
    --set values.kiali.enabled=true \
    --set "values.kiali.dashboard.jaegerURL=http://jaeger-query:16686" \
    --set "values.kiali.dashboard.grafanaURL=http://grafana:3000"

Kubeflow

在kubeflow的安装中,可以参考官网指导进行,但是由于国内镜像的限制会有很大的问题。

  1. 安装官网指导文档,进行安装,执行到下面这个步骤,下载kubeflow所有的资源文件。
kfctl build -V -f ${CONFIG_URI}
  1. 进入kustomize 文件夹,修改各资源文件中imagePullPolicy,将以Always的镜像拉取方式修改为IfNotPresent,使k8s能够加载本地镜像文件。
grep 'Always' -rl . | xargs sed -i "s/Always/IfNotPresent/g"
  1. 首先在各节点利用脚本拉取k8s需要的镜像文件。
#!/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"
    "smartliby/api-server:0.2.0,gcr.io/ml-pipeline/api-server:0.2.0"
)

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 ${image_name} > /data/k8s_img/kubeflow/${image_name##*/}.tar
    # 输入
    # microk8s.ctr --namespace k8s.io image import /data/k8s_img/kubeflow/${image_name##*/}.tar
    # 删除Tag
    docker rmi ${img_array[0]}
done

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

  1. 部署istio

  2. istio部署完成后,修改kubeflow的资源文件,注释掉istio有关的安装资源。

坑点

  1. 反复安装istio过程中,如果反复安装出现严验证不通过的问题:
kubectl delete validatingwebhookconfigurations istio-galle
  1. 删除命名空间,状态一直维持在terminating 状态,参考博文: https://hackmd.io/@raccoon/k8s-delete-namespace-stuck-in-terminating
curl -H "Content-Type: application/json" \
    -X PUT \
    --data-binary @temp.json \
    http://127.0.0.1:8080/api/v1/namespaces/<NAMESPACE>/finalize
Logo

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

更多推荐