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
  • 皆安裝於預設安裝目錄
建立步驟:
  1. 作業系統基礎環境設定
    • 關閉Swap:
      於終端機(Ctrl+Alt+T開啟)輸入
      sudo gedit /etc/fstab
      # 註釋掉所有swap的行後儲存
      sudo swapoff -a
  2. 使用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相關套件
      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
      此時基本的Kubernetes所需軟體已完成安裝
    • 啟動參數設定:
      於終端機輸入
      sudo gedit /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
      
      開啟kubeadm的啟動設定檔,加入二項環境參數
      # 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"
      重點是修改倒數二行,作用分別為Cgroup驅動設定與開啟GPU加速功能
  3. 預先下載Docker Image
    kubeadm config images pull
  4. 初始化主節點(僅主節點執行)
    • 在作為主要節點的伺服器上,於終端機輸入
      sudo kubeadm init \
        --pod-network-cidr=10.244.0.0/16 \
        --apiserver-advertise-address=XXX.XXX.XXX.XXX
      
      其中XXX.XXX.XXX.XXX為主要節點IP
      執行後會需要一點時間初始化,請耐心等待
    • 完成初始化畫面上會出現如下訊息:
      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
  5. 安裝pod network:
    • 官方提供多種方式,此處採用flannel,
      於終端機輸入下列命令安裝
      sudo kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
      如無法下載或有自行修改配置的需求,可於CoreOS-GitHub下載yml配置檔
      於檔案位置輸入下列命令安裝
      sudo kubectl apply -f kube-flannel.yml
    • 輸入下命令檢視核心元件是否皆正常啟動
      sudo kubectl get pod --all-namespaces -o wide
      若STATUS欄位皆顯示Running表示安裝完成。
  6. 主節點加入工作(僅主節點執行)(選用)
    • 若主節點伺服器效能不錯,不想浪費效能,可用下列命令將工作指派納入主節點
      sudo kubectl taint nodes --all node-role.kubernetes.io/master-
  7. 其他節點加入叢集(僅其他節點執行)
    • 要將其他節點加入叢集,首先必須完成步驟1和2,
      然後將步驟3的申請加入命令於其他節點終端機執行
      sudo kubeadm join --token [token] XXX.XXX.XXX.XXX:6443 --discovery-token-ca-cert-hash [hash]
      加入完成後,可使用下列命令查詢節點狀態
      sudo kubectl get nodes
      如主機名稱已出現在NAME欄位,表示加入成功
  8. 其他節點移出叢集(僅其他節點執行)
    • 要將其他節點移出叢集,請於主節點終端機執行
      sudo kubectl drain [node name] --delete-local-data --force --ignore-daemonsets
      kubectl delete node [node name]
      其中[node name]表示其他節點主機名稱,然後於其他節點終端機執行步驟15「異常排除:ERR_01」移除相關配置
  9. 安裝Kubernetes圖形管理界面
    • 安裝Dashboard插件,於終端機輸入下列命令安裝
      sudo kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml
      如無法下載或有自行修改配置的需求,可至kubernetes/dashboard-GitHub發行頁面下載
      於檔案位置輸入下列命令安裝
      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}')
      會穫得如下回應
      Name:         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
      紀錄下token後的通行碼,並啟動K8S的服務proxy
      kubectl proxy
    • 以瀏覽器登入圖形介面網頁
      http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
      於Kubernetes Dashboard登入畫面選擇認證方式為『token』貼上通行碼即可進入圖形管理界面
  10. 安裝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/即可查看介面
  11. 安裝Nvidia顯示驅動
    • 於終端機輸入下列命令安裝
      sudo add-apt-repository ppa:graphics-drivers/ppa 
      sudo apt update
      sudo apt-get install nvidia-384
      命令中384版本號依據官方發行最新為主
  12. 安裝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
  13. 安裝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*
  14. 設定環境變數
    • 開啟個人環境設定檔.bashrc
      gedit ~/.bashrc
      於檔案末端加入
      export CUDA_HOME=/usr/local/cuda–9.1
      export LD_LIBRARY_PATH=${CUDA_HOME}/lib64:$LD_LIBRARY_PATH
      export PATH=${CUDA_HOME}/bin:${PATH}
      存檔後重新啟動電腦,執行下命令確認GUP啟用狀態
      nvidia-smi
      如正常顯示訊息表示安裝成功,另外可編譯執行CUDA範例如下
      cd /usr/local/cuda/samples/1_Utilities/deviceQuery
      sudo make ./deviceQuery
      ./deviceQuery
      如顯示 Result = PASS 表示安裝成功
  15. 完成TensorFlow分散式運算架構!
    • 完成上述所有步驟,您的機器學習訓練平台已完成,
      如有遭遇其他問題可透過下方「異常排除」步驟解除,
      若仍有問題表示您的系統環境有其特殊性(防火牆阻擋、網管封鎖…等),
      就請自行爬文填坑了。
  16. 安裝Docker圖形化管理界面(選用)
    • 由於本系統的k8s主要基於Docker運作,
      如有需要可安裝Docker管理界面Portainer便於操作,安裝方式如下:
      sudo docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v /opt/portainer:/data portainer/portainer
      於瀏覽器進入 http://[DOCKER_HOST]:9000
      其中[DOCKER_HOST]可使用下命令查詢
      ifconfig docker0
      位址於 inet addr 項目內顯示。
  17. 異常排除
    • 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小時失效)
      [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
      並取代原本的申請加入命令中的[token]內容。
      另外可在步驟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
  18. 參考資料:
  19. 系列文章:

留言

這個網誌中的熱門文章