アプリとサービスのすすめ

アプリやIT系のサービスを中心に書いていきます。たまに副業やビジネス関係の情報なども気ままにつづります

GKEのkubenetes上でflaskを動かし、curlでPOSTした画像の予測結果を受け取る【機械学習】

flaskで機械学習の学習済みモデルを入れてkubenetes上で動かしてみた。

curlで投げて、予測結果を受け取る形式だけど、envoyとかスケーラビリティも意識した構成になってる。

kubenetes上での flask動作環境
f:id:trafalbad:20200417224845j:plain


目次
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

返ってきた。


普通のpngとかの画像をcurlで投げるコマンドはこれ

$ 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

f:id:trafalbad:20200417225002j:plain

# 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数が多くても綺麗に分散される
f:id:trafalbad:20200417225020p:plain


再度動作環境の全体像
f:id:trafalbad:20200417224845j:plain



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挟んでみたよ

Dockerfile-GCS

PIL を使って GCS にある画像を動的にリサイズして送信する

BytesIO(およびStringIO、cStringIO)の使い方【初心者向け】


追記


シンボリックリンクについて

シンボリックリンク
・ファイルやフォルダの代理人ファイル
・元のファイルとシンボリックリンクは別物
シンボリックリンクを削除しても元のファイルに影響はない
・どこにでも作れる
・フォルダに対しても作れる

■ハードリンク
・ファイルに付けたあだ名
・元のファイルとハードリンクは(ほぼ)同じ物
・状況によっては、ハードリンクが削除されると元のファイルも削除される
・同じパーティションにしか作れない
・フォルダに対しては作れない


参考サイト:シンボリックリンク(英:symbolic link)とは