用于配置 IIS 应用程序池的 DSC
DSC to Configure an IIS App Pool
我们一直在研究所需的状态配置,我被要求使用 powershell DSC 设置原型来配置 IIS 应用程序池。我知道创建配置的所有步骤,只是不确定我的配置中可能有什么。我计划使用 xWebAdministration 资源,因为它有 xWebAppPool 和 xWedbAdministration 之类的东西。关于我还可以用什么来设置它有什么建议吗?
您可能会使用 WindowsFeature
资源来安装所需的角色和功能(Web-Server
等),您可能会使用 File
资源来创建目录并且可能复制站点的文件,您可以使用 Registry
资源启用 Web 管理服务以便您可以远程管理 IIS,然后使用 Service
资源启动该服务。
前段时间我接到了完全相同的挑战任务,我创建了一个 DSC 资源原型来完成这个任务。经过初步测试后,现在可以在生产中运行。
源代码在 gihub (https://github.com/RafPe/cWebAdmin) 上,欢迎所有反馈:)
也许这会让你知道如何在你这边挑战这个
如果您有许多站点要置于配置控制之下,您可以使用我的 DSC 生成器为 IIS 功能、网站、应用程序池和虚拟目录生成 DSC。
然后我使用 Octopus Deploy 将 DSC 交付到服务器并应用 DSC。
*意识到这已经很老了,但只是偶然发现它,想为您的 DSC 获得的场景提供建议 big/unwieldly。
我首先将您的节点定义文件与您的配置文件分开,然后映射一个引用。我把我的文件并排放置,所以我会像下面这样参考。我不会进入加密,很好的 MS 指导。
$File = 'WebApp\NodeDefinitions.psd1'
$Parent = Split-Path -Parent $PSScriptRoot
$Path = Join-Path $Parent $File
WebApp -RunAs $RunAs -ConfigurationData "$Path" -OutputPath $localpath -verbose
现在,为了使事情变得更加动态,您可以在节点定义文件中创建数组或散列 table 集合,如下所示,用于文件夹、站点等。*我确实必须更改 xcertificatedsc 才能拥有它传递一系列帐户,如果您需要帮助,这并不难。
@{
NodeName = "Vm-Web-1"
Role = "DevWeb","Web","WS","SMP"
IUSRS = "Domain\User1$","Domain\User2$"
Folders = @(
("Dir1","F:\inetpub\wwwroot\SomeApp","Present"),
("Dir2","F:\inetpub\wwwroot\SomeApp2","Present"),
("Dir3","F:\inetpub\wwwroot\SomeApp2","Absent") #If something's moved or a mistake
)
Sites = @(
@("MyApp1","Domain\User1$","Present"),
@("MyApp2","Domain\User2$","Present")
)
CertPerms= @{
"somecert@domain.com" = @("Domain\User1$","Domain\User2$")
}
},
然后我在我的配置中引入非节点数据,这样站点就更适合table,我们稍后将在配置ps1 文件中加入。我还将展示如何迭代文件夹创建。
@{
Name = "MyApp1"
PoolConfigName = "ApMyApp1"
PoolName = "ApMyApp1"
PoolRtVer = "v4.0"
SiteConfigName = "WaMyApp1"
SitePath = "ApMyApp1"
SiteName = "ApMyApp1"
SiteDepends = "[File]Dir1"
},
@{
Name = "MyApp2"
PoolConfigName = "ApMyApp2"
PoolName = "ApMyApp2"
PoolRtVer = "v4.0"
SiteConfigName = "WaMyApp2"
SitePath = "ApMyApp2"
SiteName = "ApMyApp2"
SiteDepends = "[File]Dir2"
},
要遍历文件夹,您只需在节点定义文件中引用数组的元素
Foreach($Folder in $Node.Folders){
File $Folder[0]
{
Ensure = $Folder[2]
Type = "Directory"
DestinationPath = $Folder[1]
}
}
站点加入有点复杂,我对我目前引用元素而不是更容易阅读的名称的情况不太满意,但它有效。加入 node/nonnode 数据后,脚本的下一部分用于较少使用的参数。例如,我们不会在始终 运行 模式下引入很多池(除非在相关应用程序的 web.config 中验证了正确的页面初始化)。如果我要介绍一个站点并且关联服务帐户在域中未激活,我将确保关联池已停止,这样它就不会淹没 iis 工作进程。否则,您应该能够映射出节点部分(数组引用)与非节点站点数据中设置的内容。
Foreach($SiteName in $Node.Sites){
$Site = $ConfigurationData.Sites.Where{$_.Name -eq $SiteName[0]}
if ([string]::IsNullOrWhiteSpace($Site.PoolIdleTO))
{
$PoolIdleTO = 20
}
else
{
$PoolIdleTO = $Site.PoolIdleTO
}
if ([string]::IsNullOrWhiteSpace($Site.PoolStartMode))
{
$PoolStartMode = "OnDemand"
}
else
{
$PoolStartMode = $Site.PoolStartMode
}
if ([string]::IsNullOrWhiteSpace($SiteName[3]))
{
$State = "Started"
}
else
{
$State = $SiteName[3]
}
xWebAppPool $Site.PoolConfigName
{
Name = $Site.PoolName
Ensure = $SiteName[2]
State = $State
autoStart = $true
enable32BitAppOnWin64 = $false
enableConfigurationOverride = $true
managedPipelineMode = "Integrated"
managedRuntimeVersion = $Site.PoolRtVer
startMode = $PoolStartMode
queueLength = 1000
cpuAction = "KillW3wp"
cpuLimit = 95000
cpuResetInterval = (New-TimeSpan -Minutes 1).ToString()
cpuSmpAffinitized = $false
cpuSmpProcessorAffinityMask = 4294967295
cpuSmpProcessorAffinityMask2 = 4294967295
identityType = 'SpecificUser'
Credential = New-Object System.Management.Automation.PSCredential($SiteName[1], (ConvertTo-SecureString $Node.GmsaPwd.ToString() -AsPlainText -Force))
idleTimeout = (New-TimeSpan -Minutes $PoolIdleTO).ToString()
idleTimeoutAction = 'Suspend'
loadUserProfile = $false
logEventOnProcessModel = 'IdleTimeout'
logonType = 'LogonBatch'
manualGroupMembership = $false
maxProcesses = 1
pingingEnabled = $true
pingInterval = (New-TimeSpan -Seconds 30).ToString()
pingResponseTime = (New-TimeSpan -Seconds 90).ToString()
setProfileEnvironment = $false
shutdownTimeLimit = (New-TimeSpan -Seconds 90).ToString()
startupTimeLimit = (New-TimeSpan -Seconds 90).ToString()
orphanActionExe = ''
orphanActionParams = ''
orphanWorkerProcess = $false
loadBalancerCapabilities = 'HttpLevel'
rapidFailProtection = $true
rapidFailProtectionInterval = (New-TimeSpan -Minutes 1).ToString()
rapidFailProtectionMaxCrashes = 5
autoShutdownExe = 'C:\Windows\System32\iisreset.exe'
autoShutdownParams = ''
disallowOverlappingRotation = $false
disallowRotationOnConfigChange = $false
logEventOnRecycle = 'Time,Requests,Schedule,Memory,IsapiUnhealthy,OnDemand,ConfigChange,PrivateMemory'
restartMemoryLimit = 3221225472
restartPrivateMemoryLimit = 8000000
restartRequestsLimit = 20000000
restartTimeLimit = (New-TimeSpan -Minutes 0).ToString()
restartSchedule = "00:00:00"
DependsOn = '[WindowsFeature]IIS'
}
<#!!!Imperative method (runs immediately) to ensure service accounts get IIS metabase access!!#
#Need to move this into the function with a flag, obviously there'll be looping challenges...
Invoke-Command -Session (New-PSSession -ComputerName $Node.NodeName -Credential $RunAs -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck)) -ScriptBlock {
param ([string] $User)
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -ga $User
} -ArgumentList $SiteName[1]
#>
cIisAccess "IisMetabaseAccess$($Site.SiteConfigName + $SiteName[1])"
{
Account = $SiteName[1]
Ensure="Present"
}
xWebApplication $Site.SiteConfigName
{
Website = "Default Web Site"
Name = $Site.SiteName
WebAppPool = $Site.PoolName
PhysicalPath = $Node.DfSitePath + $Site.SitePath
Ensure = $SiteName[2]
PreloadEnabled = $true
DependsOn = "[xWebAppPool]$($Site.PoolConfigName)",$($Site.SiteDepends)
}
}
需要注意的一件事是我使用 GMSA,因此没有密码,并且使用了 kerberos 令牌。由于 PSCredential 要求,您仍然需要伪造的密码参考,因此您可以像下面这样向您的 allnodes 数据添加一些内容以供参考:
GmsaPwd = "none"
还有很多关于使用角色的指导,但下面是一个简单的参考。
Node $AllNodes.Where{$_.Role -contains "Web"}.NodeName
{
#Embed site/folder iterators here if preferred
}
我们一直在研究所需的状态配置,我被要求使用 powershell DSC 设置原型来配置 IIS 应用程序池。我知道创建配置的所有步骤,只是不确定我的配置中可能有什么。我计划使用 xWebAdministration 资源,因为它有 xWebAppPool 和 xWedbAdministration 之类的东西。关于我还可以用什么来设置它有什么建议吗?
您可能会使用 WindowsFeature
资源来安装所需的角色和功能(Web-Server
等),您可能会使用 File
资源来创建目录并且可能复制站点的文件,您可以使用 Registry
资源启用 Web 管理服务以便您可以远程管理 IIS,然后使用 Service
资源启动该服务。
前段时间我接到了完全相同的挑战任务,我创建了一个 DSC 资源原型来完成这个任务。经过初步测试后,现在可以在生产中运行。
源代码在 gihub (https://github.com/RafPe/cWebAdmin) 上,欢迎所有反馈:)
也许这会让你知道如何在你这边挑战这个
如果您有许多站点要置于配置控制之下,您可以使用我的 DSC 生成器为 IIS 功能、网站、应用程序池和虚拟目录生成 DSC。
然后我使用 Octopus Deploy 将 DSC 交付到服务器并应用 DSC。
*意识到这已经很老了,但只是偶然发现它,想为您的 DSC 获得的场景提供建议 big/unwieldly。
我首先将您的节点定义文件与您的配置文件分开,然后映射一个引用。我把我的文件并排放置,所以我会像下面这样参考。我不会进入加密,很好的 MS 指导。
$File = 'WebApp\NodeDefinitions.psd1'
$Parent = Split-Path -Parent $PSScriptRoot
$Path = Join-Path $Parent $File
WebApp -RunAs $RunAs -ConfigurationData "$Path" -OutputPath $localpath -verbose
现在,为了使事情变得更加动态,您可以在节点定义文件中创建数组或散列 table 集合,如下所示,用于文件夹、站点等。*我确实必须更改 xcertificatedsc 才能拥有它传递一系列帐户,如果您需要帮助,这并不难。
@{
NodeName = "Vm-Web-1"
Role = "DevWeb","Web","WS","SMP"
IUSRS = "Domain\User1$","Domain\User2$"
Folders = @(
("Dir1","F:\inetpub\wwwroot\SomeApp","Present"),
("Dir2","F:\inetpub\wwwroot\SomeApp2","Present"),
("Dir3","F:\inetpub\wwwroot\SomeApp2","Absent") #If something's moved or a mistake
)
Sites = @(
@("MyApp1","Domain\User1$","Present"),
@("MyApp2","Domain\User2$","Present")
)
CertPerms= @{
"somecert@domain.com" = @("Domain\User1$","Domain\User2$")
}
},
然后我在我的配置中引入非节点数据,这样站点就更适合table,我们稍后将在配置ps1 文件中加入。我还将展示如何迭代文件夹创建。
@{
Name = "MyApp1"
PoolConfigName = "ApMyApp1"
PoolName = "ApMyApp1"
PoolRtVer = "v4.0"
SiteConfigName = "WaMyApp1"
SitePath = "ApMyApp1"
SiteName = "ApMyApp1"
SiteDepends = "[File]Dir1"
},
@{
Name = "MyApp2"
PoolConfigName = "ApMyApp2"
PoolName = "ApMyApp2"
PoolRtVer = "v4.0"
SiteConfigName = "WaMyApp2"
SitePath = "ApMyApp2"
SiteName = "ApMyApp2"
SiteDepends = "[File]Dir2"
},
要遍历文件夹,您只需在节点定义文件中引用数组的元素
Foreach($Folder in $Node.Folders){
File $Folder[0]
{
Ensure = $Folder[2]
Type = "Directory"
DestinationPath = $Folder[1]
}
}
站点加入有点复杂,我对我目前引用元素而不是更容易阅读的名称的情况不太满意,但它有效。加入 node/nonnode 数据后,脚本的下一部分用于较少使用的参数。例如,我们不会在始终 运行 模式下引入很多池(除非在相关应用程序的 web.config 中验证了正确的页面初始化)。如果我要介绍一个站点并且关联服务帐户在域中未激活,我将确保关联池已停止,这样它就不会淹没 iis 工作进程。否则,您应该能够映射出节点部分(数组引用)与非节点站点数据中设置的内容。
Foreach($SiteName in $Node.Sites){
$Site = $ConfigurationData.Sites.Where{$_.Name -eq $SiteName[0]}
if ([string]::IsNullOrWhiteSpace($Site.PoolIdleTO))
{
$PoolIdleTO = 20
}
else
{
$PoolIdleTO = $Site.PoolIdleTO
}
if ([string]::IsNullOrWhiteSpace($Site.PoolStartMode))
{
$PoolStartMode = "OnDemand"
}
else
{
$PoolStartMode = $Site.PoolStartMode
}
if ([string]::IsNullOrWhiteSpace($SiteName[3]))
{
$State = "Started"
}
else
{
$State = $SiteName[3]
}
xWebAppPool $Site.PoolConfigName
{
Name = $Site.PoolName
Ensure = $SiteName[2]
State = $State
autoStart = $true
enable32BitAppOnWin64 = $false
enableConfigurationOverride = $true
managedPipelineMode = "Integrated"
managedRuntimeVersion = $Site.PoolRtVer
startMode = $PoolStartMode
queueLength = 1000
cpuAction = "KillW3wp"
cpuLimit = 95000
cpuResetInterval = (New-TimeSpan -Minutes 1).ToString()
cpuSmpAffinitized = $false
cpuSmpProcessorAffinityMask = 4294967295
cpuSmpProcessorAffinityMask2 = 4294967295
identityType = 'SpecificUser'
Credential = New-Object System.Management.Automation.PSCredential($SiteName[1], (ConvertTo-SecureString $Node.GmsaPwd.ToString() -AsPlainText -Force))
idleTimeout = (New-TimeSpan -Minutes $PoolIdleTO).ToString()
idleTimeoutAction = 'Suspend'
loadUserProfile = $false
logEventOnProcessModel = 'IdleTimeout'
logonType = 'LogonBatch'
manualGroupMembership = $false
maxProcesses = 1
pingingEnabled = $true
pingInterval = (New-TimeSpan -Seconds 30).ToString()
pingResponseTime = (New-TimeSpan -Seconds 90).ToString()
setProfileEnvironment = $false
shutdownTimeLimit = (New-TimeSpan -Seconds 90).ToString()
startupTimeLimit = (New-TimeSpan -Seconds 90).ToString()
orphanActionExe = ''
orphanActionParams = ''
orphanWorkerProcess = $false
loadBalancerCapabilities = 'HttpLevel'
rapidFailProtection = $true
rapidFailProtectionInterval = (New-TimeSpan -Minutes 1).ToString()
rapidFailProtectionMaxCrashes = 5
autoShutdownExe = 'C:\Windows\System32\iisreset.exe'
autoShutdownParams = ''
disallowOverlappingRotation = $false
disallowRotationOnConfigChange = $false
logEventOnRecycle = 'Time,Requests,Schedule,Memory,IsapiUnhealthy,OnDemand,ConfigChange,PrivateMemory'
restartMemoryLimit = 3221225472
restartPrivateMemoryLimit = 8000000
restartRequestsLimit = 20000000
restartTimeLimit = (New-TimeSpan -Minutes 0).ToString()
restartSchedule = "00:00:00"
DependsOn = '[WindowsFeature]IIS'
}
<#!!!Imperative method (runs immediately) to ensure service accounts get IIS metabase access!!#
#Need to move this into the function with a flag, obviously there'll be looping challenges...
Invoke-Command -Session (New-PSSession -ComputerName $Node.NodeName -Credential $RunAs -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck)) -ScriptBlock {
param ([string] $User)
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -ga $User
} -ArgumentList $SiteName[1]
#>
cIisAccess "IisMetabaseAccess$($Site.SiteConfigName + $SiteName[1])"
{
Account = $SiteName[1]
Ensure="Present"
}
xWebApplication $Site.SiteConfigName
{
Website = "Default Web Site"
Name = $Site.SiteName
WebAppPool = $Site.PoolName
PhysicalPath = $Node.DfSitePath + $Site.SitePath
Ensure = $SiteName[2]
PreloadEnabled = $true
DependsOn = "[xWebAppPool]$($Site.PoolConfigName)",$($Site.SiteDepends)
}
}
需要注意的一件事是我使用 GMSA,因此没有密码,并且使用了 kerberos 令牌。由于 PSCredential 要求,您仍然需要伪造的密码参考,因此您可以像下面这样向您的 allnodes 数据添加一些内容以供参考:
GmsaPwd = "none"
还有很多关于使用角色的指导,但下面是一个简单的参考。
Node $AllNodes.Where{$_.Role -contains "Web"}.NodeName
{
#Embed site/folder iterators here if preferred
}