天天看點

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

引言

kubeflow 是 google 開源的一個基于 kubernetes 的 ML workflow 平台,其內建了大量的機器學習工具,比如用于互動性實驗的 jupyterlab 環境,用于超參數調整的 katib,用于 pipeline 工作流控制的 argo workflow等。作為一個“大型工具箱”集合,kubeflow 為機器學習開發者提供了大量可選的工具,同時也為機器學習的工程落地提供了可行性工具。

當然,由于 kubeflow 主要是 google 在主導,雖然其作為一個開源項目,但在很多選型上都和 google 自家産品深度綁定,比如 google 自己的存儲工具 gstuil 作為一等公民,鏡像倉庫位址也大多是

grc.io

這樣的google自己的鏡像倉庫位址。

安裝部署

關于 kubeflow 的安裝部署如果沒有比較好的外網通路環境的話,大家可以參考我開源的一個project,專門做國内manifest,鏡像倉庫都是采用阿裡雲鏡像,在國内網絡環境下也能快速輕松安裝部署:

git clone https://github.com/shikanon/kubeflow-manifests.git
cd kubeflow-manifests
python install.py           

安裝完成後檢視等待所有 pod running。

$ kubectl get po -A
NAMESPACE                   NAME                                                              READY   STATUS                  RESTARTS   AGE
auth                        dex-6686f66f9b-54s96                                              1/1     Running                 0          2h6m
cattle-system               cattle-cluster-agent-5f695c79c-x9ql7                              1/1     Running                 0          3h
cert-manager                cert-manager-9d5774b59-4xjmk                                      1/1     Running                 0          2h23m
cert-manager                cert-manager-cainjector-67c8c5c665-nmcp6                          1/1     Running                 0          2h23m
cert-manager                cert-manager-webhook-75dc9757bd-z2k5c                             1/1     Running                 1          2h23m
fleet-system                fleet-agent-7d959597cb-q8ckq                                      1/1     Running                 0          3h
istio-system                authservice-0                                                     1/1     Running                 0          2h23m
istio-system                cluster-local-gateway-66bcf8bc5d-j9kvp                            1/1     Running                 0          2h23m
istio-system                istio-ingressgateway-85b49c758f-l4hgc                             1/1     Running                 0          2h22m
istio-system                istiod-5ff6cdbbcd-2v5kj                                           1/1     Running                 0          2h23m
knative-eventing            broker-controller-5c84984b97-86zkx                                1/1     Running                 0          2h23m
knative-eventing            eventing-controller-54bfbd5446-rx9ll                              1/1     Running                 0          2h23m
knative-eventing            eventing-webhook-58f56d9cf4-bnq9q                                 1/1     Running                 0          2h23m
knative-eventing            imc-controller-769896c7db-kzjv6                                   1/1     Running                 0          2h23m
knative-eventing            imc-dispatcher-86954fb4cd-9b6gz                                   1/1     Running                 0          2h23m
knative-serving             activator-75696c8c9-9c5ff                                         1/1     Running                 0          2h23m
knative-serving             autoscaler-6764f9b5c5-2gwqj                                       1/1     Running                 0          2h23m
knative-serving             controller-598fd8bfd7-bpn5k                                       1/1     Running                 0          2h23m
knative-serving             istio-webhook-785bb58cc6-ts9f2                                    1/1     Running                 0          2h23m
knative-serving             networking-istio-77fbcfcf9b-pg26h                                 1/1     Running                 0          2h23m
knative-serving             webhook-865f54cf5f-rzpjf                                          1/1     Running                 0          2h23m
kube-system                 coredns-5644d7b6d9-hwwnr                                          1/1     Running                 0          3h1m
kube-system                 coredns-5644d7b6d9-zds92                                          1/1     Running                 0          3h1m
kube-system                 etcd-kubeflow-control-plane                                       1/1     Running                 0          3h
kube-system                 kindnet-8tvm5                                                     1/1     Running                 0          3h1m
kube-system                 kindnet-zkmkq                                                     1/1     Running                 0          3h1m
kube-system                 kube-apiserver-kubeflow-control-plane                             1/1     Running                 0          3h
kube-system                 kube-controller-manager-kubeflow-control-plane                    1/1     Running                 0          3h
kube-system                 kube-proxy-c8zn7                                                  1/1     Running                 0          3h1m
kube-system                 kube-proxy-k7b8c                                                  1/1     Running                 0          3h1m
kube-system                 kube-scheduler-kubeflow-control-plane                             1/1     Running                 0          3h
kubeflow                    admission-webhook-deployment-6fb9d65887-pzvgc                     1/1     Running                 0          2h22m
kubeflow                    cache-deployer-deployment-7558d65bf4-jhgwg                        2/2     Running                 1          2h6m
kubeflow                    cache-server-c64c68ddf-stz72                                      2/2     Running                 0          22m
kubeflow                    centraldashboard-7b7676d8bd-g2s8j                                 1/1     Running                 0          2h7m
kubeflow                    jupyter-web-app-deployment-66f74586d9-scbsm                       1/1     Running                 0          2h5m
kubeflow                    katib-controller-77675c88df-mx4rh                                 1/1     Running                 0          2h22m
kubeflow                    katib-db-manager-646695754f-z797r                                 1/1     Running                 0          2h22m
kubeflow                    katib-mysql-5bb5bd9957-gbl5t                                      1/1     Running                 0          2h22m
kubeflow                    katib-ui-55fd4bd6f9-r98r2                                         1/1     Running                 0          2h22m
kubeflow                    kfserving-controller-manager-0                                    2/2     Running                 0          2h22m
kubeflow                    kubeflow-pipelines-profile-controller-5698bf57cf-btpn5            1/1     Running                 0          22m
kubeflow                    metacontroller-0                                                  1/1     Running                 0          2h7m
kubeflow                    metadata-envoy-deployment-76d65977f7-rmlzc                        1/1     Running                 0          2h7m
kubeflow                    metadata-grpc-deployment-697d9c6c67-j6dl2                         2/2     Running                 3          2h7m
kubeflow                    metadata-writer-58cdd57678-8t6gw                                  2/2     Running                 1          2h7m
kubeflow                    minio-6d6784db95-tqs77                                            2/2     Running                 0          2h7m
kubeflow                    ml-pipeline-85fc99f899-plsz2                                      2/2     Running                 1          2h7m
kubeflow                    ml-pipeline-persistenceagent-65cb9594c7-xvn4j                     2/2     Running                 1          2h7m
kubeflow                    ml-pipeline-scheduledworkflow-7f8d8dfc69-7wfs4                    2/2     Running                 0          2h7m
kubeflow                    ml-pipeline-ui-5c765cc7bd-4r2j7                                   2/2     Running                 0          2h7m
kubeflow                    ml-pipeline-viewer-crd-5b8df7f458-5b8qg                           2/2     Running                 1          2h7m
kubeflow                    ml-pipeline-visualizationserver-56c5ff68d5-92bkf                  2/2     Running                 0          2h7m
kubeflow                    mpi-operator-789f88879-n4xms                                      1/1     Running                 0          2h22m
kubeflow                    mxnet-operator-7fff864957-vq2bg                                   1/1     Running                 0          2h22m
kubeflow                    mysql-56b554ff66-kd7bd                                            2/2     Running                 0          2h7m
kubeflow                    notebook-controller-deployment-74d9584477-qhpp8                   1/1     Running                 0          2h22m
kubeflow                    profiles-deployment-67b4666796-k7t2h                              2/2     Running                 0          2h22m
kubeflow                    pytorch-operator-fd86f7694-dxbgf                                  2/2     Running                 0          2h22m
kubeflow                    tensorboard-controller-controller-manager-fd6bcffb4-k9qvx         3/3     Running                 1          2h22m
kubeflow                    tensorboards-web-app-deployment-78d7b8b658-dktc6                  1/1     Running                 0          2h22m
kubeflow                    tf-job-operator-7bc5cf4cc7-gk8tz                                  1/1     Running                 0          2h22m
kubeflow                    volumes-web-app-deployment-68fcfc9775-bz9gq                       1/1     Running                 0          2h22m
kubeflow                    workflow-controller-5449754fb4-tdg2t                              2/2     Running                 1          22m
kubeflow                    xgboost-operator-deployment-5c7bfd57cc-9rtq6                      2/2     Running                 1          2h22m
local-path-storage          local-path-provisioner-58f6947c7-mv4mg                            1/1     Running                 0          3h1m           

通路控制

kubeflow 通過dex 進行鑒權服務,安裝好kubeflow,打開本地浏覽器,看到 dex 的登入驗證框,輸出賬号密碼:

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

這裡的賬号密碼可以通過 dex 的 configmap 設定:

apiVersion: v1
data:
  config.yaml: |
    issuer: http://dex.auth.svc.cluster.local:5556/dex
    storage:
      type: kubernetes
      config:
        inCluster: true
    web:
      http: 0.0.0.0:5556
    logger:
      level: "debug"
      format: text
    oauth2:
      skipApprovalScreen: true
    enablePasswordDB: true
    staticPasswords:
    - email: "[email protected]"
      hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W"
      username: "admin"
      userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"
    staticClients:
    - idEnv: OIDC_CLIENT_ID
      redirectURIs: ["/login/oidc"]
      name: 'Dex Login Application'
      secretEnv: OIDC_CLIENT_SECRET
kind: ConfigMap
metadata:
  name: dex
  namespace: auth           

email 就是我們登入的使用者名,hash 就是我們的設定的密碼,可以通過以下這段python代碼來生成:

from passlib.hash import bcrypt
import getpass
print(bcrypt.using(rounds=12, ident="2y").hash(getpass.getpass()))           

元件功能介紹

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

可以看到新版的kubeflow多了很多功能。

這裡按子產品介紹下 Kubeflow 的幾個核心元件。

  • Notebook Servers,作為一個管理線上互動實驗的記錄工具,可以幫助算法人員快速完成算法實驗,同時notebook server 提供了統一的文檔管理能力。
  • AutoML,提供自動化的服務,對特征處理、特征選擇、模型選擇、模型參數的配置、模型訓練和評估等方面,實作了全自動模組化,降低算法人員手動實驗次數。
  • Pipeline,提供一個算法流水線的工程化工具,将算法各流程子產品以拓撲圖的形式組合起來,同時結合 argo 可以實作 MLOps。
  • Serverless,将模型直接釋出成一個對外的服務,縮短從實驗到生産的路徑。
玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

Notebook Servers

notebook 可以說是做機器學習最喜歡用到的工具了,完美的将動态語言的互動性發揮出來,kubeflow 提供了 jupyter notebook 來快速建構雲上的實驗環境,這裡以一個我們自定義的鏡像為例:

我們建立了一個

test-for-jupyter

名字的鏡像,配置了一個 tensorflow 的鏡像,點選啟動,我們可以看到在

kubeflow-user-example-com

命名空間下已經建立我們的應用了:

kubectl get po -nkubeflow-user-example-com
NAME                                               READY   STATUS            RESTARTS   AGE
ml-pipeline-ui-artifact-6d7ffcc4b6-9kxkk           2/2     Running           0          48m
ml-pipeline-visualizationserver-84d577b989-5hl46   2/2     Running           0          48m
test-for-jupyter-0                                 0/2     PodInitializing   0          44s           
玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

建立完成後點選 connect 就可以進入我們建立的應用界面中了

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻
玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

在 jupyterlab 環境中開發人員可以很友善的進行算法實驗,同時由于運作在雲上利用 k8s api甚至可以很友善建構k8s資源,比如通過 kfserving 建立一個ML服務。

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

AutoML

AutoML 是機器學習比較熱的領域,主要用來模型自動優化和超參數調整,這裡其實是用的 Katib來實作的,一個基于k8s的 AutoML 項目,詳細見

https://github.com/kubeflow/katib

Katib 主要提供了 超參數調整(Hyperparameter Tuning),早停法(Early Stopping)和神經網絡架構搜尋(Neural Architecture Search)

這裡以一個随機搜尋算法為例:

apiVersion: "kubeflow.org/v1beta1"
kind: Experiment
metadata:
  namespace: kubeflow-user-example-com
  name: random-example
spec:
  objective:
    type: maximize
    goal: 0.99
    objectiveMetricName: Validation-accuracy
    additionalMetricNames:
      - Train-accuracy
  algorithm:
    algorithmName: random
  parallelTrialCount: 3
  maxTrialCount: 12
  maxFailedTrialCount: 3
  parameters:
    - name: lr
      parameterType: double
      feasibleSpace:
        min: "0.01"
        max: "0.03"
    - name: num-layers
      parameterType: int
      feasibleSpace:
        min: "2"
        max: "5"
    - name: optimizer
      parameterType: categorical
      feasibleSpace:
        list:
          - sgd
          - adam
          - ftrl
  trialTemplate:
    primaryContainerName: training-container
    trialParameters:
      - name: learningRate
        description: Learning rate for the training model
        reference: lr
      - name: numberLayers
        description: Number of training model layers
        reference: num-layers
      - name: optimizer
        description: Training model optimizer (sdg, adam or ftrl)
        reference: optimizer
    trialSpec:
      apiVersion: batch/v1
      kind: Job
      spec:
        template:
          spec:
            containers:
              - name: training-container
                image: docker.io/kubeflowkatib/mxnet-mnist:v1beta1-45c5727
                command:
                  - "python3"
                  - "/opt/mxnet-mnist/mnist.py"
                  - "--batch-size=64"
                  - "--lr=${trialParameters.learningRate}"
                  - "--num-layers=${trialParameters.numberLayers}"
                  - "--optimizer=${trialParameters.optimizer}"
            restartPolicy: Never           

這裡以一個簡單的神經網絡為例,該程式具有三個參數 lr, num-layers, optimizer,采用的算法是随機搜尋,目标是最大化準确率(accuracy)。

可以直接在界面中填上yaml檔案,然後送出。

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

完成後會生成一張各參數和準确率的關系圖和訓練清單:

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻
玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

Experiments and Pipelines

experiments 為我們提供了一個可以建立實驗空間功能,

pipeline

定義了算法組合的模闆,通過

pipeline

我們可以将算法中各處理子產品按特定的拓撲圖的方式組合起來。

這裡可以看看官方提供的幾個 pipeline 例子:

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻
玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

kubeflow

pipeline

本質是基于 argo

workflow

實作,由于我們的kubeflow是基于kind上建構的,容器運作時用的containerd,而workflow預設的pipeline執行器是docker,是以有些特性不相容,這塊可以見 argo workflow 官方說明:

https://argoproj.github.io/argo-workflows/workflow-executors/

這裡我是把 workflow 的

containerRuntimeExecutor

改成了

k8sapi

。但

k8sapi

由于在 workflow 是二級公民,是以有些功能不能用,比如 kubeflow pipeline 在 input/output 的 artifacts 需要用到

docker cp

指令,可以參考這個issue:

https://github.com/argoproj/argo-workflows/issues/2685#issuecomment-613632304

由于以上原因 kubeflow 預設給的幾個案例并沒有用 volumes 是無法在 kind 中運作起來,這裡我們基于 argo workflow 文法自己實作一個

pipeline

基于pipeline建構一個的工作流水

第一步,建構一個 workflow pipeline 檔案:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: kubeflow-test-
spec:
  entrypoint: kubeflow-test
  templates:
  - name: kubeflow-test
    dag:
      tasks:
      - name: print-text
        template: print-text
        dependencies: [repeat-line]
      - {name: repeat-line, template: repeat-line}
  - name: repeat-line
    container:
      args: [--line, Hello, --count, '15', --output-text, /gotest/outputs/output_text/data]
      command:
      - sh
      - -ec
      - |
        program_path=$(mktemp)
        printf "%s" "$0" > "$program_path"
        python3 -u "$program_path" "$@"
      - |
        def _make_parent_dirs_and_return_path(file_path: str):
            import os
            os.makedirs(os.path.dirname(file_path), exist_ok=True)
            return file_path

        def repeat_line(line, output_text_path, count = 10):
            '''Repeat the line specified number of times'''
            with open(output_text_path, 'w') as writer:
                for i in range(count):
                    writer.write(line + '\n')

        import argparse
        _parser = argparse.ArgumentParser(prog='Repeat line', description='Repeat the line specified number of times')
        _parser.add_argument("--line", dest="line", type=str, required=True, default=argparse.SUPPRESS)
        _parser.add_argument("--count", dest="count", type=int, required=False, default=argparse.SUPPRESS)
        _parser.add_argument("--output-text", dest="output_text_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
        _parsed_args = vars(_parser.parse_args())

        _outputs = repeat_line(**_parsed_args)
      image: python:3.7
      volumeMounts:
      - name: workdir
        mountPath: /gotest/outputs/output_text/
    volumes:
      - name: workdir
        persistentVolumeClaim:
          claimName: kubeflow-test-pv
    metadata:
      annotations: 
  - name: print-text
    container:
      args: [--text, /gotest/outputs/output_text/data]
      command:
      - sh
      - -ec
      - |
        program_path=$(mktemp)
        printf "%s" "$0" > "$program_path"
        python3 -u "$program_path" "$@"
      - |
        def print_text(text_path): # The "text" input is untyped so that any data can be printed
            '''Print text'''
            with open(text_path, 'r') as reader:
                for line in reader:
                    print(line, end = '')

        import argparse
        _parser = argparse.ArgumentParser(prog='Print text', description='Print text')
        _parser.add_argument("--text", dest="text_path", type=str, required=True, default=argparse.SUPPRESS)
        _parsed_args = vars(_parser.parse_args())

        _outputs = print_text(**_parsed_args)
      image: python:3.7
      volumeMounts:
      - name: workdir
        mountPath: /gotest/outputs/output_text/
    volumes:
      - name: workdir
        persistentVolumeClaim:
          claimName: kubeflow-test-pv
    metadata:
      annotations:            

argo workflow 的文法可以參考:

https://argoproj.github.io/argo-workflows/variables/

這裡我們定義了兩個任務 repeat-line 和 print-text, repeat-line 任務會将生産結果寫入

kubeflow-test-pv

的 PVC 中, print-text 會從 PVC 中讀取資料輸出到 stdout。

這裡由于用到 PVC,我們需要先在叢集中建立一個

kubeflow-test-pv

的PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: kubeflow-test-pv
  namespace: kubeflow-user-example-com
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 128Mi           

第二步,定義好 pipeline 檔案後可以建立pipeline:

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

第三步,啟動一個pipeline:

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

啟動 pipeline 除了單次運作模式 one-off,也支援定時器循環模式 Recurring,這塊可以根據自己的需求确定。

檢視運作結果:

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

運作完後,可以将實驗進行歸檔(Archived)。

關于 MLOps 的一點思考

我們來看一個簡單的 ML 運作流程:

玩轉Kubeflow第一章: kubeflow 國内本地安裝及案例介紹參考文獻

這是一個 google 提供的 level 1 級别的機器學習流水線自動化,整個流水線包括以下幾部分:

  • 建構快速算法實驗的環境(experimentation),這裡的步驟已經過編排,各個步驟之間的轉換是自動執行的,這樣可以快速疊代實驗,并更好地準備将整個流水線移至生産環境,在這個環境中算法研究員隻進行子產品内部的工作。
  • 建構可複用的生産環境流水線,元件的源代碼子產品化,實驗環境子產品化流水線可以直接在 staging 環境和 production 環境中使用。
  • 持續傳遞模型,生産環境中的機器學習流水線會向使用新資料進行訓練的新模型持續傳遞預測服務。

基于上述功能描述我們其實可以基于 kubeflow 的

pipeline

kfserving

功能輕松實作一個簡單的 MLOps 流水線釋出流程。不過,值得注意的是,DevOps 本身并不僅僅是一種技術,同時是一種工程文化,是以在實踐落地中需要團隊各方的協同分階段的落地。這塊可以參考

《MLOps: Continuous delivery and automation pipelines in machine learning》 《Hidden Technical Debt in Machine Learning Systems》

參考文獻