【VS Code】Cosmos DBトリガーを利用したAzure Functions(Python)のデプロイ手順

に公開

こんにちは或いはこんばんは。Ryuzakiです。

先日業務で初めてAzure Functionsを利用する機会がありました。CosmosDBに格納されているデータのETL処理を実装するという比較的シンプルな要件だったのですが、単純なデプロイに思いの外四苦八苦しました。

その原因は、Python Programming Model v1/v2、CosmosDB拡張機能のversion 3/version 4など、多くの情報が錯綜していたことにあります。公式ドキュメントですらページによって対象としているバージョンが異なっていたり、複数のバージョンの情報がごちゃ混ぜになっていたりと、かなり混乱しやすい状況でした。

そこで半分備忘録として、各種バージョンの説明と現時点でのVS Codeを用いたデプロイ手順を記事としてまとめたいと思います。

利用環境

今回の記事で使用する環境は以下の通りです。

  • OS:macOS Sequoia 15.3.2
  • 言語:Python 3.11.11
  • Pythonライブラリ:
    • azure-functions:1.23.0
  • VS Code拡張機能:
    • Azure Resources:0.10.9
    • Azure Functions:1.17.1

Azure Functions runtime versionとは

まずはAzure Functionsのランタイム基盤のバージョンについて説明します。

執筆時点では以下の2つのバージョンが存在しています。

  • 1.x:.NETフレームワークを用いたC#アプリケーションのみサポート
    (2026/9/14でサポート終了予定)
  • 4.x:現時点で最新のランタイムバージョン
    (Azure Functionsで対応しているすべての言語をサポート)

https://learn.microsoft.com/en-us/azure/azure-functions/functions-versions?tabs=isolated-process,v4&pivots=programming-language-python

公式ドキュメントを見ていると「Functions 2.x+」や「Version 2 and higher」のように記載されている箇所がありますが、これらは最新バージョンの4.xを用いる場合の説明だと理解しておきましょう。

Azure FunctionsのPython Programming Modelとは

次に、Azure FunctionsのPython Programming Modelについて説明します。これは、Azure FunctionsのランタイムとしてPythonを選択した際の関数のエントリーポイントやトリガーの設定方法のお作法を定義したものです(Python自体のバージョンとは無関係です)。

最新バージョンであるProgramming Model v2は2023年5月にリリースされました。

https://azure.microsoft.com/ja-jp/updates?id=generally-available-v2-programming-model-for-azure-functions-using-python

Programming Model v1とv2の主な違いは以下の通りです。

Programming Model v1 Programming Model v2
関数のエントリーポイント 自由に設定可能
(基本は__init__.py)
function_app.py
トリガーとバインドの宣言方法 function.jsonで宣言 コード内でデコレーターを用いて宣言
ディレクトリ構造 関数ごとに専用のディレクトリを作成 各関数はブループリントと呼ばれるモジュールとして開発し、function_app.pyで登録

両方のProgramming Modelのディレクトリ構造も大きく異なります。

Programming Model v1のディレクトリ構造
project_root/
├── .venv/
├── .vscode/
├── function_one/
│   ├── __init__.py
│   └── function.json
├── function_two/
│   ├── __init__.py
│   └── function.json
├── shared_code/
│   ├── __init__.py
│   ├── helper_function1.py
│   └── helper_function2.py
├── tests/
│   └── test_function_one.py
├── .funcignore
├── host.json
├── local.settings.json
├── requirements.txt
└── Dockerfile
Programming Model v2のディレクトリ構造
project_root/
├── .venv/
├── .vscode/
├── function_app.py
├── functions/
│   ├── function_one.py
│   ├── function_two.py
│   └── shared_code/
│       ├── helper_function1.py
│       └── helper_function2.py
├── tests/
│   └── test_function_one.py
├── .funcignore
├── host.json
├── local.settings.json
├── requirements.txt
└── Dockerfile

それぞれの詳細な違いについては、以下のブログ記事で非常に分かりやすく解説されているため、詳細はそちらに委ねます。

https://qiita.com/ayukiyama/items/25a3e0a878913f1e21a3
https://zenn.dev/pinter/articles/20230903functionspythondifference

Azure Cosmos DB拡張機能とは

Azure FunctionsのトリガーとしてCosmos DBを利用したりする際に必要となる拡張機能があります。Pythonの場合はhost.jsonに以下のような記述を追記することで自動的にインストールされます。

host.json
{
  "version": "2.0",
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)" // バージョン4以上、5未満をインストール
  }
}

執筆時点でサポートされているバージョンは最新の4.xのみです。ただし、3.xが2024/08/31に廃止されたばかりということもあり3.xに関する記事も多く見かけます(公式ドキュメント内にも残っています)。

3.xと4.xの主な違いは以下の通りです。

  • 出力バインドを使用した際にIDが自動的に設定されなくなった
  • トリガーやバインドを設定する際の属性値の名称が変更された
    (変更された属性値の一覧はこちらを参照してください。)

https://learn.microsoft.com/ja-jp/azure/azure-functions/migrate-cosmos-db-version-3-version-4?tabs=isolated-process&pivots=programming-language-python

デプロイ手順

それでは実際に、VS Codeを使ってAzure Functionsをデプロイする手順を説明します。

前提条件

  • 利用するリソースグループは作成済み
  • 利用するデータベース、コンテナも作成済み

今回説明用で利用するCosmos DBアカウントの基本情報は以下の通りです。

  • リソースグループ:rg-zenn-demo
  • リージョン:Japan East
  • アカウント名:cosmos-zenn-demo
  • API:コア(SQL)
  • 容量モード:Serverless
  • Availability Zones:無効
  • バックアップポリシー:Continuous(7 days)
  • Key-based Authentication:有効
  • Data Encryption:Service Managed
  • 接続方法:すべてのネットワーク
  • Minimum TLS Protocol:TLS 1.2

今回説明用で利用するCosmos DBのコンテナ構成は以下の通りです。

ZennDemo
├── SourceContainer
└── TargetContainer

1. 必要な拡張機能をVS Codeへインストール

まずは必要な拡張機能をVS Codeへインストールします。

https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions
https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-cosmosdb

2. ローカルでFunctionプロジェクトを作成

次に、ローカルでFunctionプロジェクトを作成します。

  1. 「アクティビティバーのAzureアイコン」>「Workspace」>「Create Function Project…」を選択
  2. ダイアログに従って、以下の項目を入力
    • プロジェクトの作成場所
    • プロジェクトの言語(ここでは「Python」を選択)
    • 利用するPythonのバージョン(ここでは「3.11.11」を選択)
    • 利用するトリガー(ここでは「Cosmos DB Trigger」を選択)
    • 関数名(すぐに変更することになるため、適当でOK)
    • トリガー起点となるコンテナ名(ここでは「SourceContainer」と設定)
    • トリガー起点となるデータベース名(ここでは「ZennDemo」と設定)
    • ローカル設定で利用するJSONファイル
      (ここでは「+ Create new local app setting」を選択)
    • トリガーとして利用するCosmosDBアカウント
      (ここでは「cosmos-zenn-demo」と設定)

以上で、Programming Model v2を用いたFunctionプロジェクトが作成されます。
(以前はProgramming Model v1も選択できたようですが、今はできない模様…。)

作成後、Markdownファイルが開かれると思いますが閉じてOKです。ちなみに、面白いことに、Programming Model v2は2023年5月に正式にGA(Generally Available)となったにも関わらず、このMarkdownファイルには「currently in Preview」という記述が残されています…😅

3. コードを実装

本来はモジュールとして各関数を定義するのがベストプラクティスですが、今回は簡単のため、function_app.py に直接記述します。

SourceContainerでの変更をトリガーとしてTargetContainerにデータを複製する関数のコードは以下の通りです。

function_app.py
import logging

import azure.functions as func

app = func.FunctionApp()

@app.function_name(name="data_duplicator")
@app.cosmos_db_trigger(
    arg_name="documents",
    container_name="SourceContainer",
    database_name="ZennDemo",
    connection="SourceCosmosDBConnection",
    lease_container_name="leases",
    create_lease_container_if_not_exists=True
)
@app.cosmos_db_output(
    arg_name="outputDocument",
    container_name="TargetContainer",
    database_name="ZennDemo",
    connection="TargetCosmosDBConnection"
)
def main(documents: func.DocumentList, outputDocument: func.Out[func.Document]) -> None:
    if documents:
        for document in documents:
            try:
                doc_dict = document.to_dict()
                document_id = doc_dict.get('id', 'unknown')
                
                # 本来ならここで何らかのETL処理を実施
                
                outputDocument.set(func.Document.from_dict(doc_dict))
                logging.info(f"Document {document_id} duplicated successfully.")
            except Exception as e:
                logging.error(f"Error duplicating document {document_id}: {str(e)}")
トリガーとバインドの各属性の説明
  • cosmos_db_trigger:CosmosDBの変更フィードを監視するトリガー

    • arg_name:関数内でアクセスする引数名
    • container_name:監視対象のコンテナ名
    • database_name:データベース名
    • connection:CosmosDB接続文字列の環境変数名
    • lease_container_name:変更フィードを管理するためのコンテナ
    • create_lease_container_if_not_exists:変更フィードの管理用コンテナが存在しない場合の挙動(trueの場合は新たにコンテナが作成される)
  • cosmos_db_output:CosmosDBへの出力を定義するバインド

    • arg_name:出力用の引数名
    • container_name:出力先のコンテナ名
    • database_name:データベース名
    • connection:CosmosDB接続文字列の環境変数名

https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-cosmosdb-v2-trigger?tabs=python-v1,isolated-process,extensionv4,nodejs-v4&pivots=programming-language-python
https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-cosmosdb-v2-output?tabs=python-v2,isolated-process,nodejs-v4,extensionv4&pivots=programming-language-python

4. デプロイ先のFunction Appを作成

次に、デプロイ先のFunction Appを作成します。

  1. 「アクティビティバーのAzureアイコン」>「Resources」>「利用するサブスクリプション」>「Function App」を右クリック

  2. 表示されたメニューから「Create Function App in Azure… (Advanced)」を選択
    (利用するリソースグループ等にこだわりがない場合はもう1つの選択肢である「Create Function App in Azure…」を選択してもOK)

  3. ダイアログに従って以下の項目を入力

    • Function Appの名称(ここでは「func-zenn-demo」と設定)
    • ホスティングプラン(ここでは「Flex Consumption」を選択)
      (各ホスティングプランの違いに関してはこちらを参照)
    • リージョン(ここでは「East Asia」を選択)
    • Pythonのバージョン(ここでは「3.11」を選択)
      (ローカルと同じが好ましい)
    • メモリ容量(ここでは「2048」を選択)
    • 最大インスタンス数(ここではデフォルトの「100」と設定)
      (最大インスタンス数は40 ~ 1000の間で設定)
    • 利用するリソースグループ(ここでは「rg-zenn-demo」を選択)
    • 利用するストレージアカウント(ここでは「Create new storage account」を選択)
      • 新規で作成する場合はストレージアカウントの名称が聞かれる
        (ここでは「stzenndemo」と設定)
    • 利用するApplication Insights
      (ここでは「Create new Application Insights resource」を選択)
      • 新規で作成する場合はApplication Insightsの名称が聞かれる
        (ここでは「appi-zenn-demo」と設定)
      • 作成をSkipすることも可能だが、Application Insightsが無いと上手く動作しなかった場合のデバッグが非常に困難なため、設定するのがオススメ
    • 利用するマネージドIDを選択(ここでは「Create new user assigned identity」を選択)
      (VS CodeからFunction Appを作成する場合は、特に利用する予定が無くても必ず紐付ける必要がある)

5. 各種環境変数を設定

続いて、Function Appに必要な環境変数を設定します。

  1. 「アクティビティバーのAzureアイコン」>「Resources」>「利用するサブスクリプション」>「Function App」>「上記で作成したFunction App」>「Application Settings」を右クリック
  2. 表示されたメニューから「Add New Setting…」を選択
  3. ダイアログに従って、設定したい環境変数名と値を設定

この例では、以下の環境変数を設定します。

  • AZURE_CLIENT_ID(マネージドIDのクライアントID)

    • 今回作成したFunction AppではマネージドIDが紐付いているため、設定が必須
    • マネージドIDのクライアントIDはAzureポータル上で確認可能
  • SourceCosmosDBConnection

    • サンプルコード内でトリガー対象コンテナのconnectionとして定義している環境変数
    • トリガー対象コンテナを有しているCosmos DBアカウントの接続文字列を設定
  • TargetCosmosDBConnection

    • サンプルコード内で出力対象コンテナのconnectionとして定義している環境変数
    • 出力対象コンテナを有しているCosmos DBアカウントの接続文字列を設定
Cosmos DBアカウントの接続文字列の取得方法
  1. 「アクティビティバーのAzureアイコン」>「Resources」>「利用するサブスクリプション」>「Azure Cosmos DB」>「対象のCosmos DBアカウント」を右クリック
  2. 表示されたメニューから「Copy Connection String」を選択
マネージドIDのクライアントIDの取得方法
  1. 「アクティビティバーのAzureアイコン」>「Resources」>「利用するサブスクリプション」>「Function App」>「上記で作成したFunction App」>「Identity」>「User Assigned」>「紐付いているマネージドID」を右クリック

  2. 表示されたメニューから「Open in Portal」を選択

  3. 遷移先の画面に記載されているクライアントIDの値をコピー

6. デプロイ実施

最後に、作成したFunction Appへデプロイを実施します。

  1. 「アクティビティバーのAzureアイコン」>「Resources」>「利用するサブスクリプション」>「Function App」>「上記で作成したFunction App」>を右クリック

  2. 表示されたメニューから「Deploy to Function App…」を選択

  3. 少し間が空いて表示されるポップアップの内容を確認し、「Deploy」ボタンを押下

デプロイが完了するまで1~2分程度待つ必要があります。なお、進捗状況は、VS Codeの下部の出力パネル(「Output」タブ)から確認できます。デプロイが完了したら、トリガーとして設定したコンテナにデータを格納し、正常に動作しているか確認してみましょう!

おわりに

今回は、Azure Functionsに関わる様々なバージョンの説明と、VS Codeを用いたデプロイ手順を解説しました。

Azure Functionsはサーバーレスアーキテクチャを実現する強力なサービスですが、バージョンの違いや設定項目の多さから初めて利用する際には戸惑うことも多いかと思います。

特に、Python Programming Model v2やCosmos DB拡張機能のversion 4などの最新バージョンを用いた開発方法は、ネット上での情報がまだ少ないため、この記事が参考になれば嬉しいです。

ここまでお読みいただき、ありがとうございました。

Discussion