PowerShellクラスと並列処理によるスケーラブルなインベントリ収集基盤

Tech

本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

PowerShellクラスと並列処理によるスケーラブルなインベントリ収集基盤

【導入:解決する課題】 散在するサーバー情報の収集をクラス定義と並列処理で効率化し、型安全なデータ構造によって後続処理の保守性を極限まで高めます。(64文字)

【設計方針と処理フロー】 本設計では、PowerShell 5.0以降で導入された「クラス(Class)」を利用してデータのスキーマを定義します。従来のカスタムオブジェクト(PSCustomObject)に比べ、型の制約を課すことでデータの一貫性を担保し、大規模環境でのプロパティ欠損を防ぎます。

graph TD
A["開始"] --> B["インベントリクラスの定義"]
B --> C["ターゲットホストのリスト取得"]
C --> D["ForEach-Object -Parallel による並列実行"]
D --> E{"CIMセッション試行"}
E -->|成功| F["クラスインスタンスの生成と格納"]
E -->|失敗| G["エラーログの記録"]
F --> H["結果の集計・エクスポート"]
G --> H
H --> I["終了"]

並列処理には PowerShell 7.x 以降の ForEach-Object -Parallel を採用し、CIM (Common Information Model) インスタンス経由で効率的にシステム情報を取得します。

【実装:コアスクリプト】

# =================================================================


# 概要: PowerShellクラスを利用したサーバー情報収集スクリプト


# 要件: PowerShell 7.0以上推奨 (Parallel処理のため)


# =================================================================

# 1. データ構造の定義(再利用性の向上)

class ServerInventory {
    [string]$ComputerName
    [string]$OSCaption
    [uint64]$TotalPhysicalMemoryGB
    [datetime]$LastBootUpTime
    [string]$Status

    # コンストラクタ

    ServerInventory([string]$name) {
        $this.ComputerName = $name
        $this.Status = "Unknown"
    }

    # メモリ換算メソッド

    [void]SetMemory([uint64]$bytes) {
        $this.TotalPhysicalMemoryGB = [math]::Round($bytes / 1GB, 2)
    }
}

function Get-ServerAssetReport {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string[]]$ComputerNames,

        [Parameter()]
        [int]$ThrottleLimit = 5
    )

    process {

        # 並列処理の実行

        $results = $ComputerNames | ForEach-Object -Parallel {
            $comp = $_
            $entry = [ServerInventory]::new($comp)

            try {

                # CIMを用いたOS情報の取得

                $os = Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName $comp -ErrorAction Stop
                $cs = Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $comp -ErrorAction Stop

                $entry.OSCaption = $os.Caption
                $entry.SetMemory($cs.TotalPhysicalMemory)
                $entry.LastBootUpTime = $os.LastBootUpTime
                $entry.Status = "Success"
            }
            catch {
                Write-Error "Failed to collect data from $comp: $($_.Exception.Message)"
                $entry.Status = "Error: $($_.Exception.Message)"
            }

            # クラスオブジェクトをパイプラインへ戻す

            $entry
        } -ThrottleLimit $ThrottleLimit

        return $results
    }
}

# 実行例


# $targets = @("Server01", "Server02", "localhost")


# $report = Get-ServerAssetReport -ComputerNames $targets


# $report | Out-GridView

【検証とパフォーマンス評価】 Measure-Command を用いて、逐次処理と並列処理の比較検証を行います。

# 検証コード例

$testHosts = @("localhost") * 10 # 擬似的な負荷
$time = Measure-Command {
    $res = Get-ServerAssetReport -ComputerNames $testHosts -ThrottleLimit 5
}
Write-Host "処理時間: $($time.TotalSeconds) 秒"
  • 期待値: 100台規模の環境において、逐次処理(約5〜10分)に対し、スロットル制限5〜10の並列処理では約1〜2分程度まで短縮可能です。※ネットワーク遅延やRPCのタイムアウト設定に依存。

【運用上の落とし穴と対策】

  1. PowerShell バージョンの壁: ForEach-Object -Parallel は PowerShell 7 以降の機能です。Windows PowerShell 5.1 環境では Start-JobRunspaces への書き換え、あるいはモジュール配布の検討が必要です。

  2. CIM/WinRM の到達性: ファイアウォール(TCP 5985/5986)がブロックされている場合、Get-CimInstance がタイムアウトします。事前に Test-NetConnection でのポートチェックをフローに組み込むことを推奨します。

  3. シリアライズの制限: クラスオブジェクトを並列ブロック(scriptblock)から返す際、型情報が一部欠落(Deserialized)する場合があります。プロパティ参照には問題ありませんが、メソッドの再呼び出しが必要な場合は注意が必要です。

【まとめ】

  1. クラス定義による型安全性の確保: 出力データの構造を明確にし、スキーマ崩れを防止する。

  2. 標準コマンドレットへの準拠: 依存関係を最小限にし、標準のCIM/CIMSessionを活用してOS負荷を抑える。

  3. 並列処理の適切な制御: -ThrottleLimit を活用し、管理端末のCPUリソースとネットワーク負荷のバランスを最適化する。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

タイトルとURLをコピーしました