見出し画像

ロードバランサ(負荷分散装置)の動作確認をするためのPowershellスクリプト【LBChecker1.0】

筆者がプライベートネットワークでロードバランサでテストするときに接続元の端末を十分な台数用意できず、十分なテストができないことがありました。
このスクリプトを利用すると理論的には接続元の1台の端末だけしか用意できなくても負荷分散が確認できます。
とりあえずLBCheckerと命名します。
インフラやネットワークエンジニア等、一部の技術者しか使わないニッチなツールです。
現在、筆者の手元にロードバランサが無く実機で確認できていないので、正常に動作しなかったら連絡下さい。

機能

以下の機能を有しています。

  • Powershellが動作するWindows端末で動作します。

  • 端末に設定した複数のIPアドレス(セカンダリIPアドレス)からロードバランサに設定した仮想アドレスに対して応答確認を行います。

  • Powershellのコンソール上に緑文字で疎通成功、赤文字で疎通失敗を表示します。

  • 疎通を失敗するとビープ音でお知らせします。

  • 応答時間を出力します。

  • ログをカレントフォルダに出力します。

  • PowerShellのスクリプトのため、お客様環境の「フリーソフトは導入禁止」ポリシーを回避できます。

注意事項

以下の注意事項があります。

  • 筆者の環境で十分なテストができていないので、

  • グローバルアドレスを持っているクラウド上のロードバランサに対してこのスクリプトを使用するのは技術的に現実的ではありません。

  • httpのリターンコード200を通信成功と判定しているため負荷分散対象のサービスがhttpまたはhttpsである必要があります。

  • ロードバランサとスクリプトを実行する端末の間にIPアドレスをプライベートからグローバルに変換するようなルータが存在する場合は正常動作しません。

  • セッション維持方式でクッキーを使用している場合、セッション維持されず分散されます。

  • スクリプトを実行する端末から異なるIPアドレスでアクセスすることによって負荷分散を実現するので、端末のネットワークポートにセカンダリポートが複数付与できる環境である必要があります。

スクリプト

以下のスクリプトをテキストエディタに張り付けて保存してください。拡張子はps1です。

# 全てのIPアドレスを取得 (接続されているインターフェースのみ)
function Get-AllIPAddresses {
    # ネットワークアダプタのうち、"Up" 状態のものを取得し、そのインターフェースインデックスを抽出
    $connectedAdapters = Get-NetAdapter | Where-Object { $_.Status -eq "Up" } | Select-Object -ExpandProperty ifIndex
    
    # IPv4アドレスの中から、接続されているアダプタに関連付けられたIPアドレスを抽出
    $ipAddresses = Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceIndex -in $connectedAdapters } | Select-Object -ExpandProperty IPAddress
    
    # 取得したIPアドレスを返す
    return $ipAddresses
}

# コマンドライン引数を処理 (接続先の仮想IPアドレスまたはURLを指定)
if ($args.Count -eq 0) {
    # 引数が指定されていない場合、デフォルトで "https://google.com" に接続
    $virtualIP = "https://google.com"
} else {
    # 引数で指定された仮想IPアドレスまたはURLを使用
    $virtualIP = $args[0]
    
    # 指定されたURLが "http" または "https" で始まらない場合、自動的に "http://" を付加
    if ($virtualIP -notmatch "^https?://") {
        $virtualIP = "http://$virtualIP"
    }
}

# 接続先のURLを表示 (色はシアン)
Write-Host "Connecting to: $virtualIP" -ForegroundColor Cyan

# 現在の日付でログファイル名を生成 (カレントディレクトリに日付付きで保存)
$logFileName = "load_balancer_check_$(Get-Date -Format "yyyy-MM-dd").log"
$logFile = Join-Path -Path (Get-Location) -ChildPath $logFileName

# ログに接続先を記録
Add-Content -Path $logFile -Value "$(Get-Date) - Connecting to: $virtualIP"

# 結果を表示する関数 (成功時は緑色、失敗時は赤色で表示)
function Show-Result {
    param (
        [string]$message,    # 表示するメッセージ
        [bool]$success,      # 成功かどうかのフラグ
        [int]$responseTime = 0  # 応答時間 (ms)
    )

    # 成功の場合は緑色で応答時間を表示
    if ($success) {
        Write-Host "$message (Response Time: $responseTime ms)" -ForegroundColor Green
    } else {
        # 失敗の場合は赤色で表示し、ビープ音を鳴らす
        Write-Host $message -ForegroundColor Red
        [console]::beep()
    }
}

# リクエストを送信する関数
function Send-Request {
    param (
        [string]$sourceIP  # リクエストを送信する際の送信元IP
    )

    try {
        # curlコマンドを使用してリクエストを送信し、応答時間を計測
        $responseTime = (Measure-Command {
            $processInfo = New-Object System.Diagnostics.ProcessStartInfo
            $processInfo.FileName = "curl"
            $processInfo.Arguments = "--interface $sourceIP $virtualIP"
            $processInfo.RedirectStandardOutput = $true
            $processInfo.UseShellExecute = $false
            $processInfo.CreateNoWindow = $true
            $process = [System.Diagnostics.Process]::Start($processInfo)
            $output = $process.StandardOutput.ReadToEnd()
            $process.WaitForExit()
        }).TotalMilliseconds

        # 成功の場合、結果を表示しログに記録
        if ($process.ExitCode -eq 0) {
            $status = "Success"
            Show-Result "${sourceIP}: ${status}" $true $responseTime
            Add-Content -Path $logFile -Value "$(Get-Date) - ${sourceIP}: ${status} - Response Time: ${responseTime} ms"
        } else {
            # 失敗の場合、エラーコードとともに結果を表示しログに記録
            $status = "Failed with exit code $($process.ExitCode)"
            Show-Result "${sourceIP}: ${status}" $false
            Add-Content -Path $logFile -Value "$(Get-Date) - ${sourceIP}: ${status}"
        }
    } catch {
        # 例外発生時の処理 (エラーメッセージを表示しログに記録)
        $status = "Error: $_"
        Show-Result "${sourceIP}: ${status}" $false
        Add-Content -Path $logFile -Value "$(Get-Date) - ${sourceIP}: ${status}"
    }
}

# すべてのIPアドレスを取得
$ipAddresses = Get-AllIPAddresses

# 無限ループで各IPアドレスからリクエストを送信
while ($true) {
    foreach ($ip in $ipAddresses) {
        # 各IPアドレスからリクエストを送信
        Send-Request -sourceIP $ip
        
        # 次のリクエストまでの間隔 (秒数指定可能、ここでは即座に次のリクエスト)
        Start-Sleep -Seconds 0
    }

    # カウンターをインクリメント (用途は不明)
    $counter++
}

使用手順

この手順書では端末のIPアドレスが192168.1.1/25、ゲートウェイが192.168.1.254と仮定します。IPアドレスは個々の環境に合わせて変更してください。
ネットワークインターフェースを固定にしておき、インターフェースのIPv4プロパティの「詳細設定」を開きます。

「追加(A)…」を押します。

セカンダリアドレスとして「192.168.1.2/24」を設定して「追加(A)」を押します。

同じことを繰り返してセカンダリアドレスを追加します。この例では10個まで追加しました。ロードバランサへのアクセスの接続元としてこの10個のアドレスが利用されます。
設定が終わったら、すべての「OK」を押して設定画面を閉じます。

コマンドプロンプトより「ipconfig」を実行し全てのIPアドレスが設定されていることを確認します

ps1を分かりやすいファイルにし、わかりやすい場所に置きます。
ここでは例として「C:\temp」フォルダに「lbchecker.ps1」のファイル名で配置します。

Powershellを起動します。
以下のコマンドを入力してスクリプトが実行できるようにポリシーを変更します。

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

カレントをスクリプトの設置フォルダに移動します。(以下はスクリプト設置場所をc:\tempにした際の例)

cd c:\temp

スクリプトを実行します。(以下はスクリプト名をlbchecker.ps1にした際の例)
引数には送信先のサーバ名を入力します。

.\lbchecker.ps1 google.com

実行が成功すると以下のように表示されます。

停止する際は際は「Ctl+C」キーを押してください。

Wiresharkで確認してみると端末の各アドレスからサーバにアクセスしているのが確認できます。
実際の負荷分散状況はロードバランサの管理画面から確認できるとおもうので「Wiresharkって何?」って思った人は特に気にせずロードバランサの管理画面から確認してください。

いいなと思ったら応援しよう!