Можете представить, сколько времени уйдёт на генерацию списка VM среди сотен подписок Azure? Целая вечность. Известно, что портал Azure выводит только первые 1000 подписок, что усложняет запрос ресурсов с его помощью, когда подписок у вас намного больше. К счастью, есть способ делать это гораздо быстрее и динамичнее. В этой статье мы разберём функционал Azure Resource Graph и используем эту службу с помощью PowerShell, существенно повысив гибкость управления запросами.

Содержание статьи:

— Resource Graph и Kusto Query Language
— Модуль Resource Graph для PowerShell
— Ограничения
— Полезные виды запросов
— Форматирование результатов
— Заключение

Resource Graph и Kusto Query Language


Azure Resource Graph — это сервис, который позволяет более точно запрашивать ресурсы среди множества подписок, используя таблицы Resource Graph.

Kusto Query Language (KQL) — это язык запросов, с помощью которого Resource Graph возвращает запрашиваемые данные. KQL поддерживает много операторов, включая join и union, которые позволяют устанавливать межтабличные связи для возвращения более подробных результатов сразу по нескольким таблицам.


Прим. переводчика:

Чуть подробнее о Kusto. Это специальный процесс, язык, который позволяет получить ридонли результаты из ваших источников данных. Вся система очень похожа на SQL.
Сам запрос состоит из последовательности инструкций, разделяемых точкой с запятой. Точно как мы с вами привыкли видеть в практически любой оболочке БД. Последняя инструкция должна возвращать то, что мы называем Tabular Expression Statement. Первая инструкция обычно получает данные из какого-либо источника, последующие операторы преобразуют данные, а последний оператор рендерит эти данные.

Данные передаются от инструкции к инструкции через конвейер |. Обычный запрос в Kusto выглядит примерно так (пример из docs.microsoft.com):

StormEvents 
| where StartTime >= datetime(2007-11-01) and StartTime < datetime(2007-12-01)
| where State == "FLORIDA"  
| count

Любому хабрачеловеку тут всё будет понятно.

Запросы Resource Graph можно выполнять на портале Azure. Но мы-то с вами продвинутые пользователи, поэтому использовать будем PowerShell. Да, конечно, у нас есть Resource Graph Explorer, предлагающий UI, где можно найти доступные для использования в запросах таблицы Resource Graph. Запросы также можно сохранять для последующего использования. Но после написания пары десятков этих запросов вы уже будете знать все таблицы наизусть и сможете строчить их напрямую.


Запросы в Azure Portal можно делать с помощью проводника Resource Graph

В примере выше перечислены все ресурсы с их базовыми подробностями, такими как ID, name, subscriptionID, resourceGroup и далее.

Модуль Resource Graph для PowerShell


Модуль Az.ResourceGraph можно использовать в PowerShell для запроса ресурсов Azure по всему клиенту или среди набора подписок. Так выглядит простой запрос, который можно выполнить через PowerShell:

$KustoQuery = "
resources
| where name starts with 'Network'
"
$result = Search-AzGraph -Query $KustoQuery
$result | select name

Простой запрос Kusto для вывода списка всех ресурсов:

PS C: $KustoQuery = "
>> resources
>> | where name starts with 'Network'
>> "
$result = Search-AzGraph -Query $KustoQuery
$result | select name

name
- - - -
NetworkWatcher_cenralus
NetworkWatcher_norteurope
NetworkWatcher_westeurope
NetworkWatcher_westus
NetworkWatcher_eastus
NetworkWatcher_japanwest
NetworkWatcher_norteurope
NetworkWatcher_uksouth
NetworkWatcher_westeurope
NetworkWatcher_eastus
NetworkWatcher_norteurope

PS C:\>

Этот запрос выведет список всех ресурсов с именами, начинающимися с Network.

Прим. переводчика:
Для удобной работы с PowerShell очень рекомендуется установить oh-my-posh и использовать Windows Terminal. oh-my-posh добавляет большое количество функций к Powershell, которых так не хватает пользователям командной строки в Linux. В частности, reverse-i-search.


Ограничения


Имейте в виду, что PowerShell может запрашивать через Resource Graph только первые 1000 подписок. Если же у вас их больше, то потребуется разбить их на отдельные пакеты.

С одной стороны, это очень странное ограничение. Любой, кто работал с базами данных, тут может удивиться. Но если подумать, то оно кажется достаточно разумным. Мы же не с базой данных работаем, а запрашиваем объекты из AD. Если их наплодится больше 1000, то возможно, вам стоит подумать о том, как их структурировать в более приличном виде.

Ещё одним ограничением является вывод в ответ на запрос максимум 1000 результатов. Чтобы его обойти, можно проигнорировать определённое их число с помощью параметра Skip. В примере ниже первая команда выдаёт первые пять результатов, а вторая игнорирует эти первые результаты и выводит остальные. Так что можно просто динамически устанавливать параметры first и Skip, чтобы возвращать все результаты, не ограничиваясь 1000.

Всем, кто сталкивается с подобными ограничениями, рекомендуется обратиться к этому документу. Там вам более подробно изложат варианты работы.

$result = Search-AzGraph -Query $KustoQuery -first 5
$result | select name
$result = Search-AzGraph -Query $KustoQuery -Skip 5
$result | select name


Параметры first и Skip помогают, когда нужно вывести более 1000 ресурсов

Полезные виды запросов


Вот несколько примеров запросов, которые можно совершать с помощью Resource Graph.

Вывод ресурсов по типу


Запрос для вывода определённого типа ресурсов:

$KustoQuery = "
Resources
| where type == 'microsoft.storage/storageaccounts'
"
$result = Search-AzGraph -Query $KustoQuery
$result | select name


Вывод ресурсов учётной записи хранения

Вывод виртуальных машин Windows


Запрос для вывода только VM с Windows:

$KustoQuery = "
Resources
| where type == 'microsoft.compute/virtualmachines'
| where properties.storageProfile.osDisk.osType == 'Windows'
"
$result = Search-AzGraph -Query $KustoQuery
$result | select name, @{l="OsType";e={$_.properties.storageProfile.osDisk.osType}}


Вывод VM с Windows

Вывод всех публичных IP


В сценарии ниже мы выводим все публичные адреса IP вместе с идентификаторами их ресурсов, но в качестве имени для идентификаторов будет отображаться SampleColumnToRepresentResourceId.


Вывод публичных адресов IP с кастомным именем для ResourceId

Вывод групп ресурсов с конкретным тегом


Следующий запрос выведет только группы ресурсов с заданным тегом:

$KustoQuery = "
resourcecontainers
| where type == 'microsoft.resources/subscriptions/resourcegroups'
| where tags['Importance'] == 'High'
"
$result = Search-AzGraph -Query $KustoQuery
$result | select name


Вывод групп ресурсов с заданным тегом

Подсчёт ресурсов в определённом регионе


Следующий запрос позволит получить количество ресурсов в North Europe, сгруппированных по их subscriptionId:

$KustoQuery = "
resources
| where location == 'northeurope'
| summarize total=count () by subscriptionId
"
$result = Search-AzGraph -Query $KustoQuery
$result | select total, subscriptionId, @{l="location";e={"North Europe"}}


Подсчёт ресурсов в регионе North Europe

Вывод запущенных VM


Для вывода только запущенных VM используем такой запрос:

$KustoQuery = "
resources
| where type == 'microsoft.compute/virtualmachines'
| where properties.extended.instanceView.powerState.displayStatus == 'VM running'
| project name, location, resourceGroup
"
$result = Search-AzGraph -Query $KustoQuery
$result


Запрос для получения запущенных VM

Вывод ресурсов VM, не соответствующих политикам


VM, не соответствующие текущим политикам, выводятся так:

$KustoQuery = "
policyresources
| where type == 'microsoft.policyinsights/policystates'
| where properties.complianceState == 'NonCompliant'
| where properties.resourceType =~ 'microsoft.compute/virtualmachines'
| project resourceGroup, id=properties.resourceId, ComplianceStatus = properties.complianceState
"
$result = Search-AzGraph -Query $KustoQuery
$result | fl *


Получение списка несоответствующих ресурсов VM


Прим. переводчика:

Форматирование результатов


Конечно, не стоит забывать про то, что PowerShell имеет большое количество различных способов форматирования конечных результатов. В данном случае запросы в Kusto можно форматировать с помощью параметра в вызове метода. Существуют два способа форматирования конечных данных: Таблица и Массив Объектов.

Более того, эти данные отлично обрабатываются встроенной функцией ConvertTo-Json.

Вот пример возвращаемой таблицы данных, созданной с помощью параметра resultFormat=Table, пропущенных через ConvertTo-JSON:

{
    "totalRecords": 47,
    "count": 1,
    "data": {
        "columns": [{
                "name": "name",
                "type": "string"
            },
            {
                "name": "type",
                "type": "string"
            },
            {
                "name": "location",
                "type": "string"
            },
            {
                "name": "subscriptionId",
                "type": "string"
            }
        ],
        "rows": [
            [
                "veryscaryvm2-nsg",
                "microsoft.network/networksecuritygroups",
                "eastus",
                "11111111-1111-1111-1111-111111111111"
            ]
        ]
    },
    "facets": [],
    "resultTruncated": "true"
} 

Подобные данные очень просто обрабатывать в любых других программах. Подробности о том, как правильно отформатировать ваши данные, описаны здесь.


Заключение


Resource Graph является очень удобным и быстрым решением для выполнения запросов в Azure, который позволяет в развёрнутом виде запрашивать ресурсы среди огромного числа подписок. При этом язык KQL существенно упрощает получение данных с помощью PowerShell и Resource Graph.

Каждый уважающий себя системный администратор всегда держит под рукой репозиторий с набором скриптов, упрощающих жизнь. KQL позволяет быстро писать простейшие утилиты, позволяющие анализировать данные в Azure. Более того, уже готовые данные, собранные в виде JSON, достаточно просто отправлять в различные no-SQL базы данных для их последующего анализа. В этом случае KQL может упростить жизнь любителям ELK, Graylog и тому подобных систем сбора информации.


НЛО прилетело и оставило здесь промокоды для читателей нашего блога:


Доступно до 31 декабря 2021 г.

Комментарии (0)