Rebuild an on-premises application in Azure
This article demonstrates how the fictional company Contoso rebuilds a two-tier Windows .NET application that's running on VMware virtual machines (VMs) as part of a migration to Azure. Contoso migrates the front-end VM to an Azure App Service web app. Contoso builds the application back end by using microservices that are deployed to containers managed by Azure Kubernetes Service (AKS). The site interacts with Azure Functions to provide pet photo functionality.
The SmartHotel360 application used in this example is provided under an open-source license. If you want to use it for your own testing purposes, you can download it from GitHub.
The Contoso IT leadership team has worked closely with business partners to understand what they want to achieve with this migration:
- Address business growth. Contoso is growing and wants to provide differentiated experiences for customers on Contoso websites.
- Be agile. Contoso must be able to react faster than the changes in the marketplace to enable their success in a global economy.
- Scale. As the business grows successfully, the Contoso IT team must provide systems that can grow at the same pace.
- Reduce costs. Contoso wants to minimize licensing costs.
The Contoso cloud team has pinned down application requirements for this migration. These requirements were used to determine the best migration method:
- The application in Azure must remain as critical as it is today on-premises. It should perform well and scale easily.
- The application shouldn't use infrastructure as a service (IaaS) components. Everything should be built to use platform as a service (PaaS) or serverless services.
- Application builds should run in cloud services, and containers should reside in a private, enterprise-wide registry in the cloud.
- The API service that's used for pet photos should be accurate and reliable in the real world, because decisions made by the application must be honored in their hotels. Any pet granted access is allowed to stay at the hotels.
- To meet requirements for a DevOps pipeline, Contoso will use a Git repository in Azure Repos for source code management. Automated builds and releases will be used to build code and deploy to Azure App Service, Azure Functions, and AKS.
- Separate continuous integration/continuous development (CI/CD) pipelines are needed for microservices on the back end and for the website on the front end.
- The back-end services and the front-end web app have different release cycles. To meet this requirement, Contoso will deploy two different pipelines.
- Contoso needs management approval for all front-end website deployment, and the CI/CD pipeline must provide this.
After pinning down their goals and requirements, Contoso designs and reviews a deployment solution, and identifies the migration process, including the Azure services that will be used for the migration.
- The SmartHotel360 on-premises application is tiered across two VMs (
- The VMs are located on VMware ESXi host
- The VMware environment is managed by vCenter Server 6.5 (
vcenter.contoso.com), running on a VM.
- Contoso has an on-premises datacenter (
contoso-datacenter), with an on-premises domain controller (
- The on-premises VMs in the Contoso datacenter will be decommissioned after the migration is done.
The front end of the application is deployed as an Azure App Service web app in the primary Azure region.
An Azure function provides uploads of pet photos, and the site interacts with this functionality.
The pet photo function uses the Computer Vision API of Azure Cognitive Services along with Azure Cosmos DB.
The back end of the site is built by using microservices. These microservices will be deployed to containers that are managed in AKS.
Containers will be built using Azure DevOps and then pushed to Azure Container Registry.
For now, Contoso will manually deploy the web app and function code by using Visual Studio.
Contoso will deploy microservices by using a PowerShell script that calls Kubernetes command-line tools.
Figure 1: Scenario architecture.
Contoso evaluates the proposed design by putting together a pros and cons list.
|Pros||Using PaaS and serverless solutions for the end-to-end deployment significantly reduces the management time that Contoso must provide.
Moving to a microservices-based architecture allows Contoso to easily extend the solution over time.
New functionality can be brought online without disrupting any of the existing solutions' code bases.
The web app will be configured with multiple instances, with no single point of failure.
Autoscaling will be enabled so that the application can handle differing traffic volumes.
With the move to PaaS services, Contoso can retire out-of-date solutions that run on the Windows Server 2008 R2 operating system.
Azure Cosmos DB has built-in fault tolerance, which requires no configuration by Contoso. This means that the data tier is no longer a single point of failover.
|Cons||Containers are more complex than other migration options. The learning curve could be an issue for Contoso. They introduce a new level of complexity that provides value in spite of the curve.
The operations team at Contoso needs to ramp up to understand and support Azure, containers, and microservices for the application.
Contoso hasn't fully implemented DevOps for the entire solution. Contoso needs to consider that for the deployment of services to AKS, Azure Functions, and Azure App Service.
Contoso provisions Azure Container Registry, AKS, and Azure Cosmos DB.
Contoso provisions the infrastructure for the deployment, including the Azure App Service web app, storage account, function, and API.
After the infrastructure is in place, Contoso builds their microservices container images by using Azure DevOps, which pushes the images to the container registry.
Contoso deploys these microservices to AKS by using a PowerShell script.
Finally, Contoso deploys the function and web app.
Figure 2: The migration process.
|Azure Kubernetes Service||Simplifies Kubernetes management, deployment, and operations. Provides a fully managed Kubernetes container orchestration service.||AKS is a free service. Pay for only the VMs and the associated storage and networking resources that are consumed. Learn more.|
|Azure Functions||Accelerates development with an event-driven, serverless compute experience. Scale on demand.||Pay only for consumed resources. Plan is billed based on per-second resource consumption and executions. Learn more.|
|Azure Container Registry||Stores images for all types of container deployments.||Cost is based on features, storage, and usage duration. Learn more.|
|Azure App Service||Quickly build, deploy, and scale enterprise-grade web, mobile, and API apps that run on any platform.||App Service plans are billed on a per-second basis. Learn more.|
Here's what Contoso needs for this scenario:
|Developer prerequisites||Contoso needs the following tools on a developer workstation:
Here's how Contoso will run the migration:
- Step 1: Provision AKS and Azure Container Registry. Contoso provisions the managed AKS cluster and the container registry by using PowerShell.
- Step 2: Build Docker containers. Contoso sets up continuous integration (CI) for Docker containers by using Azure DevOps and pushes the containers to the container registry.
- Step 3: Deploy back-end microservices. Contoso deploys the rest of the infrastructure that will be used by back-end microservices.
- Step 4: Deploy front-end infrastructure. Contoso deploys the front-end infrastructure, including Blob Storage for the pet phones, Azure Cosmos DB, and the Computer Vision API.
- Step 5: Migrate the back end. Contoso deploys microservices and runs them on AKS to migrate the back end.
- Step 6: Publish the front end. Contoso publishes the SmartHotel360 application to Azure App Service along with the function app to be called by the pet service.
Provision back-end resources
Contoso admins run a deployment script to create the managed Kubernetes cluster by using AKS and Azure Container Registry. The instructions for this section use the
SmartHotel360-Backend GitHub repository. The repository contains all the software for this part of the deployment.
Ensure that prerequisites are met
Before they start, Contoso admins ensure that all prerequisite software is installed on the dev machine they're using for the deployment. They clone the repository locally to the dev machine by using Git:
git clone https://github.com/Microsoft/SmartHotel360-Backend.git
Provision AKS and Azure Container Registry
The Contoso admins provision AKS and Azure Container Registry as follows:
In Visual Studio Code, they open the folder and go to the
/deploy/k8sdirectory, which contains the script
They run the script to create the managed Kubernetes cluster, using AKS and Azure Container Registry.
Figure 3: Creating the managed Kubernetes cluster.
With the file open, they update the $location parameter to
eastus2, and save the file.
Figure 4: Saving the file.
They select View > Integrated terminal to open the integrated terminal in Visual Studio Code.
Figure 5: The terminal in Visual Studio Code.
In the PowerShell integrated terminal, they sign in to Azure using the
Connect-AzureRmAccountcommand. For more information, see Get started with PowerShell.
Figure 6: The PowerShell integrated terminal.
They authenticate the Azure CLI by running the
az logincommand and following the instructions to authenticate using their web browser. Learn more about signing in with the Azure CLI.
Figure 7: Authenticating the Azure CLI.
They run the following command while passing the resource group name of
ContosoRG, the name of the AKS cluster
smarthotel-aks-eus2, and the new registry name.
.\gen-aks-env.ps1 -resourceGroupName ContosoRg -orchestratorName smarthotelakseus2 -registryName smarthotelacreus2
Figure 8: Running the command.
Azure creates another resource group that contains the resources for the AKS cluster.
Figure 9: Azure creating a resource group.
After the deployment is finished, they install the
kubectlcommand-line tool. The tool is already installed on the Azure Cloud Shell.
az aks install-cli
They verify the connection to the cluster by running the
kubectl get nodescommand. The node has the same name as the VM in the automatically created resource group.
Figure 10: Verifying the connection to the cluster.
They run the following command to start the Kubernetes dashboard:
az aks browse --resource-group ContosoRG --name smarthotelakseus2
A browser tab opens to the dashboard. This is a tunneled connection that uses the Azure CLI.
Figure 11: A tunneled connection.
Step 2: Configure the back-end pipeline
Create an Azure DevOps project and build
Contoso creates an Azure DevOps project, configures a CI build to create the container, and then pushes it to the container registry. The instructions in this section use the
visualstudio.com, they create a new organization (
contosodevops360.visualstudio.com) and configure it to use Git.
They create a new project (
SmartHotelBackend), selecting Git for version control and Agile for the workflow.
Figure 12: Creating a new project.
They import the GitHub repo.
Figure 13: Importing the GitHub repo.
In Pipelines, they select Build and create a new pipeline by using Azure Repos Git as a source from the repository.
Figure 14: Creating a new pipeline.
They select Empty job.
Figure 15: Starting with an empty job.
They select Hosted Linux Preview for the build pipeline.
Figure 16: Setting up the build pipeline.
In Step 1, they add a Docker Compose task. This task builds the Docker Compose.
Figure 17: Building the Docker Compose.
They repeat and add another Docker Compose task. This one pushes the containers to the container registry.
Figure 18: Adding another Docker Compose task.
They select the first task to build and configure the build with the Azure subscription, the authorization, and the container registry.
Figure 19: Building and configuring the build.
They specify the path of the
docker-compose.yamlfile in the
srcfolder of the repo. They choose to build service images and include the latest tag. When the action changes to Build service images, the name of the Azure DevOps task changes to Build services automatically.
Figure 20: The specifics of the task.
Now, they configure the second Docker task (to push). They select the subscription and the container registry (
Figure 21: Configuring the second Docker task.
They enter the
docker-compose.yamlfile name and select Push service images, including the latest tag. When the action changes to Push service images, the name of the Azure DevOps task changes to Push services automatically.
Figure 22: Changing the Azure DevOps task name.
With the Azure DevOps tasks configured, Contoso saves the build pipeline and starts the build process.
Figure 23: Starting the build process.
They select the build job to check progress.
Figure 24: Checking the progress.
After the build finishes, the container registry shows the new repos, which are populated with the containers used by the microservices.
Figure 25: Viewing new repos after the build finishes.
Deploy the back-end infrastructure
With the AKS cluster created and the Docker images built, Contoso admins now deploy the rest of the infrastructure that will be used by back-end microservices.
- Instructions in this section use the
- In the
/deploy/k8s/armfolder, there's a single script to create all items.
The admins deploy the infrastructure as follows:
They open a developer command prompt and then use the command
az loginfor the Azure subscription.
They use the
deploy.cmdfile to deploy the Azure resources in the
ContosoRGresource group and
East US 2region by typing the following command:
.\deploy.cmd azuredeploy ContosoRG -c eastus2
Figure 26: Deploying the back end.
In the Azure portal, they capture the connection string for each database for later use.
Figure 27: Capturing the connection string for each database.
Create the back-end release pipeline
Now, Contoso admins do the following:
- Deploy the NGINX ingress controller to allow inbound traffic to the services.
- Deploy the microservices to the AKS cluster.
- As a first step, admins update the connection strings to the microservices by using Azure DevOps. They then configure a new Azure DevOps release pipeline to deploy the microservices.
- The instructions in this section use the
- Some of the configuration settings (for example, Active Directory B2C) aren't covered in this article. For more information about these settings, review the previously mentioned
The admins create the pipeline:
In Visual Studio, they update the
/deploy/k8s/config_local.ymlfile with the database connection information that they noted earlier.
They open Azure DevOps and, in the
SmartHotel360project, they select + New pipeline on the Releases pane.
Figure 29: Creating a new pipeline.
They select Empty Job to start the pipeline without a template.
They provide the stage and pipeline names.
Figure 30: The stage name.
Figure 31: The pipeline name.
They add an artifact.
Figure 32: Adding an artifact.
They select Git as the source type and specify the project, source, and main branch for the SmartHotel360 application.
Figure 33: The artifact settings pane.
They select the task link.
Figure 34: The task link.
They add a new Azure PowerShell task so that they can run a PowerShell script in an Azure environment.
Figure 35: Adding a new PowerShell task.
They select the Azure subscription for the task and select the
deploy.ps1script from the Git repo.
Figure 36: Running the script.
They add arguments to the script. The script will delete all cluster content (except ingress and ingress controller), and deploy the microservices.
Figure 37: Adding arguments to the script.
They set the preferred Azure PowerShell version to the latest version, and save the pipeline.
They go back to the Create a new release pane and manually create a new release.
Figure 38: Manually creating a new release.
After they create the release, they select it and, under Actions, they select Deploy.
Figure 39: Deploying a release.
When the deployment is complete, they run the following command to check the status of services, using the Azure Cloud Shell:
kubectl get services.
Step 3: Provision front-end services
Contoso admins need to deploy the infrastructure that will be used by the front-end applications. They create:
- A Blob Storage container to store the pet images.
- An Azure Cosmos DB database to store documents containing pet information.
- The Computer Vision API for the website.
Instructions for this section use the
Create Blob Storage containers
In the Azure portal, the admins open the storage account that was created, and then select Blobs.
They create a new container named
Petswith the public-access level set for the container. Users will upload their pet photos to this container.
Figure 40: Creating a new container.
They create a second new container named
settings. A file with all the front-end app settings will be placed in this container.
Figure 41: Creating a second container.
They capture the access details for the storage account in a text file for future reference.
Figure 42: A text file capturing access details.
Provision an Azure Cosmos DB database
Contoso admins provision an Azure Cosmos DB database to be used for pet information.
They create an Azure Cosmos DB database in Azure Marketplace.
Figure 43: Creating an Azure Cosmos DB database.
They specify a name
contososmarthotel, select Azure Cosmos DB for NoSQL, and place it in the production resource group
ContosoRGin the main region
East US 2.
Figure 44: Naming an Azure Cosmos DB database.
They add a new collection to the database, with default capacity and throughput.
Figure 45: Adding a new collection to the database.
They note the connection information for the database for future reference.
Figure 46: The connection information for the database.
Provision the Computer Vision API
Contoso admins provision the Computer Vision API. The API will be called by the function, to evaluate pictures that are uploaded by users.
The admins create a Computer Vision instance in Azure Marketplace.
Figure 47: A new instance in Azure Marketplace.
They provision the API (
smarthotelpets) in the production resource group
ContosoRG, in the main region (
East US 2).
Figure 48: Provisioning an API in a production resource group.
They save the connection settings for the API to a text file for later reference.
Figure 49: Saving the API connection settings.
Provision the Azure web app
Contoso admins provision the web app by using the Azure portal.
They select Web App in the portal.
Figure 50: Selecting the web app.
They provide a web app name (
smarthotelcontoso), run it on Windows, and place it in the production resource group
ContosoRG. They create a new Application Insights instance for application monitoring.
Figure 51: The web app name.
After they're done, the admins browse to the address of the application to check on whether it has been created successfully.
In the Azure portal, they create a staging slot for the code. The pipeline will be deployed to this slot. This approach ensures that code isn't put into production until the admins perform a release.
Figure 52: Adding a web app staging slot.
Provision the function app
In the Azure portal, Contoso admins provision the function app.
They select Function App.
Figure 53: Selecting the function app.
They provide a name for the function app (
smarthotelpetchecker). They place the function app in the production resource group (
ContosoRG). They set the hosting place to Consumption Plan, and place the function app in the
East US 2region. A new storage account is created along with an Application Insights instance for monitoring.
Figure 54: Function app settings.
After they've deployed the function app, the admins browse to its address to verify that it has been created successfully.
Step 4: Set up the front-end pipeline
Contoso admins create two different projects for the front-end site.
In Azure DevOps, they create a project named
Figure 55: Creating a front-end project.
They import the
SmartHotel360-WebsiteGit repository into the new project.
For the function app, they create another Azure DevOps project (
SmartHotelPetChecker) and import the PetChecker Git repository into this project.
Configure the web app
Now Contoso admins configure the web app to use Contoso resources.
The admins connect to the Azure DevOps project and clone the repository locally to the development machine.
In Visual Studio, they open the folder to show all the files in the repo.
Figure 56: Viewing all files in the repo.
They update the configuration changes as required.
- When the web app starts up, it looks for the
- This variable must contain a URL that points to a configuration file.
- By default, the setting that's used is a public endpoint.
- When the web app starts up, it looks for the
They update the
- This is the configuration file for the web when it uses the public endpoint.
- They edit the
pets_configsections with the values for the AKS API endpoints, storage accounts, and Azure Cosmos DB database.
- The URLs should match the DNS name of the new web app that Contoso will create.
- For Contoso, this is
Figure 57: The .json settings.
After they update the file, the admins rename it
smarthotelsettingsurland upload it to the Blob Storage they created earlier.
Figure 58: Renaming and uploading the file.
They select the file to get the URL. The URL is used by the application when it pulls down the configuration files.
Figure 59: The application URL.
appsettings.Production.jsonfile, they update the
SettingsURLto the URL of the new file.
Figure 60: Updating the URL to the new file.
Deploy the website to Azure App Service
Contoso admins can now publish the website.
They open Azure DevOps and, in the
SmartHotelFrontEndproject in Builds and Releases, they select + New pipeline.
They select Azure DevOps Git as a source.
They select the ASP.NET Core template.
They review the pipeline and check to ensure that Publish Web Projects and Zip Published Projects are selected.
Figure 61: Pipeline settings.
In Triggers, they enable continuous integration and add the main branch. This ensures that the build pipeline starts each time the solution has new code committed to the main branch.
Figure 62: Enabling continuous integration.
They select Save & Queue to start a build.
After the build finishes, they configure a release pipeline by using Azure App Service Deployment.
They provide a stage name, Staging.
Figure 63: Naming the environment.
They add an artifact and select the build that they've configured.
Figure 64: Adding an artifact.
They select the lightning bolt icon on the artifact and then set continuous deployment to Enabled.
Figure 65: Enabling continuous deployment.
In Environment, they select 1 job, 1 task under Staging.
After selecting the subscription and web app name, the admins open the Deploy Azure App Service task. The deployment is configured to use the staging deployment slot. This automatically builds code for review and approval in this slot.
Figure 66: Deploying to a slot.
In the Pipeline, they add a new stage.
Figure 67: Adding a new stage.
They select Azure App Service deployment with slot and then name the environment Prod.
They select 1 job, 2 tasks and then select the subscription, the app service name, and the staging slot.
Figure 68: Naming the environment.
They remove the Deploy Azure App Service to Slot from the pipeline. It was placed there by the previous steps.
Figure 69: Removing a slot from the pipeline.
They save the pipeline. On the pipeline, they select Post-deployment conditions.
Figure 70: Post-deployment conditions.
They enable Post-deployment approvals and then add a dev lead as the approver.
Figure 71: Adding an approver.
In the build pipeline, the admins manually kick off a build. This triggers the new release pipeline, which deploys the site to the staging slot. For Contoso, the URL for the slot is
After the build finishes and the release is deployed to the slot, Azure DevOps emails the dev lead for approval.
The dev lead selects View approval and can approve or reject the request in the Azure DevOps portal.
Figure 72: A pending release approval request.
The dev lead makes a comment and approves. This starts swapping the staging and prod slots and moves the build into production.
Figure 73: Moving the build into production.
The pipeline completes the swap.
Figure 74: Completing the swap.
The team checks the prod slot to verify that the web app is in production at
Deploy the PetChecker function app
Contoso admins deploy the application by doing the following:
They clone the repository locally to the development machine by connecting to the Azure DevOps project.
In Visual Studio, they open the folder to show all the files in the repo.
They open the
src/PetCheckerFunction/local.settings.jsonfile and add the app settings for storage, the Azure Cosmos DB database, and the Computer Vision API.
Figure 75: Deploying the function.
They commit the code and sync it back to Azure DevOps, pushing their changes.
They add a new build pipeline and then select Azure DevOps Git for the source.
They select the ASP.NET Core (.NET Framework) template.
They accept the defaults for the template.
Under Triggers, they select Enable continuous integration and then select Save & Queue to start a build.
After the build succeeds, they build a release pipeline, adding Azure App Service deployment with slot.
They name the environment Prod and then select the subscription. They set the App type to Function App and the app service name as
Figure 76: The function app.
They add an artifact, Build.
Figure 77: Adding an artifact.
They enable Continuous deployment trigger and then select Save.
They select Queue new build to run the full CI/CD pipeline.
After the function is deployed, it appears in the Azure portal with the status Running.
Figure 78: Updating the function's status.
They browse to the pet checker application, at
http://smarthotel360public.azurewebsites.net/pets, to verify that it's working properly.
They select the avatar to upload a picture.
Figure 79: Assigning a picture to an avatar.
The first photo they want to check is of a small dog.
Figure 80: Checking the photo.
The application returns an acceptance message.
Figure 81: An acceptance message.
Review the deployment
With the migrated resources in Azure, Contoso now needs to fully operationalize and secure the new infrastructure.
- Contoso needs to ensure that the new databases are secure. To learn more, see Overview of Azure SQL Database and SQL Managed Instance security capabilities.
- The application must be updated to use SSL with certificates. The container instance should be redeployed to answer on 443.
- Contoso should consider using Azure Key Vault to help protect secrets for their Service Fabric applications. To learn more, see Manage encrypted secrets in Service Fabric applications.
Backups and disaster recovery
- Contoso needs to review backup requirements for Azure SQL Database.
- Contoso should consider implementing SQL failover groups to provide regional failover for the database.
- Contoso can use geo-replication for the Azure Container Registry Premium SKU.
- Azure Cosmos DB is backed up automatically. To learn more, see Online backup and on-demand data restore in Azure Cosmos DB.
Licensing and cost optimization
- After all resources are deployed, Contoso should assign Azure tags based on their infrastructure planning.
- All licensing is built into the cost of the PaaS services that Contoso is consuming. This will be deducted from the Enterprise Agreement.
- Contoso will enable Azure Cost Management + Billing to help monitor and manage the Azure resources.
In this article, Contoso rebuilds the SmartHotel360 application in Azure. The on-premises application front-end VM is rebuilt for Azure App Service web apps. The application back end is built by using microservices that are deployed to containers managed by AKS. Contoso enhanced functionality with a pet photo application.
Microsoft Learn is a new approach to learning. Readiness for the new skills and responsibilities that come with cloud adoption doesn't come easily. Microsoft Learn provides a more rewarding approach to hands-on learning that helps you achieve your goals faster. With Microsoft Learn, you can earn points, rise through levels, and achieve more.
Here are two examples of tailored learning paths that align with the Contoso SmartHotel360 application in Azure.
Deploy a website to Azure with Azure App Service: By creating web apps in Azure, you can publish and manage your website easily without having to work with the underlying servers, storage, or network assets. Instead, you can focus on your website features and rely on the robust Azure platform to help provide secure access to your site.
Create computer vision solutions with Azure Cognitive Services: Azure Cognitive Services offers prebuilt functionality to enable Computer Vision functionality in your applications. Learn how to use the vision APIs in Azure Cognitive Services to detect faces, tag and classify images, and identify objects.