8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Azure Functions を利用したプライベート可用性テストを安価に実装してみた

Last updated at Posted at 2025-10-23

はじめに

プライベート可用性テストとは

Azure を利用されている皆さん、Application Insights の可用性テストは使っていますか?
外形監視目的で利用されることが多い便利な機能ですが、プライベート環境からのアクセスのみを前提とした Web サイトやアプリケーションに対して、可用性テストは利用できません。

今回は、プライベート環境内のリソースに対する可用性テスト(以降「プライベート可用性テスト」と呼びます)を、Azure Functions を使って安価に実装してみました。

安価に?

なぜ安価にとしているのか。

理由はズバリ、2024年11月に Azure Functions Flex 従量課金プランの VNet 統合が GA されたからです。

Azure Functions を利用したプライベート可用性テストについては、以前から複数のブログなどで紹介されていましたが、当時 Azure Functions の VNet 統合がサポートされていたのは Premium といった高価なプランのみであり、可用性テストのために Premium を採用するにはハードルが高すぎました。

しかし、Flex 従量課金プランの VNet 統合が使えるようになり、プライベート可用性テストを実装するハードルがかなり下がりました。

以前はコスト面で二の足を踏んでいた方も、「今はプライベート可用性テストを安く実装できるよ」ということを知ってもらえれば幸いです。

構成

アーキテクチャ

Architecture.png

構成は非常にシンプルで、 VNet 統合を有効化した Functions と可用性テストの実行結果の送信先となる Application Insights だけです。
可用性テスト用のコードを Functions にデプロイし、 Timer Trigger を使って定期実行します。実行結果は Application Insights に送信されます。

加えて、今回はテスト対象のサンプルアプリケーション基盤として Azure Container Instances ( ACI ) を使っています。

処理フロー

実装する可用性テストの処理フローは以下の通りです。

  1. 環境変数の取得・検証 : Functions は環境変数を設定できるため、テスト対象の宛先を環境変数にて指定
  2. 可用性テストの実行 : Timer Trigger にて定期的に HTTP リクエストを実行
  3. Application Insights への結果送信 : HTTP リクエストの結果を Application Insights に送信

実装

それでは、以下の順でプライベート可用性テストを実装していきます。

  1. Azure リソースの作成
  2. コードの実装
  3. コードのデプロイ
  4. 動作確認

Azure リソース

今回は Azure ポータルを使って各リソースを作成していきます。

前提

以下のリソースは作成済とします。

  • VNet および Subnet : Functions (と今回は ACI)を統合する
  • Application Insights : 可用性テストの結果送信先

Azure Container Instances

可用性テストの実行先として ACI を作成します。動作確認用に作成するリソースですので、既存のアプリケーションがある場合は不要です。

デフォルトのイメージを指定し、サイズも最小限とします。

aci_01.png

プライベート可用性テストですので、 ACI もプライベートとします。
ネットワークの種類はプライベートとし、作成した VNet と ACI を統合するサブネットを選択します。

aci_02.png

ログの設定は無効化しておきます。

aci_03.png

ACI ができました。

aci_04.png

VNet 統合が設定されていれば OK です。

aci_05.png

Azure Functions

コードの実行基盤となる Functions を作成します。

まず初めに、プランを選択します。
従量課金かつ VNet 統合がサポートされているフレックス従量課金を選択します。

func_01.png

次に、各パラメータを指定します。

ランタイムには Python 3.12 を使います。

func_02.png

仮想ネットワーク統合を有効にするをオンにし、作成した VNet と

func_03.png

Functions を統合するサブネットを選択します。

func_04.png

作成した Application Insights を選択します。

func_05.png

Functions ができました。

func_06.png

こちらも VNet 統合が設定されていれば OK です。

func_07.png

最後に、可用性テストの宛先(今回は ACI のプライベート IP )を環境変数として設定します。

func_08.png

これで Azure リソースの設定は完了です。

Functions コード

リソース作成が完了したので、 Functions にデプロイする可用性テスト用のコードを紹介します。
今回は Python を使用していますが、 Functions に対応しており Application Insights の API がサポートされている言語であれば何でもよいかと思います。

ファイル構成は以下です。

availability-test/
├── function_app.py      # メインの実装
├── host.json            # Functions ホスト設定
└── requirements.txt     # Python 依存パッケージ

メインとなるコードは以下になります。今回は非常にシンプルな実装としています。

function_app.py
import logging
import os
import json
import time
import uuid
import requests
import azure.functions as func


app = func.FunctionApp()


def perform_availability_test(target_url: str, timeout: int = 30):
    """可用性テストを実行してApplication Insightsに送信"""
    
    test_id = str(uuid.uuid4())
    start_time = time.time()
    success = False
    status_code = None
    error_message = None
    
    try:
        logging.info(f"可用性テスト開始: {target_url}")
        
        # HTTPリクエストを実行
        response = requests.get(target_url, timeout=timeout)
        status_code = response.status_code
        success = status_code < 400
        
        if not success:
            error_message = f"HTTP {status_code}"
        
        logging.info(f"テスト完了: status={status_code}")
        
    except Exception as e:
        error_message = str(e)
        logging.error(f"テスト失敗: {error_message}")
    
    # 所要時間を計算
    duration_ms = (time.time() - start_time) * 1000
    
    # Application Insightsに送信
    send_to_appinsights(test_id, target_url, success, duration_ms, error_message)
    
    return {
        'success': success,
        'duration_ms': duration_ms,
        'status_code': status_code
    }


def send_to_appinsights(test_id: str, target_url: str, success: bool, duration_ms: float, error_message: str = None):
    """Application Insightsに可用性データを送信"""
    
    connection_string = os.getenv('APPLICATIONINSIGHTS_CONNECTION_STRING')
    if not connection_string:
        logging.warning("APPLICATIONINSIGHTS_CONNECTION_STRING が設定されていません")
        return
    
    # Instrumentation Keyを抽出
    try:
        ikey = connection_string.split("InstrumentationKey=")[1].split(";")[0]
    except (IndexError, AttributeError):
        logging.error(f"接続文字列からInstrumentation Keyを抽出できません: {connection_string}")
        return
    
    # durationをISO 8601形式に変換 (例: 00:00:01.2340000)
    duration_seconds = duration_ms / 1000.0
    hours = int(duration_seconds // 3600)
    minutes = int((duration_seconds % 3600) // 60)
    seconds = duration_seconds % 60
    duration_str = f"{hours:02d}:{minutes:02d}:{seconds:09.6f}"
    
    # 可用性結果のペイロードを作成
    payload = {
        "name": "Microsoft.ApplicationInsights.AvailabilityResult",
        "time": time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime()),
        "iKey": ikey,
        "tags": {
            "ai.operation.id": test_id,
            "ai.operation.name": f"Availability Test - {target_url}",
            "ai.location.ip": "0.0.0.0"
        },
        "data": {
            "baseType": "AvailabilityData",
            "baseData": {
                "ver": 2,
                "id": test_id,
                "name": "Availability Test",
                "duration": duration_str,
                "success": success,
                "runLocation": "Azure Functions",
                "message": error_message or "",
                "properties": {
                    "TargetUrl": target_url
                }
            }
        }
    }
    
    try:
        # Application Insights REST APIに送信
        response = requests.post(
            "https://dc.applicationinsights.azure.com/v2/track",
            json=payload,
            headers={"Content-Type": "application/json"},
            timeout=10
        )
        
        if response.status_code == 200:
            logging.info("Application Insightsに送信成功")
        else:
            logging.warning(f"Application Insights送信失敗: {response.status_code} - {response.text}")
            
    except Exception as e:
        logging.error(f"Application Insights送信エラー: {e}")


@app.timer_trigger(
    schedule="0 */5 * * * *",  # 5分ごとに実行
    arg_name="myTimer",
    run_on_startup=False,
    use_monitor=False
)
def availability_test_timer(myTimer: func.TimerRequest) -> None:
    """タイマートリガーで定期的に可用性テストを実行"""
    
    logging.info('可用性テスト実行開始')
    
    # 環境変数から監視対象URLを取得
    target_url = os.getenv('TARGET_URL')
    
    if not target_url:
        logging.error('TARGET_URL 環境変数が設定されていません')
        return
    
    # 可用性テストを実行
    result = perform_availability_test(target_url)
    
    logging.info(f'可用性テスト完了: {result}')

以下は Functions のホスト設定ファイルです。

host.json
{
  "version": "2.0",
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)"
  },
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": false
      }
    }
  }
}

最後に、Python のパッケージファイルです。こちらも最小限です。

requirements.txt
azure-functions
requests

コードデプロイ

以下を実行することで、Functions にコードをデプロイできます。

> az login
> func azure functionapp publish <Function名> --python
Getting site publishing info...

~~~

[2025-10-20T16:36:43.350Z] The deployment was successful!
Functions in fnc-availabilitytest-01:
    availability_test_timer - [timerTrigger]

デプロイには以下が必要です

  • Azure CLI
  • Azure Functions Core Tools v4

動作確認

可用性テストが正常に動いていることを確認してみます。
Application Insights の「有効 ( Availability ) 」メニューを見ると、CUSTOMと表示された可用性テストが表示され、5分おきにテストが実行されていることが確認できました。

test_01.png

Functions の方も見てみましょう。
Timer Trigger が正常に実行されていることが確認できました。

test_02.png

料金比較

今回の構成で実際にどれくらいコストがかかるのか、Premium プランと比較してみます。

前提

今回の構成および動作確認の結果から、以下を前提に料金を算出してみましょう。
なお、価格は2025年10月時点とします。

  • 5分ごとに実行(月間 8,640回)
  • 1回の実行時間 : 約2秒
  • メモリ : 512 MB

Flex 従量課金プラン

月額コスト : $0(無料)

以下の通り、無料枠(250,000実行 + 100,000 GB-s/月)内に収まります。

実行回数:8,640回/月 → 無料枠内
実行時間:8,640回 × 2秒 × 0.5GB = 8,640 GB-s → 無料枠内

Premium プラン(EP1)

月額コスト : $178.85

Premium プランは最低1インスタンスが常時稼働するため、たとえ軽量なワークロードでも固定費が発生します。

コスト比較

プラン 月額 年間
Flex 従量課金 $0 $0
Premium(EP1) $178.85 $2,146

比較するまでもありませんが、 Flex 従量課金の方が圧倒的に安いです。というか、無料です。

まとめ

本記事では、Azure Functions Flex 従量課金プランの VNet 統合機能を活用して、プライベート可用性テストを安価に実装する方法を紹介しました。
以下に要点をまとめます。

  • コスト削減 : 従来の Premium プランと比較して、Flex 従量課金プランを使うことで大幅なコスト削減が可能
  • シンプルな構成 : VNet 統合した Functions と Application Insights のみで実装可能
  • 柔軟な監視 : 環境変数で監視対象を設定することで、複数の環境やエンドポイントにも対応可能
  • 標準的な可視化 : Application Insights 標準機能として可用性テストの結果が表示されるため、既存の監視フローに統合しやすい

2024年11月の Flex 従量課金プランの VNet 統合 GA により、これまでコスト面で導入が難しかったプライベート可用性テストが、現実的な選択肢となりました。

プライベート環境の監視要件がある方は、本記事の実装を参考にしてみてください。

We Are Hiring!

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?