flaskで機械学習の学習済みモデルを入れてkubenetes上で動かしてみた。
curlで投げて、予測結果を受け取る形式だけど、envoyとかスケーラビリティも意識した構成になってる。
kubenetes上での flask動作環境
目次
1.flaskアプリケーションの作成
2.Docker上でflaskを動かす
3.GKEのkubenetesでflaskを動かす
4.GKEのflask動作環境
5.minikubeのメモ
1.flaskアプリケーションの作成
# 仮想環境作成 $ Python3.7 -m venv venv && source venv/bin/activate $ pip install -r requirements.txt
projectフォルダ内のファイルの役割
・__init___.py
App = Flask(__name__)
でFlask本体を作る
Server.py単体でも動く。
・views.py
http://~でリクエストがあった時の処理
@app.route(‘/’)でhttpにリクエストがあったことをしめす
@app.route(‘/post’)とかは「https://~/post」とURLの後にその文字列をつける
・server.py
"python server.py" でHTTPにアクセスした時にする処理
rom flask import Flask, jsonify, request import requests import numpy as np import cv2 import json from flasks.predict import predict app = Flask(__name__) @app.route("/", methods=['GET']) def hello(): return "Hellos !" @app.route('/reply', methods=['GET', 'POST']) def reply(): if request.method == 'POST': data = request.data.decode('utf-8') url = json.loads(data)['key'] resp = requests.get(url, stream=True).raw img = np.asarray(bytearray(resp.read()), dtype="uint8") img = cv2.imdecode(img, cv2.IMREAD_COLOR) pred = predict(img) return int(pred) if __name__ == "__main__": app.run(host='0.0.0.0',port=5000,debug=True)
・configファイル(config.py)
環境・設定情報を書く
DEBUG =True
・ディレクトリ構成図
$ tree ├── Pipfile ├── Pipfile.lock ├── flasks │ ├── __init__.py │ ├── config.py │ |└── views.py ________templates └── server.py
・html系の「templates」ファルダ
=>views.py返す処理(レンダリング)のhtmlやCSSその他を置く場所
Djangoとほぼ同じ仕組みだけど、かなり簡単な構成になってる。
2.Docker上でflaskを動かす
今回はtensorflow-gpuを入れた。
Dockerfile
FROM tensorflow/tensorflow:devel-gpu RUN mkdir /home/app WORKDIR /home/app/ COPY requirement.txt /home/app/ RUN pip install --upgrade pip RUN pip install -r /home/app/requirement.txt ADD server.py /home/app/ ADD flasks /home/app/flasks ADD Pipfile /home/app/ ADD Pipfile.lock /home/app/ CMD ["python", "server.py"]
Makefileでコマンドをまとめて簡略化
Makefile
build: docker build -t flasks . run: docker run -p 5000:5000 -it flasks
# dockerイメージ作成 $ make build # コンテナ起動 $ make run
curl画像のURLをPOSTして、予測結果を受けってみる
# 試す curl -X POST -H "Content-Type: application/json" -d ‘{"key":"http://tore~e.jpg"}' http://localhost:5000/flask >>> 16
返ってきた。
$ curl -F "file=@test.png" http://localhost:5000/flask
3. GKEのkubenetesでflaskを動かす
全部GCPのターミナルで動かす。
# dockerイメージ作成 $ docker build -t gcr.io/[プロジェクト名]/flask . # GCRにdockerイメージのpush $ docker push gcr.io/[プロジェクト名]/flask
クラスタをGUIで作成した後のコマンド。
yamlファイルとかflaskのアプリケーションをuoloadしておく。
# クラスタのアクセス権取得 $ gcloud container clusters get-credentials cluster-1 --zone us-central1-c # yamlファイル実行 $ kubectl apply -f ~.yaml # flaskが動いてるか確認 $ kubectl get service
# curlでPOSTしてみる $ curl -X POST -H "Content-Type: application/json" -d ‘{"key":"http://tore~e.jpg"}' http://[EXTERNAL-iP]/flask >>> 16
正常に動いてる。
4.GKEのflask動作環境
外部からcurlとかでアクセスして、予測結果を受け取る形式になっている。
Podを多くしてもスケーラビリティが悪くならないようにenvoyを使った。
envoyを使うとPod数が多くても綺麗に分散される
再度動作環境の全体像
4.minikubeのメモ
minikubeはローカルでもkubectlコマンドも使えるkubenetesと同じ環境を簡単に作れて、動かすことができる。
GCPとかでいちいち動かすのが億劫なら、仮想環境に入れとくと便利。
# kubectl install $ brew update && brew install kubectl # minikube install $ brew install minikube # バージョン確認 minikube version #起動 minikube start # minikube削除 $ minikube delete
バックエンドは門外漢に近いけど、flaskとかkubenetesに詳しくなったとか、いいスキル習得になった。
参考記事
・kubernetesでgRPCするときにenvoy挟んでみたよ
・PIL を使って GCS にある画像を動的にリサイズして送信する
・BytesIO(およびStringIO、cStringIO)の使い方【初心者向け】
追記
・シンボリックリンクについて
■シンボリックリンク
・ファイルやフォルダの代理人ファイル
・元のファイルとシンボリックリンクは別物
・シンボリックリンクを削除しても元のファイルに影響はない
・どこにでも作れる
・フォルダに対しても作れる■ハードリンク
・ファイルに付けたあだ名
・元のファイルとハードリンクは(ほぼ)同じ物
・状況によっては、ハードリンクが削除されると元のファイルも削除される
・同じパーティションにしか作れない
・フォルダに対しては作れない