konchangakita

KPSを一番楽しんでいたブログ 会社の看板を背負いません 転載はご自由にどうぞ

【Xi IoT】Flask を Kubernetes Apps で Hello World

Python で Webアプリケーション作成するにはFlask使うと良いって聞きました
Flask よくわからないけど、いつもどおりとりあえず触りながら理解していってみたいと思います

f:id:konchangakita:20200606174731p:plain

flask.palletsprojects.com

anaconda 環境にFlask をインストール

いつもの ANACONDA 環境にインストールします
ANACONDA GUI上に Flask がいますので、選んでインストールしてやるだけ!簡単!
f:id:konchangakita:20200606141616p:plain


本家サイトの Quickstart を参照しながら、さっそく Jupyter Notebook で実行してみましょう
f:id:konchangakita:20200606175206p:plain

とりあえず、http://127.0.0.1:5000/ で Listen 開始したようで、ブラウザからアクセスしてみます
これまた簡単に接続できました
f:id:konchangakita:20200607142806p:plain

PowerShell 上から Curl してみると、こんな感じ

PS > curl http://127.0.0.1:5000

StatusCode        : 200
StatusDescription : OK
Content           : はろーわーるど
RawContent        : HTTP/1.0 200 OK
                    Content-Length: 21
                    Content-Type: text/html; charset=utf-8
                    Date: Sat, 06 Jun 2020 08:56:32 GMT
                    Server: Werkzeug/1.0.1 Python/3.8.1

                    はろーわーるど
Forms             : {}
Headers           : {[Content-Length, 21], [Content-Type, text/html; charset=utf-8], [Date, Sat, 06 Jun 2020 08:56:32 G
                    MT], [Server, Werkzeug/1.0.1 Python/3.8.1]}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 21


Flask 入りの Docker コンテナを作成

次に Dockerコンテナ上で Flask を稼働にチャレンジです

シンプルにコンテナ化

まずはシンプルな Dockerfile を作成
Python3.7コンテナイメージをベースに flask を pip でインストールしてやる感じです

FROM python:3.7
  
RUN python -V
RUN pip install -U pip

RUN pip3 install flask

コンテナイメージを作ってコンテナスタート!

> docker build -t flask .
> docker run --rm -it flask /bin/bash

コンテナの中に先ほどの pythonコードを "/home/app.py" の名前で設置して
Flask のお作法の "export FLASK_APP=/home/app.py" を定義してやります

root@f609e08142ec:/home# ls
app.py
root@f609e08142ec:/home# export FLASK_APP="/home/app.py"
root@f609e08142ec:/home# env
HOSTNAME=f609e08142ec
PYTHON_VERSION=3.7.6
(省略)
FLASK_APP=/home/app.py
(省略)
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
OLDPWD=/
_=/usr/bin/env


Flask の実行

root@f609e08142ec:/home# flask run

f:id:konchangakita:20200606184231p:plain
(WARNINGは、export FLASK_ENV=development してやるとよさそう)

別のコンソールから同じにコンテナにはいって動作確認

> docker exec -it コンテナID /bin/bash
root@f609e08142ec:/# curl http://127.0.0.1:5000
はろーわーるど

(備考)
検証用にはローカルのフォルダをコンテナでマウントしておけば、ローカルのエディタで変更したら即反映されるのでラク、あと
<docker run --rm -p ホストポート:コンテナポート -v ローカルフォルダ:コンテナフォルダ -it イメージ名 シェル>

PS > docker run --rm -v "$(pwd)\app:/home" -it flask /bin/bash


次にコンテナの外からのブラウザアクセスする為の設定を
 ・外向けのコンテナポートを開ける
 ・Flaskを 0.0.0.0 で Listen

完成版の Dockerfile

こんな感じでコンテナを作り直しまして

FROM python:3.7
  
RUN python -V
RUN pip install -U pip
RUN pip install flask

# flaskインスタンスのpythonコードの場所
COPY ./app/ /home/
ENV FLASK_APP=/home/app.py

CMD ["flask", "run", "--host=0.0.0.0"]

コンテナ起動(35000は適当です)

PS >docker run --rm -p 35000:5000 -it flask

これで docker 上 Flask に Webブラウザで接続できました
http://localhost:35000/

最後に Dockerhub に push しておきます

PS > docker tag c2b7f90d9f88 konchangakita/flask-app
PS > docker push konchangakita/flask-app


Xi IoT の Kubernetes Apps に Flaskコンテナをデプロイ

Xi IoTのKubernetes Appsで扱うにはちょっと一工夫に必要になります
まずは、Kubernetes 形式の yaml を書いてみます
シンプルに書くとこんな感じになるかと

apiVersion: v1
kind: Service
metadata:
  name: flask-app
spec:
  selector:
    app: flask-app
  ports:
  - name: flask-http
    port: 5000
    targetPort: 5000
    protocol: TCP
---
apiVersion: "apps/v1"
kind: "StatefulSet"
metadata:
  name: flask-app
spec:
  serviceName: flask-app
  selector:
    matchLabels:
      app: flask-app
  replicas: 1
  template:
    metadata:
      name: flask-app
      labels:
        app: flask-app
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: flask-app
        image: konchangakita/flask-app:latest
        ports:
        - containerPort: 5000


Xi IoT の Kubernetes Apps では、nodePort は使えないようなので、Web ブラウザで外部から接続するためのポートを定義してやる必要があります

Listen するポートを socat のこんな感じのおまじない書くと繋ぐことできるようです
(この辺りはもうちょっと深いとこお勉強していきたいと思います)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-front
spec:
  selector:
    matchLabels:
      app: flask-front
  template:
    metadata:
      labels:
        app: flask-front
    spec:
      containers:
      - name: flask-front
        image: alpine/socat
        args: ["TCP-LISTEN:1234,fork,reuseaddr","TCP:flask-app:5000"]
        ports:
        - containerPort: 1234
          hostPort: 1234

上の例では、Service Domain(Edge上)ポート1234 で Listen し、Flask自身の ポート5000 へフォワーディングしています

Kubernetes Apps 用のyaml

まとめるとこうなります


Kubernetes Apps へ登録

Xi IoTポータル上の Kubernetes Apps へ登録
f:id:konchangakita:20200607025309p:plain

Flask を動かしたい Project と Service Domain を選びましょう
f:id:konchangakita:20200607025848p:plain

yaml をアップロード or 貼り付け
f:id:konchangakita:20200607025413p:plain

Deploying が終わると Flask と socat の2つのコンテナが動いています
f:id:konchangakita:20200607030128p:plain


Webブラウザで確認

http://<ServiceDomainのIP>:1234
f:id:konchangakita:20200607030311p:plain
無事接続確認

今回はただただWebブラウザに表示するだけでかなり手間取ったので
なんらかの処理をさせるのは次から