🍇

Azure Functionsの基本的な使い方 with Python

2025/03/04に公開

この記事の目的

Azure Functionsは様々なアップデートを経て使い方が変わっており、新旧の情報がネット上で入り混じっていたり、公式のドキュメントは言葉足らずだったりで使い始める際の嵌まりのあるポイントサービスです。

この記事では以下のような前提で「ふつうに」Azure Functionsを開発してデプロイするための手順をまとめます。

今回の前提:

  • Ubuntu22.04
  • Python 3.X
  • HTTPトリガーで簡易なREST API関数を追加する

2024/12月時点の情報に基づいています。

環境を整える

Pythonの仮想環境を作る

pyenvでもvenvでもよいので、Python環境を整えます。
後で作るAzure上のランタイムとバージョンを合わせるためにここでは 3.11.10 をpyenvでインストールすると仮定します。

pyenv install 3.11.10
cd (作業ディレクトリ)
pyenv local 3.11.10

pyenvのインストールについては以下をご参照ください。
https://github.com/pyenv/pyenv?tab=readme-ov-file#linuxunix

Azure Functions Core Tools4のインストール

こちらのリンクを参考にAzure Functions Core Toolsをインストールします。

マイクロソフトリポジトリをaptサーバに追加します。

curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-$(lsb_release -cs 2>/dev/null)-prod $(lsb_release -cs 2>/dev/null) main" > /etc/apt/sources.list.d/dotnetdev.list'

aptパッケージリストをアップデートします。

sudo apt-get update

Core Tools4をインストールします

sudo apt-get install azure-functions-core-tools-4

(Optional)OpenSSL1.1のインストール

インストールが完了したら funcコマンドを実行してみてください。

No usable version of libssl was found

というメッセージが表示された場合、適したバージョンのOpenSSLがインストールされていません。
Ubuntu22.04の標準OpenSSLパッケージは3.0ですが、以下のページの手順でOpenSSL1.1をインストール可能です。

https://zenn.dev/mizti/articles/2f53f012b2c842

プロジェクトの骨組みを作る

プロジェクトの作成

Core Toolsを使ってAzure Functionsのプロジェクトを作ります。

func init my-function-app --worker-runtime python --model V2

これによって、以下のようなファイル構成のディレクトリが作成されます。

my-function-app/
├── function_app.py
├── host.json
├── local.settings.json
└── requirements.txt

作成したプロジェクトディレクトリに入ります。このプロジェクトがデプロイ時には「関数アプリ」に対応します。

cd my-function-app
Pythonのプログラミングモデルv1/v2について

AzureでPythonを動作させる場合、プログラミングモデルv1とv2が存在しており、現在の主流はv2です。しかし、テンプレートから作成される関数はプログラミングモデルv1となっています。
大きな違いはv1はfunctions.jsonでトリガーや出力を定義し、v2はPythonのメソッドへのアノテーションで定義を行うためfunctions.jsonが不要な点となります。

また、v1ではプロジェクトディレクトリ内に関数ごとのディレクトリを作成し__init__.pyを作りますが、v2ではルートディレクトリにあるfunction_app.pyにすべての関数を原則的に記載する点も異なります。(適宜関数定義をpythonの参照を使って外部ファイルに書き出すことは可能です)

  • Pythonプログラミングモデルv2 (参考)

(参考: Functionsの構造について)

プログラミングモデルv1とv2の違いについては以下の記事でもまとめておりますのでご参考ください。

https://zenn.dev/mizti/articles/9d654741f81b25

HTTP関数の追加

このプロジェクトに各関数を追加していきます。この関数もまずはテンプレートによって追加していきます。
まず、利用できるテンプレートの一覧を確認します。

$ func templates list
テンプレートの一覧

C# Templates:
Azure Blob Storage trigger
Azure Cosmos DB trigger
Durable Functions activity
Durable Functions entity (class)
Durable Functions entity (function)
Durable Functions Entity HTTP starter
Durable Functions HTTP starter
Durable Functions orchestrator
Azure Event Grid Cloud Event trigger
Azure Event Grid trigger
Azure Event Hub trigger
HTTP trigger
IoT Hub (Event Hub)
Kafka output
Kafka trigger
Azure Queue Storage trigger
RabbitMQ trigger
SendGrid
Azure Service Bus Queue trigger
Azure Service Bus Topic trigger
SignalR negotiate HTTP trigger
SQL Input Binding
SQL Output Binding
SQL Trigger
Timer trigger

Custom Templates:
Azure Blob Storage trigger
Azure Cosmos DB trigger
Azure Event Grid trigger
Azure Event Hub trigger
HTTP trigger
IoT Hub (Event Hub)
Kafka trigger
Azure Queue Storage trigger
RabbitMQ trigger
SendGrid
Azure Service Bus Queue trigger
Azure Service Bus Topic trigger
SignalR negotiate HTTP trigger
Timer trigger

JavaScript Templates:
Azure Blob Storage trigger
Azure Cosmos DB trigger
Dapr Publish Output Binding
Dapr Service Invocation Trigger
Dapr Topic Trigger
Durable Functions activity
Durable Functions entity
Durable Functions Entity HTTP starter
Durable Functions HTTP starter
Durable Functions orchestrator
Azure Blob Storage Trigger (using Event Grid)
Azure Event Grid trigger
Azure Event Hub trigger
HTTP trigger
IoT Hub (Event Hub)
Kafka output
Kafka trigger
Azure Queue Storage trigger
RabbitMQ trigger
SendGrid
Azure Service Bus Queue trigger
Azure Service Bus Topic trigger
SignalR negotiate HTTP trigger
SQL Input Binding
SQL Output Binding
SQL Trigger
Timer trigger
Azure Blob Storage trigger
Azure Cosmos DB trigger
Durable Functions entity
Durable Functions orchestrator
Azure Blob Storage trigger (using Event Grid)
Azure Event Grid trigger
Azure Event Hub trigger
HTTP trigger
Azure Queue Storage trigger
Azure Service Bus Queue trigger
Azure Service Bus Topic trigger
Timer trigger
Dapr Publish Output Binding
Dapr Service Invocation Trigger
Dapr Topic Trigger

PowerShell Templates:
Azure Blob Storage trigger
Azure Cosmos DB trigger
Dapr Publish Output Binding
Dapr Service Invocation Trigger
Dapr Topic Trigger
Durable Functions activity
Durable Functions HTTP starter
Durable Functions orchestrator
Azure Blob Storage Trigger (using Event Grid)
Azure Event Grid trigger
Azure Event Hub trigger
HTTP trigger
IoT Hub (Event Hub)
Kafka output
Kafka trigger
Azure Queue Storage trigger
RabbitMQ trigger
SendGrid
Azure Service Bus Queue trigger
Azure Service Bus Topic trigger
SignalR negotiate HTTP trigger
SQL Input Binding
SQL Output Binding
SQL Trigger
Timer trigger

Python Templates:
Azure Blob Storage trigger
Azure Cosmos DB trigger
Dapr Publish Output Binding
Dapr Service Invocation Trigger
Dapr Topic Trigger
Durable Functions activity
Durable Functions entity
Durable Functions HTTP starter
Durable Functions orchestrator
Azure Blob Storage Trigger (using Event Grid)
Azure Event Grid trigger
Azure Event Hub trigger
HTTP trigger
Kafka output
Kafka trigger
Azure Queue Storage trigger
RabbitMQ trigger
Azure Service Bus Queue trigger
Azure Service Bus Topic trigger
SQL Input Binding
SQL Output Binding
SQL Trigger
Timer trigger

TypeScript Templates:
Azure Blob Storage trigger
Azure Cosmos DB trigger
Durable Functions activity
Durable Functions entity
Durable Functions Entity HTTP starter
Durable Functions HTTP starter
Durable Functions orchestrator
Azure Blob Storage Trigger (using Event Grid)
Azure Event Grid trigger
Azure Event Hub trigger
HTTP trigger
IoT Hub (Event Hub)
Kafka output
Kafka trigger
Azure Queue Storage trigger
RabbitMQ trigger
SendGrid
Azure Service Bus Queue trigger
Azure Service Bus Topic trigger
SignalR negotiate HTTP trigger
SQL Input Binding
SQL Trigger
Timer trigger
Azure Blob Storage trigger
Azure Cosmos DB trigger
Durable Functions entity
Durable Functions orchestrator
Azure Blob Storage trigger (using Event Grid)
Azure Event Grid trigger
Azure Event Hub trigger
HTTP trigger
Azure Queue Storage trigger
Azure Service Bus Queue trigger
Azure Service Bus Topic trigger
Timer trigger

func new --template "Http Trigger" --name my_http_func

すると

Select a number for Auth Level:
1. FUNCTION
2. ANONYMOUS
3. ADMIN
Choose option: 

と聞かれるため、ここでは1(FUNCTION)を選んでおきます。これは関数のセキュリティレベルを選択するもので、FUNCTIONの場合、各関数ごとに発行される関数キーがリクエストに必要になります。

ローカル実行する

デプロイに先立ちまずはローカルで実行します。

func start

上記を実行すると以下のようにサーバが起動します。

リクエストをしてみます

curl http://localhost:7071/api/my-http-func
This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.

というレスポンスが戻ってきて正常にAPIリクエストが捌かれていることがわかります。

POSTリクエストも投げてみます。

curl -X POST -d '{"name":"John"}' http://localhost:7071/api/my-http-func
Hello, John. This HTTP triggered function executed successfully.

name要素で与えた名前が戻ってきます。(ローカルで実行しているときは認証不要です)

Azure側のリソースを作成する

デプロイする

func azure functionapp publish $FUNCTION_APP_NAME

Azure上にデプロイされた関数にアクセスする

関数の認証レベルには以下の三種類があります。

認証レベル 意味
Function(デフォルト) 関数キーが必要
Admin 関数アプリ全体のキー(マスターキー)が必要
Anonymous 認証なしでアクセス可能

テンプレートで作成されたHTTPは認証レベルが "authLevel": "function" に設定されています。このためAzure上にデプロイされたFunctionにアクセスする際には関数キーを付与してリクエストする必要があります。

鍵の取得コマンド

az functionapp keys list --name $FUNCTION_APP_NAME --resource-group $RESOURCE_GROUP_NAME

ポータルで関数を選択>関数キーからでも確認可能です。

GETリクエストをしてみます。

curl https://$FUNCTION_APP_NAME.azurewebsites.net/api/my-http-func?code=$FUNCTION_KEY

POSTリクエストをしてみます。

curl -X POST -H "Content-Type: application/json" -H"x-functions-key: $FUNCTION_KEY" -d '{"name":"John"}' https://$FUNCTION_APP_NAME.azurewebsites.net/api/my-http-func

ログを確認する

ログの種類ごとに確認方法が異なります。

基盤ログ確認 (Premiumプランのみ)

基盤側で出力されているデプロイログ等のログです。

  1. リアルタイムなログ確認
az webapp log tail --name $FUNCTION_APP_NAME --resource-group $RESOURCE_GROUP_NAME

過去ログ数十行が表示された後、同ログの最新をストリームで表示し続けます。
このログはデプロイに関するログや、Functionのトリガー、出力などを含んでいるためこのログを見るだけでも一応デバッグ等も可能ではありますが、出力が多すぎるためアプリケーションのデバッグには後述の方法を併用することもお勧めします。

  1. Kuduサイトによる確認
    https://{$FUNCTION_APP_NAME}.scm.azurewebsites.net/ にアクセスすると、以下のような画面が表示されます。


この画面のLog Streamタブから1.と同様のログを確認できます。

アクセスログの確認

HTTPアクセスログは関数アプリに連携しているApplication Insights(内のLog Analytics)のrequestsテーブルに保存されています。
関数アプリの左メニュー > 監視 > ログからアクセスし、requestsテーブルをリクエストすることでログを確認できます。

※ログ出力がLog Analyticsに反映されるまで30秒~1分程度時間を要します。

Log AnalyticsへのクエリはKQLと呼ばれるクエリ言語で行います。テーブル内容をまとめてみる以上の高度なクエリを作りたい場合には以下をご参照ください。
https://learn.microsoft.com/ja-jp/training/modules/explore-fundamentals-kql/4-kql-query-structure

アプリケーションログの確認

print()logging.info等で出力されたアプリケーションログを確認したい場合にはアクセスログと同様にLog Analyticsのtracesテーブルで確認することができます。

例外ログの確認

アプリケーションで発生した例外はLog Analyticsのexceptionsテーブルで確認が可能です。このテーブル内のinnermostMessageテーブルがアプリから送信された生のスタックトレースを保持しています。

保存されているメッセージの例

Result: Failure
Exception: SyntaxError: unmatched ')' (init.py, line 10)
Stack: File "/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/dispatcher.py", line 535, in _handle__function_load_request
func = loader.load_function(
File "/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/utils/wrappers.py", line 44, in call
return func(*args, **kwargs)
File "/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/loader.py", line 220, in load_function
mod = importlib.import_module(fullmodname)
File "/usr/local/lib/python3.11/importlib/init.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 846, in exec_module
File "<frozen importlib._bootstrap_external>", line 983, in get_code
File "<frozen importlib._bootstrap_external>", line 913, in source_to_code
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed

開発に入る

ここまでの確認できた後でテンプレートを修正しながら具体的なPythonコード開発に入るのが良いと思います。

参考

Discussion