如何自动创建虚拟机? 详细说

创建新的虚拟机是一个耗时的例程。 基础设施和组织越多,与此过程相关的程序就越多。 我们使用PowerShell使该过程自动化。

如果您有兴趣,欢迎来到凯特。




程序员不喜欢做双重工作,系统管理员也不喜欢。

以下是我们其中一位客户的自动化示例。

我们希望确保任何工程师或项目经理都能以最少的精力和最短的时间创建新的虚拟机。 我们的客户有一个ITSM系统,在本例中为ServiceNow,我们在服务目录中创建了相应的Web表单。 要“订购”一台新机器,经理需要填写字段并确认“订购”,然后启动流程链,然后在输出端准备好机器投入使用。

因此,让我们看一下管理者需要定义什么才能创建新的虚拟机:



VM描述:虚拟机描述
这里需要一些澄清。 在我们的解决方案中,PowerShell 5.1被积极使用,因此尽管仅Windows,但将来我们将尝试添加对Unix计算机的支持并切换到PowerShell Core。

操作系统 。 使用Windows 2008(R2)没有特别的障碍,但是我们使用的是2012R2或2016。

VM Size ,虚拟机大小。 每种情况都可以以自己的方式确定,在此示例中为小型1CPU-4Gb Ram,中型2CPU-8Gb,大型4-16。

VM存储 ,磁盘0(C:\)具有无法更改的固定大小,只有快速/慢速存储选择器可用。 “快速”可以是带有SSD的存储层,“慢速”可以存储在“常规” HDD(当然是SAN)上。 Disk1(从Disk2开始)还具有一个用于选择“存储”的选择器,以及用于输入所需大小(以GB为单位),用于分区和群集大小的字母(对于SQL Server很重要)的字段。

信任 ,我们确定计算机是否必须加入域,以及是否可以从公共网络访问。

类型 ,机器类型。 在所有其他情况下,几乎每台机器都可以定义为前端或后端应用程序或其他应用程序。 根据所选的类型,我们可以进一步确定最适合该计算机的子网。

环境 ,在客户的基础架构中,有两个数据中心:主要(生产)和次要(开发/测试),DC通过快速通信通道连接并提供容错能力。 根据协议,主DC中的所有虚拟机都有一个IP地址,从10.230开始,而从DC中的所有虚拟机都从10.231开始。

(SLA)服务水平协议 ,此参数影响此机器的服务质量。

应用领域 我们增加了安装和配置SQL Server的功能。 您必须选择版本,实例名称和排序规则。 也可以同时配置Web服务器角色和更多其他角色。

现在我们需要确定如何存储所选值。 我们认为最方便的格式是JSON文件。 如前所述,客户环境使用ITSM ServiceNow。 选择所有必需的值后,管理器单击“订购”按钮,然后ServiceNow将所有参数传递到我们的PowerShell脚本(到后端ServiceNow),该脚本将创建JSON文件。 看起来像这样:

.\CreateConfiguration.ps1 -SecurityZone trusted -VMDescription "VM for CRM System" -Requestor "evgeniy.vpro" -OSVersion 2k16 -OSEdition Standard -BuildNewVM -VMEnvironment Prod -VMServiceLevel GOLD -VMSize Medium -Disk0Tier Fast -Disk1Size 50 -Disk1Tier Eco -Disk1Letter D -MSSQLServer -MSSQLInstanceName "Instance1" -SQLCollation Latin1_General_CI_AS -SQLEdition Standard -Disk2Size 35 -Disk3Size 65 


在CreateConfiguration .ps1脚本的主体中:

 # PowerShell- $config = [ordered]@{} #    . $config.SecurityZone=$SecurityZone 


最后,将我们的对象导出到JSON文件:

 $ServerConfig = New-Object –TypeName PSObject $config ConvertTo-Json -InputObject $ServerConfig -Depth 100 | Out-File "C:\Configs\TargetNodes\Build\$($Hostname.ToLower()).json" -Force 


样本配置:

 { "Hostname": "dsctest552", "SecurityZone": "trusted", "Domain": "testdomain", "Requestor": "evgeniy.vpro", "VM": { "Size": "Medium", "Environment": "Prod", "SLA": "GOLD", "DbEngine": "MSSQL", "RAM": 8, "Storage": [ { "Id": 0, "Tier": "Fast", "Size": "100", "Allocation": 4, "Letter": "C" }, { "Id": 1, "Tier": "Eco", "Size": 50, "Label": "Data", "Allocation": 64, "Letter": "D" }, { "Id": 2, "Tier": "Fast", "Size": 35, "Label": "Data", "Allocation": 64, "Letter": "E" }, { "Id": 3, "Tier": "Fast", "Size": 65, "Label": "Data", "Allocation": 64, "Letter": "F" } ] }, "Network": { "MAC": "", "IP": "10.230.168.50", "Gateway": "10.230.168.1", "VLAN": “VLAN168” }, "OS": { "Version": "2k16", "Edition": "Standard", "Administrators": [ "LocaAdmin", "testdomain\\ Security-LocalAdmins" ] }, "OU": "OU=Servers,OU=Staging,DC=testdomain", "Applications": [ { "Application": "Microsoft SQL Server 2016", "InstanceName": "vd", "Collation": "Latin1_General_CI_AS", "Edition": "Standard", "Features": "SQLENGINE", "Folders": { "DataRoot": "E:\\MSSQL", "UserDB": "E:\\MSSQL\\MSSQL11.vd\\MSSQL\\Data", "UserLog": "E:\\MSSQL\\MSSQL11.vd\\MSSQL\\Log", "TempDB": "D:\\MSSQL\\MSSQL11.vd\\MSSQL\\TempDB", "TempDBLog": "D:\\MSSQL\\MSSQL11.vd\\MSSQL\\TempDB", "Backup": "E:\\MSSQL\\MSSQL11.vd\\MSSQL\\Backup" }, "MaxMemory": 2147483647 } ], "Description": "VM for CRM", "Certificate": { "File": null, "Thumbprint": null }, "Version": 0 } 


您可能已经注意到,Web表单没有虚拟机名称和IP地址。 我们自动获得这些值,如下所示:

计算机的名称 ITSM ServiceNow有一个特殊的部分:CMDB(配置管理数据库),此数据库存储有关现有虚拟机,它们的状态,支持团队等的所有记录。 我们已经创建了约200个具有已分配状态的备份记录。 为了获得虚拟机的名称,我们向CMDB发出REST请求,并获取第一个“免费”记录,并将其状态从“已分配”安装更改为“待处理”安装。

IP地址和VLAN ,我们在网络上部署了IPAM-这是Windows Server 2016中的内置功能,可让您管理网络上的IP地址。 完全没有必要使用IPAM的所有功能(DHCP,DNS,AD),而仅将其用作具有潜在功能扩展的IP地址数据库。 创建JSON文件的脚本向IPAM请求子网中的第一个空闲IP地址。 然后根据所选的SLA,环境,信任和类型值确定VLAN子网(x / 24子网)。
配置文件已准备就绪,所有字段均已就绪,您可以创建机器。 问题是“如何存储我们所有脚本的凭据?”。 我们使用CredentialManager包。 该软件包与内置的Windows Credential Manager API一起用于存储密码。 创建密码的示例:

 New-StoredCredential -Target "ESXi" -UserName "testdomain.eu\vmwareadm" -Password "veryultraP@ssw00rd." -Type Generic -Persist LocalMachine 


密码可在本机和帐户中读取。

 $ESXiAdmin = Get-StoredCredential -Type Generic -Target ESXi 


我们有一台存储GIT所有配置的服务器,现在我们可以可靠地跟踪配置的所有更改:谁,什么,何时何地。

在此服务器上配置了计划的任务:检查包含配置的文件夹,然后将所有更改写入Windows事件日志。

15分钟后,计划的任务将向Windows EventLog写入已检测到新的配置文件。

现在该检查此配置了。 首先,我们需要确保文件格式正确:

 $Configuration=(Get-Content -Raw $File | Out-String | ConvertFrom-Json) 


如果一切顺利,是时候开始创建机器并运行BuildVM.ps1脚本了。

在BuildVM.ps1中,我们验证配置文件是否具有虚拟机所有特征的描述:大小,环境,sla,类型,存储,内存,网络。

确保检查基础结构(CheckVM.ps1)中是否存在具有相同名称的计算机。
我们通过VMWare PowerShell CLI连接到我们的vSphere:

 $VmWareAdmin = Get-StoredCredential -Type Generic -Target ESXi Connect-VIServer -Server "vSphereSrv" -Credential $VmWareAdmin | Out-Null 


检查基础架构中是否有同名机器

 $VM=Get-VM $server -ErrorAction SilentlyContinue 


并关闭:

 Disconnect-VIServer * -Force -Confirm:$false 


确保计算机在WinRM上也不可用

 $ping=Test-NetConnection -ComputerName $Configuration.Hostname -CommonTCPPort WINRM -InformationLevel Quiet -ErrorAction SilentlyContinue 


如果$ VM和$ ping为空,则可以创建新计算机。 (当机器已在ESXi中手动创建或该机器在另一个数据中心中时,我们会处理这种情况。)

关于汽车的几句话。 这是一个准备好的虚拟机映像,由sysprep完成,并在我们的vSphere中转换为模板。 使用我们知道的密码的本地管理员已保存在映像中,sysprep后该帐户不会崩溃,这将使我们能够从此模板访问每台计算机,并且出于安全目的,以后可以替换此密码。


创建虚拟机


查找相应的SLR群集:

 $Cluster=Get-Cluster -Name $Configuration.VM.SLA 


检查数据存储上是否有足够的空间:

 $DatastoreCluster = Get-DatastoreCluster |Where-Object {$_.Name -like $Datastore1Name} $Datastore1 = Get-Datastore -Location $DatastoreCluster |sort -Property "FreeSpaceGB" |select -Last 1 IF ($Datastore1.FreeSpaceGB -le "200"){ Write-Host -foreground red "STOP: Not enough datastore capacity for DISK" $vdisk.Id Break } 


和足够的内存:

 $VMHost = Get-VMHost -Location $Cluster |sort -Property "MemoryUsageGB" |select -First 1 IF ($VMHost.MemoryUsageGB -le "20"){ Write-Host -foreground red "STOP: No enough ESXi host capacity" Break } 


我们拿我们的模板

 $VMTemplate = Get-Template -Name 'Win2016_Std_x64_Template' 


并创建一个新的虚拟机

 New-VM -Name $Configuration.Hostname.ToUpper() -VMHost $VMHost -ResourcePool $ResourcePool -Datastore $Datastore -Template $VMTemplate -Location "AutoDeployed VMs" 


将网络接口连接到启用了DHCP的子网很重要。

我们启动虚拟机

 Start-VM $VM 


并保存机器的描述,以便以后可以在VMWare级别确定机器。

 Set-Annotation -Entity $VM -CustomAttribute "Change request" -Value $Configuration.Request -Confirm:$false Set-VM $VM -Notes $Configuration.Description -Confirm:$false 


机器启动,现在我们可以找到接收到的MAC地址:

 $vMAC = (($VM | Get-NetworkAdapter | Select-Object -Property "MacAddress").MacAddress).Replace(':','') 


将此值保存到我们的JSON文件中。

 $Configuration.Network.MAC=$VMAC ConvertTo-Json -InputObject $Configuration -Depth 100 | Out-File "C:\Configs\TargetNodes\Build\$Hostname.json" -Force 


现在是时候承诺我们的Git机器已经创建并拥有自己的唯一MAC。

机器开始初始化(在sysprep之后),设置设备和初始配置。

让我们等到WinRM计算机可以使用IncludeConnection.ps1脚本。

首先我们找出机器从DHCP接收到的IP:

 # $MAC = $vMAC while($isOnline -ne $true){ if((Get-DhcpServerv4Lease -ClientId $MAC -ScopeId $StagingDHCPScope -ComputerName $DHCPServer -ErrorAction Ignore).IPAddress.IPAddressToString){ $tempIP=(Get-DhcpServerv4Lease -ClientId $MAC -ScopeId $StagingDHCPScope -ComputerName $DHCPServer).IPAddress.IPAddressToString break } else{ if($isOnline -ne $true){ Write-Host "`r$i`t" -NoNewline $i++ } } } 


现在,当计算机在WinRM上可用时,我们将等待:

 $LocalAdmin = Get-StoredCredential -Type Generic -Target LocalAdmin $i=0 $isOnline=$false while($isOnline -ne $true){ if(Invoke-Command -ComputerName $tempIP -ScriptBlock{ Get-ItemProperty -Path "Registry::\HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing" } -Credential $LocalAdmin -ErrorAction SilentlyContinue){ $isOnline=$true break } else{ if($isOnline -ne $true){ Write-Host "`r$i" -NoNewline $i++ Start-Sleep -Seconds 1 } } } 


机器已准备好驱动。

所需状态配置


要配置所需的配置,我们使用PowerShell部件-DSC(所需状态配置)。 网络上有一个已配置的DSC Pull服务器:dscpull.testdomain.eu。
以下是我们的DSC Pull服务器的配置。 关于配置DSC拉取的好文章。

 Node $NodeName { WindowsFeature DSCServiceFeature { Ensure = "Present" Name = "DSC-Service" } xDscWebService PSDSCPullServer { Ensure = "Present" EndpointName = "PSDSCPullServer" Port = 8080 PhysicalPath = "$env:SystemDrive\inetpub\PSDSCPullServer" CertificateThumbPrint = $certificateThumbPrint ModulePath = "$env:PROGRAMFILES\WindowsPowerShell\DscService\Modules" ConfigurationPath = "$env:PROGRAMFILES\WindowsPowerShell\DscService\Configuration" State = "Started" DependsOn = "[WindowsFeature]DSCServiceFeature" RegistrationKeyPath = "$env:PROGRAMFILES\WindowsPowerShell\DscService" AcceptSelfSignedCertificates = $true UseSecurityBestPractices = $true } File RegistrationKeyFile { Ensure = 'Present' Type = 'File' DestinationPath = "$env:ProgramFiles\WindowsPowerShell\DscService\RegistrationKeys.txt" Contents = $RegistrationKey } } 


可从以下网址获得: https : //dscpull.testdomain.eu : 8080

它的端点: https ://dscpull.testdomain.eu:8080/ PSDSCPullserver.svc

所有拉式服务器客户端都必须安装PowerShell 5.1
如果未安装PowerShell 5.1:

 $PSVersionTable.PSVersion.Major –lt 5 


安装PowerShell 5.1:

 Write-Host "Download PowerShell 5.1" Invoke-Command -ComputerName $Node -ScriptBlock { [System.Net.ServicePointManager]::SecurityProtocol=[System.Net.SecurityProtocolType]::Tls12;Invoke-WebRequest -Uri "https://dscpull.testdomain.eu:8080/Files/Updates/WMF.msu" -OutFile C:\TEMP\WMF.MSU } Write-Host "Extract PowerShell 5.1" Invoke-Command -ComputerName $Node -ScriptBlock {Start-Process -FilePath 'wusa.exe' -ArgumentList "C:\temp\WMF.msu /extract:C:\temp\" -Wait -PassThru } Write-Host "Apply PowerShell 5.1" Invoke-Command -ComputerName $Node -ScriptBlock {Start-Process -FilePath 'dism.exe' -ArgumentList "/online /add-package /PackagePath:C:\temp\WindowsBlue-KB3191564-x64.cab /Quiet" -Wait -PassThru } Write-Host "PowerShell 5.1 has been installed" 


PKI服务器也已部署在我们的网络上。 这是对存储在DSC mof文件中的凭据进行安全加密的条件(Mof文件是Pull Server及其客户端进行通信的“语言”)。 当客户端尝试在Pull Server上注册时,有必要指定一个Thumbprint证书,以后在Pull Server上将使用此证书来加密密码。 下面我们将看到它是如何工作的。

将根CA导入我们的新计算机:

  Invoke-Command -ComputerName $server -ScriptBlock{ $PKI="-----BEGIN CERTIFICATE----- MIIF2TCCA8GgAwIBAgIQSPIjcff9rotNdxbg3+ygqDANBgkqhkiG9w0BAQUFADAe **************************************************************** znafMvVx0B4tGEz2PFss/FviGdC3RohBHG0rF5jO50J4nS/3cGGm+HGdn1w/tZd0 a0FWpn9VCOSmXM2It+tSW1f4nZVt6T2kr1ZlTxkDhT7HMSGsrX/XJswzCkDGe3dE qrVVjNUkhVTaeeBWdujB5J6mcx7YkNsAUhODiS9Cf7FnYnxLFA72M0pijI48P5F0 ShM9HWAAUIrLkv13ug== -----END CERTIFICATE-----" $PKI | Out-File RootCA.cer Import-Certificate RootCA.cer -CertStoreLocation Cert:\LocalMachine\Root | select Thumbprint | Out-Null } -Credential $LocalAdmin | Out-Null 


为了进一步的工作,我们需要一对RSA密钥。 我们将生成一个自签名证书并暂时使用它。

现在我们可以在拉取服务器上注册:

 $DscHostFQDN = [System.Net.Dns]::GetHostEntry([string]$env:computername).HostName $DscPullServerURL = "https://$($DscHostFQDN):8080/PSDSCPullserver.svc" $DscWebConfigChildPath = '\inetpub\psdscpullserver\web.config' $DscWebConfigPath = Join-Path -Path $env:SystemDrive -ChildPath $DscWebConfigChildPath $DscWebConfigXML = [xml](Get-Content $DscWebConfigPath) $DscRegKeyName = 'RegistrationKeys.txt' $DscRegKeyXMLNode = "//appSettings/add[@key = 'RegistrationKeyPath']" $DscRegKeyParentPath = ($DscWebConfigXML.SelectNodes($DscRegKeyXMLNode)).value $DscRegKeyPath = Join-Path -Path $DscRegKeyParentPath -ChildPath $DscRegKeyName $DscRegKey = Get-Content $DscRegKeyPath [DSCLocalConfigurationManager()] configuration RegisterOnPull { Node $Node { Settings { ConfigurationModeFrequencyMins = 1440 CertificateID = $Thumbprint RefreshMode ='Pull' RefreshFrequencyMins = 1440 RebootNodeIfNeeded = $true ConfigurationMode ='ApplyAndAutoCorrect' AllowModuleOverwrite = $true DebugMode = 'None' StatusRetentionTimeInDays = 1 } ConfigurationRepositoryWeb $([string]$env:computername) { ServerURL = $DscPullServerURL RegistrationKey = $DscRegKey CertificateID = $Thumbprint ConfigurationNames = @("$hostx") } } } RegisterOnPull -OutputPath $MetaConfigsStorage Set-DscLocalConfigurationManager -ComputerName $Node -Path $MetaConfigsStorage -Verbose -Force -Credential $LocalAdmin 


将第一个配置发送到我们的机器

 Configuration Rename { param ( [Parameter()] [System.String[]] $Node, $hostname ) Import-DscResource -ModuleName xComputerManagement Import-DscResource –ModuleName PSDesiredStateConfiguration Node $Node { xComputer JoinDomain { Name = $hostname } } } Rename -Node $Node -OutputPath $DscConfigPath -hostname $hostname New-DscChecksum $DscConfigPath -Force Invoke-Command -ComputerName $Node -ScriptBlock{Update-DscConfiguration -Verbose -Wait } -Credential $LocalAdmin -Verbose 


服务器将自动重命名并重新启动。 现在我们可以执行Join Domain。

 Configuration JoinAD { param ( [Parameter()] [System.String[]] $Node, [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [System.Management.Automation.PSCredential] $DomainAdmin, $hostname, $domain ) Import-DscResource -ModuleName xComputerManagement Import-DscResource –ModuleName PSDesiredStateConfiguration Node $Node { xComputer JoinDomain { Name = $hostname DomainName = $domain Credential = $DomainAdmin JoinOU = "OU=Servers,OU=Staging,DC=testdomain,DC=eu" } GroupSet LocalAdmins { GroupName = @( 'Administrators') Ensure = 'Present' MembersToInclude = @( 'testdomain-eu\dscstaging' ) } } } $cd = @{ AllNodes = @( @{ NodeName = $Node PSDscAllowPlainTextPassword = $false PSDscAllowDomainUser=$true Certificatefile = $CertFile Thumbprint = $Certificate.ToString() } ) } JoinAD -Node $Node -OutputPath $DscConfigPath -DomainAdmin $DomainAdmin -hostname $hostname -ConfigurationData $cd -domain $domain New-DscChecksum $DscConfigPath -Force Invoke-Command -ComputerName $Node -ScriptBlock{Update-DscConfiguration -Verbose -Wait } -Credential $LocalAdmin -Verbose 


这是我们的mof文件的样子:

 instance of MSFT_Credential as $MSFT_Credential1ref { Password = "-----BEGIN CMS-----\nMIIBsgYJKoZIhvcNAQcDoIIBozCCAZ8CAQAxggFKMIIBRgIBADAuMBoxGDAWBgNVBAMMD1dJTi1H\nNFFKTFFQME4xNQIQOQN77pxew75HU6l7GPn99TANBgkqhkiG9w0BAQcwAASCAQAlhFf7Zs2gJbJEnc1DEK2yWbKcO+BEyD2cr6vKHdn\nQ9TrjvbysEOvYjT15o6MccwkMEwGCSqGSIb3DQEHATAdBglghkgBZQMEASoEEEdKJT+GX4IkPezR\nwYncyQiAIAFKxwJocH4ufRsq9L2Ipkp+VQCx2ljlwif6ac4X/PqG\n-----END CMS-----"; UserName = "testdomain.eu\\service_DomainJoin_001"; }; instance of MSFT_xComputer as $MSFT_xComputer1ref { ResourceID = "[xComputer]JoinDomain"; Credential = $MSFT_Credential1ref; DomainName = "testdomain.eu"; SourceInfo = "C:\\Program Files\\WindowsPowerShell\\Scripts\\JoinAD.ps1::34::9::xComputer"; Name = "dsctest51"; JoinOU = "OU=Servers,OU=Staging,DC=testdomain,DC=eu"; ModuleName = "xComputerManagement"; ModuleVersion = "4.1.0.0"; ConfigurationName = "JoinAD"; }; nMIIBsgYJKoZIhvcNAQcDoIIBozCCAZ8CAQAxggFKMIIBRgIBADAuMBoxGDAWBgNVBAMMD1dJTi1H \ nNFFKTFFQME4xNQIQOQN77pxew75HU6l7GPn99TANBgkqhkiG9w0BAQcwAASCAQAlhFf7Zs2gJbJEnc1DEK2yWbKcO + BEyD2cr6vKHdn \ nQ9TrjvbysEOvYjT15o6MccwkMEwGCSqGSIb3DQEHATAdBglghkgBZQMEASoEEEdKJT + GX4IkPezR \ nwYncyQiAIAFKxwJocH4ufRsq9L2Ipkp + VQCx2ljlwif6ac4X / PQG \ n ----- END CMS -----”; instance of MSFT_Credential as $MSFT_Credential1ref { Password = "-----BEGIN CMS-----\nMIIBsgYJKoZIhvcNAQcDoIIBozCCAZ8CAQAxggFKMIIBRgIBADAuMBoxGDAWBgNVBAMMD1dJTi1H\nNFFKTFFQME4xNQIQOQN77pxew75HU6l7GPn99TANBgkqhkiG9w0BAQcwAASCAQAlhFf7Zs2gJbJEnc1DEK2yWbKcO+BEyD2cr6vKHdn\nQ9TrjvbysEOvYjT15o6MccwkMEwGCSqGSIb3DQEHATAdBglghkgBZQMEASoEEEdKJT+GX4IkPezR\nwYncyQiAIAFKxwJocH4ufRsq9L2Ipkp+VQCx2ljlwif6ac4X/PqG\n-----END CMS-----"; UserName = "testdomain.eu\\service_DomainJoin_001"; }; instance of MSFT_xComputer as $MSFT_xComputer1ref { ResourceID = "[xComputer]JoinDomain"; Credential = $MSFT_Credential1ref; DomainName = "testdomain.eu"; SourceInfo = "C:\\Program Files\\WindowsPowerShell\\Scripts\\JoinAD.ps1::34::9::xComputer"; Name = "dsctest51"; JoinOU = "OU=Servers,OU=Staging,DC=testdomain,DC=eu"; ModuleName = "xComputerManagement"; ModuleVersion = "4.1.0.0"; ConfigurationName = "JoinAD"; }; 


DSC使用具有自签名证书的具有Domain Admin权限的服务帐户对凭据进行加密,即:testdomain.eu \\ service_DomainJoin_001。 DSC客户端及其私钥将解密凭据,并使用指定的域凭据来应用所有配置模块。 在这种情况下,它将在指定的组织单位中执行域加入。

 GroupSet LocalAdmins { GroupName = @( 'Administrators') Ensure = 'Present' MembersToInclude = @( testdomain-eu\dscstaging' ) } 


此模块将dscstaging添加到本地管理员以进行进一步配置。

重新启动后,我们将能够使用域凭据输入计算机。

我们正在等待服务器从PKI接收证书(已配置自动注册),将来我们将使用PKI颁发的证书。

 $vmcert=Invoke-Command -ComputerName $server -ScriptBlock{ return Get-ChildItem -Path cert:\LocalMachine\My | where {$_.EnhancedKeyUsageList.FriendlyName -eq "Document Encryption"-and $_.Issuer -eq "CN=TestDomain Issuing CA, DC=testdomain, DC=eu"} } -ErrorAction Ignore 


现在,使用更新的指纹再次注册Pull Server。

就是这样,加入域的机器,我们可以按照适合自己的方式使用它。

安装SQL Server


JSON文件描述了MS SQL Server的要求,我们还使用DSC来安装和配置SQL Server。 配置如下所示:

 Configuration $Node{ WindowsFeature "NetFramework35"{ Name = "NET-Framework-Core" Ensure = "Present" Source = "\\$DscHostFQDN\Files\Updates" } WindowsFeature "NetFramework45"{ Name = "NET-Framework-45-Core" Ensure= "Present" } SqlSetup "MSSQL2012NamedInstance"{ InstanceName = $MSSQL.InstanceName Features = $MSSQL.Features ProductKey = $ProductKey SQLCollation = $MSSQL.Collation SQLSysAdminAccounts = @('testdomain-EU\SQLAdmins',' testdomain-EU\Backup') InstallSharedDir = "C:\Program Files\Microsoft SQL Server" InstallSharedWOWDir = "C:\Program Files (x86)\Microsoft SQL Server" InstallSQLDataDir = $MSSQL.DataRoot SQLUserDBDir = $MSSQL.UserDBDir SQLUserDBLogDir = $MSSQL.UserLogDir SQLTempDBDir = $MSSQL.TempDBDir SQLTempDBLogDir = $MSSQL.TempDBLogDir SQLBackupDir = $MSSQL.BackupDir SourcePath = $SQLSource SAPwd = $SA SecurityMode = 'SQL' UpdateSource = ".\Updates" Action = "Install" ForceReboot = $True SQLSvcAccount = $SqlServiceCredential AgtSvcAccount = $SqlServiceCredential ISSvcAccount = $SqlServiceCredential BrowserSvcStartupType = "Automatic" DependsOn = '[WindowsFeature]NetFramework35', '[WindowsFeature]NetFramework45' } 

其中定义了$ MSSQL:
 $MSSQL=$Configuration.Applications | where {$_.Application -eq "Microsoft SQL Server 2012"} 


$ MSSQL.InstanceName-所有这些都在我们的Json文件中指示。 应用此配置将安装MS SQL Server,并将所有更新存储在Updates文件夹中,并在必要时重新启动服务器。

汽车准备好了。

现在服务


Service-Now中有几个可用的API 。 我们使用Rest API。
要获取具有已分配状态的计算机的列表,请使用以下形式的查询:
instance.service-now.com/cmdb_ci_server_list.do?sysparm_query=install_status=16 ^ u_subtype = ^ ORDERBY名称
在PowerShell中,如下所示:
 $url="https://instance.service-now.com/api/now/table/cmdb_ci_server?sysparm_query=install_status=16^u_subtype=^ORDERBYname" $uri= new-object System.Uri("https://instance.service-now.com/") #       $credentials = (Get-StoredCredential -Type Generic -Target DSC).GetNetworkCredential() $credentials = new-object System.Net.NetworkCredential $credentials.UserName, $credentials.SecurePassword Add-Type -AssemblyName System.Net.Http $handler = New-Object System.Net.Http.HttpClientHandler $handler.CookieContainer = New-Object System.Net.CookieContainer $handler.UseCookies=$true $handler.Credentials=$credentials $HttpClient = New-Object System.Net.Http.HttpClient($handler) $HttpClient.BaseAddress= $uri $Header = New-Object System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json") $HttpClient.DefaultRequestHeaders.Accept.Clear() $HttpClient.DefaultRequestHeaders.Accept.Add($Header); $response=$HttpClient.GetAsync($url) $respStream=$response.Result.Content.ReadAsStringAsync() $Servers = $respStream.Result | ConvertFrom-Json #   Configuration Items  $ServersCI=$Servers.result 

第一个数组对象是我们需要的主机名。
如果计算机已准备就绪,则可以在Service-Now中更改计算机的状态,为此,使用UpdateCI.ps1脚本:
 param( $CI, [ValidateSet("Allocated","In use","Pending install")] $NewStatus='In use' ) $url="https://instance.service-now.com/api/now/table/cmdb_ci_server?sysparm_query=name=$CI" $uri= new-object System.Uri("https://instance.service-now.com/") $credentials = (Get-StoredCredential -Type Generic -Target DSC).GetNetworkCredential() $credentials = new-object System.Net.NetworkCredential $credentials.UserName, $credentials.SecurePassword Add-Type -AssemblyName System.Net.Http $handler = New-Object System.Net.Http.HttpClientHandler $handler.CookieContainer = New-Object System.Net.CookieContainer $handler.UseCookies=$true $handler.Credentials=$credentials $HttpClient = New-Object System.Net.Http.HttpClient($handler) $HttpClient.BaseAddress= $uri $Header = New-Object System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json") $HttpClient.DefaultRequestHeaders.Accept.Clear() $HttpClient.DefaultRequestHeaders.Accept.Add($Header); $response=$HttpClient.GetAsync($url) $respStream=$response.Result.Content.ReadAsStringAsync() $Servers = $respStream.Result | ConvertFrom-Json $ServerCI=$Servers.result[0] $update=@{} if($NewStatus -eq "In use"){ $update.install_status=1 } if($NewStatus -eq "Pending install"){ $update.install_status=4 } $stringcontent = New-Object System.Net.Http.StringContent((ConvertTo-Json -InputObject $update -Depth 100),[System.Text.Encoding]::UTF8, "application/json"); $result=$HttpClient.PutAsync("https://instance.service-now.com/api/now/table/cmdb_ci_server/$($ServerCI.sys_id)", $stringcontent) 

要获取表和记录,将使用REST API GET请求来更改记录PUT / POST请求,您需要在其中更改字段的主体。

我们使用图形工具(如Azure Portal)创建了一个方便的工具,该工具使我们能够为我们和我们的客户尽可能方便地管理本地基础结构。
PS 12.24.2018。 一切似乎都过时了吗? 现在该使用Azure DevOps了。 在下一篇文章中,我将向您展示如何使用Azure DevOps管道完成所有这些操作。

Source: https://habr.com/ru/post/zh-CN425129/


All Articles