1 參考
- Github地址:https://github.com/Microsoft/pai
- OpenPAI官方安裝文檔:https://openpai.readthedocs.io/zh_CN/latest/manual/cluster-user/quick-start.html
- kubespray: 安裝一個(gè)適用于生成環(huán)境的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開發(fā)接口: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簡介
微軟開發(fā)的一套針對機(jī)器學(xué)習(xí)的資源調(diào)度系統(tǒng),通常有用戶端和管理員端兩個(gè)入口。管理員端主要用于管理OpenPAI集群,客戶端主要提供給用戶提交任務(wù)。
OpenPAI支持兩種調(diào)度器,Kubernets default scheduler以及hivedscheduler。hivedscheduler是OpenPAI的默認(rèn)調(diào)度器,它支持虛擬集群劃分,拓?fù)涓兄馁Y源保證、以及性能優(yōu)化的 Gang Scheduling,這些都是 k8s default scheduler 不支持的。對于CPU worker或NVIDIA GPU worker,可以使用k8s default scheduler或hivedscheduler。
3 安裝
本文在Ubuntu20.04換機(jī)上安裝,使用OpenPAI官方的腳本未安裝成功,因此嘗試先直接使用kubespray安裝k8s集群,然后在使用PAI的腳本安裝PAI服務(wù)。
3.1 主機(jī)信息:
- 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 準(zhǔn)備工作
- 每臺(tái)主機(jī)安裝Nvidia Driver、Docker、Docker-runtime、Anaconda。直接使用ansible playbook安裝。
- 其它基本準(zhǔn)備命令
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 代理設(shè)置
配置docker容器內(nèi)代理:在docker客戶端配置代理,這個(gè)代理在容器內(nèi)部使用。https://docs.dochttps://docs.docker.com/network/proxy/ker.com/network/proxy/
配置dockerd代理【下載鏡像時(shí)需要在此配置代理】:https://www.serverlab.ca/tutorials/containers/docker/how-to-set-the-proxy-for-docker-on-ubuntu/。
systemctl daemon-reload
systemctl restart docker
- privoxy配置代理,主要用于將http請求轉(zhuǎn)發(fā)到配置的socks5的隧道上。
3.3 使用kubespray安裝k8s
【采坑】:因?yàn)榘姹驹?,本文修改group_vars/k8s_cluster/k8s-cluster.yml中kube_version為v1.20.9,而不是1.21.3。kuberspray暫時(shí)不支持1.21.3的配置文件格式,所以將k8s的版本降級了。
安裝kubespray官方文檔執(zhí)行下面操作:
# 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 【在該文件中啟動(dòng)dasshboard,dashboard_enabled: true】
# install 暫時(shí)全部使用默認(rèn)配置
ansible-playbook -i inventory/mycluster/hosts.yaml --become --become-user=root cluster.yml 【該步驟執(zhí)行時(shí)間較長,同時(shí)因?yàn)闊o法訪問問題,必須配置docker代理,否則執(zhí)行會(huì)失敗。】
3.4 參考o(jì)penpai倉庫中的代碼在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創(chuàng)建容器:
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文件,腳本會(huì)根據(jù)這兩個(gè)文件生成services-configuration.yaml文件。
- /opt/pai-deploy/kube 創(chuàng)建該目錄,并從k8s任意一臺(tái)集群上拷貝~/.kube/*到該目錄下,同時(shí)將config文件中127.0.0.1的地址替換為k8s主機(jī)節(jié)點(diǎn)地址。
- /opt/software/pai-1.8.0 PAI的源碼
dev-box容器相關(guān)操作
docker stop dev-box-quick-start && docker rm dev-box-quick-start # 停止并刪除容器
docker exec -it dev-box-quick-start bash # 進(jìn)入容器
docker exec dev-box-quick-start kubectl get node # 獲取k8s集群節(jié)點(diǎn),判斷能否連接到k8s的api-server
docker exec -w /mnt/pai dev-box-quick-start /bin/bash ./contrib/kubespray/script/start-service-in-dev-box.sh # 啟動(dòng)dev-box服務(wù)
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服務(wù)配置yaml,即生成services-configuration.yaml文件。
- ./paictl.py config push -p /cluster-configuration -m service < cluster-id 將配置文件寫入k8s。
- ./paictl.py service start < cluster-id 啟動(dòng)pai服務(wù)。
修改生成的services-configuration.yaml,啟動(dòng)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參考自簽證書 **
腳本執(zhí)行步驟如下:
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服務(wù)配置yaml
./paictl.py config push -p /cluster-configuration -m service < cluster-id # 將配置文件寫入k8s
./paictl.py service start < cluster-id # 啟動(dòng)pai服務(wù)
重啟PAI服務(wù)的方法:
./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的默認(rèn)用戶名和密碼:admin/admin-password
4 添加一個(gè)NFS存儲(chǔ)到k8s并在PAI中使用
安裝nfs-common并驗(yàn)證NFS服務(wù)器是否能夠正常訪問【這里的NFS我已經(jīng)搭建好】
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/ # 取消掛載
創(chuàng)建PV和PVC,nfs-storage.yaml文件內(nèi)容如下:
# 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相對應(yīng)
執(zhí)行nfs-storage.yaml文件:
kubectl apply -f nfs-storage.yaml
由于k8s中的資源和分組是綁定的,必須綁定上分組之后,在當(dāng)前分組中的用戶才可以使用。
在openpai中使用添加的卷資源,
- ① 從openpai用戶信息中獲取token,【在openpai的頁面上獲取即可】
- ② 獲取分組信息,openpai api開發(fā)手冊
curl -i -X GET "https://172.18.18.207/rest-server/api/v2/groups/default" \
-H "Authorization: Bearer TOKEN" --insecure
- ③ 根據(jù)分組信息組裝數(shù)據(jù)包,更新分組信息。
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開發(fā)接口:https://developer.box.com/reference/get-groups-id/
執(zhí)行完畢,在openpai的用戶信息中即可看到新創(chuàng)建的卷。
5 配OpenPAI中加載K8S的Dashboard
安裝K8S時(shí),需要在group_vars/k8s_cluster/addons.yml 中啟動(dòng)dasshboard,即將dashboard_enabled: true。
檢測是否安裝dashboard服務(wù)
kubectl -n kube-system get service kubernetes-dashboard
pai中需要使用https才能訪問k8s的dashboard,因此需要參考openpai的https配置。在open-pai的中修改一下內(nèi)容:services-configuration.yaml,添加內(nèi)容如下,
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參考自簽證書**
停止、配置以及啟動(dòng)pylon服務(wù)
./paictl.py service stop -n pylon # 停止pylon服務(wù)
./paictl.py config pull -o /cluster-configuration # 獲取集群當(dāng)前的配置
vim /cluster-configuration/services-configuration.yaml # 邊界當(dāng)前的配置信息,將pylon信息填入該文件
./paictl.py config push -p /cluster-configuration -m service # 將新的配置信息寫入到pai中。
./paictl.py service start -n pylon # 啟動(dòng)pylon服務(wù)
此時(shí)可以通過pai的web界面加載kubernetes-dashboard,但需要用戶認(rèn)證,這里通過用戶令牌認(rèn)證。首先,在k8s中創(chuàng)建用戶,admin-user.yaml文件內(nèi)容如下:
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
執(zhí)行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
移除集群中的節(jié)點(diǎn)
ansible-playbook -i inventory/mycluster/hosts.yaml remove-node.yml
OpenPAI集群管理
Worker機(jī)器【踩的第一個(gè)坑,環(huán)境檢查一直不通過】
worker機(jī)器必須安裝的nvidia-container-runtime,且docker的配置文件daemon.json中,必須添加如下runtime相關(guān)的內(nèi)容
{
"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 是腳本中默認(rèn)使用的版本,這里直接使用。我直接把這兩個(gè)文件下載下來,然后配置了一個(gè)web服務(wù)器,直接從我自己的web服務(wù)器中下載。
PAI環(huán)境準(zhǔn)備
- dev box機(jī)器:172.18.18.248
- 用于安裝、維護(hù)和卸載,需要指定唯一一臺(tái)dev box機(jī)器
- 可以訪問Docker Hub
- master機(jī)器:172.18.18.204
- 用于運(yùn)行核心Kubernetes組件和OpenPAI服務(wù),目前OpenPAI還不支持高可用
- 內(nèi)存需要40G以上,可以訪問Docker Hub
- NTP已被成功開啟。 您可以用命令apt install ntp來檢查。
- worker機(jī)器(NVIDIA GPU Worker):172.18.18.206
- 可以訪問Docker Hub
- GPU驅(qū)動(dòng)已被正確安裝
- nvidia-container-runtime已被正確安裝