Configurer un second contrôleur de sites Web
S’applique à : Windows Azure Pack
Microsoft Azure Pack : Sites Web peut avoir au maximum deux contrôleurs de sites web. Pour la haute disponibilité, il est vivement recommandé de configurer un second contrôleur de sites Web. Vous pouvez effectuer cette opération de deux façons :
- Lorsque vous créez une batterie de serveurs
- Ajouter un contrôleur à une batterie de serveurs existante
Ajouter un deuxième contrôleur de sites web à une nouvelle batterie de serveurs (avec Update Release 6 et versions ultérieures)
À l’aide de la console de gestion des sites web Azure Pack Windows, vous pouvez ajouter un deuxième contrôleur de sites web lorsque vous configurez une nouvelle batterie de serveurs.
- Lors de la sélection du type de contrôleur, sélectionnez Joindre le serveur à un cloud Sites Web existants en tant que contrôleur secondaire.
- Dans la liste des clés système et des connexions de base de données, cliquez sur Configurer
- Dans la fenêtre contextuelle, entrez des valeurs pour ces champs :
- Contrôleur principal
- Nom d'utilisateur
- Mot de passe
- Cliquez sur OK pour configurer le deuxième contrôleur.
Ajouter un deuxième contrôleur de sites web à une batterie de serveurs existante
Utilisez les scripts suivants pour ajouter un contrôleur à une batterie de serveurs existante :
OnStartSecondaryController.cmd - Installe WebPlatform Installer (Web PI) sur le serveur Windows 2012 ou la machine virtuelle que vous avez préparé. Il appelle ensuite les scripts HostingBootstrapperBootstrapper et OnStartSecondaryController à la suite pour terminer la configuration du contrôleur secondaire. Les paramètres requis comprennent les informations d'identification d'administration de SQL Server et du contrôleur qui seront utilisées dans votre configuration.
HostingBootstrapperBootstrapper.ps1 - Appelle Program Files\Microsoft\Web Platform Installer\WebpiCmd.exe pour installer le second contrôleur de sites Web. Il utilise la même procédure que pour l'installation du contrôleur primaire, mais ignore le portail de configuration en spécifiant le commutateur de ligne de commande /SuppressPostFinish.
OnStartSecondaryController.ps1 - Copie les données de configuration du contrôleur primaire vers le contrôleur secondaire, y compris les clés
SystemCore
etSiteRuntime
et les chaînes de connexion d'hébergement et de contrôle des ressources. Lorsqu'il a terminé, il démarre le WebFarmService.Common.ps1 - Fournit des fonctions d'assistance pour le script OnStartSecondaryController.ps1.
Important
Ces scripts exigent que Windows Remote Management (WinRM) soit activé sur le contrôleur primaire.
Étapes d’exécution des scripts
Copiez les fichiers de script dans un dossier sur le serveur qui sera le contrôleur secondaire.
Copiez le fichier WebPlatformInstaller.msi dans le même dossier que les scripts. Cela est nécessaire car le script OnStartSecondaryController.cmd automatise l'installation de Web PI.
Exécutez OnStartSecondaryController.cmd avec des droits d'administrateur, en fournissant les paramètres indiqués dans le tableau ci-dessous. Des privilèges d'administrateur sont requis afin que les produits appropriés puissent être installés via l'automatisation Web PI et afin que le contrôleur primaire soit accessible via WinRM.
Notes
Dans un scénario WORKGROUP, vous devrez peut-être activer WinRM sur le contrôleur primaire, ou exécuter les commandes dans le script OnStartSecondaryController.cmd manuellement.
OnStartSecondaryController.cmd
Syntaxe
OnStartSecondaryController.cmd -feed %Feed% -webSitesInstanceName %WebSitesInstanceName% -sqlservername %DatabaseServerName% -sqlsysadmin %DatabaseSysAdminAccount% -sqlsysadminpwd %DatabaseSysAdminPassword% -controllerAdminUserName %ControllerAdminUserName% -controllerAdminPassword %ControllerAdminPassword%
Paramètres
Nom du paramètre | Description | Remarques |
feed |
Spécifie le flux Web PI qui sera utilisé pour installer le contrôleur (facultatif). | Si ce paramètre n'est pas spécifié, le flux principal Web PI par défaut est utilisé. |
webSitesInstanceName |
Utilisé comme préfixe pour les objets de base de données. | Doit correspondre au nom du préfixe de la base de données dans l'installation. |
sqlservername |
Nom de l'instance du serveur SQL | |
sqlsysadmin |
Nom du compte d'administrateur système SQL Server | Doit être membre des rôles de serveur sysadmin. |
sqlsysadminpwd |
Mot de passe du compte d'administrateur système SQL Server | |
controllerAdminUserName |
Nom du compte d'administrateur Web Farm Framework (WFF) à configurer | Si c'est un compte de domaine, il sera ajouté au groupe d'administrateurs local. Si le serveur est dans un groupe de travail, il tentera de créer l'utilisateur s'il n'existe pas, puis l'ajoutera au groupe d'administrateurs local. |
controllerAdminPassword |
Mot de passe du compte d'administrateur WFF à configurer |
OnStartSecondaryController.cmd Script
@echo off
echo Starting OnStartSecondaryController.cmd
rem ---------------------------------------------
rem Initialize Variables
rem ---------------------------------------------
set POWERSHELL=%windir%\System32\WindowsPowerShell\v1.0\powershell.exe
set FEED=
set INSTANCE_NAME=
set SQL_SERVERNAME=
set SQL_SYSADMIN=
set SQL_SYSADMINPWD=
set CONTROLLER_ADMIN_USERNAME=
set CONTROLLER_ADMIN_PASSWORD=
rem ---------------------------------------------
rem Parse command line parameters
rem ---------------------------------------------
:parse_param
set PARAM_MATCHED=0
if "%1"=="" (
goto :parse_param_completed
)
if /I "%1"=="-feed" (
set FEED=%2
shift
set PARAM_MATCHED=1
)
if /I "%1"=="-webSitesInstanceName" (
set INSTANCE_NAME=%2
shift
set PARAM_MATCHED=1
)
if /I "%1"=="-sqlservername" (
set SQL_SERVERNAME=%2
shift
set PARAM_MATCHED=1
)
if /I "%1"=="-sqlsysadmin" (
set SQL_SYSADMIN=%2
shift
set PARAM_MATCHED=1
)
if /I "%1"=="-sqlsysadminpwd" (
set SQL_SYSADMINPWD=%2
shift
set PARAM_MATCHED=1
)
if /I "%1"=="-controllerAdminUserName" (
set CONTROLLER_ADMIN_USERNAME=%2
shift
set PARAM_MATCHED=1
)
if /I "%1"=="-controllerAdminPassword" (
set CONTROLLER_ADMIN_PASSWORD=%2
shift
set PARAM_MATCHED=1
)
if "%PARAM_MATCHED%"=="0" (
echo Parameter %1 was not matched
exit 1
)
shift
goto :parse_param
:parse_param_completed
rem -----------------------------------------------------------------------
rem Provision Controller
rem ------------------------------------------------------------------------
echo Installing WebPlatformInstaller.
start /wait %windir%\system32\msiexec.exe /qn /i WebPlatformInstaller.msi /l %SystemDrive%\WebPlatformInstaller.log
if errorlevel 1 (
echo WebPlatform Installer installation failed. See log at %SystemDrive%\WebPlatformInstaller.log for more details.
exit 1
)
echo WebPlatformInstaller setup completed successfully.
echo Enabling remote desktop access.
start /wait cscript %windir%\system32\scregedit.wsf /ar 0
if errorlevel 1 (
echo Enabling remote desktop failed.
exit 1
)
echo Remote desktop access has been enabled successfully.
if exist StrongNameHijack.msi (
echo Installing StrongNameHijack...
start /wait %windir%\system32\msiexec.exe /qn /i StrongNameHijack.msi /l %SystemDrive%\StrongNameHijack.log
if errorlevel 1 (
echo "StrongNameHijack installation failed. See log at %SystemDrive%\StrongNameHijack.log for more details."
exit 1
)
echo StrongNameHijack setup completed successfully.
net stop msiserver & net start msiserver
)
echo Starting HostingBootstrapperBootstrapper.ps1
if "%FEED%"=="" (
%POWERSHELL% -ExecutionPolicy Unrestricted -File HostingBootstrapperBootstrapper.ps1
) else (
%POWERSHELL% -ExecutionPolicy Unrestricted -File HostingBootstrapperBootstrapper.ps1 -mainFeed "%FEED%"
)
if errorlevel 1 (
echo HostingBootstrapperBootstrapper.ps1 failed.
exit 1
)
echo HostingBootstrapperBootstrapper.ps1 completed successfully.
echo Starting OnStartSecondaryController.ps1
%POWERSHELL% -ExecutionPolicy Unrestricted -File OnStartSecondaryController.ps1 -webSitesInstanceName "%INSTANCE_NAME%" -sqlservername "%SQL_SERVERNAME%" -sqlsysadmin "%SQL_SYSADMIN%" -sqlsysadminpwd "%SQL_SYSADMINPWD%" -controllerAdminUserName "%CONTROLLER_ADMIN_USERNAME%" -controllerAdminPassword "%CONTROLLER_ADMIN_PASSWORD%"
if errorlevel 1 (
echo OnStartSecondaryController.ps1 failed.
exit 1
)
echo OnStartSecondaryController.ps1 completed successfully.
echo OnStartSecondaryController.cmd completed successfully.
exit 0
HostingBootstrapperBootstrapper.ps1
# PowerShell script to setup Web Sites Controller using WebPI.
# Copyright (c) Microsoft Corporation. All rights reserved.
Param
(
[string] $boostrapperProductId = "HostingPrimaryControllerBootstrapper_v2",
[string] $mainFeed = "",
[string] $customFeed = ""
)
# Change Error Action to Stop
$ErrorActionPreference="Stop"
Function BootstrapBootstrapper ()
{
$WebPiCmd = [System.Environment]::ExpandEnvironmentVariables("%ProgramW6432%\Microsoft\Web Platform Installer\WebpiCmd.exe")
$WebPiLog = [System.Environment]::ExpandEnvironmentVariables("%SystemDrive%\HostingPrimaryControllerBootstrapper.log")
If ($mainFeed -eq "")
{
Invoke-Command -ScriptBlock { & $WebPiCmd /Install /Products:$boostrapperProductId /AcceptEula /SuppressReboot /SuppressPostFinish /Log:$WebPiLog }
}
Else
{
If ($customFeed -eq "")
{
Invoke-Command -ScriptBlock { & $WebPiCmd /Install /Products:$boostrapperProductId /AcceptEula /SuppressReboot /SuppressPostFinish /XML:$mainFeed /Log:$WebPiLog }
}
Else
{
Invoke-Command -ScriptBlock { & $WebPiCmd /Install /Products:$boostrapperProductId /AcceptEula /SuppressReboot /SuppressPostFinish /XML:$mainFeed /Feeds:$customFeed /Log:$WebPiLog }
}
}
If ($lastexitcode -ne $Null -And $lastexitcode -ne 0)
{
Exit $lastexitcode
}
}
# Entry Point
BootstrapBootstrapper
OnStartSecondaryController.ps1
# PowerShell script to setup a Web Sites secondary controller.
# Copyright (c) Microsoft Corporation. All rights reserved.
Param
(
[string] $webSitesInstanceName,
[string] $sqlservername,
[string] $sqlsysadmin,
[string] $sqlsysadminpwd,
[string] $controllerAdminUserName,
[string] $controllerAdminPassword
)
# Init Global Variables
$cnstr = "server=$($sqlservername);database=Hosting;uid=$($sqlsysadmin);pwd=$($sqlsysadminpwd);"
# Load common script file
$startDir = "."
$common = [System.IO.Path]::Combine($startDir, "Common.ps1")
. $common
Function Get-PrimaryController()
{
Try
{
$siteManager = New-Object Microsoft.Web.Hosting.SiteManager $cnstr
$primaryController = $siteManager.Controllers.GetPrimaryController([Microsoft.Web.Hosting.PlatformOptions]::VirtualMachineManager)
Return $primaryController.MachineName;
}
Finally
{
If($siteManager -ne $Null)
{
$siteManager.Dispose()
}
}
}
Function Test-PrimaryController()
{
Try
{
$PrimaryController = Get-PrimaryController
Return $PrimaryController -ne $Null
}
Catch [Microsoft.Web.Hosting.WebHostingObjectNotFoundException]
{
Write-Host "$(Get-Date): Primary Controller NOT Ready"
Return $False;
}
}
Function WaitForPrimaryControllerToBeReady()
{
$WaitIndex=0;
$MaxWait=15
$WaitInterval=60000
Write-Host "$(Get-Date): Waiting for Primary Controller to be ready"
$valid = Test-PrimaryController
If ($valid -eq $False)
{
While ($WaitIndex -lt $MaxWait -and $valid -eq $False)
{
[System.Threading.Thread]::Sleep($WaitInterval);
$WaitIndex = $WaitIndex + 1
$valid = Test-PrimaryController
}
}
If ($valid -eq $False)
{
Throw New-Object [System.Exception] "Primary Controller NOT ready. Timed out waiting."
}
Write-Host "$(Get-Date): Primary Controller is Ready"
}
Function Copy-SystemCoreKeyFromPrimaryController([string] $PrimaryController)
{
Write-Host "$(Get-Date): Copy SystemCore key"
$remoteCommand = {
Add-PSSnapIn WebHostingSnapIn
Get-WebSitesConfig -Type SecurityKey -SymmetricKeyName SystemCore
}
$SystemCoreKey = Invoke-Command -ComputerName $PrimaryController -ScriptBlock $remoteCommand
Set-WebSitesConfig -Type SecurityKey -SymmetricKeyName SystemCore -SymmetricKey $SystemCoreKey -Force
}
Function Copy-SiteRuntimeKeyFromPrimaryController([string] $PrimaryController)
{
Write-Host "$(Get-Date): Copy SiteRuntime key"
$remoteCommand = {
Add-PSSnapIn WebHostingSnapIn
Get-WebSitesConfig -Type SecurityKey -SymmetricKeyName SiteRuntime
}
$SiteRuntimeKey = Invoke-Command -ComputerName $PrimaryController -ScriptBlock $remoteCommand
Set-WebSitesConfig -Type SecurityKey -SymmetricKeyName SiteRuntime -SymmetricKey $SiteRuntimeKey -Force
}
Function Copy-HostingConnectionStringFromPrimaryController([string] $PrimaryController)
{
Write-Host "$(Get-Date): Copy hosting connection string"
$remoteCommand = {
Add-PSSnapIn WebHostingSnapIn
[Microsoft.Web.Hosting.SiteManager]::GetDefaultConnectionString()
}
$HostingCnStr = Invoke-Command -ComputerName $PrimaryController -ScriptBlock $remoteCommand
Set-WebSitesConnectionString -Type Hosting -ConnectionString $HostingCnStr
}
Function Copy-MeteringConnectionStringFromPrimaryController([string] $PrimaryController)
{
Write-Host "$(Get-Date): Copy metering connection string"
$remoteCommand = {
Add-PSSnapIn WebHostingSnapIn
[Microsoft.Web.Hosting.SiteManager]::GetMeteringConnectionString()
}
$computerName = [Microsoft.Web.Hosting.Common.NetworkHelper]::GetComputerName([Microsoft.Web.Hosting.Common.ComputerNameFormat]::DnsFullyQualified)
$MeteringCnStr = Invoke-Command -ComputerName $PrimaryController -ScriptBlock $remoteCommand
Set-WebSitesConnectionString -Type Metering -ConnectionString $MeteringCnStr -ServerName $computerName
}
Function OnStartSecondaryController()
{
Try
{
Write-Host "$(Get-Date): Starting OnStartSecondaryController()" -ForegroundColor Green
Add-PSSnapin WebHostingSnapin
ConfigureRoleAdministrator $controllerAdminUserName $controllerAdminPassword
WaitForHostingDatabaseToBeReady $cnstr
WaitForPrimaryControllerToBeReady
$PrimaryController = Get-PrimaryController
Copy-SystemCoreKeyFromPrimaryController $PrimaryController
Copy-SiteRuntimeKeyFromPrimaryController $PrimaryController
Copy-HostingConnectionStringFromPrimaryController $PrimaryController
Copy-MeteringConnectionStringFromPrimaryController $PrimaryController
Start-Service WebFarmService
Write-Host "$(Get-Date): OnStartSecondaryController completed successfully" -ForegroundColor Green
}
Catch [System.Exception]
{
Write-Host "$(Get-Date): Exception encountered while executing OnStartSecondaryController:" -ForegroundColor Red
Write-Host $_ -ForegroundColor Red
Write-Host "$(Get-Date): Exiting OnStartSecondaryController.ps1" -ForegroundColor Red
Exit -1
}
}
# Entry Point
OnStartSecondaryController
Common.ps1
# PowerShell Web Sites common script.
# Copyright (c) Microsoft Corporation. All rights reserved.
Function LoadHostingFramework()
{
$mwhc = Get-Item ".\Microsoft.Web.Hosting.Common.dll"
[void] [System.Reflection.Assembly]::LoadFrom($mwhc.FullName)
Write-Host "$(Get-Date): Microsoft.Web.Hosting.Common assembly was successfully loaded from: $mwhc"
$mwh = Get-Item ".\Microsoft.Web.Hosting.dll"
[void] [System.Reflection.Assembly]::LoadFrom($mwh.FullName)
Write-Host "$(Get-Date): Microsoft.Web.Hosting assembly was successfully loaded from: $mwh"
}
Function IsHostingDatabaseReady([string] $cnstr)
{
Try
{
$siteManager = New-Object Microsoft.Web.Hosting.SiteManager $cnstr
$siteManager.TestConnection([Microsoft.Web.Hosting.PlatformOptions]::VirtualMachineManager)
Return $true;
}
Catch [Exception]
{
Write-Host "$(Get-Date): Hosting Database NOT Ready"
Return $false;
}
Finally
{
If($siteManager -ne $Null)
{
$siteManager.Dispose()
}
}
}
Function WaitForHostingDatabaseToBeReady ([string] $cnstr)
{
$WaitIndex=0;
$MaxWait=120
$WaitInterval=60000
Write-Host "$(Get-Date): Waiting for Hosting Database to be ready"
$ready = IsHostingDatabaseReady $cnstr
If($ready -ne $true)
{
While ($WaitIndex -lt $MaxWait -and $ready -ne $true)
{
[System.Threading.Thread]::Sleep($WaitInterval);
$WaitIndex = $WaitIndex + 1
$ready = IsHostingDatabaseReady $cnstr
}
}
If ($ready -ne $true)
{
Throw New-Object [System.Exception] "Hosting Database NOT ready. Timed out waiting."
}
Write-Host "$(Get-Date): Hosting Database is Ready"
}
Function ConfigureRoleAdministrator([string] $roleadminusr, [string] $roleadminpwd)
{
$isDomain = $false
# Identify if user is a domain user account
$values = $roleadminusr.Split('\');
If ($values.Length -eq 1)
{
$domain = $env:COMPUTERNAME
$username = $values[0]
}
ElseIf ($values.Length -eq 2)
{
If ([String]::Equals($values[0], ".") -Or
[String]::Equals($values[0], [Environment]::MachineName, [StringComparison]::OrdinalIgnoreCase))
{
$isDomain = $false
$domain = $env:COMPUTERNAME
$username = $values[1]
}
Else
{
$isDomain = $true
$domain = $values[0]
$username = $values[1]
}
}
Else
{
Throw New-Object ArgumentException "Invalid user name" "roleadminusr"
}
# Create user if specified user is not a domain account
if ($isDomain -eq $false)
{
Try
{
$computer = [ADSI]"WinNT://$env:COMPUTERNAME"
$user = $computer.Create("User", $username)
$user.setpassword($roleadminpwd)
$user.SetInfo()
}
Catch [System.Runtime.InteropServices.COMException]
{
# User already exists
If ($_.Exception.ErrorCode -eq -2147022672)
{
Write-Host "$(Get-Date): User $domain\$username already exits."
Write-Host "$(Get-Date): Updating password for User $domain\$username."
$user = [ADSI]("WinNT://$env:COMPUTERNAME/$username,user")
$user.setpassword($roleadminpwd)
$user.SetInfo()
}
Else
{
Write-Host "$(Get-Date): Error creating user $domain\$username." -ForegroundColor Red
Throw
}
}
}
# Add user to local administrators group
#first translate the "Administrators" name to the name based on locale (make well known SID -> Name translation)
$administratorsSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544")
$administratorsGroupName = $administratorsSID.Translate([System.Security.Principal.NTAccount]).Value
# retrieve the short name eg in german translate VORDEFINIERT\Administratoren ->Administratoren
# the translation should always return fully qualified name equivalent to BUILTIN\Administrators
$localizedAdministratorsGroupName=$administratorsGroupName.Split("\\")[1]
$adminGroup = [ADSI]("WinNT://$env:COMPUTERNAME/$localizedAdministratorsGroupName,group")
Try
{
If ($isDomain -eq $true)
{
$adminGroup.add("WinNT://$domain/$username,user")
}
Else
{
$adminGroup.add("WinNT://$env:COMPUTERNAME/$username,user")
}
}
Catch [System.Runtime.InteropServices.COMException]
{
If ($_.Exception.ErrorCode -eq -2147023518) # ERROR_MEMBER_IN_ALIAS 1378 (0x562)
{
Write-Host "$(Get-Date): User $domain\$username is already member of Administrators group."
}
Else
{
Write-Host "$(Get-Date): Error adding user $domain\$username to Administrators group." -ForegroundColor Red
Throw
}
}
}