Help us understand the problem. What is going on with this article?

【Azure】Azure Functionsを使ってみる

はじめに

サーバーレスコンピューティングの代表格、FaaS(Function as a Service)をAzureでやってみたときのメモです。

Azureには"Azure Functions"(関数アプリ)という関数をデプロイするための機能があります。
AWSだと"AWS Lambda"に対応する機能です。

とりあえずローカルで作った何かしらの関数をデプロイするやり方を忘れないようにと思って書き残しておきます。

(やり方はほかにもいくつかあります)

用意するもの

  • Visual Studio Code
    • Azure functions拡張機能
    • Azure Account拡張機能
    • python拡張機能
  • Azure subscription

pythonは3.7.3で作ってます。AzureはMicrosoftのサービスなので(??)、VScodeを使って作ります。
※Azure Functionsの拡張機能はまだプレビュー版みたいです(2020/3/26現在)。以後仕様が変わるかもしれません。

手順

作るのは「年/月/日を入力したら曜日を返す関数」です。

デスクトップに"sample functions"という材料を入れておく用の空のフォルダを作って、その中で作業していきます。
スクリーンショット (400).png

①前作業:azure-functions-core-toolsをインストール

Azure Functions Core Toolsはローカルでターミナルやコマンドプロンプトから関数の開発・テストを行うためのモジュールらしいです。とりあえず最初に入れておきます。

VScodeのターミナルを開いてコマンド打つだけです。

npm install -g azure-functions-core-tools

②関数を作る

続いてターミナルで

func init

と打ちます。
「使用する言語を選んでください」的な画面が出てくるので、'python'を選択します。

すると、フォルダの中にいくつかファイルが生成されます。

これらはデプロイに必要なファイルです。追加のライブラリが必要であればrequirements.txtに追加したりします。

続いて、ターミナルで

func new

と打ちます。
そうすると、「使うテンプレートを選んでください」的な画面が出てきます。

今回はクエリを投げたら何かの値を返してくれる関数を作りたいので、Http triggerを選択します。
「関数の名前を教えて」と言われるので、今回は"WhatDayOfWeek"としておきます。

"sample function"フォルダの中に"WhatDayOfWeek"という名前のフォルダが作られ、中にテンプレートが入っています。
スクリーンショット (423).png

この__init__.pyがクラウド側で行う処理を記述したものです。
テンプレートでは、HTTPリクエストで文字列を投げたら、『Hello 【入力した名前】!』と返ってくる関数になっています。
loggingはログを扱うためのpythonの標準モジュールです。requirements.txtに書いてませんが使えます。(逆に下手に追加するとデプロイできなくなりました。)

加工するのはこの__init__.pyだけでOKです。

__init__.py
import logging

import azure.functions as func

#うるう年かどうかだけを判定する関数
def LeapOrNot(Y):
    if (Y % 4 != 0):
        return False
    elif (Y % 100 != 0):
        return True
    elif (Y % 400 != 0):
        return False
    else:
        return True

#閏年の回数判定 基準は1970年1月1日木曜日
def HowManyLeap(Y):
    mul4 = Y // 4 - 492 #492 = 1970 // 4
    mul100 = Y // 100 - 19 # 19 = 1970 // 100
    mul400 = Y // 400 - 4 # 4 = 1970 // 400
    return mul4 - mul100 + mul400

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')
    days = ['Thu', 'Fri', 'Sat', 'Sun', 'Mon', 'Tue', 'Wed']
    day_num = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

    Year = req.params.get('Year')
    Month = req.params.get('Month')
    Date = req.params.get('Date')

    if not (Year and Month and Date):
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            Year = req_body.get('Year')
            Month = req_body.get('Month')
            Date = req_body.get('Date')

    Y = int(Year)
    M = int(Month)
    D = int(Date)

    #edit validation
    if Y < 1970:
        return func.HttpResponse('1970年以前には対応していません',status_code=400)
    elif M > 12:
        return func.HttpResponse('日付が間違っています',status_code=400)
    elif LeapOrNot(Y):
        if M == 2:
            if day_num[M-1] + 1 < D:
                return func.HttpResponse('日付が間違っています',status_code=400)
        elif day_num[M-1] < D:
            return func.HttpResponse('日付が間違っています',status_code=400)
    else: 
        if day_num[M-1] < D:
            return func.HttpResponse('日付が間違っています',status_code=400)

    #経過日数を計算
    passed_num = (Y - 1970) * 365 + sum(day_num[:M-1]) + D - 1
    if LeapOrNot(Y) and M > 2:
        leap_num = HowManyLeap(Y)
    elif LeapOrNot(Y):
        leap_num = HowManyLeap(Y-1)
    else:
        leap_num = HowManyLeap(Y)

    return func.HttpResponse('{}'.format(days[(passed_num + leap_num) % 7]))

これで関数自体はできました。
"sample function"フォルダ内でfunc newを打てば、また別の関数を作ることもできます。

(③)ローカルでテスト

ちゃんと期待した動作ができているかテストしたい場合は

func start

とやれば、フォルダ内のすべての関数に対して
WhatDayOfWeek: [GET,POST] http://localhost:7071/api/WhatDayOfWeek
といったようなURLが得られます。
これを使えば、
http://localhost:7071/api/WhatDayOfWeek?Year=2020&Month=3&Day=26
とパラメータを投げてThuと返ってくるといったテストが行えます。

④クラウドにデプロイ

ローカルで関数を完成させたらデプロイです。

Azure系の拡張機能を入れると、VScodeのアクティビティバーからAzure系の機能を使えるようになります。サイドバーに"FUNCTIONS"が出てくるので、そこから"Local Project"->"Functions"でローカルで作られた関数が表示されるはずです。

ここで赤枠で示した部分からデプロイできます。(Azureアカウントにloginしてなければここでログインが必要です。)
このボタンだけで、"Local Project"内に入っている関数がまとめてデプロイできます。

ここからはAzure上でのデプロイ作業をVScodeから操作します。
(Azure portalでリソースを一通り作っておけば元々あるAzure Functionsのリソースにそのままデプロイするだけなのですぐです。)

一から作っていきます。

<1> +Create new Function App in Azure (Advanced)

新しい関数アプリを作るかどうか聞かれます。ログインしているサブスクリプションで作った関数アプリが表示されるので、あらかじめ作っておけば、ここでそれを選ぶだけです。
"Advanced"と書いてない方もありますが、そちらの方が設定事項が少ないです。

<2> 関数アプリの名前を入力

Azure上で作る関数アプリの名前を聞かれるので、入力します。ここでは"samplefunctions"としておきます。
この名前は'globally unique'でなければいけないらしいですが、この名前で作れるということはあまり利用者がいない説??

<3> 言語選択

関数アプリで使う言語を選択します。node.jsやjavaなどが選択できますが、ここではpythonにします。ローカルで作ったときにも聞かれたのにここでも聞かれるの?とは思う

<4> 課金プラン選択

"Select a hosting plan"と出てきます。これは課金プランのことで、Azureの公式ドキュメントに詳しく書いてあります。
ざっくり言うと、

  • 関数の実行ごとに課金(従量課金,「Consumption」)
  • 立てたインスタンスごとに課金(「Premium」)
  • ほかのwebサービスと同一の課金制度にする(「App Service Plan」)

の3択です。
従量課金が一番FaaSっぽい?という所感。今回はConsumptionにしておきます。

<5> リソースグループを選択

関数アプリが所属するリソースグループを選びます。新しく作ると、おそらく作るリージョンとか聞かれるかと思いますが、ここでは元々あるものを使います。

<6> ストレージアカウントを選択

データを入れるストレージです。これも元々あるやつを使います。

<7> Application Insightsを選択

Application Insightsは関数の監視モニター的なものです。ログやパフォーマンス状況が見れるみたいです。(公式ドキュメント

元々他のApp Serviceで作ってあれば、それを選択して統合することもできるみたいです。
これはSkipできるので、とりあえず関数を作りたいだけならいらないかもしれないです。

ここまでやると、デプロイが開始されます。
デプロイ中のログはVScodeの"出力"から見ることもできます。
スクリーンショット (420).png

⑤作った関数を使ってみる

"Deployment to ~~ completed"と出ればデプロイ終了です。
この時点でAzure portalから関数のページを見ることもできます。
スクリーンショット (421).png
この画面で"URL"をクリックすれば、「あなたの関数は動いてますよ!」的な画面が出てくるはずです。

関数のURLは、VScodeの方から、【サブスクリプション名】->【作った関数名】->"Functions"->【関数名】を右クリックから、"Copy Function Url"で取得できます。

ローカルで適当にpythonコードを作って実験してみます。

python
import requests

url = "【取得したURL】"

param = {'Year':2020,'Month':3,'Date':26}

res = requests.get(url, params = param)

print(res.text)

☟結果

Thu

さいごに

AzureでFaaSを使う際、すべてCLIでやるやり方もあるらしいです。
自分も結構理解はあやふやです。公式ドキュメントを見ながら試行錯誤してましたが苦労しました。
「とりあえず関数作ってデプロイ」がやりたいだけならこんなもんかな、と思います。

kyamada101
大学で機械学習・深層学習関連の研究をしています。専門はNLP(自然言語処理)ですが、画像処理をいじったりもしています。
https://github.com/kyamada101
InoueLab
確率的な情報処理について研究する研究室のリソースとサーバーを管理・保守・運用する学生団体
http://www.inoue.eb.waseda.ac.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away