SQL 2008 R2 cluster via command line

Ik ben momenteel bezig bij een klant om het mogelijk te maken een SharePoint farm inclusief SQL server volledig unattended te deployen.
Deze post laat een voorbeeld zien, hoe een SQL Server 2008 R2 cluster met de database engine via command line te installeren.

Er zijn uiteraard meerdere wegen naar Rome, en daarnaast vele zaken waar je bij productiesystemen rekening mee moet houden. Zaken die ik niet beschrijf om deze post kort en bondig te houden. Deze post is puur bedoeld als voorbeeld, waar vanuit verder gewerkt kan worden.

Meer informatie over SQL clustering is te vinden op: http://msdn.microsoft.com/en-us/library/ms189134.aspx

Voorbereiden cluster

Een SQL server cluster maakt gebruik van de Windows Server clustering features, en voordat je een SQL cluster kunt installeren, moet er een Windows Cluster zijn met de volgende eigenschappen:

  • Een of meerdere Windows Server failover cluster nodes
  • Een cluster resource group met:
    • Network name
    • IP addresses
    • Shared disks voor SQL Server data en logs

Verder hebben we het volgende nodig:

  • Vier static IPs (twee voor de nodes, twee voor het cluster).
  • Een DNS A record voor het cluster.
  • Twee domain accounts voor de SQL Server en SQL Agent services.
  • Een setup account met local administrator rechten op beide nodes, de userrights SeBackupPrivilege, SeDebugPrivilege en SeSecurityPrivilege (http://support.microsoft.com/default.aspx?scid=kb;en-US;2000257 )

Ik ga er vanuit dat je weet hoe je twee servers installeert, en IP adressen, domain accounts en DNS records regelt.
Zodra je dit alles hebt geregeld, maken we van beide Windows servers een cluster d.m.v. Powershell, gebruik makend van het setup account.

Eerst installeren we de cluster features en –tools op beide servers:

Import-Module ServerManager
Add-WindowsFeature Failover-Clustering,RSAT-Clustering

Vervolgens testen we of de systemen gereed zijn om een cluster te vormen:

Import-Module FailoverClusters
Test-Cluster server1,server2

In mijn geval kan ik wel een cluster vormen, maar heb ik warnings gekregen op bepaalde tests rondom disk en netwerk,
wat klopt, want ik had nog geen Shared storage toegevoegd en heb slechts een enkele NIC (wat dus een single point of failure is voor de nodes).
Voor meer informatie kan je kijken in het report, waar erg veel waardevolle informatie in staat rondom de tests en uitkomsten.

Nu kan ik het cluster gaan vormen, maar om een disk resource te kunnen maken in een clustergroup moet ik natuurlijk wel een disk hebben.
Lees mijn blogpost @ voor een voorbeeld iSCSI implementatie.

Om het cluster te maken voeren we de volgende commando's uit:

Import-Module FailoverClusters
New-Cluster –Name ClusterNaam1 -Node server1,server2 –StaticAddress x.x.x.x [-IgnoreNetwork x.x.x.x/xx] –NoStorage
$q = Get-ClusterAvailableDisk | Sort Size | Select -First 1
Get-ClusterAvailableDisk | Add-ClusterDisk
Set-ClusterQuorum -NodeAndDiskMajority $q.name

New-Cluster zal standaard proberen alle Shared Volumes meteen toe te voegen als cluster resource, en daarnaast voor elk beschikbaar netwerk een IP vragen om als resource op te voeren. Via –NoStorage kun je de disks later toevoegen, en via –IgnoreNetwork, kunt je netwerken negeren. Voor elke netwerk wat niet is opgenomen in de ignore list, moet je een shared IP opgeven in –StaticAddress.

Om een Node en Disk majority Quorum te kunnen maken, sorteer ik alle beschikbare disken op grootte en gebruik de kleinste voor het Quorum (volgens de boeken is 512MB genoeg, dus zo groot maak ik mijn Quorum disk, waardoor deze altijd de kleinste is [waarvoor zou je anders een kleine shared disk gebruiken??]).

Het cluster is nu gereed voor de SQL installatie.

Installatie SQL Server

SQL Server heeft .NET 3.5 SP1 nodig, dus voordat we de setup draaien voegen we eerste de juiste Windows Feature toe:

    Import-Module ServerManager
    Add-WindowsFeature AS-NET-Framework

Om de SQL clustergroup te maken draaien we vervolgens de setup van het SQL installatie medium met de juiste parameters (ik heb een voorkeur voor het gebruik van een config file).

We maken op een textbestand aan met de volgende inhoud:

[SQLSERVER2008]
QUIET="True"
ACTION="InstallFailoverCluster"
FEATURES="SQLENGINE,SSMS,ADV_SSMS"
INSTANCENAME="SharePoint"
INSTANCEID="SharePoint"
INSTANCEDIR="C:\Program Files\Microsoft SQL Server"
INSTALLSHAREDWOWDIR="C:\Program Files (x86)\Microsoft SQL Server"
INSTALLSHAREDDIR="C:\Program Files\Microsoft SQL Server"
SQLSVCACCOUNT="HOME\sa.SqlSvc"
AGTSVCACCOUNT="HOME\sa.SqlAgent"
SQLSVCPASSWORD="P@ssw0rd!"
AGTSVCPASSWORD="P@ssw0rd!"
INSTALLSQLDATADIR= "X:\SQLData"
SQLCOLLATION="Latin1_General_CI_AS_KS_WS"
FAILOVERCLUSTERGROUP="SQL Cluster Group"

FAILOVERCLUSTERDISKS="Cluster Disk 1"
FAILOVERCLUSTERIPADDRESSES="IPv4;192.168.1.46;Cluster Network 1;255.255.255.0"
FAILOVERCLUSTERNETWORKNAME="CLUSTERNAAM2"

SQLSYSADMINACCOUNTS="DOMEIN\USER"

In een nutshell vertel ik setup een installatie moet doen met alleen de database engine, management tools (advanced), de services onder bepaalde domain accounts moeten draaien, en het een cluster moet vormen. De parameters betekenen in het kort:

INSTANCENAME

Naam van de SQL instance

INSTANCEID

Instance ID wat gebruikt wordt in namen van folders en configuratie

INSTANCEDIR

De configuratiedirectory van de instance

INSTALLSHAREDWOWDIR

De installatiedirectory for 32 bit componenten

INSTALLSHAREDDIR

De installatiedirectory for 64 bit componenten

SQLSVCACCOUNT

SQL Server Service account

AGTSVCACCOUNT

SQL Agent Service account

SQLSVCPASSWORD

Password voor SQL Server Service account

AGTSVCPASSWORD

Password voor SQL Agent Service account

INSTALLSQLDATADIR

De default directory voor de database data

SQLCOLLATION

De default collation

FAILOVERCLUSTERGROUP

De naam van de clustergroup die SQL aanmaakt

FAILOVERCLUSTERDISKS

De shared disks die toegevoegd worden aan de cluster group

FAILOVERCLUSTERIPADDRESSES

Een nieuw shared IP adres en een verwijzing naar een bestaand cluster netwerk resource

FAILOVERCLUSTERNETWORKNAME

De clusternaam die SQL gaat gebruiken

SQLSYSADMINACCOUNTS

Accounts die toegevoegd dienen te worden aan sysadmin

Voor meer informatie over de beschikbare parameters zie: http://msdn.microsoft.com/en-us/library/ms144259.aspx

Ik heb hier gewoon wat waarden ingezet, maar wil je volledige automatisch deployed, zul je je config file moeten genereren, en wat logica in je scripts moeten bakken, zodat bijvoorbeeld de FAILOVERCLUSTERDISKS en FAILOVERCLUSTERIPADDRESSES, automatisch gevuld wordt met de juiste disks en NICS.
Mijn gotcha's waren:

  • Dat de parameter FAILOVERCLUSTERGROUP een unieke naam moet hebben. Bij het configureren van het initiële cluster zijn de namen "Cluster Group" en "Available Storage" al geclaimd.
  • De FAILOVERCLUSTERNETWORKNAME een bestaande WINS of DNS naam moet zijn, en verwijzen naar het een ander nieuw IP adres, en een andere naam zijn dan diegene die je gebruikt hebt bij het initieel aanmaken van het Windows Cluster. Je gebruikt dus in totaal 4 IP adressen (2 private voor de nodes, en 2 cluster adressen).

Op de eerste node draaien we dan vervolgens:

    ./Setup.exe /configurationfile=padnaarconfigfile.ini /IndicateProgress /IAcceptSQLServerLicenseTerms

De SQLSetup.log file is te vinden onder %temp%, maar persoonlijk had ik meer aan de logs onder padnaarsqlinstalldir \100\Setup Bootstrap\xxxxxxxx_xxxxxx\*.log.

Zodra de SQL installatie succesvol is afgerond, maak je op de andere Node ook een configuratiebestand aan. Ik gebruik hier als voorbeeld:

[SQLSERVER2008]
QUIET="True"
ACTION="AddNode"
INSTANCENAME="SharePoint"
SQLSVCACCOUNT="HOME\sa.SqlSvc"
AGTSVCACCOUNT="HOME\sa.SqlAgent"
SQLSVCPASSWORD="P@ssw0rd!"
AGTSVCPASSWORD="P@ssw0rd!"

Voor meer informatie over de beschikbare parameters zie: http://msdn.microsoft.com/en-us/library/ms144259.aspx

Op deze node draaien we vervolgens wederom:

    ./Setup.exe /configurationfile=padnaarconfigfile.ini /IndicateProgress /IAcceptSQLServerLicenseTerms

Voila, het cluster is gereed. Wat nu rest is ervoor zorgen dat het A-record voor de clusternaam gewijzigd mag worden door het computer account wat voor het cluster is aangemaakt in AD. Als DNS AD integrated is, geef je het cluster computer account (dus niet de afzonderlijke nodes) via de DNS Server mmc snap-in FULL CONTROL op het A-record.

Appendix

Aangezien ik in deze post alleen een installatie van de database engine behandel, hebben we geen Distributed Transaction Coordinator nodig. Ik kwam bij mijn zoektocht naar informatie echter een script tegen op http://www.sqlha.com/2009/09/02/creating-a-clustered-distributed-transaction-coordinator-msdtcdtc-using-powershell-method-1/ waarvan ik dacht COPY PASTE… Voor het geval ik of jij het ooit nodig heeft. Ik heb het niet getest, dus garantie tot de virtuele deur…

$clunm = "Windows failover cluster name"

$dtcdisknm = "Name of the disk resource to use with DTC"

$dtcdnsnm = "Name for DTC in DNS"

$dtcgrpnm = "Name of the DTC resource group"

$dtcipaddr = "IP address for DTC"

$dtcsubnet = "Subnet mask for DTC"

$dtcipresnm = "Name of the DTC IP address resource"

$dtcnetnm = "Name of the DTC network name resource"

$dtcresnm = "Name of the DTC resource name"

 

Add-ClusterGroup $dtcgrpnm -Cluster $clunm

Add-ClusterResource $dtcipresnm -ResourceType "IP Address" -Cluster $clunm -Group $dtcgrpnm

$ipres = Get-ClusterResource $dtcipresnm

$ipaddr = New-Object Microsoft.FailoverClusters.PowerShell.ClusterParameter $ipres,Address,$dtcipaddr

$subnet = New-Object Microsoft.FailoverClusters.PowerShell.ClusterParameter $ipres,Address,$dtcsubnet

$setparams = $ipaddr,$subnet

$setparams | Set-ClusterParameter

Add-ClusterResource $dtcnetnm -ResourceType "Network name" -Cluster $clunm -Group $dtcgrpnm

$nnres = Get-ClusterResource $dtcnetnm

$netnm = New-Object Microsoft.FailoverClusters.PowerShell.ClusterParameter $nnres,Address,$dtcdnsnm

$netnm | Set-ClusterParameter

Add-ClusterResourceDependency $dtcnetnm $dtcipresnm -Cluster $clunm

Add-ClusterResource $dtcresnm -ResourceType "Distributed Transaction Coordinator" -Cluster $clunm -Group $dtcgrpnm

Add-ClusterResourceDependency $dtcresnm $dtcnetnm -Cluster $clunm

Move-ClusterResource $dtcdisknm -Cluster $clunm -Group $dtcgrpnm

Add-ClusterResourceDependency $dtcresnm $dtcdisknm -Cluster $clunm