With the impending retirement of the classic Cloud Service (CS) on August 31st, 2024, an increasing number of users have initiated the migration of their classic Cloud Service to Cloud Service Extended Support (CSES). To facilitate this transition, an official feature known as in-place migration has been introduced, enabling the seamless migration of classic CS to CSES without incurring any downtime. However, certain limitations exist, with the VM size used by the CS role being a notable factor. As per documentation, the A-series, encompassing Small, Medium, and Large VM sizes, is no longer supported in CSES, necessitating their conversion to corresponding VM sizes as a preliminary step.
To apply a change in the VM size utilized in classic CS, a redeployment/upgrade is required subsequent to modifying the VM size in the .csdef file. While this is generally a straightforward operation, in cases where the project deployed in the classic CS is considerably dated, there is a possibility that the original project may be lost. Consequently, re-packaging the project into .cspkg and .cscfg files for redeployment/upgrade becomes unfeasible.
This blog will primarily address this specific scenario and outline strategies for resolving this predicament.
Attention! By following this way, a short downtime is unavoidable. If this needs to be applied on a production environment, please do the same test in another environment at first.
The expected result is that the .cspkg and .cscfg files will be found in the classic storage account container. Please download them to local machine.
New-AzureReservedIP –ReservedIPName <reserved ip name> –Location <classic CS location> -ServiceName <classic CS name>
The reserved IP address will be found in a resource group called Default-Networking.
c. Cut down the association between reserved IP and classic CS.
After running this command, the classic CS IP address will be changed. If the application/client side is using IP address to connect to classic CS, it will start failing.
Remove-AzureReservedIPAssociation –ReservedIPName <reserved ip name> -ServiceName <classic CS name>
Reference of step b and c can be found here: Manage Azure reserved IP addresses (Classic) | Microsoft Learn
d. Refer to this document, convert the reserved IP address into a public IP address which can be used by CSES.
Move-AzureReservedIP -ReservedIPName <reserved IP name> -Validate
Move-AzureReservedIP -ReservedIPName <reserved IP name> -Prepare
Move-AzureReservedIP -ReservedIPName <reserved IP name> -Commit
After the command is finished, you will find the converted public IP in a resource group called <publicipaddress-name>-Migrated.
3. By default the public IP address is without any domain name. If it’s needed, please configure it in Configuration page.
4. Move the public IP address to the same resource group where the new CSES resource will be created.
<NetworkConfiguration>
<VirtualNetworkSite name="xxx" />
<AddressAssignments>
<InstanceAddress roleName="xxx">
<Subnets>
<Subnet name="xxx" />
</Subnets>
</InstanceAddress>
</AddressAssignments>
</NetworkConfiguration>
(optional) If the step 2 is followed, please also add ReservedIPs part.
<NetworkConfiguration>
<VirtualNetworkSite name="xxx" />
<AddressAssignments>
<InstanceAddress roleName="xxx">
<Subnets>
<Subnet name="xxx" />
</Subnets>
</InstanceAddress>
<ReservedIPs>
<ReservedIP name="xxx" />
</ReservedIPs>
</AddressAssignments>
</NetworkConfiguration>
After modifying the .cscfg file, please upload the .cscfg and .cspkg file into a storage account, blob container, then generate and note down the SAS URL of these two files.
If the Key Vault is not used, remove the first $osProfile part and the last OSProfile parameter of New-AzCloudService command.
$keyVault = Get-AzKeyVault -ResourceGroupName <key vault resource group> -VaultName <key vault resource name>
$certificate = Get-AzKeyVaultCertificate -VaultName <key vault resource name> -Name <certificate name in Key Vault>
$secretGroup = New-AzCloudServiceVaultSecretGroupObject -Id $keyVault.ResourceId -CertificateUrl $certificate.SecretId
$osProfile = @{secret = @($secretGroup)}
$cspkgSAS = <SAS URL of cspkg file>
$cscfgSAS = <SAS URL of cscfg file>
$role1 = New-AzCloudServiceRoleProfilePropertiesObject -Name <Role1 name> -SkuName <new supported vm size> -SkuTier 'Standard' -SkuCapacity <instance number>
$role2 = New-AzCloudServiceRoleProfilePropertiesObject -Name <Role2 name> -SkuName <new supported vm size> -SkuTier 'Standard' -SkuCapacity <instance number>
$roleProfile = @{role = @($role1, $role2)}
$publicIP = Get-AzPublicIpAddress -ResourceGroupName <public IP resource group> -Name <public IP name>
$feIpConfig = New-AzCloudServiceLoadBalancerFrontendIPConfigurationObject -Name <frontend IP config name> -PublicIPAddressId $publicIP.Id
$loadBalancerConfig = New-AzCloudServiceLoadBalancerConfigurationObject -Name <load balancer config> -FrontendIPConfiguration $feIpConfig
$networkProfile = @{loadBalancerConfiguration = $loadBalancerConfig}
# Create Cloud Service
New-AzCloudService -Name <CSES name> -ResourceGroupName <resource group name> -Location <CSES Location> -AllowModelOverride -PackageUrl $cspkgSAS -ConfigurationUrl $cscfgSAS -UpgradeMode 'Auto' -RoleProfile $roleProfile -NetworkProfile $networkProfile -OSProfile $osProfile
If Key Vault is not used, remember to remove the secrets in osprofile, keep it empty as
"osProfile": {}, remove secrets parameter part in template file and remove secrets parameter from parameter file.
Template file:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"cloudServiceName": {
"type": "string",
"metadata": {
"description": "Name of the cloud service"
}
},
"location": {
"type": "string",
"metadata": {
"description": "Location of the cloud service"
}
},
"deploymentLabel": {
"type": "string",
"metadata": {
"description": "Label of the deployment"
}
},
"packageSasUri": {
"type": "securestring",
"metadata": {
"description": "SAS Uri of the CSPKG file to deploy"
}
},
"configurationSasUri": {
"type": "securestring",
"metadata": {
"description": "SAS Uri of the service configuration (.cscfg)"
}
},
"roles": {
"type": "array",
"metadata": {
"description": "Roles created in the cloud service application"
}
},
"publicIPName": {
"type": "string",
"defaultValue": "contosocsIP",
"metadata": {
"description": "Name of public IP address"
}
},
"upgradeMode": {
"type": "string",
"defaultValue": "Auto",
"metadata": {
"UpgradeMode": "UpgradeMode of the CloudService"
}
},
"secrets": {
"type": "array",
"metadata": {
"description": "The key vault id and certificates referenced in the .cscfg file"
}
}
},
"variables": {
"cloudServiceName": "[parameters('cloudServiceName')]",
"subscriptionID": "[subscription().subscriptionId]",
"lbName": "[concat(variables('cloudServiceName'), 'LB')]",
"lbFEName": "[concat(variables('cloudServiceName'), 'LBFE')]",
"resourcePrefix": "[concat('/subscriptions/', variables('subscriptionID'), '/resourceGroups/', resourceGroup().name, '/providers/')]"
},
"resources": [
{
"apiVersion": "2020-10-01-preview",
"type": "Microsoft.Compute/cloudServices",
"name": "[variables('cloudServiceName')]",
"location": "[parameters('location')]",
"tags": {
"DeploymentLabel": "[parameters('deploymentLabel')]"
},
"properties": {
"packageUrl": "[parameters('packageSasUri')]",
"configurationUrl": "[parameters('configurationSasUri')]",
"upgradeMode": "[parameters('upgradeMode')]",
"allowModelOverride": true,
"roleProfile": {
"roles": "[parameters('roles')]"
},
"networkProfile": {
"loadBalancerConfigurations": [
{
"id": "[concat(variables('resourcePrefix'), 'Microsoft.Network/loadBalancers/', variables('lbName'))]",
"name": "[variables('lbName')]",
"properties": {
"frontendIPConfigurations": [
{
"name": "[variables('lbFEName')]",
"properties": {
"publicIPAddress": {
"id": "[concat(variables('resourcePrefix'), 'Microsoft.Network/publicIPAddresses/', parameters('publicIPName'))]"
}
}
}
]
}
}
]
},
"osProfile": {
"secrets": "[parameters('secrets')]"
}
}
}
]
}
Parameter file:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"cloudServiceName": {
"value": <CSES name>
},
"location": {
"value": <CSES region>
},
"deploymentLabel": {
"value": "deployment label of cses by ARM template"
},
"packageSasUri": {
"value": <.csdef SAS URL>
},
"configurationSasUri": {
"value": <.cscfg SAS URL>
},
"roles": {
"value": [
{
"name": <role1 name>,
"sku": {
"name": <new supported VM size>,
"tier": "Standard",
"capacity": <instance number>
}
},
{
"name": <role2 name>,
"sku": {
"name": <new supported VM size>,
"tier": "Standard",
"capacity": <instance number>
}
}
]
},
"publicIPName": {
"value": <public IP address name>
},
"upgradeMode": {
"value": "Auto"
},
"secrets": {
"value": [
{
"sourceVault": {
"id": "/subscriptions/<subscription id>/resourceGroups/<resource group name>/providers/Microsoft.KeyVault/vaults/<key vault name>"
},
"vaultCertificates": [
{
"certificateUrl": "https://<key vault name>.vault.azure.net/secrets/<certificate name>/<secret ID>"
}
]
}
]
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.