はじめに
Azure Functions(Python)で消費プランを使用したデプロイにとても苦戦したので、デプロイできないときに見直すと良いポイントをまとめます。
この記事では、実際に遭遇したトラブルとその解決策を詳しく解説します。
基本的なデプロイ前チェック項目
1. Azure Functions バージョンの確認
最も重要な確認ポイント
Azure Functionsには大きく分けてv1とv2(v2プログラミングモデル)があり、設定方法が大きく異なります。
v1の特徴
-
function.jsonファイルでバインディングを定義 - 従来のディレクトリ構造(関数ごとにフォルダ分け)
- レガシーな設定方法
v2の特徴
- Pythonコード内でデコレータを使用してバインディングを定義
- シンプルなプロジェクト構造
- モダンなPythonの書き方に対応
確認方法
Azure Portal の関数アプリ設定で「FUNCTIONS_WORKER_RUNTIME」と「FUNCTIONS_EXTENSION_VERSION」を確認してください。
対処法
プロジェクトのバージョンと関数アプリの設定を一致させ、対応するドキュメントに従って開発を進めてください。
2. 消費プランとフレックス消費プランの違いを理解する
消費プラン
- 料金: 実行時間とメモリ使用量に基づく従量課金
- 制約: 実行時間10分まで、メモリ1.5GBまで
- 特徴: 完全なサーバーレス、自動スケーリング
フレックス消費プラン
- 料金: より柔軟な課金体系
- 制約: より高いリソース制限
- 特徴: より高度な設定オプション
重要: プランによってデプロイ方法、環境変数の設定方法、ログの扱いが異なります。
よくある設定不備とその解決策
3. AzureWebJobsStorage接続文字列の設定不備
これが原因の場合のエラー例
The host.json file is missing a required connection string value for 'AzureWebJobsStorage'.
詳細な原因
Azure Functionsの動作メカニズムを理解することが重要です:
- 関数コードの保存: デプロイされた関数コードはBlob Storageに保存される
- 実行時読み込み: 関数実行時にBlobから必要なファイルを読み込む
- ログ保存: 実行ログや状態情報もBlobに保存される
- 内部状態管理: Azure Functions自体の内部状態もこのストレージを使用
設定手順
- Azure Portal で関数アプリを選択
- 「設定」→「構成」→「アプリケーション設定」
-
AzureWebJobsStorageの値を確認 - 正しい形式の接続文字列を設定:
DefaultEndpointsProtocol=https;AccountName=<ストレージアカウント名>;AccountKey=<アクセスキー>;EndpointSuffix=core.windows.net
追加注意点
- ストレージアカウントは関数アプリと同じリージョンに配置することを推奨
- アクセス制限がある場合は、関数アプリからのアクセスを許可する設定が必要
4. PYTHONPATH問題の詳細解決
問題が発生するケース
プロジェクト構造例:
/home/site/wwwroot/
├── requirements.txt
├── host.json
├── function_app.py # メイン関数
└── src/
├── __init__.py
├── utils.py # 自作ユーティリティ
└── models.py # データモデル
この構造でfunction_app.pyからsrc.utilsをインポートしようとすると失敗します。
Pythonモジュール検索の詳細
Azure Functions実行時のPythonパス解決順序:
-
組み込みモジュール:
sys,osなど -
標準ライブラリ:
json,datetimeなど -
カレントディレクトリ:
/home/site/wwwroot -
site-packages:
pip installされたパッケージ - PYTHONPATH: 環境変数で指定されたパス
解決策
方法1: PYTHONPATHの設定
Azure Portal の関数アプリ設定で環境変数を追加:
- 名前:
PYTHONPATH - 値:
/home/site/wwwroot/src
方法2: プロジェクト構造の変更(推奨)
/home/site/wwwroot/
├── requirements.txt
├── host.json
├── function_app.py
├── utils.py # 直接配置
└── models.py # 直接配置
方法3: __init__.pyとパッケージ化
srcディレクトリを適切なPythonパッケージとして設定し、sys.pathを動的に追加:
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), 'src'))
デバッグとログ設定の重要性
5. ログストリームの詳細設定と活用
ログの流れと仕組み
関数実行 → Function Host → ログストリーム表示
↓
Application Insights → 永続化・分析
設定手順
Step 1: Application Insightsの有効化
- Azure Portal で関数アプリを選択
- 「監視」→「Application Insights」
- 「Application Insightsを有効にする」をクリック
- 新しいリソースを作成または既存のものを選択
Step 2: ログレベルの設定
host.jsonでログレベルを適切に設定:
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true
}
},
"logLevel": {
"default": "Information",
"Function": "Information",
"Host.Results": "Information"
}
}
}
ログ活用のベストプラクティス
リアルタイムデバッグ
import logging
import azure.functions as func
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
# デバッグ情報を詳細に出力
logging.info(f'Request method: {req.method}')
logging.info(f'Request URL: {req.url}')
try:
# 処理内容
result = process_request(req)
logging.info('Processing completed successfully')
return result
except Exception as e:
logging.error(f'Error occurred: {str(e)}')
raise
Application Insightsでの高度な分析
- KQLクエリ例:
traces
| where timestamp > ago(1h)
| where severityLevel >= 2
| project timestamp, message, severityLevel
| order by timestamp desc
消費プランでの注意点
-
ファイルシステムへの書き込み不可:
/tmp以外への永続的なログ保存は不可 - コールドスタート影響: 初回実行時のログには起動時間も含まれる
- 実行時間制限: 10分を超える処理はタイムアウトしログが途切れる可能性
デプロイ手順の確認ポイント
6. requirements.txtの適切な管理
よくある間違い
# ❌ バージョンを固定しすぎ
numpy==1.21.0
pandas==1.3.0
# ❌ 開発用パッケージも含んでいる
pytest==6.2.4
black==21.5b2
推奨設定
# ✅ 互換性を保ちつつ適度にバージョン指定
azure-functions>=1.11.0,<2.0.0
requests>=2.25.0
pandas>=1.3.0,<2.0.0
numpy>=1.21.0
7. local.settings.jsonと本番環境の設定分離
ローカル開発用(local.settings.json)
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "python",
"CUSTOM_API_KEY": "development-key"
}
}
本番環境設定
Azure Portal の「構成」で同じキーに本番用の値を設定。
まとめ
Azure Functionsのデプロイ問題は複数の要因が絡み合うことが多く、系統的なアプローチが重要です:
- 事前確認: バージョンとプランの確認
- 基本設定: ストレージ接続とPython環境
- コード構造: インポートパスとモジュール設計
- ログ設定: 問題特定のための適切な監視体制
特に消費プランでは、サーバーレスの制約を理解した上で設計することが成功の鍵となります。問題が発生した際は、ログストリームとApplication Insightsを活用して、段階的に原因を特定していくことをお勧めします。