Коллеги, а также все, кто интересуется темой системного администрирования и автоматизацией, приветствую!
В этой статье мы будем автоматизировать виртуальное окружение для различных задач тестирования при помощи Vagrant и PowerShell DSC. В этой части мы начнем с минимального набора любой доменной инфраструктуры Windows. В конкретном случае песочница будет состоять из 2-х узлов: контроллер домена и хост-член домена.
А зачем оно вообще нужно?
Это, пожалуй, главный вопрос на который нужно ответить. Думаю, что у каждого может быть свое мнение по этому поводу. Однако, если свести вопрос к общему случаю, то подобный подход позволяет сократить затраты времени на этапе конфигурации виртуальной лаборатории.
Однажды подготовив сценарий автоматизации, его можно многократно использовать в дальнейшем по требованию, не вспоминая нюансы ручной конфигурации и исключая человеческие ошибки вызванные особенностями нашей памяти.
Иными словами — если появилась задача смоделировать работу реальных компонентов инфрастуктуры, перед нами встает первый вопрос:
Как это сделать?
Хорошо если необходимо проверить работу какого-нибудь компонента или ПО на одной виртуальной машине, но что делать, если для этого требуются несколько (напр. сложная топология Active Directory)?
Поняв, сколько ручных действий придется для этого выполнить возникает следующий вопрос:
Как это автоматизировать?
Ответу на этот вопрос и посвящена статья. Если вы также, как и я, задаете его себе, то предлагаю наконец-то перейти к предмету изучения.
Стек используемых технологий и скучная терминология
Для начала разберемся с набором ПО и необходимой терминологией которые понадобятся для реализации нашей задумки.
- Поставщик виртуализации — ПО или средства реализующие функционал виртуализации (напр. VirtualBox, VmWare, Hyper-V).
- VirtualBox — один из примеров поставщика технологии виртуализации. Благодаря этому компоненту, мы сможем создавать и конфигурировать виртуальные машины. В нашей статье мы используем в качестве поставщика виртуализации именно VirtualBox. В зависимости от провайдера, настройки файла конфигурации Vagrant могут отличаться. Чтобы избежать этой ситуации, а также для универсальности и кроссплатформенности (можно использовать как на хостах Windows, так и на Linux), выбор был сделан в пользу VirtualBox. Конечно, никто не мешает использовать любой другой провайдер.
- Vagrant — компонент, позволяющий автоматизировать конфигурацию виртуальных машин. Слой или уровень, позволяющий конфигурировать виртуальные машины в едином стиле.
- PowerShell DSC (Desired State Configuration) — средство автоматизации задач, в основе которого лежит декларативная парадигма (декларативный подход). Иными словами, мы описываем состояние, которое хотим получить, но не описываем процесс получения этого состояния. В процессе выполнения сценариев DSC происходит магия 🙂
- Ресурсы DSC — специальные модули позволяющие конфигурировать систему.
Установка необходимого ПО на хост Windows
Автоматическая установка
Существует отличная возможность автоматизировать процесс путем установки ПО через пакетный менеджер Chocolatey.
- Windows 7+ / Windows Server 2003+
- PowerShell v2+
- .NET Framework 4+
Если требования к установке Chocolatey удовлетворены, то предлагаю открыть cmd.exe от имени администратора, вставить код ниже и чего-нибудь выпить, пока выполняется установка 🙂
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" && choco install -y vagrant & choco install -y virtualbox
Ручная установка
Также нам никто не мешает выполнить установку в ручном режиме.
- Скачиваем и устанавливаем VirtualBox
- Скачиваем и устанавливаем Vagrant
Сам процесс установки ПО несложен, не будем останавливаться на этом.
Разворачиваем и автоматизируем песочницу
Небольшое отступление. Сначала выполним некоторые вещи без особых разбирательств, а уже потом разберем, что же мы там наворотили и почему оно работает или не работает 🙂
Начинаем.
Создаем проект нашей тестовой лаборатории и формируем нижеуказанную структуру папок и файлов, где:
- LAB — название корневой папки проекта.
- Vagrantfile — файл (подробнее дальше) с указаниями по разворачиванию виртуальных машин.
- provision — папка, где будут лежать сценарии DSC (будут использоваться для конфигурации виртуальных машин).
- Файлы с расширением .ps1 — непосредственно сценарии DSC для конфигурирования ОС.
Ниже определим назначение каждого сценария .ps1
- ConfigureRebootOnNode.ps1 — конфигурирует перезапуск хоста, если это необходимо.
- DSCInstallDHCP.ps1 — устанавливает роль DHCP, RSAT-DHCP, авторизует DHCP сервер в AD после установки и конфигурирует область.
- DSCInstallDomain.ps1 — устанавливает роль AD DS, RSAT-ADDS, конфигурирует домен PARTY.HARD.
- DSCJoinDomain.ps1 — добавляет хост в домен Active Directory.
- PreDSCInstall.ps1 — устанавливает необходимые для работы модули DSC.
Ниже прикрепляю визуализацию структуры.
LAB
│ Vagrantfile
│
└───provision
ConfigureRebootOnNode.ps1
DSCInstallDHCP.ps1
DSCInstallDomain.ps1
DSCJoinDomain.ps1
PreDSCInstall.ps1
Копируем файл Vagrantfile в папку с проектом.
Vagrantfile
# -*- mode: ruby -*- # # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vagrant.plugins = "vagrant-reload" config.vm.define "lab-dc1" do |subconfig| subconfig.vm.box = "gusztavvargadr/windows-server" subconfig.vm.hostname = "lab-dc1" subconfig.vm.provider :virtualbox do |vb| vb.gui = false end subconfig.vm.network "private_network", ip: "192.168.11.2", virtualbox__intnet: true subconfig.winrm.username = "vagrant" subconfig.winrm.password = "vagrant" subconfig.winrm.transport = :plaintext subconfig.winrm.basic_auth_only = true #Install DSC Modules subconfig.vm.provision "shell", path: "provision\\PreDSCInstall.ps1" #https://github.com/dsccommunity/ActiveDirectoryDsc subconfig.vm.provision "shell", path: "provision\\DSCInstallDomain.ps1" #Restart VM to finish Active Directory Domain Services installation subconfig.vm.provision :reload #https://github.com/dsccommunity/xDhcpServer subconfig.vm.provision "shell", path: "provision\\DSCInstallDHCP.ps1" end config.vm.define "lab-test" do |subconfig| subconfig.vm.box = "gusztavvargadr/windows-server" subconfig.vm.hostname = "lab-test" subconfig.vm.provider :virtualbox do |vb| vb.gui = false end subconfig.vm.network "private_network", ip: "127.0.0.2", auto_config: false, virtualbox__intnet: true subconfig.winrm.username = "vagrant" subconfig.winrm.password = "vagrant" subconfig.winrm.transport = :plaintext subconfig.winrm.basic_auth_only = true subconfig.vm.provision "shell", path: "provision\\ConfigureRebootOnNode.ps1" subconfig.vm.provision "shell", path: "provision\\PreDSCInstall.ps1" subconfig.vm.provision "shell", path: "provision\\DSCJoinDomain.ps1" end end
Копируем файл PreDSCInstall.ps1 в папку provision
PreDSCInstall.ps1
Install-Module -Name ActiveDirectoryDsc -Force Install-Module -Name PSDscResources -Force Install-Module -Name ComputerManagementDsc -Force Install-Module -Name xDhcpServer -Force
Копируем файл DSCInstallDomain.ps1 в папку provision
DSCInstallDomain.ps1
Configuration ADDomain_NewForest_Config { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCredential] $Credential, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCredential] $SafeModePassword ) Import-DscResource -ModuleName PSDscResources Import-DscResource -ModuleName ActiveDirectoryDsc Import-DscResource -ModuleName ComputerManagementDsc Node 'localhost' { WindowsFeature 'Active Directory Domain Services' { Name = 'AD-Domain-Services' Ensure = 'Present' } WindowsFeature 'RSAT-ADDS' { Name = 'RSAT-ADDS' Ensure = 'Present' } ADDomain 'party.hard' { DomainName = 'party.hard' Credential = $Credential SafemodeAdministratorPassword = $SafeModePassword ForestMode = 'WinThreshold' } } } #Next block is using to allow password as plain text $cd = @{ AllNodes = @( @{ NodeName = 'localhost' PSDscAllowPlainTextPassword = $true } ) } #Define user and password for ADDomain deployment (also used for restore). $password = ConvertTo-SecureString "RestorePassword123$" -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential('vagrant',$password) #Create MOF ADDomain_NewForest_Config -Credential $cred -SafeModePassword $cred -ConfigurationData $cd #Execute MOF Start-DscConfiguration -Path .\ADDomain_NewForest_Config -Force -Wait -Verbose
Копируем файл DSCInstallDHCP.ps1 в папку provision
Configuration xDhcpsServerScope_NewScope { Import-DscResource -ModuleName xDHCpServer #Define NIC IP $IP = Get-NetIPAddress -InterfaceAlias "Ethernet 2" | Where-Object {$_.IPAddress -notlike "*:*" } | select -ExpandProperty IPAddress Node 'localhost' { WindowsFeature 'RSAT-DHCP' { Name = 'RSAT-DHCP' Ensure = 'Present' } WindowsFeature 'DHCP' { Name = 'DHCP' Ensure = 'Present' } xDhcpServerAuthorization RemoteServerActivation { Ensure = 'Present' DnsName = $env:COMPUTERNAME + '.party.hard' IPAddress = $IP } xDhcpServerScope Scope { ScopeId = '192.168.11.0' Ensure = 'Present' IPEndRange = '192.168.11.254' IPStartRange = '192.168.11.10' Name = '11.0/24' SubnetMask = '255.255.255.0' LeaseDuration = ((New-TimeSpan -Hours 8 ).ToString()) State = 'Active' AddressFamily = 'IPv4' } xDhcpServerOption Option { Ensure = 'Present' ScopeID = '192.168.11.0' DnsDomain = 'party.hard' DnsServerIPAddress = '192.168.11.2' AddressFamily = 'IPv4' Router = '192.168.11.1' } } } xDhcpsServerScope_NewScope Start-DscConfiguration -Path .\xDhcpsServerScope_NewScope -Force -Wait -Verbose
Копируем файл DSCJoinDomain.ps1 в папку provision
DSCJoinDomain.ps1
Configuration JoinDomainConfiguration { param ( [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [System.Management.Automation.PSCredential] $Credential ) Import-DscResource -Module ComputerManagementDsc Node 'localhost' { Computer JoinDomain { Name = $env:COMPUTERNAME DomainName = 'PARTY' Credential = $Credential # Credential to join to domain } } } #Next block is using to allow password as plain text $cd = @{ AllNodes = @( @{ NodeName = 'localhost' PSDscAllowPlainTextPassword = $true } ) } #Define user and password for ADDomain deployment (also used for restore). $password = ConvertTo-SecureString "vagrant" -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential('party.hard\vagrant',$password) #Create MOF JoinDomainConfiguration -Credential $cred -ConfigurationData $cd #Execute MOF Start-DscConfiguration -Path .\JoinDomainConfiguration -Force -Wait -Verbose
Копируем файл ConfigureRebootOnNode.ps1 в папку provision
Configuration ConfigureRebootOnNode { Node 'localhost' { LocalConfigurationManager { RebootNodeIfNeeded = $true } } } #Create MOF ConfigureRebootOnNode Set-DscLocalConfigurationManager .\ConfigureRebootOnNode -Verbose Get-DscLocalConfigurationManager
Структура проекта сформирована, что дальше?
Мы с вами выполнили, пожалуй, самую сложную часть, поздравляю. Теперь, чтобы автоматически развернуть нашу небольшую тестовую лабораторию достаточно выполнить команду:
vagrant up
Все. Идем пить чай. В зависимости от производительности вашей машины и скорости интернет, возможно, придется выпить не одну кружку 🙂
По возвращению Вы обнаружите маленькое виртуальное окружение, которое состоит из двух узлов. Мы можем убедиться в этом выполнив команду:
vagrant status
Мы увидим список запущенных виртуальных машин
Current machine states: lab-dc1 running (virtualbox) lab-test running (virtualbox) This environment represents multiple VMs. The VMs are all listed above with their current state. For more information about a specific VM, run `vagrant status NAME`.
Либо, открыв менеджер управления виртуальными машинами VirtualBox. Мы увидим те же ВМ и тот же статус.
Что же случилось и что происходило под капотом?
Vagrant
Давайте поэтапно разберем что произошло. Вся ключевая логика и построчные комментарии описаны в файле Vagrantfile. Для удобства я добавлю комментарии к строкам на русском языке. Вернемся к файлу Vagrantfile и рассмотрим конфигурацию одной из машин.
config.vm.define "lab-dc1" do |subconfig| #Определяем готовый образ ОС для виртуальной машины. Vagrant скачает указанный образ из публичного репозитория (https://app.vagrantup.com/boxes/search) subconfig.vm.box = "gusztavvargadr/windows-server" #Определяем название хоста виртуальной машины subconfig.vm.hostname = "lab-dc1" #Определяем настройки провайдера виртуализации (необязательно) subconfig.vm.provider :virtualbox do |vb| #Запускам виртуальную машину в фоне vb.gui = false end #Определяем конфигурацию сети: тип адаптера, ip. subconfig.vm.network "private_network", ip: "192.168.11.2", virtualbox__intnet: true #Определяем логин и пароль для подключения и дальнейшей конфигурации ВМ subconfig.winrm.username = "vagrant" subconfig.winrm.password = "vagrant" #Определяем параметры подключения. subconfig.winrm.transport = :plaintext subconfig.winrm.basic_auth_only = true #Выполняем Powershell сценарий, который установит необходимые DSC модули subconfig.vm.provision "shell", path: "provision\\PreDSCInstall.ps1" #Выполняем Powershell DSC сценарий, который развернет службы AD #https://github.com/dsccommunity/ActiveDirectoryDsc subconfig.vm.provision "shell", path: "provision\\DSCInstallDomain.ps1" #Выполняем перезагрузку ВМ после инсталляции служб AD subconfig.vm.provision :reload #Выполняем Powershell DSC сценарий, который развернет и настроит службу DHCP #https://github.com/dsccommunity/xDhcpServer subconfig.vm.provision "shell", path: "provision\\DSCInstallDHCP.ps1" end
Подробное раскрытие темы Vagrant выходит за рамки статьи, для более подробного изучения предлагаю воспользоваться ссылками в разделе дополнительной литературы.
Дополнительная литература
https://www.vagrantup.com/docs/
https://youtu.be/Q8baD4TS_l0
Для полноты картины следует рассмотреть также сценарии DSC, которые используются в процессе развертывания. Давайте вернемся к ним, чтобы разобраться в принципах работы.
PowerShell DSC
В начале статьи уже упоминалось, что в отличии от привычных нам PowerShell сценариев, DSC использует декларативный подход. Обратите внимание, что мы не указываем как именно мы будем приводить систему к желаемому состоянию. Фактически нам необходимо только задекларировать (описать) желаемое состояние.
Также в начале статьи упоминалось понятие — ресурсы Powershell. Для технологии PowerShell DSC, понятие ресурсов является ключевым. Именно благодаря ним определяется и выполняется конфигурация. Существуют как стандартные ресурсы (входящие в систему), так и пользовательские (импортируются отдельно).
Вы, возможно, обратили внимание, что в некоторых сценариях импортируются ресурсы. Подобные как раз являются примером пользовательских (расширяемых) ресурсов, которые были скачаны с репозитория github сообщества dsccommunity.
Для примера возьмем DSCInstallDHCP.ps1, который устанавливает и конфигурирует DHCP.
Также, для удобства, я прокомментирую строки на русском языке.
#Декларируем название конфигурации Configuration xDhcpsServerScope_NewScope { #Импортируем необходимые ресурсы Import-DscResource -ModuleName xDHCpServer #Декларируем хосты на которых будет применяться конфигурация Node 'localhost' { #Декларируем установку компонента RSAT-DHCP при помощи ресурса WindowsFeature (пример стандартного ресурса) WindowsFeature 'RSAT-DHCP' { #Декларируем необходимые имя и статус инсталляции компонента. Name = 'RSAT-DHCP' Ensure = 'Present' } #Декларируем установку компонента DHCP при помощи ресурса WindowsFeature (пример стандартного ресурса) WindowsFeature 'DHCP' { #Декларируем необходимые имя и статус инсталляции компонента. Name = 'DHCP' Ensure = 'Present' } #Декларируем необходимость авторизации сервера при помощи ресурса xDhcpServerAuthorization (пример пользовательского ресурса) xDhcpServerAuthorization LocalServerActivation { Ensure = 'Present' } #Декларируем необходимость создания области DHCP при помощи ресурса xDhcpServerScope (пример пользовательского ресурса) xDhcpServerScope Scope { #Декларируем настройки области ScopeId = '192.168.11.0' Ensure = 'Present' IPEndRange = '192.168.11.254' IPStartRange = '192.168.11.10' Name = '11.0/24' SubnetMask = '255.255.255.0' LeaseDuration = ((New-TimeSpan -Hours 8 ).ToString()) State = 'Active' AddressFamily = 'IPv4' } #Декларируем необходимость создания параметров области DHCP при помощи ресурса xDhcpServerOption (пример пользовательского ресурса) xDhcpServerOption Option { Ensure = 'Present' ScopeID = '192.168.11.0' DnsDomain = 'party.hard' DnsServerIPAddress = '192.168.11.2' AddressFamily = 'IPv4' Router = '192.168.11.1' } } } #Формируем MOF файл для применения конфигурации xDhcpsServerScope_NewScope #Применяем конфигурацию на хосте Start-DscConfiguration -Path .\xDhcpsServerScope_NewScope -Force -Wait -Verbose
Подробное раскрытие темы PowerShell DSC выходит за рамки статьи, для более подробного изучения предлагаю воспользоваться ссылками в разделе дополнительной литературы.
Дополнительная литература
https://channel9.msdn.com/Series/PowerShell-Desired-State-Configuration https://habr.com/ru/company/microsoft/blog/253497/
А оно точно работает?
Вполне резонный вопрос 🙂
Предлагаю лично убедиться в том, что все службы были развернуты и корректно сконфигурированы в соответствии с описанными требованиями.
Какого функционала мы ожидаем от песочницы?
Глобально, мы ожидаем два хоста в локальной сети 192.168.11.0/24. Один — контроллер домена PARTY.HARD, другой — член этого домена.
LAB-DC1 — 192.168.11.2
- Active Directory Domain Services
- AD RSAT
- Конфигурация домена PARTY.HARD
- DHCP
- DHCP RSAT
- Авторизация DHCP
- Конфигурация области DHCP
LAB-TEST — 192.168.11.10 (выдано DHCP сервером)
- Присоединение к домену PARTY.HARD
После развертывания домена, стала доступна доменная учетная запись Administrator со стандартным паролем vagrant. Попробую воспользоваться этой учеткой и зайти в систему используя VirtualBox Manager.
Итоги
Похоже, что нам удалось развернуть виртуальное окружение. Различных сценариев применения можно придумать великое множество, все зависит от ваших задач, хотелок, размера оперативной памяти и скорости дисковой подсистемы 🙂
В следующей части статьи мы с вами попробуем увеличить размеры песочницы и расширить сценарии применения.
До встречи!
Приветствую!
Отлично, спасибо за проделанную работу.
Но у меня сходу не поднялось
Хотя бы, куда оно не может распаковать образ?
«`
PS D:\Scripts\LAB> vagrant up
Bringing machine ‘lab-dc1’ up with ‘virtualbox’ provider…
Bringing machine ‘lab-test’ up with ‘virtualbox’ provider…
==> lab-dc1: Box ‘gusztavvargadr/windows-server’ could not be found. Attempting to find and install…
lab-dc1: Box Provider: virtualbox
lab-dc1: Box Version: >= 0
==> lab-dc1: Loading metadata for box ‘gusztavvargadr/windows-server’
lab-dc1: URL: https://vagrantcloud.com/gusztavvargadr/windows-server
==> lab-dc1: Adding box ‘gusztavvargadr/windows-server’ (v1809.0.1912) for provider: virtualbox
lab-dc1: Downloading: https://vagrantcloud.com/gusztavvargadr/boxes/windows-server/versions/1809.0.1912/providers/virtualbox.box
lab-dc1: Download redirected to host: vagrantcloud-files-production.s3.amazonaws.com
lab-dc1:
The box failed to unpackage properly. Please verify that the box
file you’re trying to add is not corrupted and that enough disk space
is available and then try again.
The output from attempting to unpackage (if any):
x Vagrantfile
x box.ovf
x gusztavvargadr-ws2019s-1912.0.0-1578083647-disk001.vmdk: Write failed
x metadata.json
bsdtar.EXE: Error exit delayed from previous errors.
Иван, приветствую Вас!
Стандартное расположение для скачиваемых боксов для ОС Windows — C:\Users\USERNAME\vagrant.d\boxes.
Его можно можно изменить путем добавления в среду пользователя или системы переменной с именем VAGRANT_HOME и указанием папки (имеет смысл размещать боксы на дисках побыстрее).
Судя по вашему логу, очень похоже, что закончилось место на диске C.
Для решения проблемы можно попробовать:
1) Освободить место под боксы на диске C.
2) Запустить cmd и ввести команду — setx VAGRANT_HOME «D:\LAB\boxes» (возможно потребуется дополнительно создать папку boxes по этому пути), перезапустите cmd и попробуйте выполнить команду vagrant up еще раз.
Команда setx добавит переменную в среде пользователя. Если проблема действительно была в свободном месте и в новом расположении его будет достаточно, то процесс должен пойти дальше.
Не могли бы Вы проверить это? Попробуем разобраться и добавим информацию в статью для наших коллег.
Спасибо!
Всем привет. Хорошая затея))) Ну так то а где это можно как DEMO посмотреть? Это типа как ознакомительные версии с майкрософта? Спасибо.
Сергей, приветствую!
Возможно, если будет время, сделаю видео к статье в качестве демонстрации.
Для разворота виртуальных машин действительно используются триальные версии Windows Server (на 180 дней). Скорее Вы их удалите после тестов в лаборатории, чем они успеют закончится 🙂
В крайнем случае можно продлить триал или повторно развернуть виртуальные машины (будут созданы новые сервера, с новым триалом).