Extending AlwaysOn AG to Cross Region Azure DC

advertisement
Extending AlwaysOn Availability Group to Remote Azure
Datacenter (PowerShell)
If you are looking for multi region continuous availability, by extending your current availability group to a remote Azure
datacenter, then this blog is for you. We start with an existing availability group already setup within Azure, walk you
through setting up VPN connectivity by taking advantage of the Azure-to-Azure VPN functionality, extend your
infrastructure and setup your asynchronous replica. At the end of this blog, your SQL Server AlwaysOn Availability Group
in Azure will consist of the following elements:




2 virtual networks with VPN connectivity between West US and East US, as an example.
A domain controller on each site with Active Directory (AD) and Domain Name Services (DNS).
2 synchronous replicas in WestUS and an asynchronous replica in EastUS. Synchronous was chosen for the
WestUS replicas since they are within the same region and asynchronous for the EastUS replica since it is cross
region.
An extended availability group with an asynchronous commit replica of an availability database.
Below are a couple diagrams showing you what your environment should look like before you start (Figure 1) and what
it will look like when you are finished (Figure 2).
Figure 1: Initial State
Figure 2: Final State
Prerequisites:



An Azure subscription (http://azure.microsoft.com/en-us/pricing/free-trial/)
Azure PowerShell configured (http://azure.microsoft.com/en-us/documentation/articles/install-configurepowershell/)
A SQL Server AlwaysOn Availability Group setup in Azure on your primary site (Pictured in Figure 1)
(http://msdn.microsoft.com/en-us/library/jj870963.aspx)
The following steps will be covered to extend your existing SQL Server AlwaysOn
Availability Group:
1. Connect to your Azure subscription, create a virtual network in your EastUS site and establish a VPN connection
between the two sites.
2. Create a storage account and create your secondary domain controller that you will use to extend your WestUS
cloud IT infrastructure to EastUS.
3. Create your SQL Server on the EastUS site.
4. Add the probe port and SQL endpoints to your new SQL VM.
5. Add EastSQL-01 to the availability group.
Connect to your Azure subscription, create a virtual network in your EastUS site
and establish a VPN connection between the two sites.
Azure-to-Azure VPN tutorial: http://msdn.microsoft.com/en-us/library/azure/dn690122.aspx
Note:
When setting up your EastUS network, be sure to specify the WestUS DNS first under the EastUS
configuration. If you don’t, you may have troubles promoting your EastUS DC.
For our scenario, we used the following IP range and endpoint configuration:
West Coast (10.3.0.0/16)
DNS: 10.3.0.12, 172.16.0.12
Name
IP
Endpoints
WestDC-01
10.3.0.12
WestSQL-01
10.3.0.13
Probe Port (DSR): 59999
SQL Server (DSR): 1433
WestSQL-02
10.3.0.14
Probe Port (DSR): 59999
SQL Server (DSR): 1433
Name
EastDC-01
EastSQL-01
East Coast (172.16.0.0/16)
DNS: 10.3.0.12, 172.16.0.12
IP
Endpoints
172.16.0.12
172.16.0.13
Probe Port (DSR): 59999
SQL Server (DSR): 1433
Create a storage account and create your secondary domain controller that you
will use to extend your WestUS cloud IT infrastructure to EastUS.
1. From an elevated PowerShell window on your local machine, define the following global variables.
$affinityGroupName = "EastAG"
$affinityGroupDescription = "East SQL HADR Affinity Group"
$affinityGroupLabel = "IaaS Affinity Group"
$virtualNetworkName = "CloudContosoEastNet"
$storageAccountName = "<uniquestorageaccountname>" #The name of a new storage
account that will get created in EastUS for step 2.
$storageAccountLabel = "Contoso East HADR Storage Account"
$storageAccountContainer = "https://" + $storageAccountName +
".blob.core.windows.net/vhds/"
$availabilitySetName = "SQLHADR"
$vmAdminUser = “azureuser”
$vmAdminPassword = "Contoso!000"
$domainName = "cloudcontoso"
$FQDN = "cloudcontoso.local"
$subscriptionName = "<your azure subscription name>"
2. Create a new storage account in EastUS and set your default subscription and storage account.
New-AzureStorageAccount `
-StorageAccountName $storageAccountName `
-Label $storageAccountLabel `
-AffinityGroup $affinityGroupName
#select Azure subscription
select-azuresubscription $subscriptionName
#default storage account
Set-AzureSubscription $subscriptionName -CurrentStorageAccountName
$storageAccountName
3. Provisioning the DC (Domain Controller) VM (EastDC-01).
#EastDC-01 variables
$dcServerName = "EastDC-01" #The name of your EastUS domain controller
$dcServiceName = "EastDC"
$winImageName = (Get-AzureVMImage | where {$_.Label -like "Windows Server 2012 R2
Datacenter*"} `
| sort PublishedDate -Descending)[0].ImageName #This is the image that will get
used for your domain controller VM
#EastDC-01 creating the VM
New-AzureVMConfig `
-Name $dcServerName `
-InstanceSize Medium `
-ImageName $winImageName `
-MediaLocation "$storageAccountContainer$dcServerName.vhd" `
-DiskLabel "OS" -Verbose |
Add-AzureProvisioningConfig `
-Windows `
-DisableAutomaticUpdates `
-AdminUserName $vmAdminUser `
-Password $vmAdminPassword -Verbose |
New-AzureVM `
-ServiceName $dcServiceName `
-AffinityGroup $affinityGroupName `
-VNetName $virtualNetworkName –Verbose
4. Setup your EastUS site in Active Directory Sites and Services by logging on to your DC in the WestUS site
(WestDC-01) and running the following script from an elevated PowerShell window.
$secondarySiteName = "EastCoast" #This is the name of your secondary site used in
AD sites and services
$secondarySiteSubnet = "172.16.0.0/16" #Secondary site subnet
#Create site “EastCoast” in AD sites and services
New-ADReplicationSite -Name $secondarySiteName
New-ADReplicationSubnet -Name $secondarySiteSubnet -Site
$secondarySiteName -Location $secondarySiteName
5. Logoff WestDC-01.
6. Now we will be configuring your EastUS DC. Login to EastDC-01 as the local user account, once it is done being
provisioned and from an elevated PowerShell window, run the following script to install Active Domain Services
and tools and add a tree to your current forest.
#EastDC-01 DC variables
$secondarySiteName = "EastCoast" #This is the name of your secondary site in AD
Sites and Services
$domainAdminUserName = "cloudcontoso\domainuser" #A domain account that has
permissions to promote a VM to a DC
$domainAdminPassword = "Contoso!000"
$domainSafeModePassword = "Contoso!000" #Safe mode / recovery password
$domainName = “cloudcontoso.local” #Name of the existing domain on the WestUS site
#Install Active Directory Domain Services and Tools
Add-WindowsFeature AD-Domain-Services, `
RSAT-AD-Tools, `
RSAT-ADDS, `
RSAT-ADDS-Tools, `
RSAT-AD-AdminCenter, `
RSAT-AD-PowerShell
#Convert password string to secure password
$secDomainSafeModePassword = ConvertTo-SecureString $domainSafeModePassword AsPlainText -Force
$secDomainAdminPassword = ConvertTo-SecureString $domainAdminPassword -AsPlainText
-Force
$secDomainCreds = New-Object System.Management.Automation.PSCredential
($domainAdminUserName, $secDomainAdminPassword)
#Promotes the VM to a DC and adds EastDC-01 to the EastCoast site in active
directory sites and services
Install-ADDSDomainController -DomainName $domainName -Credential $secDomainCreds –
InstallDns `
-SiteName $secondarySiteName -SafeModeAdministratorPassword
$secDomainSafeModePassword
7. Let EastDC-01 reboot.
Create your SQL Server on the EastUS site.
1. Provision the SQL Server VM (EastSQL-01).
Note:
The VHD and disks for this SQL server will reside in EastUS
#EastSQL-01 variables
$sqlServerName = "EastSQL-01"
$sqlImageName = (Get-AzureVMImage | where {$_.Label -like "SQL Server 2014 RTM
Enterprise*"} `
| sort PublishedDate -Descending)[0].ImageName
$sqlServiceName = "EastSQL"
$domainUser = "domainuser" #User with permissions to join a machine to a domain (do
not include <domain>\<username, just use <domain username>
$domainPassword = "Contoso!000"
#EastSQL-01 creating the VM
New-AzureVMConfig `
-Name $sqlServerName `
-InstanceSize Large `
-ImageName $sqlImageName `
-MediaLocation "$storageAccountContainer$sql1ServerName.vhd" `
-AvailabilitySetName $availabilitySetName `
-HostCaching "ReadOnly" `
-DiskLabel "OS" |
Add-AzureProvisioningConfig `
-WindowsDomain `
-AdminUserName $vmAdminUser `
-Password $vmAdminPassword `
-DisableAutomaticUpdates `
-Domain $domainName `
-JoinDomain $FQDN `
-DomainUserName $domainUser `
-DomainPassword $domainPassword |
New-AzureVM `
-ServiceName $sqlServiceName `
-AffinityGroup $affinityGroupName `
-VNetName $virtualNetworkName –Verbose
2. Once EastSQL-01 is finished provisioning, login with the local administrator account.
3. Setup your directory structure to match that of your SQL servers on the primary site.
Note:
When configuring your SQL Server, be sure you mirror the same data structure of that on your primary
site. Make sure you provision the appropriate disks. i.e. If you use e:\SQLData and f:\SQLLog, make sure
these drives and directories exist on the new VM
4. Install Windows Failover Clustering.
Import-Module ServerManager
Add-WindowsFeature Failover-Clustering, RSAT-Clustering-Mgmt, RSAT-ClusteringPowerShell, RSAT-Clustering-CmdInterface
5. Open SQL Server Management Studio and add any necessary accounts needed to perform SQL administrative
tasks.
6.
Open firewall ports for SQL, AlwaysOn listener and probe port.
#Ports and port name Variables
$sqlServerPort = "1433" #SQL Server port
$sqlServerPortName = "SQL Server" #SQL Server port name/description
$alwaysOnListenerPort = "5022" #AlwaysOn listener port
$alwaysOnListenerPortName = "AlwaysOn Listener" #AlwaysOn listener port
name/description
$csProbePort = "59999" #Cloud Service probe port
$csProbePortName = "Cloud Service Probe Port" #Cloud Service probe port name
/description
#SQL Server
$port = New-Object -ComObject HNetCfg.FWOpenPort
$port.Port = $sqlServerPort
$port.Name = $sqlServerPortName
$port.Enabled = $true
$fwMgr = New-Object -ComObject HNetCfg.FwMgr
$profile = $fwMgr.LocalPolicy.CurrentProfile
$profile.GloballyOpenPorts.Add($port)
#Cloud Service Probe Port
$port = New-Object -ComObject HNetCfg.FWOpenPort
$port.Port = $csProbePort
$port.Name = $csProbePortName
$port.Enabled = $true
$fwMgr = New-Object -ComObject HNetCfg.FwMgr
$profile = $fwMgr.LocalPolicy.CurrentProfile
$profile.GloballyOpenPorts.Add($port)
#AlwaysOn Listener
$port = New-Object -ComObject HNetCfg.FWOpenPort
$port.Port = $alwaysOnListenerPort
$port.Name = $alwaysOnListenerPortName
$port.Enabled = $true
$fwMgr = New-Object -ComObject HNetCfg.FwMgr
$profile = $fwMgr.LocalPolicy.CurrentProfile
$profile.GloballyOpenPorts.Add($port)
7. Logoff.
Add the probe port and SQL endpoints to your new SQL VM
1. From your local machine, run the following PowerShell scripts to create your probe port endpoint and SQL
Server endpoint.
Note:
Make sure your probe port and SQL ports match that of your primary site ports. i.e. if you use 1433 for
SQL on WestUS, make sure you use 1433 on your EastUS site.
# Define variables
$agNode = "EastSQL-01" # all availability group nodes should be included,
separated by commas
$serviceName = "EastSQL" # the name of the cloud service that contains the
availability group nodes
$probeEndpointName = "probePortEP" # name of the endpoint
$probeEndpointPort = "59999" # public port to use for the endpoint
$sqlEndpointName = "SQLServerEP" # name of the endpoint
$sqlEndpointPort = "1433" # public port to use for the endpoint
# Configure a load balanced endpoint for each node in $AGNodes, with direct
server return enabled
Get-AzureVM -ServiceName $ServiceName -Name $AGNode | Add-AzureEndpoint -Name
$probeEndpointName -Protocol "TCP" -PublicPort $probeEndpointPort -LocalPort
$probeEndpointPort -LBSetName "$probeEndpointName-LB" -ProbePort 59999 ProbeProtocol "TCP" -DirectServerReturn $true | Update-AzureVM
Get-AzureVM -ServiceName $ServiceName -Name $AGNode | Add-AzureEndpoint -Name
$sqlEndpointName -Protocol "TCP" -PublicPort $sqlEndpointPort -LocalPort
$sqlEndpointPort -LBSetName "$sqlEndpointName-LB" -ProbePort 59999 ProbeProtocol "TCP" -DirectServerReturn $true | Update-AzureVM
Add EastSQL-01 to the availability group
Note:
You will be running the following PowerShell scripts in this section from your primary node (WestSQL01) on the WestUS site.
1. Login to your WestSQL-01 on your WestUS site.
2. Define the following variables from an elevated PowerShell window.
$server1 = "EastSQL-01"
$server2 = "WestBackup-01"
$acct1 = "cloudcontoso\sqlservice"
$password = "Contoso!000"
$primaryNodeName = "WestSQL-01"
$timeout = New-Object System.TimeSpan -ArgumentList 0, 0, 30
$db = "AdventureWorks"
$backupShare = "\\$server2\backup"
$ag = "AWAG"
$FQDN = "cloudcontoso.local"
$agPath = "SQLSERVER:\Sql\$primaryNodeName\InstanceName\AvailabilityGroups\$ag"
$endpointURL = "TCP://$primaryNodeName.$FQDN:5022"
$failoverMode = "Manual"
$availabilityMode = "AsynchronousCommit"
$secondaryReadMode = "AllowAllConnections"
3. Add EastSQL-01 to the cluster.
get-cluster $primaryNodeName | Add-ClusterNode $server1
4. From an elevated PowerShell window, add the new cloud service IP to your current client access point and
configure the dependencies. This step needs to be done before you are able to add EastSQL-01 to your
availability group.
Note:
For the next step, please see Appendices to find out the following:
Appendix A: Determining the name of your second network ($clusterNetworkName)
Appendix B: Determining the name of an IP Resource ($ipResourceName1)
Appendix C: Determining the name of your client access point ($capName)
# Define variables
$clusterNetworkName = "NetworkName" #This is the network name of your second
network
$cloudServiceIP = "<CloudServiceIP>" #IP address of your east SQL cloud service
$ipResourceName1 = "<IpRresourceName >" #the IP Address resource name of your
current cloud service
$ipResourceName2 = "IP Address $CloudServiceIP" #No need to edit
$ag = "<NameOfAg>"
$capName = "<NameOfClientAccessPoint>" #Client access point name
Import-Module FailoverClusters
Add-ClusterResource -Name $IPResourceName2 -ResourceType "IP Address" -Group $ag
Get-ClusterResource $IPResourceName2 | Set-ClusterParameter -Multiple
@{"Address"="$CloudServiceIP";"ProbePort"="59999";SubnetMask="255.255.255.255";"
Network"="$ClusterNetworkName";"OverrideAddressMatch"=1;"EnableDhcp"=0}
Set-ClusterResourceDependency -Resource $capName -Dependency "[$IPResourceName1]
or [$IPResourceName2]"
5. Import the SQL Server PowerShell Provider.
Set-ExecutionPolicy RemoteSigned -Force
Import-Module "sqlps" -DisableNameChecking
6. Change the SQL Server service account on EastSQL-01.
$wmi1 = new-object ("Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer")
$server1
$wmi1.services | where {$_.Type -eq 'SqlServer'} |
foreach{$_.SetServiceAccount($acct1,$password)}
$svc1 = Get-Service -ComputerName $server1 -Name 'MSSQLSERVER'
$svc1.Stop()
$svc1.WaitForStatus([System.ServiceProcess.ServiceControllerStatus]::Stopped,$ti
meout)
$svc1.Start();
$svc1.WaitForStatus([System.ServiceProcess.ServiceControllerStatus]::Running,$ti
meout)
7. Enable AlwaysOn on EastSQL-01.
$svc2 = Get-Service -ComputerName $server1 -Name 'MSSQLSERVER'
$timeout = New-Object System.TimeSpan -ArgumentList 0, 0, 30
Enable-SqlAlwaysOn `
-Path SQLSERVER:\SQL\$server1\Default `
-Force
$svc2.Stop()
$svc2.WaitForStatus([System.ServiceProcess.ServiceControllerStatus]::Stopped,$ti
meout)
$svc2.Start();
$svc2.WaitForStatus([System.ServiceProcess.ServiceControllerStatus]::Running,$ti
meout)
8. Take a full database and a log backup and restore to EastSQL-01 WITH NO RECOVERY option.
Backup-SqlDatabase -Database $db -BackupFile "$backupShare\db.bak" ServerInstance $primaryNodeName
Backup-SqlDatabase -Database $db -BackupFile "$backupShare\db.log" ServerInstance $primaryNodeName -BackupAction Log
Restore-SqlDatabase -Database $db -BackupFile "$backupShare\db.bak" ServerInstance $server1 -NoRecovery
Restore-SqlDatabase -Database $db -BackupFile "$backupShare\db.log" ServerInstance $server1 -RestoreAction Log -NoRecovery
9. Create an endpoint for EastSQL-01.
$endpoint =
New-SqlHadrEndpoint MyMirroringEndpoint `
-Port 5022 `
-Path "SQLSERVER:\SQL\$server1\Default"
Set-SqlHadrEndpoint `
-InputObject $endpoint `
-State "Started"
10. Add EastSQL-01 to the availability group and join the secondary database to the availability group.
New-SqlAvailabilityReplica `
-Name $server1 `
-EndpointURL "TCP://$server1.cloudcontoso.local:5022" `
-AvailabilityMode "AsynchronousCommit" `
-FailoverMode "Manual" `
-ConnectionModeInSecondaryRole AllowAllConnections `
-Path "SQLSERVER:\Sql\$primaryNodeName\Default\AvailabilityGroups\$ag"
Join-SqlAvailabilityGroup -Path SQLSERVER:\SQL\$server1\DEFAULT -Name $ag
Add-SqlAvailabilityDatabase `
-Path "SQLSERVER:\Sql\$server1\Default\AvailabilityGroups\$ag" `
-Database $db
11. Verify that EastSQL-01 is in the “Synchronizing” state.
$SqlServer = New-Object Microsoft.SqlServer.Management.Smo.Server($primaryNodeName)
Do
{
$syncState = ( $SqlServer.AvailabilityGroups[$ag].DatabaseReplicaStates | where
{$_.AvailabilityReplicaServerName -EQ $server1 } | select {$_.SynchronizationState} )
$SqlServer.AvailabilityGroups["partestag"].DatabaseReplicaStates |
Select-Object
AvailabilityReplicaServerName,AvailabilityDatabaseName,SynchronizationState
Start-Sleep -Seconds 5
}
While ( $syncState.'$_.SynchronizationState' -ne "Synchronizing" )
Appendices:
Appendix A: Determining the name of your second network
- Open Windows Server Failover Clustering.
- Connect to your cluster.
- Expand Networks and the one that matches your second subnet will be the name you are looking for i.e. “Cluster
Network 2”.
Appendix B: Determining the name of an IP Resource
- Open Windows Server Failover Clustering.
- Connect to your cluster.
- Expand Roles, click resources at the bottom of the page and double click “IP Address: *.*.*.*” and the name will
be the first field in the properties window. Be sure to verify that the network matches the network of your
primary site.
Appendix C: Determining the name of your client access point
- Open Windows Server Failover Clustering.
- Connect to your cluster.
- Expand Roles and click resources and your client access point will be the name following “Name:”.
Download