簡體   English   中英

通過 Powershell 獲取與 Azure ARM VM 的一組 NIC 關聯的當前 IP 地址

[英]Get current IP addresses associated with an Azure ARM VM's set of NICs via Powershell

我正在嘗試編寫一些 Powershell 來獲取 Azure ARM 虛擬機(非經典)列表以及其 NIC 的當前關聯 IP 地址。

在經典中,這是 VM 對象的一部分,但在 ARM 中,它是一個單獨的對象,我正在努力讓 Powershell 以我想要的方式工作。

我有以下代碼段:

$nic = (((Get-AzureRmVM).NetworkProfile).NetworkInterfaces).Id
ForEach ($i in $nic) {
  $nicname = $i.substring($i.LastIndexOf("/")+1)
  Get-AzureRmNetworkInterface -Name $nicname -ResourceGroupName RGTEST | Get-AzureRmNetworkInterfaceIpConfig | select-object  PrivateIpAddress,PrivateIpAllocationMethod
}

這有效,但僅適用於指定資源組“RGTEST”中的 VM。

似乎Get-AzureRmNetworkInterface只能在傳入NIC Name和ResourceGroupName時才能工作,但我似乎無法從VM中獲取要傳入的RGname。

可能真的很容易,但我正在努力!

我使用此代碼獲取我所有的 ARM VM、它們的私有 IP 地址和分配方法,它可以跨資源組工作。

$vms = get-azurermvm
$nics = get-azurermnetworkinterface | where VirtualMachine -NE $null #skip Nics with no VM

foreach($nic in $nics)
{
    $vm = $vms | where-object -Property Id -EQ $nic.VirtualMachine.id
    $prv =  $nic.IpConfigurations | select-object -ExpandProperty PrivateIpAddress
    $alloc =  $nic.IpConfigurations | select-object -ExpandProperty PrivateIpAllocationMethod
    Write-Output "$($vm.Name) : $prv , $alloc"
}

示例輸出:
proddc : 10.0.0.4 , 靜態
stagedc : 10.1.0.4 , 靜態

下面是我用來獲取 Azure ARM VM 的私有和公共 IP 的腳本。 如果 VM 具有多個 NIC 或 IpConfig,則可能需要使用循環。

$rg = Get-AzureRmResourceGroup -Name "MyResourceGroup01"
$vm = Get-AzureRmVM -ResourceGroupName $rg.ResourceGroupName -Name "MyVM01"
$nic = Get-AzureRmNetworkInterface -ResourceGroupName $rg.ResourceGroupName -Name $(Split-Path -Leaf $VM.NetworkProfile.NetworkInterfaces[0].Id)
$nic | Get-AzureRmNetworkInterfaceIpConfig | Select-Object Name,PrivateIpAddress,@{'label'='PublicIpAddress';Expression={Set-Variable -name pip -scope Global -value $(Split-Path -leaf $_.PublicIpAddress.Id);$pip}}
(Get-AzureRmPublicIpAddress -ResourceGroupName $rg.ResourceGroupName -Name $pip).IpAddress

#Output:    
Name      PrivateIpAddress PublicIpAddress
----      ---------------- ---------------
ipconfig1 10.0.0.10        MyVM01-pip

40.80.217.1

對於那些正在尋找跨租戶中的多個訂閱的解決方案的人,這里有一個腳本,循環遍歷每個訂閱並報告每個私有 IP、NIC、VM、資源組和相關訂閱。 輸出采用對象格式並導出為 CSV 文件。

<#
    .SYNOPSIS
        Returns IP addresses and associated network interfaces and virtual machines across all Azure subscriptions the
        user has access to.

    .DESCRIPTION
        This script returns all private IP addresses, the IP configuration resources they are associated with, the network interfaces and virtual
        machines across all subscriptions. This script requires:

        1. The Azure module to be installed (https://docs.microsoft.com/en-us/powershell/azure/install-az-ps?view=azps-2.8.0)
        2. The user to be logged in to an Azure account using Connect-AzAccount / Connect-AzureRmAccount
        3. The user must have subscription wide read permissions assigned for each subscription being queried

    .PARAMETER FileName
        Optional. Specify the file name and path for a CSV export.

    .EXAMPLE
        Get-IpAddressAllocation.ps1 -FileName .\AzureIpAddressReport.csv
#>

<#
    .AUTHOR
        Michael Wheatfill

    .LICENSEURI
        https://github.com/mwheatfill/mwheatfill.github.io/blob/master/LICENSE.txt
#>

#region Parameters
[CmdletBinding()]
param (
    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [String]
    $FileName
)
#endregion Parameters

#region Initializations
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
#endregion Initializations

#region Functions
function Get-IpAddresses {
    param ()

    $networkInterfaces = Get-AzNetworkInterface | Where-Object {$_.VirtualMachine -ne $null}
    $virtualMachines = Get-AzVM
    $results = @()

    foreach($interface in $networkInterfaces) {
        $ipConfigurations = $interface.IpConfigurations

        foreach($ipConfig in $ipConfigurations) {
            $vm = $virtualMachines | Where-Object {$_.Id -eq $interface.VirtualMachine.Id}

            $ipDetails = [pscustomobject]@{
                PrivateIpAddress = $ipConfig.PrivateIpAddress
                VMName = $vm.Name
                NetworkInterface = $interface.Name
                IpConfigName = $ipConfig.Name
                Primary = $ipConfig.Primary
                ResourceGroup = $vm.ResourceGroupName
                Subscription = $subscription.Name
            }
            $results += $ipDetails
        }
    }
    return $results
}
#endregion Functions

#region Main
$subscriptions = Get-AzSubscription | Select-Object
$ipAddressesInAllSubscriptions = @()
$progressCount = 0

foreach ($subscription in $subscriptions) {
    $progressCount++
    $progressComplete = ($progressCount / $subscriptions.count * 100)
    $progressMessage = "Gathering IP address informtion for subscription $progressCount of $($subscriptions.Count)"
    Write-Progress -Activity $progressMessage -Status ($subscription.Name) -PercentComplete $progressComplete

    $subscription | Select-AzSubscription > $null
    $ipAddressesInSubscription = Get-IpAddresses -SubscriptionObject $subscription
    $ipAddressesInAllSubscriptions += $ipAddressesInSubscription
}

$ipAddressesInAllSubscriptions | Sort-Object -Property Subscription, VMName, NetworkInterface, IpConfigName, Primary | Format-Table
$ipAddressesInAllSubscriptions | Export-Csv -Path $FileName -NoTypeInformation
#endregion Main

由於這個問題是在 2016 年被問到的,微軟決定在2020 年 12 月之后不再維護AzureRM模塊,以及隨之*-AzureRM**-AzureRM* cmdlet。 Az模塊將在未來取代它。

但是,通過使用 Azure 資源圖 (ARG),有一種快速替代方法可用於檢索 Azure VM 及其關聯 IP(私有和公共 IP)的列表。

具體而言,對於分布在數百個 Azure 訂閱中的數千個 VM,使用 ARG 只需幾秒鍾,而使用AzGet-AzVM cmdlet 則需要 20 多分鍾。

即使在多個 vmNic 和每個 vmNic 的多個 IP 配置上,腳本進一步向下也會正確報告。 它將跨租戶中的 Azure 訂閱檢索所有 ARM VM 數據。 如果從本地 Powershell 會話或 Cloud Shell 運行,請確保首先安裝了Az.ResourceGraph模塊。

小型測試 Azure 租戶的示例輸出:

在此處輸入圖片說明

腳本如下:

function RunARGquery {
    param (
        [string[]]$SubscriptionIds,
        [string]$ARG_query
    )
    
    $fullResultSet = @()
    $pageSize = 5000
    
    # Subscription batching code below taken
    #  from https://docs.microsoft.com/en-us/azure/governance/resource-graph/troubleshoot/general#toomanysubscription
    # Create a counter, set the batch size, and prepare a variable for the results
    $counter = [PSCustomObject] @{ Value = 0 }
    $batchSize = 1000
    # Group the subscriptions into batches
    $subscriptionsBatch = $subscriptionIds | Group -Property { [math]::Floor($counter.Value++ / $batchSize) }

    $currentBatchNo = 0
    # Run the query for each batch
    foreach ($batch in $subscriptionsBatch) {
        $pagesProcessedSoFar = 0
        do {
            $results = @()
            if($pagesProcessedSoFar -eq 0) {
                $results = Search-AzGraph -Subscription $batch.Group -Query $ARG_query -First $pageSize
            }
            else {
                $results = Search-AzGraph -Subscription $batch.Group -Query $ARG_query -First $pageSize -Skip ($pagesProcessedSoFar * $pageSize)
            }
            $pagesProcessedSoFar++
            Write-Host "Processed $pagesProcessedSoFar pages so far. A number of $(($results | Measure-Object).count) results returned in the last page"
            $fullResultSet += $results
        } while(($results | Measure-Object).count -eq $pageSize)
        Write-Host "Finished subscription batch $currentBatchNo"
        $currentBatchNo++
    }
    return $fullResultSet
}

# Get the date/time now, for timestamping both output files
$currentDateTime = Get-Date -Uformat "%Y%m%d-%H%M%S"

Write-Host "Getting list of Azure subscriptions..."
# Fetch the full array of subscription IDs
$subscriptions = Get-AzSubscription
$subscriptionIds = $subscriptions.Id
Write-Host "Found $(($subscriptionIds | Measure-Object).count) subscriptions"

# ARG query from Listing 23
$ARM_ARG_query = @"
Resources
    | where type =~ 'microsoft.compute/virtualmachines'
    | project id, vmId = tolower(tostring(id)), vmName = name
    | join (Resources
        | where type =~ 'microsoft.network/networkinterfaces'
        | mv-expand ipconfig=properties.ipConfigurations
        | project vmId = tolower(tostring(properties.virtualMachine.id)), privateIp = ipconfig.properties.privateIPAddress, publicIpId = tostring(ipconfig.properties.publicIPAddress.id)
        | join kind=leftouter (Resources
            | where type =~ 'microsoft.network/publicipaddresses'
            | project publicIpId = id, publicIp = properties.ipAddress
        ) on publicIpId
        | project-away publicIpId, publicIpId1
        | summarize privateIps = make_list(privateIp), publicIps = make_list(publicIp) by vmId
    ) on vmId
    | project-away vmId, vmId1
    | sort by vmName asc
"@
Write-Host "Running ARM ARG query..."
RunARGquery -SubscriptionIds $subscriptionIds -ARG_query $ARM_ARG_query `
    | Select-Object -ExcludeProperty ResourceId `
    | Sort-Object -Property vmName `
    | Export-Csv -NoTypeInformation "AzureVMs_$currentDateTime.csv"

如果您還希望檢索經典 Azure VM(ASM 模型),也可以使用 ARG, 此處提供一個腳本。 可以在這篇博文中找到有關用於檢索 VM 數據、限制、權限等的 Azure 資源圖查詢的詳細討論。

這是我用來獲取用於各種任務的相關 VM 私有/公共 IP 地址信息的腳本。 它將從 MAC 操作系統或 Windows 操作系統運行,因為我有一個帶有 Widows 10 Parallels VM 的 MAC 運行以確保兼容性。 隨心所欲地使用它。

它將導出為 CSV 並嘗試在 Excel 或注冊到 CSV 擴展名的任何內容中打開。 在下面的示例中,它被保存為 PS_AzureRM_Get_VMs.ps1 或者只是在 PowerShell 中作為原始代碼運行它。

#Login to AZURE from PowerShell
#Below works in MAC/Linux PowerShell 6.0.1+ and Windows WMF 4.0+
#pwsh on MAC OS or powershell_ise.exe on Windows
#Connect-AzureRmAccount (Login-AzureRMAcount and Add-AzureRMAccount are the older Azure cmdlets)
# Goto URL https://microsoft.com/devicelogin and the password it provides example Q9KZ3HGN2
#  You may need to select-azurermsubscription -subscriptionid $SubscriptionID #Define $SubscriptionID = 'replace everything with your actual subscription  xxx-xxxx-xxx'

#Example location using the . way of running a script or just cut and paste to PowerShell
#Example location using the . way of running a script
#MAC PWSH syntax
#. ~/Documents/Scripts/AzureRM/PS_AzureRM_Get_VMs.ps1
#Windows PowerShell.exe/PowerShell_ISE.exe syntax
#. $env:userprofile\Scripts\AzureRM\PS_AzureRM_Get_VMs.ps1

$Project="DevOps"
$clientFilePrefix="AzureRM"
$clientFileCampaign="VMs"

#Get Date Time
$Date = ([DateTime]::Now).ToString("yyyyMMdd")
$Time = ([DateTime]::Now).ToString("HHmmss")
$DateStart=get-date

#Change to Windows Path if running in Windows $env:USERPROFILE
If ($($env:USERPROFILE)) {
  $fldrRoot="$($env:USERPROFILE)\"
  $fldrPathseparator='\'
} Else {
  $fldrRoot="~/"
  $fldrPathseparator='/'
}

# Make Directory if not exist
$fldrPath=$fldrRoot+"Documents"+$fldrPathseparator+$Project+$fldrPathseparator+$clientFilePrefix+$fldrPathseparator+$clientFileCampaign
New-Item -ErrorAction Ignore -ItemType directory -Path $fldrPath

#Make Imports Folder
$fldrPathimports=$fldrPath+$fldrPathseparator+"Imports"
New-Item -ErrorAction Ignore -ItemType directory -Path $fldrPathimports

#Make Exports Folder Directory
$fldrPathexports=$fldrPath+$fldrPathseparator+"Exports"
New-Item -ErrorAction Ignore -ItemType directory -Path $fldrPathexports

#Assign the variable to the export file Prefix
$VMInfo_Export=$fldrPathexports+$fldrPathseparator+$clientFilePrefix+"_"+$Project+"_"+$clientFileCampaign+"_"+$Date+"_"+$Time+".csv"

#Create a Table to use for filtering the results
$VMInfo = New-Object System.Data.DataTable
#Now Add some columns for use later
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'ResourceGroup',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'VM',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Location',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'VM_ID',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'VM_NIC',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'IP',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Public_IP_Name',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Public_IP',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'IP_MAC',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Priv_Dyn',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Status',([String])))
$VMInfo.Columns.Add((New-Object System.Data.DataColumn 'Date_Time',([String])))
$VMInfo_Array_Count=($VMInfo | Measure-Object | Select Count).Count

#List the Array to show it='s empty
Write-Host "Created Array VMInfo with $VMInfo_Array_Count objects"

$Date_Time=([DateTime]::Now).ToString("yyyy/MM/dd")+" "+([DateTime]::Now).ToString("HH:mm:ss")
#Check the OS type
If ($($ENV:OS)) {$OSTYPE="WINDOWS";Write-Host "The OS is"$OSTYPE" Based"} Else {$OSTYPE="LINUX";Write-Host "The OS is"$OSTYPE" Based"}
#Get the VM's
$VMs = Get-AzureRmVM
$VMstatus = Get-AzureRmVM -Status
#Get the NIC and their properties for matching against the VMs
$NICs = get-azurermnetworkinterface | where VirtualMachine -NE $null #skip NICs with no VM
#Get the Public IPs for matching against the VMs
#Public IPs work only if the naming convention starts with the VM Name used in Azure
$PublicIPs=Get-AzureRmPublicIpAddress | Select-Object Name,ResourceGroupName,IpAddress

#Now Loop through the NICs in Azure and match against the VMs and the Public IPs
ForEach ($nic in $NICs)
{
    #Get the VM Info
    $VM = $VMs | where-object -Property Id -EQ $nic.VirtualMachine.id
    $VM_Name = $($VM.name)
    $VM_Location = $($VM.Location)
    $VM_Resourcegroup = $($VM.ResourceGroupName)
    $VM_ID = $($VM.VMid)
    $VM_NIC = $nic.Name -Join ';'
    $VM_Status = (($VMstatus | Where {$_.ResourceGroupName -eq $VM_Resourcegroup -and $_.Name -eq $VM_Name}).PowerState).Replace('VM ', '')
    $VM_IP =  ($nic.IpConfigurations | select-object -ExpandProperty PrivateIpAddress) -Join ';'
    $VMPIPName = ($nic.IpConfigurations.PublicIpAddress.Id -Split '/')[-1]
    $VM_PublicIP =  ($PublicIPs | Where-Object {$_.ResourcegroupName -eq $VM_Resourcegroup -and $_.Name -like "$VMPIPName"} | Select IpAddress).IpAddress
    $VM_IP_MAC =  (($nic | Select MacAddress).MacAddress) -Join ';'
    $VM_Alloc =  $nic.IpConfigurations | select-object -ExpandProperty PrivateIpAllocationMethod

    #Uncomment this to check the values before going into the Array $VMINFO
    #Write-Output "$($VM.ResourceGroupName), $($VM.Name), $($VM.VMid), $($VM.Location), $VM_IP, $VM_PublicIP, $VM_IP_MAC, $VM_Alloc"

    #Now populate the $VMInfo array
    $row = $VMInfo.NewRow()
    $row.'ResourceGroup'=$VM_Resourcegroup
    $row.'VM'=$VM_Name
    $row.'VM_ID'=$VM_ID
    $row.'VM_NIC'=$VM_NIC
    $row.'Location'=$VM_Location
    $row.'IP'=$VM_IP
    $row.'Public_IP_Name'=$VMPIPName
    $row.'Public_IP'=$VM_PublicIP
    $row.'IP_MAC'=$VM_IP_MAC
    $row.'Priv_Dyn'=$VM_Alloc
    $row.'Status'=$VM_Status
    $row.'Date_Time'=$Date_Time
    $VMInfo.Rows.Add($row)
}
cls
$TotalTime=(NEW-TIMESPAN –Start $DateStart –End $(GET-DATE))
Write-Host "Script Ran in $($TotalTime.Hours) hours and $($TotalTime.Minutes) minutes and $($TotalTime.Seconds) seconds"

#Export the Info
Write-Host "Exporting VMINFO Report to `n`t$($VMInfo_Export)"
$VMInfo | Export-CSV -NoTypeInformation -Path $VMInfo_Export

#Depending on OS run the Open/Start command for the CSV Export
If ($OSTYPE -eq "LINUX") {open $VMInfo_Export} `
ElseIf ($OSTYPE -eq "WINDOWS") {start $VMInfo_Export} `
Else {Write-Host "Unknown OS"}

break

#####     ######     #####
#######     ######     #####
##     Extra Tasks to Filter the Exports
#####     ######     #####
#######     ######     #####

#Get the Array Size
$VMInfo_Array_Count=($VMInfo | Measure-Object | Select Count).Count

#ECHO the Array size
Write-Host "`n`n*****     *****"
Write-Host "Array VMInfo has $VMInfo_Array_Count objects"
Write-Host "*****     *****"

break
#Shows Configured Resource Group Names
$VMInfo_ResourceGroupNames=($vminfo | Select ResourceGroup -Unique).ResourceGroup

#ECHO Configured Resource Group Names
Write-Host "`n`n*****     *****"
Write-Host "*****     List of Groups*****"
Write-Host "*****     *****"
$($VMInfo_ResourceGroupNames)

break
#Get DC's from resource Group Name
$VM_Environment="dtdaily"
$VMInfo_GetDCs=$vminfo | where {$_.ResourceGroup -eq $VM_Environment -and $_.VM -like "*dc*"}

#ECHO DC's from resource Group Name
Write-Host "`n`n*****     *****"
Write-Host "*****     List of DC's"
Write-Host "*****     *****"
$($VMInfo_GetDCs)

break
#Get Public IP VMs
$VMInfo_PublicIPs=$vminfo | Where {$_.Public_IP -like "*.*"}

#ECHO Public IP VMs
Write-Host "`n`n*****     *****"
Write-Host "*****     *****"
Write-Host "*****     List of Public IP VMs"
Write-Host "*****     *****"
$($VMInfo_PublicIPs)

break
#ECHO All VMs
$VMInfo

Break

我搜索了很多,終於成功了。 使用資源組名稱和 azure vm 名稱,您可以檢索私有或公共 ip 地址:

$Resourcegroup=""

$VmName=""

$VmNetworkdetails= (((Get-AzureRmVM -ResourceGroupName $Resourcegroup -Name $VmName).NetworkProfile).NetworkInterfaces).Id

$nicname = $VmNetworkdetails.substring($VmNetworkdetails.LastIndexOf("/")+1)

$privateIp =(Get-AzureRmNetworkInterface -Name $nicname -ResourceGroupName $Resourcegroup)|Select-Object -ExpandProperty IPConfigurations 

write-host $privateIp.PrivateIpAddress

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM