VM Insights からのマップ データのクエリ

VM insights でプロセスと依存関係を有効にすると、マップ機能をサポートするために、コンピューターとプロセスのインベントリ データが収集されます。 このデータについては、マップを使用して分析できるだけでなく、Log Analytics を使用して直接クエリを実行することもできます。 この記事では、使用可能なデータについて説明し、クエリの例を示します。

VM Insights では、パフォーマンスと接続のメトリック、コンピューターとプロセスのインベントリ データ、および正常性状態の情報の収集と、Azure Monitor 内の Log Analytics ワークスペースへの転送が行われます。 このデータは、Azure Monitor でクエリ用に使用できます。 このデータは、移行計画、容量の分析、探索、必要に応じたパフォーマンスのトラブルシューティングといったシナリオに適用できます。

重要

この記事で説明するテーブルを作成するには、それらのテーブルについて VM insights のプロセスと依存関係を有効にしておく必要があります。

Map レコード

レコードは、個々のプロセスまたはコンピューターが起動または VM Insights に追加されたときに生成されるほか、個々の一意なコンピューターとプロセスについて 1 時間ごとに 1 件ずつ生成されます。 VMComputer テーブルのフィールドと値は、ServiceMap Azure Resource Manager API のマシン リソースのフィールドにマップされます。 VMProcess テーブルのフィールドと値は、ServiceMap Azure Resource Manager API のプロセス リソースのフィールドにマップされます。 _ResourceId フィールドは、対応する Resource Manager リソースの名前フィールドと一致します。

個々のプロセスとコンピューターの識別に使用できる、内部生成されたプロパティがあります。

  • コンピューター: Log Analytics ワークスペース内のコンピューターは _ResourceId を使用して一意に識別されます。
  • プロセス: Log Analytics ワークスペース内のプロセスは _ResourceId を使用して一意に識別されます。

指定の時間範囲にある指定のプロセスとコンピューターについては、複数のレコードが存在できるため、クエリは、同じコンピューターまたはプロセスに対して複数のレコードを返すことがあります。 最新のレコードのみが返されるようにするには、| summarize arg_max(TimeGenerated, *) by ResourceId をクエリに追加します。

接続とポート

VMConnectionVMBoundPort では、マシンの接続 (受信および送信) と、それらのマシンで開かれている/アクティブであるサーバー ポートの情報が得られます。 接続メトリックは、時間枠の間に特定のメトリックを取得する手段を提供する API を介して公開されています。 リスニング ソケットで "受諾する" ことで得られる TCP 接続は受信ですが、所定の IP とポートに "接続する" ことで作成される接続は送信です。 Direction プロパティは接続の方向を表します。これは inbound または outbound に設定できます。

これらのテーブル内のレコードは、Dependency Agent によって報告されるデータから生成されます。 いずれの記録も、1 分の時間間隔での観測を表します。 TimeGenerated プロパティは、時間間隔の開始を示します。 各レコードには、それぞれのエンティティを特定する情報、つまり接続またはポートと、そのエンティティに関連付けられたメトリックが含まれています。 現在のところ、TCP over IPv4 を使用することで発生するネットワーク アクティビティのみが報告されます。

コストと複雑さを管理するため、接続レコードは個々の物理ネットワーク接続を表すものではありません。 複数の物理ネットワーク接続は、論理接続にグループ化され、その後それぞれのテーブルに反映されます。 つまり、VMConnection テーブル内のレコードは論理的なグループに対応しており、観察対象である個々の物理接続に対応するものではありません。 1 分単位で区切られた 1 つの期間内において、以下の属性値が共通である物理ネットワーク接続は、VMConnection 内では 1 つの論理レコードにまとめて扱われます。

メトリック

VMConnectionVMBoundPort では、当該の論理接続またはネットワーク ポート (BytesSentBytesReceived) で送受信されたデータの量に関する情報を反映したメトリック データを取得できます。 また、応答時間 (ResponseTimeMaxResponseTimeMinResponseTimeSum) も知ることができます。これは、個々の接続を介して送信された要求がリモート エンドポイントによって処理され、応答が返されるまでの、呼び出し元に発生した待ち時間です。 報告される応答時間は、内在するアプリケーション プロトコルの実際の応答時間の推定値です。 これは、物理ネットワーク接続の送信元と送信先の間のデータ フローの観察に基づき、経験則を使用して計算されます。 これは、概念上、要求の最後のバイトが送信者を離れる時間と、応答の最後のバイトが送信者に返される時間の差です。 これらの 2 つのタイムスタンプは、所定の物理接続で要求イベントと応答イベントを明確化するために使用されます。 これらの差は、1 つの要求の応答時間を表します。

このアルゴリズムは近似値を求めるものであり、正確さの度合いは、当該ネットワーク接続で実際にどのようなアプリケーション プロトコルが使用されるかによって異なります。 たとえば、現在のアプローチは、HTTP(S) のような要求 - 応答ベースのプロトコルでは正しく動作しますが、一方向またはメッセージ キュー ベースのプロトコルでは動作しません。

たとえば、以下のような事項を考慮する必要があります。

  1. プロセスが同じ IP アドレスでも複数のネットワーク インターフェイスで接続を受け入れる場合、インターフェイスごとに別のレコードが報告されます。
  2. ワイルドカード IP 付きレコードにはアクティビティはありません。 これらは、マシン上のポートが受信トラフィックにオープンであるという事実を表すために加えられています。
  3. 冗長性とデータ量を減らすために、ワイルドカード IP 付きレコードは、特定の IP アドレスと一致するレコード (同じプロセス、ポート、プロトコル) がある場合は省略されます。 ワイルドカード IP レコードが省略された場合、特定の IP アドレスが指定された IsWildcardBind レコード プロパティは、ポートが報告マシンのあらゆるインターフェイスで公開されることを示す True に設定されます。
  4. 特定のインターフェイスにのみバインドされているポートでは、IsWildcardBindFalse に設定されます。

命名と分類

便宜上、接続のリモート側の IP アドレスは RemoteIp プロパティに加えられています。 受信接続の場合、RemoteIpSourceIp と同じですが、送信接続の場合は DestinationIp と同じです。 RemoteDnsCanonicalNames プロパティは、RemoteIp 向けにマシンにより報告される DNS 正規名を表します。 RemoteDnsQuestions プロパティは、RemoteIp についてマシンから報告された DNS の質問を表します。 RemoveClassification プロパティは、将来使用するために予約されています。

悪意のある IP

VMConnection テーブルに含まれる個々の RemoteIp プロパティは、悪意ある既知のアクティビティに関連した一連の IP と照合されます。 悪意あるものとして識別された RemoteIp については、以下のプロパティが設定されます。 悪意あるものと見なされない IP については、これらのプロパティは空です。

  • MaliciousIp
  • IndicatorThreadType
  • Description
  • TLPLevel
  • Confidence
  • Severity
  • FirstReportedDateTime
  • LastReportedDateTime
  • IsActive
  • ReportReferenceLink
  • AdditionalInformation

サンプルのマップのクエリ

既知のすべてのマシンを一覧表示する

VMComputer | summarize arg_max(TimeGenerated, *) by _ResourceId

VM が最後に再起動された時期を調べる

let Today = now(); VMComputer | extend DaysSinceBoot = Today - BootTime | summarize by Computer, DaysSinceBoot, BootTime | sort by BootTime asc

Azure VM の概要をイメージ、場所、SKU 別に表示する

VMComputer | where AzureLocation != "" | summarize by Computer, AzureImageOffering, AzureLocation, AzureImageSku

すべての管理対象コンピューターの物理メモリ容量を一覧表示する

VMComputer | summarize arg_max(TimeGenerated, *) by _ResourceId | project PhysicalMemoryMB, Computer

コンピューター名、DNS、IP、OS を一覧表示する

VMComputer | summarize arg_max(TimeGenerated, *) by _ResourceId | project Computer, OperatingSystemFullName, DnsNames, Ipv4Addresses

コマンド ラインに "sql" が含まれるすべてのプロセスを検索する

VMProcess | where CommandLine contains_cs "sql" | summarize arg_max(TimeGenerated, *) by _ResourceId

特定のマシン (最新のレコード) をリソース名から検索する

search in (VMComputer) "m-4b9c93f9-bc37-46df-b43c-899ba829e07b" | summarize arg_max(TimeGenerated, *) by _ResourceId

特定のマシン (最新のレコード) を IP アドレスから検索する

search in (VMComputer) "10.229.243.232" | summarize arg_max(TimeGenerated, *) by _ResourceId

指定したマシン上の既知のプロセスをすべて一覧表示する

VMProcess | where Machine == "m-559dbcd8-3130-454d-8d1d-f624e57961bc" | summarize arg_max(TimeGenerated, *) by _ResourceId

SQL Server を実行しているすべてのコンピューターを一覧表示する

VMComputer | where AzureResourceName in ((search in (VMProcess) "*sql*" | distinct Machine)) | distinct Computer

データセンター内で使用される curl の一意な製品バージョンをすべて一覧表示する

VMProcess | where ExecutableName == "curl" | distinct ProductVersion

送受信されたバイト数の動向を調べる

VMConnection | summarize sum(BytesSent), sum(BytesReceived) by bin(TimeGenerated,1hr), Computer | order by Computer desc | render timechart

送信されているバイト数が特に多い Azure VM を調べる

VMConnection | join kind=fullouter(VMComputer) on $left.Computer == $right.Computer | summarize count(BytesSent) by Computer, AzureVMSize | sort by count_BytesSent desc

リンク ステータスの動向を調べる

VMConnection | where TimeGenerated >= ago(24hr) | where Computer == "acme-demo" | summarize dcount(LinksEstablished), dcount(LinksLive), dcount(LinksFailed), dcount(LinksTerminated) by bin(TimeGenerated, 1h) | render timechart

接続エラーの動向を調べる

VMConnection | where Computer == "acme-demo" | extend bythehour = datetime_part("hour", TimeGenerated) | project bythehour, LinksFailed | summarize failCount = count() by bythehour | sort by bythehour asc | render timechart

バインドされたポートを表示する

VMBoundPort
| where TimeGenerated >= ago(24hr)
| where Computer == 'admdemo-appsvr'
| distinct Port, ProcessName

マシン群の上で開かれているポートの数を表示する

VMBoundPort
| where Ip != "127.0.0.1"
| summarize by Computer, Machine, Port, Protocol
| summarize OpenPorts=count() by Computer, Machine
| order by OpenPorts desc

ワークスペース内のプロセスを、開かれているポートの数に基づいてスコアリングする

VMBoundPort
| where Ip != "127.0.0.1"
| summarize by ProcessName, Port, Protocol
| summarize OpenPorts=count() by ProcessName
| order by OpenPorts desc

各ポートの挙動を集約する

このクエリは、アクティビティごとにポートにスコアを付けるために使用できます。たとえば、最も送受信トラフィックが多いポート、最も接続が多いポートなどです。

VMBoundPort
| where Ip != "127.0.0.1"
| summarize BytesSent=sum(BytesSent), BytesReceived=sum(BytesReceived), LinksEstablished=sum(LinksEstablished), LinksTerminated=sum(LinksTerminated), arg_max(TimeGenerated, LinksLive) by Machine, Computer, ProcessName, Ip, Port, IsWildcardBind
| project-away TimeGenerated
| order by Machine, Computer, Port, Ip, ProcessName

一群のマシンから外に対して行われた接続の要約を表示する

// the machines of interest
let machines = datatable(m: string) ["m-82412a7a-6a32-45a9-a8d6-538354224a25"];
// map of ip to monitored machine in the environment
let ips=materialize(VMComputer
| summarize ips=makeset(todynamic(Ipv4Addresses)) by MonitoredMachine=AzureResourceName
| mvexpand ips to typeof(string));
// all connections to/from the machines of interest
let out=materialize(VMConnection
| where Machine in (machines)
| summarize arg_max(TimeGenerated, *) by ConnectionId);
// connections to localhost augmented with RemoteMachine
let local=out
| where RemoteIp startswith "127."
| project ConnectionId, Direction, Machine, Process, ProcessName, SourceIp, DestinationIp, DestinationPort, Protocol, RemoteIp, RemoteMachine=Machine;
// connections not to localhost augmented with RemoteMachine
let remote=materialize(out
| where RemoteIp !startswith "127."
| join kind=leftouter (ips) on $left.RemoteIp == $right.ips
| summarize by ConnectionId, Direction, Machine, Process, ProcessName, SourceIp, DestinationIp, DestinationPort, Protocol, RemoteIp, RemoteMachine=MonitoredMachine);
// the remote machines to/from which we have connections
let remoteMachines = remote | summarize by RemoteMachine;
// all augmented connections
(local)
| union (remote)
//Take all outbound records but only inbound records that come from either //unmonitored machines or monitored machines not in the set for which we are computing dependencies.
| where Direction == 'outbound' or (Direction == 'inbound' and RemoteMachine !in (machines))
| summarize by ConnectionId, Direction, Machine, Process, ProcessName, SourceIp, DestinationIp, DestinationPort, Protocol, RemoteIp, RemoteMachine
// identify the remote port
| extend RemotePort=iff(Direction == 'outbound', DestinationPort, 0)
// construct the join key we'll use to find a matching port
| extend JoinKey=strcat_delim(':', RemoteMachine, RemoteIp, RemotePort, Protocol)
// find a matching port
| join kind=leftouter (VMBoundPort 
| where Machine in (remoteMachines) 
| summarize arg_max(TimeGenerated, *) by PortId 
| extend JoinKey=strcat_delim(':', Machine, Ip, Port, Protocol)) on JoinKey
// aggregate the remote information
| summarize Remote=makeset(iff(isempty(RemoteMachine), todynamic('{}'), pack('Machine', RemoteMachine, 'Process', Process1, 'ProcessName', ProcessName1))) by ConnectionId, Direction, Machine, Process, ProcessName, SourceIp, DestinationIp, DestinationPort, Protocol

次のステップ