PowerShellとCIMを活用したマルチノード・システムヘルスチェック自動化

Tech

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

PowerShellとCIMを活用したマルチノード・システムヘルスチェック自動化

【導入:解決する課題】 複数台のWindowsサーバーに対する手動のヘルスチェックを排除し、CIMセッションを用いた並列スキャンにより障害検知の初動を数分から秒単位へ短縮します。

【設計方針と処理フロー】 従来のWMI(RPC/DCOM)ではなく、最新のWS-Managementプロトコルを利用するCIMコマンドレットを採用します。これにより、Firewallフレンドリーな通信と、CimSessionの使い回しによるオーバーヘッド削減を実現します。

graph TD
A[Start] --> B["Generate CimSession List"]
B --> C{"Session Check"}
C -->|Success| D["Parallel Fetch: OS/Disk/EventLog"]
C -->|Failure| E["Log Connection Error"]
D --> F["Format PS-CustomObject"]
F --> G["Export CSV/JSON"]
G --> H[Finish]

【実装:コアスクリプト】 以下は、PowerShell 7の並列処理(-Parallel)を考慮しつつ、標準的なCIM操作をカプセル化した実戦向けスクリプトです。

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

        [int]$MaxEventLogs = 10
    )

    # セッションオプションの設定

    $option = New-CimSessionOption -Protocol Wsman -ConnectTimeout (New-TimeSpan -Seconds 10)

    # 並列処理の実行 (PowerShell 7.x 推奨、5.1の場合はForEach-Objectで代替)

    $results = $ComputerNames | ForEach-Object -Parallel {
        $comp = $_
        try {

            # セッションの確立

            $session = New-CimSession -ComputerName $comp -SessionOption $using:option -ErrorAction Stop

            # 1. OS情報の取得 (稼働時間算出)

            $os = Get-CimInstance -CimSession $session -ClassName Win32_OperatingSystem
            $uptime = (Get-Date) - $os.LastBootUpTime

            # 2. ディスク空き容量 (Cドライブ)

            $disk = Get-CimInstance -CimSession $session -Query "SELECT FreeSpace, Size FROM Win32_LogicalDisk WHERE DeviceID = 'C:'"

            # 3. 直近のエラーイベントログ

            $logs = Get-CimInstance -CimSession $session -Query "SELECT Message, EventID, SourceName FROM Win32_NTLogEvent WHERE Logfile = 'System' AND Type = 'Error'" | 
                    Select-Object -First $using:MaxEventLogs

            # データ集約

            [PSCustomObject]@{
                PSComputerName = $comp
                Status         = "Success"
                UptimeDays     = [Math]::Round($uptime.TotalDays, 2)
                FreeSpaceGB    = [Math]::Round($disk.FreeSpace / 1GB, 2)
                DiskUsage      = "{0:P2}" -f (1 - ($disk.FreeSpace / $disk.Size))
                RecentErrors   = ($logs.Message -join "; ")
                Timestamp      = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
            }
        }
        catch {
            [PSCustomObject]@{
                PSComputerName = $comp
                Status         = "Failed: $($_.Exception.Message)"
                UptimeDays     = $null
                FreeSpaceGB    = $null
                DiskUsage      = $null
                RecentErrors   = $null
                Timestamp      = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
            }
        }
        finally {
            if ($session) { Remove-CimSession $session }
        }
    } -ThrottleLimit 10

    return $results
}

# 実行例


# $report = Get-RemoteSystemHealth -ComputerNames "SRV-01", "SRV-02"


# $report | Export-Csv -Path "./HealthReport.csv" -NoTypeInformation -Encoding utf8

【検証とパフォーマンス評価】

  • 計測手法: Measure-Command { Get-RemoteSystemHealth -ComputerNames (1..50 | % { "Target-$_" }) }

  • 期待値:

    • 逐次処理(PS 5.1): 約120〜180秒(タイムアウト待ちを含む)。

    • 並列処理(PS 7.x -Parallel): 約15〜30秒。

  • スケーラビリティ: 100台を超える環境では -ThrottleLimit を調整し、ドメインコントローラーへの同時認証負荷を分散させる必要があります。

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

  1. PowerShell 5.1 vs 7:

    • 5.1環境では ForEach-Object -Parallel が存在しません。代わりに Workflow (非推奨) か、軽量な Runspaces を利用する、あるいは外部モジュール ThreadJob の検討が必要です。
  2. WinRMの有効化と認証:

    • Enable-PSRemoting が必須。また、ワークグループ環境では TrustedHosts の設定や、Kerberos認証(AD環境)の利用を確認してください。
  3. WMIクエリのコスト:

    • SELECT * は避け、必要なプロパティのみを明示的に指定することで、リモートノードのCPU負荷とネットワークトラフィックを削減します。

【まとめ】

  1. CIMの優先利用: DCOM依存を排除し、ポート5985/5986(WS-Man)での運用を標準化する。

  2. エラーハンドリングの徹底: 疎通不可を前提とした try/catch 設計により、スクリプトの停止を防ぐ。

  3. 構造化データ出力: PSCustomObject で出力し、後続のCSV出力やDB登録を容易にする。

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

コメント

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