分類システムなしで数百台のVMを管理する苦労
自社のVMware clusterを8台のESXi hostで管理しているのですが、かなり頭を悩ませた時期がありました。VMの数がわずか6ヶ月で40台から200台近くに増えたのです。各チームが独自の命名規則で名前をつけていて――backendチームはapi-prod-01、dataチームはspark-node-3、QAチームはtest-env-ubuntu-22という具合に。共通のルールは何もありませんでした。
実際の影響はこうです:「paymentチームのproductionで動いているVMはどれ?」と聞かれると、VM名を一つひとつ確認するか、各チームリーダーに聞き直すしかありませんでした。非常に時間の無駄でした。さらに悪いのは、急ぎのsecurity patchが必要なとき、どのVMがどの環境に属しているかわからず、対応の優先順位をつけられないことでした。
心当たりがある方も多いのではないでしょうか?VMwareインフラが急速に拡大する際に、最初からmetadata管理の戦略を立てていなかった場合によく見られる状況です。
VM名だけでは不十分な理由
VM名を命名規則に沿って付ければ十分と思っている方も多いでしょう。例えば{env}-{team}-{app}-{番号}という形式です。一見良さそうですが、実際にはいくつかの問題があります:
- 名前に多次元の情報を詰め込めない:1台のVMがproductionであり、チームAに属し、tier 1で動作し、金曜日のmaintenance windowに含まれるということもあります。これらをすべて名前に詰め込むと、読みにくい文字列になってしまいます。
- 複数条件での同時検索が難しい:vSphere Clientには強力なfull-text searchがありません。「backendチームのproduction VMのうち、停止中のもの」を絞り込むことは、名前だけではできません。
- 補足情報を保存する場所がない:チケット番号、担当者名、cost center、ライセンス有効期限――これらはどこに保存するのでしょうか?コメント欄?別のspreadsheet?どちらも情報が古くなり、実態と乖離するリスクがあります。
- vSphereのFolderは一次元のツリー構造:VMは一度に一つのfolderにしか配置できません。複数の基準で同時に分類することはできません。
よく使われる対処方法
方法1:SpreadsheetでVMインベントリを管理する
中小企業でよく見られる方法です。VM名、IP、owner、環境、メモなどの列を持つExcelファイルです。問題はvSphereと直接連携していないため、常に情報が古くなることです。VMが削除されてもspreadsheetには残り、新しいVMを作っても誰も更新しないということが起きます。
方法2:vSphereのFolder構造を使う
チーム名や環境ごとにfolderを作成してVMを配置する方法です。spreadsheetよりは優れていますが、前述の通り、VMは一つのfolderにしか入れられないため、一つの基準でしか分類できません。
方法3:vSphere Tags + Custom Attributes――実際に使っている方法
VMware純正のソリューションで、vSphereに直接統合されており、PowerCLIとの連携も非常に優れています。Tagsは一つのVMに複数のラベルを付けることができ、Custom Attributesは任意のkey-value情報を保存できます。
vSphere Tagsの使い方:VMに多次元のラベルを付ける
vSphereのTagsはCategory → Tagというモデルで動作します。各Categoryが一つの分類軸であり、各Tagはその軸の値です。例えば:Category「Environment」には「Production」「Staging」「Development」というTagがあります。
優れている点は、一つのVMが複数の異なるcategoryからtagを受け取れることです――folderとはまったく異なります。
PowerCLIでCategoryとTagを作成する
# vCenterに接続する
Connect-VIServer -Server vcenter.company.local -User [email protected] -Password "P@ssword"
# Environmentカテゴリを作成する(各VMにはこのカテゴリのtagを1つだけ割り当て可能)
New-TagCategory -Name "Environment" -Cardinality Single -EntityType VirtualMachine
# EnvironmentカテゴリにTagを作成する
New-Tag -Name "Production" -Category "Environment"
New-Tag -Name "Staging" -Category "Environment"
New-Tag -Name "Development" -Category "Environment"
# Teamカテゴリを作成する(複数チームで共有するVMには複数のtagを割り当て可能)
New-TagCategory -Name "Team" -Cardinality Multiple -EntityType VirtualMachine
New-Tag -Name "Backend" -Category "Team"
New-Tag -Name "Frontend" -Category "Team"
New-Tag -Name "Data" -Category "Team"
New-Tag -Name "DevOps" -Category "Team"
# 重要度を階層化するためTierカテゴリを作成する
New-TagCategory -Name "Tier" -Cardinality Single -EntityType VirtualMachine
New-Tag -Name "Tier1-Critical" -Category "Tier"
New-Tag -Name "Tier2-Important" -Category "Tier"
New-Tag -Name "Tier3-Normal" -Category "Tier"
VMにtagを割り当てる
# 特定のVMにtagを割り当てる
$vm = Get-VM -Name "api-payment-01"
New-TagAssignment -Entity $vm -Tag (Get-Tag -Name "Production" -Category "Environment")
New-TagAssignment -Entity $vm -Tag (Get-Tag -Name "Backend" -Category "Team")
New-TagAssignment -Entity $vm -Tag (Get-Tag -Name "Tier1-Critical" -Category "Tier")
# 一括割り当て:名前が"api-"で始まるすべてのVMをProductionに設定する
Get-VM | Where-Object { $_.Name -like "api-*" } | ForEach-Object {
New-TagAssignment -Entity $_ -Tag (Get-Tag -Name "Production" -Category "Environment")
}
Tagを使ってVMを検索する
ここがtagsの真価が発揮される場面です。200台のVMリストをスクロールする代わりに、コマンドで即座に絞り込めます:
# Productionで動作しているすべてのVMを取得する
Get-VM | Where-Object {
(Get-TagAssignment -Entity $_ | Select-Object -ExpandProperty Tag).Name -contains "Production"
}
# Get-TagAssignmentを直接使うより速い方法
$prodVMs = (Get-TagAssignment -Tag (Get-Tag -Name "Production")).Entity
# ProductionかつBackendチームのVMを絞り込む
$prodVMs = (Get-TagAssignment -Tag (Get-Tag -Name "Production")).Entity
$backendVMs = (Get-TagAssignment -Tag (Get-Tag -Name "Backend")).Entity
$target = $prodVMs | Where-Object { $backendVMs -contains $_ }
$target | Select-Object Name, PowerState
Custom Attributes:各VMに補足情報を保存する
Tagsは分類や絞り込みには優れていますが、自由記述のテキスト情報を保存するのには向いていません。担当者名、チケット番号、デプロイ日、cost centerなどを保存するのがCustom Attributesの役割です。
Custom Attributeを作成する
# VMのカスタム属性を作成する
New-CustomAttribute -Name "Owner" -TargetType VirtualMachine
New-CustomAttribute -Name "Cost Center" -TargetType VirtualMachine
New-CustomAttribute -Name "Ticket" -TargetType VirtualMachine
New-CustomAttribute -Name "Deploy Date" -TargetType VirtualMachine
New-CustomAttribute -Name "Note" -TargetType VirtualMachine
Custom Attributeの値を設定・読み取る
# VMに情報を設定する
$vm = Get-VM -Name "api-payment-01"
Set-Annotation -Entity $vm -CustomAttribute "Owner" -Value "山田 太郎"
Set-Annotation -Entity $vm -CustomAttribute "Cost Center" -Value "IT-PAYMENT-001"
Set-Annotation -Entity $vm -CustomAttribute "Ticket" -Value "JIRA-2891"
Set-Annotation -Entity $vm -CustomAttribute "Deploy Date" -Value "2025-03-15"
# 情報を読み取る
Get-Annotation -Entity (Get-VM "api-payment-01")
# カスタム属性を含む全VMのレポートをエクスポートする
Get-VM | ForEach-Object {
$vm = $_
$annotations = Get-Annotation -Entity $vm
[PSCustomObject]@{
VMName = $vm.Name
PowerState = $vm.PowerState
Owner = ($annotations | Where-Object {$_.Name -eq "Owner"}).Value
CostCenter = ($annotations | Where-Object {$_.Name -eq "Cost Center"}).Value
Ticket = ($annotations | Where-Object {$_.Name -eq "Ticket"}).Value
}
} | Export-Csv -Path "vm-inventory.csv" -NoTypeInformation -Encoding UTF8
実際の現場でのTagsとCustom Attributesの組み合わせ
現在、8台のESXi hostにこのモデルを採用しています:
- Tags:素早い分類と一括フィルタリングのため――Environment、Team、Tier、OS、Maintenance Window
- Custom Attributes:識別情報の保存のため――Owner、Cost Center、Ticket、SLA Level
実際の例:毎週金曜日に定期maintenanceがある場合、「Maintenance-Friday」タグを持つVMを絞り込むコマンドを実行するだけで、shutdownが必要なVMのリストがすぐに得られます。一つひとつの名前を覚えたり、spreadsheetを調べたりする必要はありません。
もう一点:vRealize OperationsやAria Operationsを使用している場合、vSphereのtagsはコスト報告書やcapacity planningに自動的に取り込まれます――チームやプロジェクトごとにコストを配分する際に非常に便利です。
導入チェックリスト(初めて取り組むチーム向け)
- チームで必要な分類軸を話し合って決める(Environment、Team、Tierが最低限のセット)
- 新しいVMを作成する前に、Tag CategoriesとTagsを作成しておく
- PowerCLI scriptを使って既存のVMに遡ってtagを付与する(数時間かかりますが、やる価値はあります)
- ルール化:新しく作成するVMはすべて、引き渡す前にEnvironment tagとOwner attributeの設定を必須とする
- 定期的にtagが未設定のVMをチェックするscriptを実行し、インベントリを常に整った状態に保つ
# Environment tagが未設定のVMをチェックするScript
Get-VM | ForEach-Object {
$tags = Get-TagAssignment -Entity $_ | Select-Object -ExpandProperty Tag
$hasEnv = $tags | Where-Object { $_.Category.Name -eq "Environment" }
if (-not $hasEnv) {
Write-Output "[MISSING TAG] $($_.Name) — Environment tagが設定されていません"
}
}

