使用Docker和Kubernetes託管機器學習模型

Docker是在雲中部署ML模型的絕佳工具。如果你想在雲中創建一套生產級部署,那麼AWS和GCP上有很多選項可用。我正在撰寫一本書,其中的第4章重點介紹用於模型服務的ECS,同時還會深入探索谷歌Kubernetes引擎。這篇文章省略了第4章關於AWS的容器部署部分,其餘部分則沒有刪減。

可複製模型的容器

部署數據科學模型時,重點在於復現培訓時的環境和用於服務的環境。容器的理念是形成一個隔離的環境,你可以在其中設置執行任務所需的依賴項。任務可以是執行ETL工作、服務ML模型、支持API或託管交互式Web應用程序。容器框架的目標是在實例之間提供隔離,同時只佔用很少的資源。使用容器框架,你可以指定代碼所需的依賴項,並讓該框架管理不同的執行環境。Docker是容器的事實標準,人們圍繞這一平臺構建了大量工具。

彈性容器環境(例如彈性容器服務器——ECS)提供了與無服務器函數類似的功能,這種環境將服務器的概念從數據科學模型託管中抽象了出來。關鍵區別在於無服務器生態系統僅限於特定的運行時,通常具有內存限制,很難使用深度學習框架,並且是特定於雲的。使用ECS,你可以設置用於服務模型的實例類型,可以使用服務模型所需的任何語言,並且想用多少內存都沒問題。ECS也還是AWS的專有工具,但是諸如EKS之類的較新選項建立在開源和可移植的Kubernetes之上。

以下是我見過的一些容器數據科學用例:

  • 可重現分析:容器是打包分析的好辦法,分析被打包後其他團隊成員就可以在幾個月或幾年後重新啓動你的工作。
  • Web應用程序:在第2章中,我們使用Dash構建了一個交互式Web應用程序。部署應用時,容器提供了一種很好的方式來抽象出託管事宜。
  • 模型部署:如果要將模型公開爲端點,容器提供了一種很好的方法來分離模型應用程序代碼與模型服務基礎架構。

本章的重點是最後一個用例。我們會使用第二章中的Web端點,並將應用程序包裝在一個Docker容器中。我們首先會在EC2實例上本地運行容器,然後試着使用ECS創建可擴展、支持負載平衡和容錯的模型部署。接下來,我們將展示如何使用Kubernetes在GCP上獲得類似的結果。

既然我們正在探索可擴展的計算環境,那麼使用ECS和GKE時務必要注意雲成本。對於AWS,我們應該密切關注服務了多少EC2實例;在GCP上,計費工具可很好地跟蹤成本。關於編排的部分是專門針對AWS的,並且使用的方法不能遷移到其他雲環境中。如果AWS環境不適合你的模型部署,請直接跳到Kubernetes的部分。

Docker

Docker和其他平臺即服務工具提供了稱爲容器的虛擬化概念。容器在主機操作系統之上運行,但是爲容器內運行的代碼提供了標準化的環境。這種虛擬化方法的主要目標之一是你可以爲目標環境編寫代碼,然後任何運行Docker的系統都可以運行你的容器。

容器是提供類似功能的虛擬機的輕量級替代方案。關鍵區別在於容器的啓動速度要快得多,同時提供與虛擬機相同的隔離級別。另一個好處是,容器可以複用其他容器中的層,這樣就可以更快地構建和共享容器。當你需要在一臺機器上運行相沖突版本的Python運行時或庫時,容器是一個很好的解決方案。

使用docker,你可以編寫一個名爲Dockerfile的文件,該文件用於定義容器的依賴項。構建Dockerfile的結果是一個Docker鏡像,該鏡像打包了運行應用程序所需的所有運行時、庫和代碼。Docker容器是運行應用程序的實例化鏡像。Docker的一個很有用的功能是新鏡像可以在已有鏡像的基礎上構建。對於我們的模型部署,我們將擴展ubuntu:latest鏡像。

本節將展示:如何在EC2實例上設置Docker;編寫Dockerfile來構建第2章中echo服務的鏡像;使用Docker生成鏡像及運行容器。要在EC2實例上安裝Docker,可以使用amazon-linux-extras工具簡化過程。下面的命令將安裝Docker,在EC2實例上啓動服務,並列出正在運行的容器,這裏將返回一個空列表。

sudo yum install -y python3-pip python3 python3-setuptools
sudo yum update -y
sudo amazon-linux-extras install docker
sudo service docker start
sudo docker ps

我們要部署的應用程序是第2章中的echo服務。這個服務是Flask應用程序,它可以解析GET或POST中的msg屬性,並返回一個JSON負載來回顯所提供的消息。這裏與之前應用程序的唯一區別是Flask應用現在運行在80端口上,如下面的echo.py代碼片段的最後一行所示。

# load Flask 
import flask
app = flask.Flask(__name__)
# define a predict function as an endpoint 
@app.route("/predict", methods=["GET","POST"])
def predict():
    data = {"success": False}
    # get the request parameters
    params = flask.request.json
    if (params == None):
        params = flask.request.args
    # if parameters are found, echo the msg parameter 
    if (params != None):
        data["response"] = params.get("msg")
        data["success"] = True
    # return a response in json format 
    return flask.jsonify(data)
  
# start the flask app, allow remote connections
app.run(host='0.0.0.0', port = 80)

現在我們已經安裝了Docker和要容器化的應用程序,我們需要編寫一個Dockerfile來描述如何構建鏡像。下面的代碼片段展示了用於執行此任務的Dockerfile。第一步是使用FROM命令來標識要使用的基本鏡像。ubuntu鏡像提供了一個支持apt-get命令的linux環境。MAINTAINER命令將鏡像維護者的名稱添加到與鏡像關聯的元數據信息中。接下來使用RUN命令安裝python,設置符號鏈接並安裝Flask。對於具有許多Python庫的容器,也可以使用requirements.txt文件。Copy命令將腳本插入鏡像,並將文件放置在根目錄中。最後的命令指定要執行應用程序時要運行的參數。

FROM ubuntu:latest
MAINTAINER Ben Weber  
RUN apt-get update \  
  && apt-get install -y python3-pip python3-dev \  
  && cd /usr/local/bin \  
  && ln -s /usr/bin/python3 python \  
  && pip3 install flask  
  
COPY echo.py echo.py 
ENTRYPOINT ["python3","echo.py"]

編寫Dockerfile之後,你可以使用Docker提供的build命令來創建鏡像。下面的代碼段中展示的第一個命令,顯示瞭如何使用文件./Dockerfile構建標記爲echo_service的鏡像。第二個命令顯示了實例上可用的Docker鏡像列表。輸出將顯示我們用作鏡像基礎的ubuntu鏡像以及新創建的鏡像。

sudo docker image build -t "echo_service" .
sudo docker images

要將鏡像作爲容器運行,我們可以使用下面的代碼段中所示的run命令。-d標誌指定容器應作爲守護進程運行,即使終端關閉,這個守護進程仍將繼續運行。-p標誌會將主機上的端口映射到容器用來通信的端口上。沒有這個設置,我們的容器就無法接收外部連接。ps命令顯示正在運行的容器列表,這個列表現在應包括echo服務。

sudo docker run -d -p 80:80 echo_service
sudo docker ps

爲了測試容器,我們可以使用之前的一套流程,當時我們在Web瀏覽器中使用了EC2實例的外部IP,並將msg參數傳遞給/predict端點。由於我們設置了從主機端口80到容器端口80的端口映射,因此我們可以在開放的Web上直接調用容器。下面的例子顯示了來自echo服務容器的調用和結果。

http://34.237.242.46/predict?msg=Hi_from_docker
{"response":"Hi_from_docker","success":true}

現在,我們完成了Docker鏡像的構建,並將該鏡像作爲容器運行在EC2實例上。儘管這一方法確實提供了隔離機器上不同服務的解決方案,但它沒有提供擴展和容錯功能,而這通常是生產級模型部署所必需的。

GCP上的Kubernetes

谷歌雲平臺提供了一項稱爲谷歌Kubernetes引擎(GKE)的服務,用於服務Docker容器。Kubernetes是最初由谷歌開發的容器編排系統,現已開源。這個平臺的用例覆蓋很大的範圍,但我們將重點關注使用託管版Kubernetes託管我們echo服務的任務。

使用Kubernetes託管Docker容器的流程很像ECS,第一步是將鏡像保存到可以與編排系統對接的Docker私有倉庫(Registry)中。這個私有倉庫服務的GCP版本稱爲容器倉庫(Container Registry)。要將鏡像從AWS上的EC2實例獲取到GCP容器倉庫,我們將再次使用docker login命令。爲使此過程正常進行,你將需要我們在第1章中設置的GCP憑證json文件。下面的代碼段顯示瞭如何將json文件傳遞給docker login命令,標記該鏡像以將其上傳到倉庫, 並將鏡像推送到容器倉庫。

cat dsdemo.json | sudo docker login -u _json_key 
                               --password-stdin https://us.gcr.io
sudo docker tag echo_service us.gcr.io/[gcp_account]/echo_service 
sudo docker push us.gcr.io/[gcp_account]/echo_service

你需要使用完整的谷歌帳戶ID替換此腳本中的gcp_acount參數。執行完這些步驟後,echo服務鏡像應顯示在GCP控制檯的Registry視圖下,如圖4.8所示。通常來說,如果你使用GCP來服務模型,則可能會使用谷歌Compute實例而不是EC2,但是最好練習在不同雲平臺的組件之間對接。

圖4.8:GCP容器倉庫上的echo鏡像

與使用ECS所需的一大堆步驟相比,使用GKE託管容器的過程簡化了許多。我們首先使用GCP控制檯在Kubernetes上設置一個容器,然後將服務公開到開放的Web上。要部署echo服務容器,請從GCP控制檯執行以下步驟:

  1. 找到並選擇“Kubernetes Engine”
  2. 點擊“Deploy Container”
  3. 選擇“Existing Container Image”
  4. 選擇“echo_service:latest”
  5. 分配應用程序名稱“echo-kge”
  6. 點擊“Deploy”

現在我們已經部署了Kubernetes集羣,並準備提供echo服務。在GKE上部署Kubernetes集羣可能需要幾分鐘來設置。部署完成後,你應該能在集羣列表下方看到echo集羣,如圖4.9所示。

圖4.9:通過Kubernetes部署的echo鏡像

要使用該服務,我們需要通過GCP控制檯執行以下步驟,將集羣公開到開放的Web上:

  1. 從GKE菜單中選擇你的集羣
  2. 點擊“Workloads”
  3. 選擇“echo-gke”負載
  4. 選擇“Actions”標籤,然後選擇“Expose”
  5. 對於服務類型,選擇“load balancer”

執行完這些步驟後,集羣將配置一個可用於調用服務的外部IP,如圖4.10所示。GKE將根據需要自動進行負載平衡並擴展服務以匹配負載。

圖4.10:echo服務已部署到開放的Web

http://35.238.43.63/predict?msg=Hi_from_GKE
{"response":"Hi_from_GKE","success":true}

上面的代碼段顯示了使用服務的示例。我們能夠使用GKE快速獲取一個Docker鏡像並將其部署在Kubernetes生態系統中。用Kubernetes託管Docker鏡像的體驗非常好,因爲它是一種可移植的解決方案,可跨多個雲環境運行,並且已被許多開源項目採用。

小結

容器非常適合用來在不同環境下重現你的分析和模型。儘管容器可以在單臺機器上保持依賴項整潔有序,但它的主要好處是讓數據科學家能夠編寫模型端點,而不必擔心容器是怎樣託管的。關注點分離後,我們就更容易與工程團隊合作將模型部署到生產環境中;或者使用本章中展示的方法,數據和應用科學團隊也可以自行將模型部署到生產環境中。

用來服務模型的最佳方法取決於你的部署環境和預期的負載。通常,在一家公司工作時,你只能使用特定的雲平臺,因爲模型服務可能需要與雲中的其他組件(例如數據庫或雲存儲)交互。在AWS中有多種託管容器的選項,而GCP在GKE上整合爲單個解決方案。你主要關心的一個問題是使用無服務器函數技術或彈性容器技術服務模型是否更具成本效益。正確的答案將取決於你需要處理的流量、最終用戶可以忍受的延遲以及需要託管的模型的複雜程度。容器化解決方案非常適合用來服務複雜的模型,並確保你可以滿足延遲要求,但是與無服務器函數方案相比,前者可能需要更多的DevOps開銷。

原文鏈接https://towardsdatascience.com/using-docker-kubernetes-to-host-machine-learning-models-780a501fda49

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章