はじめに

Azure Monitor Agent では、Data Collection Rule で収集した OpenTelemetry パフォーマンスメトリクスを Azure Monitor Workspace に送信できます。閉域な Azure Monitor Workspace でメトリクスを送信・検索したことがなかったので、実際に試してみました。具体的には、Data Collection Endpoint と Azure Monitor Workspace までの公開ネットワークアクセスを無効化し、Private Link 経由で system.cpu.time のメトリクスを取得できることを確認します。

検証構成

次のリソースを使用します。

リソース 名前 役割
Windows Server 仮想マシン vm0509-1 Azure Monitor Agent の実行元
Azure Monitor Workspace amw-je OpenTelemetry メトリクスの保存先
Data Collection Endpoint otel-ingest メトリクスの取り込み endpoint
Data Collection Rule amw-opentelemetry Microsoft-OtelPerfMetrics の収集と転送
Azure Monitor Private Link Scope lab-je-ampls Data Collection Endpoint の Private Link 接続

Azure Monitor Workspace と Data Collection Endpoint の設定

閉域構成にするには、Azure Monitor Workspace と Data Collection Endpoint の両方で公開ネットワークアクセスを無効化する必要があります。Azure Monitor Workspace は publicNetworkAccess、Data Collection Endpoint は NetworkAclsPublicNetworkAccessDisabled に設定します。

Azure Monitor Workspace の設定は以下の通りです。

$amwResource = Get-AzResource `
    -ResourceGroupName $amwResourceGroup `
    -ResourceType "microsoft.monitor/accounts" `
    -Name $amwName `
    -ExpandProperties

$amwResource.Properties |
    Select-Object provisioningState, publicNetworkAccess |
    Format-List

provisioningState   : Succeeded
publicNetworkAccess : Disabled

Data Collection Endpoint の設定は以下の通りです。

$dce = Get-AzDataCollectionEndpoint `
    -ResourceGroupName $dceResourceGroup `
    -Name $dceName

$dce |
    Select-Object ProvisioningState, NetworkAclsPublicNetworkAccess |
    Format-List

ProvisioningState              : Succeeded
NetworkAclsPublicNetworkAccess : Disabled

Azure Monitor Workspace と Data Collection Endpoint はどちらも Succeeded で、公開ネットワークアクセスは Disabled です。

Data Collection Rule に必要な接続先設定

Data Collection Rule には、取り込みに使用する Data Collection Endpoint のリソース識別子と、送信先となる Azure Monitor Workspace のリソース識別子を設定する必要があります。また、データフローの stream に Microsoft-OtelPerfMetrics、destination に対象の Azure Monitor Workspace を指定します。

Data Collection Rule に格納されている Data Collection Endpoint と Azure Monitor Workspace の参照情報は以下の通りです。出力中のサブスクリプション識別子は匿名化しています。

$dcr = Get-AzDataCollectionRule `
    -ResourceGroupName $dcrResourceGroup `
    -Name $dcrName

$dcr.DataCollectionEndpointId

/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/rg-monitor/providers/Microsoft.Insights/dataCollectionEndpoints/otel-ingest

$dcr.DestinationMonitoringAccount |
  Format-List AccountId, AccountResourceId, Name

AccountId         : 54584085-4b6b-4a6d-82d1-81a1cab58540
AccountResourceId : /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/rg-monitor/providers/microsoft.monitor/accounts/amw-je
Name              : amw-1358540776

DataCollectionEndpointId は Data Collection Endpoint otel-ingest を参照し、DestinationMonitoringAccount.AccountResourceId は Azure Monitor Workspace amw-je を参照しています。Azure Monitor Workspace の destination 名は amw-1358540776 です。

データフローの設定は以下の通りです。Microsoft-OtelPerfMetrics の送信先として、Azure Monitor Workspace の destination amw-1358540776 が設定されています。

ConvertTo-Json `
    -InputObject $dcr.DataFlow `
    -Depth 6

[
  {
    "BuiltInTransform": null,
    "Destination": [
      "amw-1358540776"
    ],
    "OutputStream": null,
    "Stream": [
      "Microsoft-OtelPerfMetrics"
    ],
    "TransformKql": null
  }
]

Private Endpoint と Azure Monitor Agent に必要な設定

Data Collection Endpoint を閉域で利用するには、Data Collection Endpoint を Azure Monitor Private Link Scope の scoped resource として登録し、Azure Monitor Private Link Scope の Private Endpoint Connection を承認済みにする必要があります。scoped resource と Private Endpoint Connection の設定は以下の通りです。

$ampls = Get-AzResource `
  -ResourceGroupName $amplsResourceGroup `
  -ResourceType "microsoft.insights/privateLinkScopes" `
  -Name $amplsName

$amplsScopedResources = Get-AzInsightsPrivateLinkScopedResource `
  -ResourceGroupName $amplsResourceGroup `
  -ScopeName $amplsName

$dceScopedResource = $amplsScopedResources |
  Where-Object { $_.LinkedResourceId -eq $dce.Id }

$dceScopedResource | Format-List Name, LinkedResourceId, ProvisioningState

Name              : scoped-otel-ingest-13aad157-be4b-4d5d-afa1-4b37a480e009
LinkedResourceId  : /subscriptions/<SUBSCRIPTION_ID>/resourcegroups/rg-monitor/providers/microsoft.insights/datacollectionendpoints/otel-ingest
ProvisioningState : Succeeded

$amplsPrivateEndpointConnections = Get-AzPrivateEndpointConnection `
  -PrivateLinkResourceId $ampls.ResourceId

$amplsPrivateEndpointConnections.PrivateLinkServiceConnectionState.Status

Approved

Azure Monitor Workspace の Prometheus query endpoint を閉域で利用するには、 prometheusMetrics の Private Endpoint が必要です。Azure Monitor Workspace 本体の Private Endpoint Connection の設定は以下の通りです。

ConvertTo-Json `
    -InputObject $amwResource.Properties.privateEndpointConnections `
    -Depth 8

[
  {
    "id": "/subscriptions/<SUBSCRIPTION_ID>/resourcegroups/rg-monitor/providers/microsoft.monitor/accounts/amw-je/privateEndpointConnections/amw-query.44dcdff0-fd49-4977-ae76-e0491e787669",
    "name": "amw-query.44dcdff0-fd49-4977-ae76-e0491e787669",
    "type": "Microsoft.Monitor/accounts/privateEndpointConnections",
    "properties": {
      "provisioningState": "Succeeded",
      "privateEndpoint": {
        "id": "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/rg-monitor/providers/Microsoft.Network/privateEndpoints/amw-query"
      },
      "groupIds": [
        "prometheusMetrics"
      ],
      "privateLinkServiceConnectionState": {
        "status": "Approved",
        "description": "Auto-Approved",
        "actionsRequired": "None"
      }
    }
  }
]

メトリクスを収集する仮想マシンには Azure Monitor Agent 拡張と対象 Data Collection Rule の association が必要です。Azure Monitor Agent 拡張の設定は以下の通りです。

$amaExtension | Format-List Name, Publisher, ExtensionType, TypeHandlerVersion, ProvisioningState

Name               : AzureMonitorWindowsAgent
Publisher          : Microsoft.Azure.Monitor
ExtensionType      : AzureMonitorWindowsAgent
TypeHandlerVersion : 1.0
ProvisioningState  : Succeeded

Data Collection Rule association の設定は以下の通りです。amw-opentelemetry-association は Data Collection Rule amw-opentelemetry を参照しています。

$dcrAssociations | Format-List Name, DataCollectionRuleId, DataCollectionEndpointId, ProvisioningState

Name                     : amw-opentelemetry-association
DataCollectionRuleId     : /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/rg-monitor/providers/Microsoft.Insights/dataCollectionRules/amw-opentelemetry
DataCollectionEndpointId :
ProvisioningState        :

名前解決の上書き

プライベートエンドポイント経由でメトリクスを送信するためには、FQDN を名前解決したときにプライベート IP アドレスが返ってくるようにする必要があります。

Data Collection Endpoint と Azure Monitor Workspace query endpoint を名前解決した結果は以下の通りです。FQDN のうち、リソースごとに自動生成される固有文字列のみ <UNIQUE_ID> として匿名化しています。

Resolve-DnsName -Name $ingestHost

Name       : otel-ingest-<UNIQUE_ID>.japaneast-1.metrics.ingest.privatelink.monitor.azure.com
QueryType  : A
TTL        : 9
Section    : Answer
IP4Address : 10.1.2.27
Resolve-DnsName -Name $queryHost

Name       : amw-je-<UNIQUE_ID>.privatelink.japaneast.prometheus.monitor.azure.com
QueryType  : A
TTL        : 10
Section    : Answer
IP4Address : 10.1.2.31

メトリクスを取得する

メトリクスのインジェストができているはずなので、実際に Azure Monitor Workspace にクエリを送ってデータを取得します。今回は仮想マシンからクエリを送信したかったので、仮想マシンの system-assigned managed identity に Monitoring Data Reader ロールを割り当てました。

system-assigned managed identity に割り当てられているロールは以下の通りです。出力中のサブスクリプション識別子は匿名化しています。

$vm = Get-AzVM `
  -ResourceGroupName "ACS" `
  -Name "vm0509-1"

$vmRoleAssignments = Get-AzRoleAssignment `
  -ObjectId $vm.Identity.PrincipalId

$vmRoleAssignments |
  Select-Object RoleDefinitionName, Scope |
  Format-Table -Wrap -AutoSize

RoleDefinitionName     Scope
------------------     -----
Monitoring Data Reader /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/rg-monitor/providers/microsoft.monitor/accounts/amw-je
Monitoring Data Reader /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/rg-monitor
Monitoring Reader      /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/rg-monitor/providers/microsoft.monitor/accounts/amw-je
Monitoring Data Reader /subscriptions/<SUBSCRIPTION_ID>

Monitoring Data Reader ロールには、Azure Monitor Workspace のメトリクスを読み取るための DataAction が含まれています。

$monitoringDataReader = Get-AzRoleDefinition `
  -Name "Monitoring Data Reader"

$monitoringDataReader |
  Select-Object Name, Id, Actions, DataActions, NotActions, NotDataActions |
  Format-List

Name           : Monitoring Data Reader
Id             : b0d8363b-8ddd-447d-831f-62ca05bff136
Actions        : {}
DataActions    : {Microsoft.Monitor/accounts/data/metrics/read}
NotActions     : {}
NotDataActions : {}

それでは実際に、仮想マシンの system-assigned managed identity を使用して、Azure Instance Metadata Service からアクセストークンを取得し、Azure Monitor Workspace の Prometheus インターフェースにアクセスします。

$imdsTokenResponse = Invoke-RestMethod `
    -Headers @{ Metadata = "true" } `
    -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2019-08-01&resource=https%3A%2F%2Fprometheus.monitor.azure.com" `
    -Method GET

$imdsTokenResponse |
    Select-Object token_type, expires_on, resource |
    Format-List

token_type : Bearer
expires_on : 1785412402
resource   : https://prometheus.monitor.azure.com

取得したアクセストークンを使用して、Azure Monitor Workspace の Prometheus インターフェースへ送信する Authorization ヘッダーを作成します。

$headers = @{
  Authorization = "Bearer $($imdsTokenResponse.access_token)"
}

対象仮想マシンのリソース識別子をラベルセレクターに指定し、system.cpu.time を問い合わせます。実際のリソース識別子に含まれるサブスクリプション識別子は匿名化しています。

$metricSelector = `
    '{__name__="system.cpu.time","microsoft.resourceid"="<VM_RESOURCE_ID>"}'

$encodedMetricSelector = [System.Uri]::EscapeDataString($metricSelector)

$response = Invoke-RestMethod `
  -Uri "https://amw-je-<UNIQUE_ID>.japaneast.prometheus.monitor.azure.com/api/v1/query?query=$encodedMetricSelector" `
    -Method GET `
    -Headers $headers

取得した応答を同じ PowerShell セッションで要約した結果です。ちゃんと値が取れています。

$checkedAt = [DateTimeOffset]::UtcNow
$metricTime = [DateTimeOffset]::FromUnixTimeMilliseconds(
  [long]($response.data.result[0].value[0] * 1000)
)

[PSCustomObject]@{
  Status        = $response.status
  ResultType    = $response.data.resultType
  SeriesCount   = $response.data.result.Count
  FirstCpu      = $response.data.result[0].metric.cpu
  FirstState    = $response.data.result[0].metric.state
  FirstValue    = $response.data.result[0].value[1]
  MetricTimeUtc = $metricTime.UtcDateTime.ToString("o")
  CheckedAtUtc  = $checkedAt.UtcDateTime.ToString("o")
  AgeSeconds    = [math]::Round(($checkedAt - $metricTime).TotalSeconds, 3)
} | Format-List

Status        : success
ResultType    : vector
SeriesCount   : 16
FirstCpu      : cpu1
FirstState    : system
FirstValue    : 1067.046875
MetricTimeUtc : 2026-07-29T12:19:07.1460000Z
CheckedAtUtc  : 2026-07-29T12:19:23.9909732Z
AgeSeconds    : 16.845

閉域化した Azure Monitor Workspace のデータを可視化する

Azure Monitor Workspace のメトリクスを可視化します。可視化で利用できるものは次の3つです。

  1. Azure Monitor Workbook
  2. Grafana を利用したダッシュボード
  3. Azure VM Insight

各手法でクエリを送信するエンドポイントが異なるため、利用元の環境によって見える・見えないが変わってきます。

Azure Monitor Workspace がクエリを投げる Prometheus インターフェースの URL は、次の URL です。

https://amw-je-<UNIQUE_ID>.japaneast.prometheus.monitor.azure.com/api/v1/query_range

Grafana を利用したダッシュボードがクエリを投げる Prometheus インターフェースの URL は、次の URL です。

https://global.gateway.dashboard.azure.com/api/ds/query?ds_type=prometheus&requestId=SQR101

VM Insight がクエリを投げる Prometheus インターフェースの URL は、次の URL です。この URLは Azure Monitor Workspace 全体にクエリを送るのではなく、特定のリソースのスコープに限ってクエリを送るときに利用されるものです。

https://query.eastus.prometheus.monitor.azure.com/api/v1/query_range

Azure Monitor ワークスペースにおけるリソーススコープのクエリ

閉域内外からのアクセスでの動作結果は以下の通りです

アクセス元 Azure Monitor Workbook Grafana ダッシュボード VM Insight
閉域外
閉域内

閉域外からこれらのツールを利用すると、なぜか VM Insight だけが動きます。VM Insightが利用するリソーススコープのエンドポイントが、現時点で閉域をサポートしていないためでしょうか。サポートしていないならアクセスできないようにしてほしいところですが、現状はアクセスできてしまいます。

現在、エンドポイントはパブリック インターネット経由でのみ使用できます。 Private Link (AMPLS) は現在サポートされていません。

制限事項

残りの2つについては「Access through public network is disabled for this resource.」というエラーが表示されてデータが表示されません。

一方で、閉域内からアクセスすると、Grafana ダッシュボードだけが「Access through public network is disabled for this resource.」というエラーが表示されてデータが表示されません。Azure Monitor Workspace 自体の FQDN にクエリを投げている Azure Monitor Workbook は正常に動作するようになります。ここは想定通りの結果です。

まとめ

今回の検証では、Azure Monitor Workspace と Data Collection Endpoint の公開ネットワークアクセスを無効化した状態でも、Azure Monitor Agent が収集した OpenTelemetry パフォーマンスメトリクスを Private Link 経由で送信できることを確認しました。また、閉域内から Prometheus インターフェースへクエリしてメトリクスを取得できることを確認しました。

インジェストは想定通りでしたが、可視化の部分がツールによって動作が異なる点に注意です。Azure Monitor Workspace への直接クエリが成功することと、各可視化機能が利用できることは分けて考え、採用するツールごとにネットワーク経路と Private Link の対応状況を事前に確認したほうがよさそうです。

参考リンク

  • 当サイトは個人のブログです。このブログに示されている見解や意見は個人的なものであり、所属組織の見解や意見を表明するものではありません。
  • 公開情報を踏まえて正確な情報を掲載するよう努めますが、その内容の完全性や正確性、有用性、安全性、最新性について一切保証しません。
  • 添付文章やリンク先などを含む本サイトの内容は作成時点でのものであり、予告なく変更される場合があります。