1 参考
- Github地址:https://github.com/Microsoft/pai
- OpenPAI官方安装文档:https://openpai.readthedocs.io/zh_CN/latest/manual/cluster-user/quick-start.html
- kubespray: 安装一个适用于生成环境的k8s集群, https://github.com/kubernetes-sigs/kubespray
- installkubectl: https://www.kubernetes.org.cn/installkubectl
- hyperhube(多合一工具):https://kubernetes.feisky.xyz/concepts/components/hyperkube
- kubernetes: https://github.com/kubernetes/kubernetes
- openpai开发接口:https://developer.box.com/reference/get-groups-id/
- OpenPAI restful api: https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/microsoft/pai/master/src/rest-server/docs/swagger.yaml
2 OpenPAI简介
微软开发的一套针对机器学习的资源调度系统,通常有用户端和管理员端两个入口。管理员端主要用于管理OpenPAI集群,客户端主要提供给用户提交任务。
OpenPAI支持两种调度器,Kubernets default scheduler以及hivedscheduler。hivedscheduler是OpenPAI的默认调度器,它支持虚拟集群划分,拓扑感知的资源保证、以及性能优化的 Gang Scheduling,这些都是 k8s default scheduler 不支持的。对于CPU worker或NVIDIA GPU worker,可以使用k8s default scheduler或hivedscheduler。
3 安装
本文在Ubuntu20.04换机上安装,使用OpenPAI官方的脚本未安装成功,因此尝试先直接使用kubespray安装k8s集群,然后在使用PAI的脚本安装PAI服务。
3.1 主机信息:
- node1:172.18.18.207
- node2:172.18.18.208
- node3:172.18.18.209
- node4:172.18.18.210
- node5:172.18.18.206
3.2 准备工作
- 每台主机安装Nvidia Driver、Docker、Docker-runtime、Anaconda。直接使用ansible playbook安装。
- 其它基本准备命令
sed -i 's/^#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config
systemctl restart sshd
ansible gpu -m shell -a "mkfs.ext4 /dev/sda"
ansible gpu -m shell -a "echo '/dev/sda /data ext4 defaults 0 0' >> /etc/fstab"
ansible gpu -m shell -a "init 6"
ansible gpu -m shell -a "systemctl stop ufw"
ansible gpu -m shell -a "systemctl disable ufw"
ansible gpu -m shell -a "install nfs-common -y"
ansible gpu -m shell -a "apt update"
- docker 代理设置
配置docker容器内代理:在docker客户端配置代理,这个代理在容器内部使用。https://docs.dochttps://docs.docker.com/network/proxy/ker.com/network/proxy/
配置dockerd代理【下载镜像时需要在此配置代理】:https://www.serverlab.ca/tutorials/containers/docker/how-to-set-the-proxy-for-docker-on-ubuntu/。
systemctl daemon-reload
systemctl restart docker
- privoxy配置代理,主要用于将http请求转发到配置的socks5的隧道上。
3.3 使用kubespray安装k8s
【采坑】:因为版本原因,本文修改group_vars/k8s_cluster/k8s-cluster.yml中kube_version为v1.20.9,而不是1.21.3。kuberspray暂时不支持1.21.3的配置文件格式,所以将k8s的版本降级了。
安装kubespray官方文档执行下面操作:
# Install dependencies from ``requirements.txt``
sudo pip3 install -r requirements.txt
# Copy ``inventory/sample`` as ``inventory/mycluster``
cp -rfp inventory/sample inventory/mycluster
# Update Ansible inventory file with inventory builder
declare -a IPS=(172.18.18.207 172.18.18.208 172.18.18.209) # 修改为集群IP
CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]}
# Review and change parameters under ``inventory/mycluster/group_vars``
cat inventory/mycluster/group_vars/all/all.yml
cat inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml 【在该文件中修改k8s的版本,即kube_version为v1.20.9】
catinventory/mycluster/group_vars/k8s_cluster/addons.yml 【在该文件中启动dasshboard,dashboard_enabled: true】
# install 暂时全部使用默认配置
ansible-playbook -i inventory/mycluster/hosts.yaml --become --become-user=root cluster.yml 【该步骤执行时间较长,同时因为无法访问问题,必须配置docker代理,否则执行会失败。】
3.4 参考openpai仓库中的代码在k8s集群上安装openpai
pai的版本为:pai-1.8.0
pai-1.8.0/contrib/kubespray/config目录下layout.yaml的配置如下:
machine-sku:
master-machine: # define a machine sku
mem: 48Gi
cpu:
vcore: 24
gpu-machine:
computing-device:
type: nvidia.com/gpu
model: GeForce RTX 3090
count: 2
mem: 48Gi
cpu:
vcore: 20
machine-list:
- hostname: node1 # name of the machine, **do not** use upper case alphabet letters for hostname
hostip: 172.18.18.207
machine-type: master-machine # only one master-machine supported
pai-master: "true"
- hostname: node2
hostip: 172.18.18.208
machine-type: gpu-machine
pai-worker: "true"
- hostname: node3
hostip: 172.18.18.209
machine-type: gpu-machine
pai-worker: "true"
pai-1.8.0/contrib/kubespray/config目录下config.yaml除了修改docker_image_tag版本之外,其他不变
user: root
password: schinper
docker_image_tag: v1.8.0
...
使用dev-box:v1.8.0创建容器:
docker run -itd \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /opt/pai-deploy/cluster-cfg:/cluster-configuration \
-v /opt/pai-deploy/kube:/root/.kube \
-v /opt/software/pai-1.8.0:/mnt/pai \
--pid=host \
--privileged=true \
--net=host \
--name=dev-box-quick-start \
openpai/dev-box:v1.8.0
- /opt/pai-deploy/cluster-cfg,该目录下保存了kubespray中的layout.yaml和config.yaml文件,脚本会根据这两个文件生成services-configuration.yaml文件。
- /opt/pai-deploy/kube 创建该目录,并从k8s任意一台集群上拷贝~/.kube/*到该目录下,同时将config文件中127.0.0.1的地址替换为k8s主机节点地址。
- /opt/software/pai-1.8.0 PAI的源码
dev-box容器相关操作
docker stop dev-box-quick-start && docker rm dev-box-quick-start # 停止并删除容器
docker exec -it dev-box-quick-start bash # 进入容器
docker exec dev-box-quick-start kubectl get node # 获取k8s集群节点,判断能否连接到k8s的api-server
docker exec -w /mnt/pai dev-box-quick-start /bin/bash ./contrib/kubespray/script/start-service-in-dev-box.sh # 启动dev-box服务
tart-service-in-dev-box.sh脚本的主要功能:
- python3 ./contrib/kubespray/script/openpai_generator.py -l ./contrib/kubespray/config/layout.yaml -c ./contrib/kubespray/config/config.yaml -o /cluster-configuration 生成PAI服务配置yaml,即生成services-configuration.yaml文件。
- ./paictl.py config push -p /cluster-configuration -m service < cluster-id 将配置文件写入k8s。
- ./paictl.py service start < cluster-id 启动pai服务。
修改生成的services-configuration.yaml,启动openpai的web的端的https访问
pylon:
port: 80
uri: "http://172.18.18.207:80"
ssl:
crt_name: schinper-pai.crt
crt_path: /open-pai-ssl/schinper-pai.crt
key_name: schinper-pai.key
key_path: /open-pai-ssl/schinper-pai.key
** /open-pai-ssl/schinper-pai.crt和 /open-pai-ssl/schinper-pai.crt参考自签证书 **
脚本执行步骤如下:
echo "pai" > cluster-id
python3 ./contrib/kubespray/script/openpai_generator.py -l ./contrib/kubespray/config/layout.yaml -c ./contrib/kubespray/config/config.yaml -o /cluster-configuration # 生成PAI服务配置yaml
./paictl.py config push -p /cluster-configuration -m service < cluster-id # 将配置文件写入k8s
./paictl.py service start < cluster-id # 启动pai服务
重启PAI服务的方法:
./paictl.py service start PAI-ID
./paictl.py service start PAI-ID
浏览PAI的界面:
- http 浏览地址:http://172.18.18.207:9286/
- https 浏览地址:https://172.18.18.207/
- pai的默认用户名和密码:admin/admin-password
4 添加一个NFS存储到k8s并在PAI中使用
安装nfs-common并验证NFS服务器是否能够正常访问【这里的NFS我已经搭建好】
apt-get install nfs-common -y # 挂载nfs
showmount -e 172.18.18.245 # 查看共享地址
mount -t nfs 172.18.18.245:/volume1/schinper-nfs/pai-data /schinper-nfs/ -o rw -o user=schinper -o vers=4.1 #挂载
umount /schinper-nfs/ # 取消挂载
创建PV和PVC,nfs-storage.yaml文件内容如下:
# NFS Persistent Volume
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-storage-pv
labels:
name: nfs-storage
spec:
capacity:
storage: 500Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
mountOptions:
- nfsvers=4.1
nfs:
path: /volume1/schinper-nfs/pai-data
server: 172.18.18.245
---
# NFS Persistent Volume Claim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-storage
spec:
accessModes:
- ReadWriteMany
volumeMode: Filesystem
resources:
requests:
storage: 500Gi # 不要超过上面PV的capacity
selector:
matchLabels:
name: nfs-storage # 和上面PV的label相对应
执行nfs-storage.yaml文件:
kubectl apply -f nfs-storage.yaml
由于k8s中的资源和分组是绑定的,必须绑定上分组之后,在当前分组中的用户才可以使用。
在openpai中使用添加的卷资源,
- ① 从openpai用户信息中获取token,【在openpai的页面上获取即可】
- ② 获取分组信息,openpai api开发手册
curl -i -X GET "https://172.18.18.207/rest-server/api/v2/groups/default" \
-H "Authorization: Bearer TOKEN" --insecure
- ③ 根据分组信息组装数据包,更新分组信息。
curl -i -X PUT "https://172.18.18.207/rest-server/api/v2/groups" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"groupname": "default",
"extension": {
"acls": {
"storageConfigs": ["nfs-storage"],
"admin": false,
"virtualClusters": ["default"]
}
}
},
"patch": true
}' --insecure
openpai开发接口:https://developer.box.com/reference/get-groups-id/
执行完毕,在openpai的用户信息中即可看到新创建的卷。
5 配OpenPAI中加载K8S的Dashboard
安装K8S时,需要在group_vars/k8s_cluster/addons.yml 中启动dasshboard,即将dashboard_enabled: true。
检测是否安装dashboard服务
kubectl -n kube-system get service kubernetes-dashboard
pai中需要使用https才能访问k8s的dashboard,因此需要参考openpai的https配置。在open-pai的中修改一下内容:services-configuration.yaml,添加内容如下,
pylon:
port: 80
uri: "http://172.18.18.207:80"
ssl:
crt_name: schinper-pai.crt
crt_path: /open-pai-ssl/schinper-pai.crt
key_name: schinper-pai.key
key_path: /open-pai-ssl/schinper-pai.key
** /open-pai-ssl/schinper-pai.crt和 /open-pai-ssl/schinper-pai.crt参考自签证书**
停止、配置以及启动pylon服务
./paictl.py service stop -n pylon # 停止pylon服务
./paictl.py config pull -o /cluster-configuration # 获取集群当前的配置
vim /cluster-configuration/services-configuration.yaml # 边界当前的配置信息,将pylon信息填入该文件
./paictl.py config push -p /cluster-configuration -m service # 将新的配置信息写入到pai中。
./paictl.py service start -n pylon # 启动pylon服务
此时可以通过pai的web界面加载kubernetes-dashboard,但需要用户认证,这里通过用户令牌认证。首先,在k8s中创建用户,admin-user.yaml文件内容如下:
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kube-system
执行yaml
kubectl apply -f admin-user.yaml
获取token
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
用获取到的令牌登录k8s的dashboard。
其他
K8S集群管理
安装集群
ansible-playbook -i inventory/mycluster/hosts.yaml --become --become-user=root cluster.yml
卸载集群
ansible-playbook -i inventory/mycluster/hosts.yaml reset.yml
移除集群中的节点
ansible-playbook -i inventory/mycluster/hosts.yaml remove-node.yml
OpenPAI集群管理
Worker机器【踩的第一个坑,环境检查一直不通过】
worker机器必须安装的nvidia-container-runtime,且docker的配置文件daemon.json中,必须添加如下runtime相关的内容
{
"insecure-registries": [
"172.18.18.222:5000",
"http://172.18.18.204:30500"
],
"registry-mirrors": [
"http://172.18.18.204:30500",
"https://docker.mirrors.ustc.edu.cn"
],
"data-root": "/www/docker",
"default-runtime": "nvidia",
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}
坑2:PAI安装手册中给出的kubeadm下载地址无法访问
kubeadm和hyperkube
获取最新版k8s:https://storage.googleapis.com/kubernetes-release/release/stable.txt
https://storage.googleapis.com/kubernetes-release/release/v1.15.11/bin/linux/amd64/kubeadm
https://storage.googleapis.com/kubernetes-release/release/v1.15.11/bin/linux/amd64/hyperkube
docker run --rm -it --mount type=bind,source=/opt/kubespray-2.16.0/inventory/sample,dst=/inventory \
--mount type=bind,source=/root/.ssh/id_rsa,dst=/root/.ssh/id_rsa \
quay.io/kubespray/kubespray:v2.16.0 bash
v1.15.11 是脚本中默认使用的版本,这里直接使用。我直接把这两个文件下载下来,然后配置了一个web服务器,直接从我自己的web服务器中下载。
PAI环境准备
- dev box机器:172.18.18.248
- 用于安装、维护和卸载,需要指定唯一一台dev box机器
- 可以访问Docker Hub
- master机器:172.18.18.204
- 用于运行核心Kubernetes组件和OpenPAI服务,目前OpenPAI还不支持高可用
- 内存需要40G以上,可以访问Docker Hub
- NTP已被成功开启。 您可以用命令apt install ntp来检查。
- worker机器(NVIDIA GPU Worker):172.18.18.206
- 可以访问Docker Hub
- GPU驱动已被正确安装
- nvidia-container-runtime已被正确安装