-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUpdateCosmosAvailabilityZones.ps1
228 lines (182 loc) · 8.59 KB
/
UpdateCosmosAvailabilityZones.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
<#PSScriptInfo
.VERSION 2.0
.GUID 4c077ade-b16c-40db-91c0-f5ec123edb6f
.AUTHOR Joel Forsyth
.COMPANYNAME
.COPYRIGHT
.TAGS Cosmos, ZoneAvailability
.LICENSEURI
.PROJECTURI
.ICONURI
.EXTERNALMODULEDEPENDENCIES Az,Az.Cosmos
.REQUIREDSCRIPTS
.EXTERNALSCRIPTDEPENDENCIES
.RELEASENOTES
.PRIVATEDATA
#>
#Requires -Module Az
#Requires -Module Az.Cosmos
<#
.DESCRIPTION
This script will upgrade a list of Cosmos accounts to zone redundant in a single region without service interruption.
.PARAMETER subscriptionId
Azure subscription Id associated with the Cosmos accounts
.PARAMETER tenantId
Tenant Id associated with the Cosmos accounts
.PARAMETER resourceGroupName
Name of the resource group where the Cosmos accounts are located
.PARAMETER accounts
Names of the Cosmos accounts to be upgraded to zone-redundant
.PARAMETER primaryLocation
Name of the Azure region where the Cosmos accounts currently reside and should persist
.PARAMETER secondaryLocation
Name of the temporary secondary location that needs to be added in order to hotswap zone availability. This location is only used while upgrading.
.EXAMPLE
./UpdateCosmosAvailabilityZones.ps1 -subscriptionId <subscriptionId> -tenantId <tenantId> -resourceGroupName MyResourceGroup -accounts @('accountone', 'accounttwo') -primaryLocation centralus -secondaryLocation eastus
.LINK
https://docs.microsoft.com/en-us/azure/cosmos-db/high-availability
.NOTES
Azure does not allow the adding of zone availabilty to an existing Cosmos DB account. We must jump through a series of hoops in order to do this without losing the account data or introducing down time.
This is a seven-step process. The steps are mentioned here: https://docs.microsoft.com/en-us/azure/cosmos-db/high-availability#replica-outages
1. Add a second region
2. Disable automatic failover to prevent an accidental move while we are removing regions
3. Failover to second region
4. Remove first region
5. Add back first region with zone redundancy
6. Failover back to the first region
7. Remove second region
#>
#>
param (
[Parameter(Mandatory = $True)][string]$subscriptionId,
[Parameter(Mandatory = $True)][string]$tenantId,
[Parameter(Mandatory = $True)][string]$resourceGroupName,
[Parameter(Mandatory = $True)][string[]]$accounts,
[Parameter(Mandatory = $True)][string]$primaryLocation,
[Parameter(Mandatory = $True)][string]$secondaryLocation
)
function Update-CosmosRegions {
param (
[string]$ResourceGroupName,
[string]$CosmosName,
[Microsoft.Azure.Commands.CosmosDB.Models.PSLocation[]]$Locations
)
Write-Host "Updating regions..." -ForegroundColor White
$account = Update-AzCosmosDBAccountRegion `
-ResourceGroupName $ResourceGroupName `
-Name $CosmosName `
-LocationObject $Locations
if($account)
{
Write-Host "Update Successful." -ForegroundColor Green
while($true)
{
Write-Host "Checking status in 10 seconds..." -ForegroundColor White
Start-Sleep -Seconds 10
$account = Get-AzCosmosDBAccount -ResourceGroupName $ResourceGroupName -Name $CosmosName
Write-Host "Account is in the state:" $account.ProvisioningState -ForegroundColor White
if ($account.ProvisioningState -eq "Succeeded")
{
Write-Host "Update complete." -ForegroundColor Green
break
}
elseif ($account.ProvisioningState -eq "Failed")
{
Write-Host "Update failed." -ForegroundColor Red
break
}
}
}
else
{
Write-Host "Update failed." -ForegroundColor Red
}
}
function Update-CosmosFailover {
param (
[string]$ResourceGroupName,
[string]$CosmosName,
[string[]]$Locations
)
Write-Host "Updating failover priority..." -ForegroundColor White
$account = Update-AzCosmosDBAccountFailoverPriority -ResourceGroupName $ResourceGroupName -Name $CosmosName -FailoverPolicy $Locations
if($account)
{
Write-Host "Update Successful." -ForegroundColor Green
while($true)
{
Write-Host "Checking status in 10..." -ForegroundColor White
Start-Sleep -Seconds 10
$account = Get-AzCosmosDBAccount -ResourceGroupName $ResourceGroupName -Name $CosmosName
Write-Host "Write region is now" $account.WriteLocations.LocationName -ForegroundColor White
if ($account.ProvisioningState -eq "Succeeded")
{
Write-Host "Update complete." -ForegroundColor Green
break
}
elseif ($account.ProvisioningState -eq "Failed")
{
Write-Host "Update failed." -ForegroundColor Red
break
}
}
}
else
{
Write-Host "Update failed." -ForegroundColor Red
}
}
Write-Host "Getting context..." -ForegroundColor Yellow
Connect-AzAccount -SubscriptionId $subscriptionId -TenantId $tenantId
$stopwatch = [system.diagnostics.stopwatch]::StartNew()
foreach ( $accountName in $accounts )
{
Write-Host "Starting on" $accountName -ForegroundColor Cyan
$account = Get-AzCosmosDBAccount -ResourceGroupName $resourceGroupName -Name $accountName
if ($account.ProvisioningState -eq "Succeeded")
{
Write-Host "Verified Cosmos Account:" $account.DocumentEndpoint
Write-Host "Primary Region is:" $primaryLocation
Write-Host "Secondary Region is:" $secondaryLocation
# Add secondary region to setup locations. Regions have to be added before changes can be made
# The first region cannot have zone redundancy
Write-Host "Adding primary and secondary regions..." -ForegroundColor Cyan
$locations = @()
$locations += New-AzCosmosDBLocationObject -LocationName $primaryLocation -FailoverPriority 0 -IsZoneRedundant 0
$locations += New-AzCosmosDBLocationObject -LocationName $secondaryLocation -FailoverPriority 1 -IsZoneRedundant 0
Update-CosmosRegions -ResourceGroupName $resourceGroupName -CosmosName $account.Name -Locations $locations
# Disable automatic failover just in case
Write-Host "Disabling automatic failover..." -ForegroundColor Cyan
Update-AzCosmosDBAccount -ResourceGroupName $resourceGroupName -Name $account.Name -EnableAutomaticFailover:$false
#Swap the failover priority to manually cause failover, allowing us to update the primary region
Write-Host "Failing over to secondary region..." -ForegroundColor Cyan
$failoverlocations = @($secondaryLocation, $primaryLocation)
Update-CosmosFailover -ResourceGroupName $resourceGroupName -CosmosName $account.Name -Locations $failoverlocations
#Remove the primary region
Write-Host "Removing the primary region..." -ForegroundColor Cyan
$locations = @()
$locations += New-AzCosmosDBLocationObject -LocationName $secondaryLocation -FailoverPriority 0 -IsZoneRedundant 0
Update-CosmosRegions -ResourceGroupName $resourceGroupName -CosmosName $account.Name -Locations $locations
#Add back primary region with zone redundancy
Write-Host "Adding back primary region with zone redundancy..." -ForegroundColor Cyan
$locations = @()
$locations += New-AzCosmosDBLocationObject -LocationName $secondaryLocation -FailoverPriority 0 -IsZoneRedundant 0
$locations += New-AzCosmosDBLocationObject -LocationName $primaryLocation -FailoverPriority 1 -IsZoneRedundant 1
Update-CosmosRegions -ResourceGroupName $resourceGroupName -CosmosName $account.Name -Locations $locations
#Swap back to primary region, allowing us to delete secondary region
Write-Host "Failing over to primary region..." -ForegroundColor Cyan
$failoverlocations = @($primaryLocation, $secondaryLocation)
Update-CosmosFailover -ResourceGroupName $resourceGroupName -CosmosName $account.Name -Locations $failoverlocations
#Remove the secondary region
Write-Host "Removing the secondary region..." -ForegroundColor Cyan
$locations = @()
$locations += New-AzCosmosDBLocationObject -LocationName $primaryLocation -FailoverPriority 0 -IsZoneRedundant 1
Update-CosmosRegions -ResourceGroupName $resourceGroupName -CosmosName $account.Name -Locations $locations
}
else
{
Write-Host "Cannot Process. Account is in the state:" $account.ProvisioningState -ForegroundColor Red
}
}
Write-Host ("Total time: {0}" -f $stopwatch.Elapsed) -ForegroundColor Cyan
Read-Host -Prompt "Press Enter to exit"