ADG Оставить заявку
Блог Автоматизация 5 мин чтения

PowerShell 5.0 preview: DSC-классы как попытка сделать Windows-автоматизацию читаемой

WMF 5.0 preview добавил DSC-классы и PackageManagement. Переписали несколько конфигураций с MOF на классы - разница в читаемости заметная, тестировать тоже проще.

Контекст момента

PowerShell 5.0 Preview (WMF 5.0) вышел с DSC-классами и модулем PackageManagement

Microsoft выпустил WMF 5.0 preview - Windows Management Framework с PowerShell 5.0 внутри. Из заметного: DSC-классы на синтаксисе PowerShell вместо MOF, модуль PackageManagement для установки пакетов из разных источников и улучшения в дебаггере. Мы занялись этим сразу, потому что DSC у нас в работе уже несколько месяцев и вопрос читаемости конфигураций стоит остро.

Что было не так с MOF

DSC в PowerShell 4.0 строился на MOF - Managed Object Format. Для тех кто не работал с WMI вплотную, MOF - это отдельный язык с отдельным синтаксисом, который надо изучать поверх PowerShell. Описываешь ресурс в одном синтаксисе, логику в другом, конфигурацию в третьем. Получается многослойный пирог, который сложно читать и ещё сложнее отлаживать.

Конкретный пример - ресурс для управления службой Windows. В схеме MOF это выглядит как класс с типизированными свойствами, потом отдельно PowerShell-скрипты для Get/Set/Test, потом всё это надо правильно упаковать в модуль с манифестом. Минимальный кастомный ресурс - пять-шесть файлов. При этом если что-то пошло не так, сообщение об ошибке нередко указывает не туда.

На сопровождении у нас несколько клиентов на Windows Server, и конфигурации DSC там появились ещё в прошлом году. Когда конфигурации начали разрастаться - стало понятно что поддерживать это сложно. Не потому что DSC плохой, а потому что MOF добавляет ненужный слой сложности между намерением и реализацией.

Классы меняют ситуацию

В PowerShell 5.0 можно описать DSC-ресурс прямо на PowerShell с атрибутом [DscResource()]:

[DscResource()]
class WindowsServiceConfig {
    [DscProperty(Key)]
    [string] $ServiceName

    [DscProperty(Mandatory)]
    [string] $StartupType

    [DscProperty()]
    [bool] $Ensure = $true

    [void] Set() {
        Set-Service -Name $this.ServiceName -StartupType $this.StartupType
    }

    [bool] Test() {
        $svc = Get-Service -Name $this.ServiceName -ErrorAction SilentlyContinue
        if (-not $svc) { return $false }
        return $svc.StartType -eq $this.StartupType
    }

    [WindowsServiceConfig] Get() {
        $svc = Get-Service -Name $this.ServiceName
        $this.StartupType = $svc.StartType
        return $this
    }
}

Это один файл. Без MOF-схемы, без отдельных папок под каждый метод. Логика Get/Set/Test живёт рядом, видно что откуда берётся. Инженер смотрит на класс и понимает что происходит - не надо держать в голове где лежит нужный скрипт.

Что переписали и что заметили

Взяли несколько существующих ресурсов и переписали на классы. Не всё подряд - только то где MOF-слой реально мешал. Наблюдения:

Читаемость выросла заметно. Новый человек в команде берёт класс и разбирается без вводной лекции про структуру MOF-ресурса. Раньше это был разговор минут на двадцать минимум.

Тестирование упростилось. Класс можно инстанцировать в Pester-тесте напрямую, вызвать Test() или Get() и проверить результат. С MOF-ресурсом приходилось либо поднимать конфигурацию целиком, либо городить обёртки. Сейчас юнит-тесты под DSC-ресурс пишутся почти как обычные.

Отладка стала предсказуемее. Стектрейс указывает на строку в классе, а не куда-то в глубины WMI-стека. Это кажется мелочью пока не сидишь полчаса с отладчиком над ресурсом который падает с невнятным CIM-исключением.

Ограничения есть. Наследование работает, но с нюансами. Если базовый класс помечен [DscResource()], дочерний должен переопределить все три метода - иначе ошибка при компиляции. Можно сделать базовый класс без атрибута DSC и использовать его как хелпер - это работает нормально. Несколько кастомных ресурсов мы так и разложили: общая логика в базовом классе, конкретные ресурсы наследуют и добавляют специфику.

PackageManagement: пощупали, пока осторожно

Второй заметный кусок WMF 5.0 - модуль PackageManagement (бывший OneGet). Идея простая: единый интерфейс для разных пакетных менеджеров. Поставил провайдер под Chocolatey - управляешь Chocolatey-пакетами через стандартный Install-Package. Поставил NuGet-провайдер - те же командлеты, другой источник.

В теории это решает давнюю боль: на одних машинах Chocolatey, на других корпоративный NuGet-репозиторий, и надо писать разную логику в DSC-конфигурациях. С PackageManagement можно унифицировать.

На практике мы пока используем осторожно. Провайдеры в preview-версии работают неровно, и несколько пакетов установились с ошибками которых не было при прямом вызове Chocolatey. Для production-конфигураций пока держим прямые вызовы, PackageManagement тестируем на стендах.

Где это относительно Puppet и Chef

Вопрос закономерный. DSC-классы приближают Windows-автоматизацию к модели Puppet/Chef - описываешь желаемое состояние на нормальном языке, движок делает сходимость. Читаемость конфигураций сопоставимая, структура ресурсов понятная.

Разница в зрелости экосистемы. Под Puppet тысячи готовых модулей, сообщество, устоявшиеся практики. DSC-ресурсов значительно меньше, и качество у них разное. Но для чисто Windows-инфраструктуры DSC работает нативно, без лишних агентов и зависимостей. WinRM есть везде начиная с Server 2008 R2 - никакого Ruby, никакого Puppet Master если не нужен.

Если у клиента смешанная среда - Linux и Windows - Ansible или Puppet дают единый язык для всего. Если Windows-only с Group Policy в основе - DSC с PowerShell 5.0 выглядит разумным выбором.

Итого

WMF 5.0 - пока preview, финальный релиз Microsoft не объявил. Для production мы ждём GA. Но классовый синтаксис DSC уже достаточно стабилен чтобы писать новые ресурсы на нём и не бояться. Переписывать рабочие MOF-ресурсы ради переписывания смысла нет - только там где поддержка реально болит.

Следим за PackageManagement: если провайдеры доведут до стабильного состояния, это закрывает один из неудобных кусков Windows-автоматизации. Пока - стенды.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.