TensorFlow機器學習系統(一):以Kubernetes建立分散式架構
本文將介紹使用Google所開源的TensorFlow機器智慧框架之分散式訓練系統建立方法,原則上採用官方文件所推薦方式建構,並輔以填坑過程,適合初入此門的同好參考。
系統環境:
系統環境:
- Ubuntu 18.04.1 LTS
- TensorFlow 1.12
- Kubernetes 1.18.3 (簡稱k8s)
- CUDA 9.0 (須安裝支援該技術NVIDIA顯示卡)
- cuDNN 7.4.1
- 皆安裝於預設安裝目錄
- 作業系統基礎環境設定
- 關閉Swap:
於終端機(Ctrl+Alt+T開啟)輸入
sudo gedit /etc/fstab # 註釋掉所有swap的行後儲存 sudo swapoff -a
- 使用kubeadm安裝Kubernetes系統
- 首先安裝Docker CE:
sudo apt-get update sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo apt-key fingerprint 0EBFCD88 sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" sudo apt-get update sudo apt-get install docker-ce=5:19.03.12~3-0~ubuntu-bionic systemctl enable docker sudo docker run hello-world
- 安裝kubeadm相關套件
此時基本的Kubernetes所需軟體已完成安裝sudo su curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - cat <<EOF >/etc/apt/sources.list.d/kubernetes.list deb http://apt.kubernetes.io/ kubernetes-xenial main EOF apt-get update apt-get install -y kubelet kubeadm kubectl kubernetes-cni
- 啟動參數設定:
於終端機輸入
開啟kubeadm的啟動設定檔,加入二項環境參數sudo gedit /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
重點是修改倒數二行,作用分別為Cgroup驅動設定與開啟GPU加速功能# Note: This dropin only works with kubeadm and kubelet v1.11+ [Service] Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf" Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml" # This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env # This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use # the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file. EnvironmentFile=-/etc/default/kubelet ExecStart= ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=cgroupfs" Environment="KUBELET_EXTRA_ARGS=--feature-gates=Accelerators=true"
- 預先下載Docker Image
kubeadm config images pull
- 初始化主節點(僅主節點執行)
- 在作為主要節點的伺服器上,於終端機輸入
其中XXX.XXX.XXX.XXX為主要節點IPsudo kubeadm init \ --pod-network-cidr=10.244.0.0/16 \ --apiserver-advertise-address=XXX.XXX.XXX.XXX
執行後會需要一點時間初始化,請耐心等待 - 完成初始化畫面上會出現如下訊息:
紀錄下最後一行的申請加入命令,後續加入其他節點會使用Your Kubernetes master has initialized successfully! To start using your cluster, you need to run (as a regular user): mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: http://kubernetes.io/docs/admin/addons/ You can now join any number of machines by running the following on each node as root: kubeadm join --token [token] XXX.XXX.XXX.XXX:6443 --discovery-token-ca-cert-hash [hash]
- 同樣在終端機輸入下列指令,複製配置資訊供kubeclt連接叢集使用
完成配置資訊,輸入叢集狀態查詢命令,沒錯誤訊息就表示初始化完成。mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl get cs
- 安裝pod network:
- 官方提供多種方式,此處採用flannel,
於終端機輸入下列命令安裝
如無法下載或有自行修改配置的需求,可於CoreOS-GitHub下載yml配置檔sudo kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
於檔案位置輸入下列命令安裝
sudo kubectl apply -f kube-flannel.yml
- 輸入下命令檢視核心元件是否皆正常啟動
若STATUS欄位皆顯示Running表示安裝完成。sudo kubectl get pod --all-namespaces -o wide
- 主節點加入工作(僅主節點執行)(選用)
- 若主節點伺服器效能不錯,不想浪費效能,可用下列命令將工作指派納入主節點
sudo kubectl taint nodes --all node-role.kubernetes.io/master-
- 其他節點加入叢集(僅其他節點執行)
- 要將其他節點加入叢集,首先必須完成步驟1和2,
然後將步驟3的申請加入命令於其他節點終端機執行
加入完成後,可使用下列命令查詢節點狀態sudo kubeadm join --token [token] XXX.XXX.XXX.XXX:6443 --discovery-token-ca-cert-hash [hash]
如主機名稱已出現在NAME欄位,表示加入成功sudo kubectl get nodes
- 其他節點移出叢集(僅其他節點執行)
- 要將其他節點移出叢集,請於主節點終端機執行
其中[node name]表示其他節點主機名稱,然後於其他節點終端機執行步驟15「異常排除:ERR_01」移除相關配置sudo kubectl drain [node name] --delete-local-data --force --ignore-daemonsets kubectl delete node [node name]
- 安裝Kubernetes圖形管理界面
- 安裝Dashboard插件,於終端機輸入下列命令安裝
如無法下載或有自行修改配置的需求,可至kubernetes/dashboard-GitHub發行頁面下載sudo kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml
於檔案位置輸入下列命令安裝
sudo kubectl apply -f kubernetes-dashboard.yaml
- 新增ServiceAccount管理權限,建立配置檔kubernetes-dashboard-admin.rbac.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
sudo kubectl apply -f kubernetes-dashboard-admin.rbac.yaml
- 查詢登入dashboard的token碼,於終端機輸入
會穫得如下回應kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
紀錄下token後的通行碼,並啟動K8S的服務proxyName: admin-user-token-6gl6l Namespace: kube-system Labels:
Annotations: kubernetes.io/service-account.name=admin-user kubernetes.io/service-account.uid=b16afba9-dfec-11e7-bbb9-901b0e532516 Type: kubernetes.io/service-account-token Data ==== ca.crt: 1025 bytes namespace: 11 bytes token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX kubectl proxy
- 以瀏覽器登入圖形介面網頁
於Kubernetes Dashboard登入畫面選擇認證方式為『token』貼上通行碼即可進入圖形管理界面http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
- 安裝Kubernetes資源監控功能
- 安裝Weave Scope插件,於終端機輸入下列命令安裝
sudo kubectl apply -f https://cloud.weave.works/k8s/scope.yaml sudo kubectl port-forward svc/weave-scope-app -n weave 4040:80
- 使用瀏覽器開啟http://localhost:4040/即可查看介面
- 安裝Nvidia顯示驅動
- 於終端機輸入下列命令安裝
命令中384版本號依據官方發行最新為主sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt update sudo apt-get install nvidia-384
- 安裝CUDA
- 至NVIDIA CUDA Toolkit Archive選擇適當版本安裝(目前支援9.0版),安裝命令依序如下:
並安裝更新檔輸入命令如下:sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.1.85-1_amd64.deb sudo apt install ./cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
用其他方式安裝會導致版本更新,不建議採用。 其他選用功能安裝如下:wget http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1604/x86_64/nvidia-machine-learning-repo-ubuntu1604_1.0.0-1_amd64.deb sudo apt install ./nvidia-machine-learning-repo-ubuntu1604_1.0.0-1_amd64.deb sudo apt update
# Install CUDA and tools. Include optional NCCL 2.x sudo apt install cuda9.0 cuda-cublas-9-0 cuda-cufft-9-0 cuda-curand-9-0 \ cuda-cusolver-9-0 cuda-cusparse-9-0 libcudnn7=7.2.1.38-1+cuda9.0 \ libnccl2=2.2.13-1+cuda9.0 cuda-command-line-tools-9-0 # Optional: Install the TensorRT runtime (must be after CUDA install) sudo apt update sudo apt install libnvinfer4=4.1.2-1+cuda9.0
- 安裝cuDNN
- 至NVIDIA cuDNN註冊並進入下載頁面選擇for CUDA 9.0 的 7.2以上版本壓縮檔,
於壓縮檔位置開啟終端機輸入:tar zxvf cudnn-9.0-linux-x64-v7.4.1.5.tgz sudo cp -P cuda/include/cudnn.h /usr/local/cuda/include sudo cp -P cuda/lib64/libcudnn* /usr/local/cuda/lib64 sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn*
- 設定環境變數
- 開啟個人環境設定檔.bashrc
於檔案末端加入gedit ~/.bashrc
存檔後重新啟動電腦,執行下命令確認GUP啟用狀態export CUDA_HOME=/usr/local/cuda–9.1 export LD_LIBRARY_PATH=${CUDA_HOME}/lib64:$LD_LIBRARY_PATH export PATH=${CUDA_HOME}/bin:${PATH}
如正常顯示訊息表示安裝成功,另外可編譯執行CUDA範例如下nvidia-smi
如顯示 Result = PASS 表示安裝成功cd /usr/local/cuda/samples/1_Utilities/deviceQuery sudo make ./deviceQuery ./deviceQuery
- 完成TensorFlow分散式運算架構!
- 完成上述所有步驟,您的機器學習訓練平台已完成,
如有遭遇其他問題可透過下方「異常排除」步驟解除,
若仍有問題表示您的系統環境有其特殊性(防火牆阻擋、網管封鎖…等),
就請自行爬文填坑了。 - 安裝Docker圖形化管理界面(選用)
- 由於本系統的k8s主要基於Docker運作,
如有需要可安裝Docker管理界面Portainer便於操作,安裝方式如下:
於瀏覽器進入 http://[DOCKER_HOST]:9000sudo docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v /opt/portainer:/data portainer/portainer
其中[DOCKER_HOST]可使用下命令查詢
位址於 inet addr 項目內顯示。ifconfig docker0
- 異常排除
- ERR_01:節點初始化異常,請用下列命令移除所有配置再重新初始化
sudo -i kubeadm reset ifconfig cni0 down ip link delete cni0 ifconfig flannel.1 down ip link delete flannel.1 rm -rf /var/lib/cni/
- ERR_02:其他節點無法加入(token過期)
加入其他節點時收到如下列訊息,表示主節點生成的申請加入token碼過期(預設24小時失效)
請用下列命令重新生成token碼[discovery] Failed to connect to API Server "XXX.XXX.XXX.XXX:6443": there is no JWS signed token in the cluster-info ConfigMap. This token id "[token]" is invalid for this cluster, can't connect
並取代原本的申請加入命令中的[token]內容。sudo kubeadm token create
另外可在步驟3初始化命令加入token-ttl參數使token永久有效,基於安全考量不建議使用sudo kubeadm init \ --pod-network-cidr=10.244.0.0/16 \ --apiserver-advertise-address=XXX.XXX.XXX.XXX \ --token-ttl 0
- 參考資料:
- 系列文章:
留言
張貼留言