Данная статья не претендует ни на что, кроме шпаргалки. Здоровая критика приветствуется.
Часть 1. Пояснительная.
Появилась у меня задача поставить на 20+ машин SQL сервер. И как обычно надо было сделать вчера. А задача пришла считай вечером и надо быстро и срочно.
SCCM и прочее отсутствует, так что надо обойтись ручками. Зато на выручку пришел Powershell. А точнее Powershell DSC. Desired State Configuration. Этакий Ansible для винды. Судя по всему MS забил дело на это все, но поддержка сохраняется и развитие происходит силами энтузиастов. Ну не суть. Вернемся к DSC.
Вам потребуется модуль Powershell PSDesiredStateConfiguration.
Ставим на машинке подключенной к интернету с помощью командлета
Install-Module -Name PSDesiredStateConfiguration -RequiredVersion 2.0.5
Первое. Это все очень просто. Вы пишете скрипт, в котором указываете, что бы вы хотели видеть на целевой машине. Потом запускаете команду, которая делает для вас mof-файл, в котором лежит скомпилированная конфигурация. Его можно даже посмотреть в блокнотике. Ну и последнее. На своей рабочей машине\сервере запускаете скрипт который применяет эту конфигурацию к целевому компьютеру по сети.
Начнем с простого.
Сначала создаем Конфигурацию
Configuration MyDscConfiguration #название конфигурации
{
}
Внутри конфигурации описываем Ноду\ноды (целевые серверы) на которых мы будем производить изменения.
Configuration MyDscConfiguration #название конфигурации
{
Node SERVER1 #имя сервера на котором будет что-то настраиваться
{
#Тут код с магией настройки
}
}
Ну и внутри Node собственно происходит магия
И соответственно полный код для выполнения вашей конфигурации:
Configuration MyDscConfiguration #название конфигурации
{
Node SERVER1 #имя сервера на котором будет что-то настраиваться
{
#Тут код с магией настройки
}
}
MyDscConfiguration
Start-DscConfiguration -Path MyDscConfiguration -Wait -Verbose -Force
MyDscConfiguration # запуск создание mof файла и директории под него
Start-DscConfiguration -Path MyDscConfiguration -Wait -Verbose -Force # Запуск установки на сервере. Путь MyDscConfiguration – так как при создании mof-файла создается папка с именем конфигурации. Например если у вас скрипт лежит в c:\scripts – и вы запускаете пош из этой директории, то папка будет у вас в c:\scripts\MyDscConfiguration
Ну наконец давайте рассмотрим магию DSC. Например создание папки.
Configuration MyDscConfiguration #название конфигурации
{
Node SERVER1 #имя ноды - сервера, на котором будет создана папка
{
File CreateNugetFolder #File - указывает на операции с файловой системой.
{
Ensure = "Present" #проверяет наличие. если нет, то создает
Type = "Directory" #тип создаваемого элемента
DestinationPath = "C:\Program Files\PackageManagement\ProviderAssemblies\nuget\2.8.5.208" #полный путь создаваемого элемента. Если какие-то папки в пути отсутствуют - то будут созданы.
}
}
}
Пример 2.
Копирование файла из шары.
копируем dll в директорию созданную автоматом чуть раньше.
File nugetCopy
{
Ensure = "Present" # проверка наличия
Type = "File" # тип File
#Recurse = $true # рекурсивное копирование если бы вдруг копировали директорию
SourcePath = "\\srv-01\repo\Microsoft.PackageManagement.NuGetProvider.dll" #полный путь к шаре где лежит файл
DestinationPath = "C:\Program Files\PackageManagement\ProviderAssemblies\nuget\2.8.5.208\Microsoft.PackageManagement.NuGetProvider.dll"
Checksum = "modifiedDate" #сравнение двух файлов
Force = $true
MatchSource = $true # Определяет, должен ли ресурс отслеживать новые файлы, добавленные в исходный каталог после первоначальной копии.
}
Пример 3. Установка фичи (feature)
WindowsFeature 'NetFramework45'
{
Name = 'NET-Framework-45-Core'
Ensure = 'Present'
}
тут думаю можно без комментариев.
Небольшое дополнение.
Ensure = ‘Present’ – Определяет наличие. Если есть, то ничего не делает, если нет, то создает.
Ensure = ‘Absent’ – Определяет наличие. Если нет, то ничего не делает, если есть, то удаляет
Пример 4. Запуск скриптов.
настраиваем NUGET как будто он с инета сам поставился
Script ScriptNugetImport
{
SetScript = {
Import-PackageProvider -Name NuGet
}
TestScript = { if (Get-PackageProvider -ListAvailable -Name Nuget -ErrorAction SilentlyContinue) { $true } else { $false } }
GetScript = {@{Result = (if (Get-PackageProvider -ListAvailable -Name Nuget -ErrorAction SilentlyContinue) { $true } else { $false }) } }
}
Тут есть 3 пункта. SET TEST GET
SET – запуск самого скрипта. Если подробнее – Метод Set ресурса пытается заставить узел стать совместимым с желаемым состоянием ресурса. Метод Set должен быть идемпотентным, что означает, что Set можно запускать несколько раз и всегда получать один и тот же результат без ошибок. Когда вы запускаете Start-DSCConfiguration, LCM циклически перебирает каждый ресурс в текущей применяемой конфигурации. LCM извлекает значения ключей для текущего экземпляра ресурса из файла «.mof» и использует их в качестве параметров для метода Test. Если метод Test возвращает $true, узел соответствует текущему ресурсу, а метод Set пропускается. Если тест возвращает $false, узел не соответствует требованиям. LCM передает значения ключа экземпляра ресурса в качестве параметров методу Set ресурса, восстанавливая соответствие узла.
GET – получение состояния системы. Подробнее – Метод Get ресурса извлекает состояние ресурса, настроенное на целевом узле. Это состояние возвращается в виде хеш-таблицы. Ключами хеш-таблицы будут настраиваемые значения или параметры, которые принимает ресурс.
Метод Get сопоставляется непосредственно с командлетом Get-DSCConfiguration. Когда вы вызываете Get-DSCConfiguration, LCM запускает метод Get каждого ресурса в текущей применяемой конфигурации. LCM использует значения ключей, хранящиеся в файле .mof, в качестве параметров для каждого соответствующего экземпляра ресурса.
TEST – Проверка соответствия системы. Метод Test возвращает $true или $false только для того, чтобы указать, соответствует ли узел требованиям. Когда вы вызываете Test-DSCConfiguration, LCM вызывает метод Test каждого ресурса в текущей применяемой конфигурации. LCM использует значения ключей, хранящиеся в файле «.mof», в качестве параметров для каждого соответствующего экземпляра ресурса.
Если результатом теста любого отдельного ресурса является $false, Test-DSCConfiguration возвращает $false, указывая, что узел не соответствует требованиям. Если все методы Test ресурса возвращают $true, Test-DSCConfiguration возвращает $true, чтобы указать, что узел соответствует требованиям.
На самом деле можно еще подня ть сервер, где будет проверяться состояние системы и возврат ее к исходному (указанному в конфигурации состоянию) если что-то изменилось, но речь не об этом.
Методы TEST и GET возвращают только булевские значения. Т.е. только true или false. Это необходимо учитывать когда пишите проверку.
Если нужно подробнее то тут:
https://docs.microsoft.com/en-us/powershell/dsc/resources/get-test-set?view=dsc-1.1
https://scriptimus.wordpress.com/2015/04/15/powershell-inside-desired-state-configuration-dsc-getset-and-test/
Часть вторая. Мучительно-подготовительная.
Как вы понимаете, все действия происходят в доменной среде. Не надо настраивать никаких trustedHosts и т.д., т.к. машинки уже в домене. Все было бы хорошо, если бы у них еще был доступ к интернету, для скачивания модулей и т.д. Но нет. Тут жизнь повернулась к нам боком. Хорошо, что машина с которой все ставилось, была подключена к интернету.
Сначала подготовительный этап , потом конфиг машин на которых будет производиться установка, а потом уже собственно сама установка.
Предварительная подготовка.
Была создана шара \repo в которой лежали:
файлик Microsoft.PackageManagement.NuGetProvider.dll – Он ставится при установке модулей Powershell из интернета. Он обычно требует установки Nuget – пакетного передачи кода (пакетов) Можно скопировать с любой машины где уже стоит.
также в шаре – отдельная папка с распакованным iso образом ms sql
sqlserverdsc.15.2.0.nupkg – модуль Powershell DSC для SQL сервер. Скачать можно отсюда https://www.powershellgallery.com/packages/SqlServerDsc/15.2.0
* пояснение*
Так как инета нет, но нам нужно поставить DSC модули для SQL на целевые сервера, пришлось создать папочку, засунуть туда dll и зарегистрировать Nuget как Package Provider. Путь
Configuration SQLPREPARECONF
{
Node "ТУТ ИМЯ МАШИНЫ ПОЛНЫЙ FQDN куда ставим"
{
#создаем директорию для nupkg
File CreateNugetFolder
{
Ensure = "Present"
Type = "Directory"
DestinationPath = "C:\Program Files\PackageManagement\ProviderAssemblies\nuget\2.8.5.208"
}
#создаем директорию куда будем копировать
File CreateDistrFolder
{
Ensure = "Present"
Type = "Directory"
DestinationPath = "C:\Distr"
}
#копируем dll в директорию созданную автоматом чуть раньше.
File nugetCopy
{
Ensure = "Present" # Present, Absent.
Type = "File" # File, Directory
#Recurse = $true # $true, $false
SourcePath = "\\srv-01\repo\Microsoft.PackageManagement.NuGetProvider.dll"
DestinationPath = "C:\Program Files\PackageManagement\ProviderAssemblies\nuget\2.8.5.208\Microsoft.PackageManagement.NuGetProvider.dll"
Checksum = "modifiedDate"
Force = $true
MatchSource = $true
}
#настраиваем NUGET как будто он с инета сам поставился
Script ScriptNugetImport
{
SetScript = {
Import-PackageProvider -Name NuGet
}
TestScript = { if (Get-PackageProvider -ListAvailable -Name Nuget -ErrorAction SilentlyContinue) { $true } else { $false } }
GetScript = {@{Result = (if (Get-PackageProvider -ListAvailable -Name Nuget -ErrorAction SilentlyContinue) { $true } else { $false }) } }
}
#делаем нашу шару репозитарием для пошика
Script ScriptImportRepo
{
SetScript = {Register-PSRepository -Name PSREPO -SourceLocation "\\srv-01\repo\" -ScriptSourceLocation "\\srv-01\repo\" -InstallationPolicy Trusted }
TestScript = { if (Get-PSRepository -Name PSREPO -ErrorAction SilentlyContinue) {$true} else {$false} }
GetScript = {@{Result =(if (Get-PSRepository -Name PSREPO -ErrorAction SilentlyContinue) {$true} else {$false})}
}
}
#ставим модуль для SQL DSC из нашей новой репы
Script ScriptInstallModule
{
SetScript = {Install-Module -Name SqlServerDsc -RequiredVersion 15.2.0 -Repository PSREPO -Force}
TestScript = { if (Get-InstalledModule -Name SqlServerDsc -ErrorAction SilentlyContinue) {$true} else {$false} }
GetScript = {@{Result =(if (Get-InstalledModule -Name SqlServerDsc -ErrorAction SilentlyContinue) {$true} else {$false})} }
}
}
}
# create mof
SQLPREPARECONF
# load configuration from mof
Start-DscConfiguration -Path SQLPREPARECONF -Wait -Verbose -Force
Таким образом после запуска и исполнения данного скрипта, наш многострадальный сервер готов к установке MS SQL Server