Tutorial: Deploy apps to Azure and Azure Stack
Applies to: Azure Stack integrated systems and Azure Stack Development Kit
Learn how to deploy an application to Azure and Azure Stack using a hybrid continuous integration/continuous delivery (CI/CD) pipeline.
In this tutorial, you'll create a sample environment to:
- Initiate a new build based on code commits to your Azure DevOps Services repository.
- Automatically deploy your app to global Azure for user acceptance testing.
- When your code passes testing, automatically deploy the app to Azure Stack.
Benefits of the hybrid delivery build pipe
Continuity, security, and reliability are key elements of application deployment. These elements are essential to your organization and critical to your development team. A hybrid CI/CD pipeline enables you to consolidate your build pipes across your on-premises environment and the public cloud. A hybrid delivery model also lets you change deployment locations without changing your application.
Other benefits to using the hybrid approach are:
- You can maintain a consistent set of development tools across your on-premises Azure Stack environment and the Azure public cloud. A common tool set makes it easier to implement CI/CD patterns and practices.
- Apps and services deployed in Azure or Azure Stack are interchangeable and the same code can run in either location. You can take advantage of on-premises and public cloud features and capabilities.
To learn more about CI and CD:
Microsoft Azure Stack is an extension of Azure. Azure Stack brings the agility and innovation of cloud computing to your on-premises environment and enabling the only hybrid cloud that allows you to build and deploy hybrid apps anywhere.
The whitepaper Design Considerations for Hybrid Applications reviews pillars of software quality (placement, scalability, availability, resiliency, manageability and security) for designing, deploying and operating hybrid applications. The design considerations assist in optimizing hybrid application design, minimizing challenges in production environments.
You need to have components in place to build a hybrid CI/CD pipeline. The following components will take time to prepare:
- An Azure OEM/hardware partner can deploy a production Azure Stack. All users can deploy the Azure Stack Development Kit (ASDK).
- An Azure Stack Operator must also: deploy the App Service, create plans and offers, create a tenant subscription, and add the Windows Server 2016 image.
If you already have some of these components deployed, make sure they meet the all the requirements before you start this tutorial.
This tutorial assumes that you have some basic knowledge of Azure and Azure Stack. To learn more before starting the tutorial, read the following articles:
- If you don't have an Azure subscription, create a free account before you begin.
- Create a Web App in Azure. Make note of the Web App URL, you need to use it in the tutorial.
Azure Stack requirements
Use an Azure Stack integrated system or deploy the Azure Stack Development Kit (ASDK). To deploy the ASDK:
- The Tutorial: deploy the ASDK using the installer gives detailed deployment instructions.
Use the ConfigASDK.ps1 PowerShell script to automate ASDK post-deployment steps.
The ASDK installation takes approximately seven hours to complete, so plan accordingly.
- Deploy App Service PaaS services to Azure Stack.
- Create Plan/Offers in Azure Stack.
- Create a tenant subscription in Azure Stack.
- Create a Web App in the tenant subscription. Make note of the new Web App URL for later use.
- Deploy a Windows Server 2012 Virtual Machine in the tenant subscription. You will use this server as your build server and to run Azure DevOps Services.
- Provide a Windows Server 2016 image with .NET 3.5 for a virtual machine (VM). This VM will be built on your Azure Stack as a private build agent.
Developer tool requirements
- Create an Azure DevOps Services workspace. The sign-up process creates a project named MyFirstProject.
- Install Visual Studio 2017 and sign-in to Azure DevOps Services.
Connect to your project and clone it locally.
Your Azure Stack environment needs the correct images syndicated to run Windows Server and SQL Server. It must also have App Service deployed.
Prepare the private Azure Pipelines agent for Azure DevOps Services integration
Azure DevOps Services authenticates against Azure Resource Manager using a Service Principal. Azure DevOps Services must have the Contributor role to provision resources in an Azure Stack subscription.
The following steps describe what's required to configure authentication:
- Create a Service Principal, or use an existing Service Principal.
- Create Authentication keys for the Service Principal.
- Validate the Azure Stack Subscription via Role-Based Access Control to allow the Service Principal Name (SPN) to be part of the Contributor’s role.
- Create a new Service Definition in Azure DevOps Services using the Azure Stack endpoints and SPN information.
Create a Service Principal
Refer to the Service Principal Creation instructions to create a service principal. Choose Web App/API for the Application Type or use the PowerShell script as explained in the article Create an Azure Resource Manager service connection with an existing service principal .
If you use the script to create an Azure Stack Azure Resource Manager endpoint, you need to pass the -azureStackManagementURL parameter and -environmentName parameter. For example:
-azureStackManagementURL https://management.local.azurestack.external -environmentName AzureStack
Create an access key
A Service Principal requires a key for authentication. Use the following steps to generate a key.
From App registrations in Azure Active Directory, select your application.
Make note of the value of Application ID. You will use that value when configuring the service endpoint in Azure DevOps Services.
To generate an authentication key, select Settings.
To generate an authentication key, select Keys.
Provide a description for the key, and set the duration of the key. When done, select Save.
After you save the key, the key VALUE is displayed. Copy this value because you can't get this value later. You provide the key value with the application ID to sign in as the application. Store the key value where your application can retrieve it.
Get the tenant ID
As part of the service endpoint configuration, Azure DevOps Services requires the Tenant ID that corresponds to the AAD Directory that your Azure Stack stamp is deployed to. Use the following steps to get the Tenant ID.
Select Azure Active Directory.
To get the tenant ID, select Properties for your Azure AD tenant.
Copy the Directory ID. This value is your tenant ID.
Grant the service principal rights to deploy resources in the Azure Stack subscription
To access resources in your subscription, you must assign the application to a role. Decide which role represents the best permissions for the application. To learn about the available roles, see RBAC: Built in Roles.
You can set the scope at the level of the subscription, resource group, or resource. Permissions are inherited to lower levels of scope. For example, adding an application to the Reader role for a resource group means it can read the resource group and any of its resources.
Navigate to the level of scope you wish to assign the application to. For example, to assign a role at the subscription scope, select Subscriptions.
In Subscription, select Visual Studio Enterprise.
In Visual Studio Enterprise, select Access Control (IAM).
In Add permissions, select the role you that you want to assign to the application. In this example, the Owner role.
By default, Azure Active Directory applications aren't displayed in the available options. To find your application, you must provide its name in the Select field to search for it. Select the app.
Select Save to finish assigning the role. You see your application in the list of users assigned to a role for that scope.
Role-Based Access Control
Azure Role-Based Access Control (RBAC) provides fine-grained access management for Azure. By using RBAC, you can control the level of access that users need to do their jobs. For more information about Role-Based Access Control, see Manage Access to Azure Subscription Resources.
Azure DevOps Services Agent Pools
Instead of managing each agent separately, you can organize agents into agent pools. An agent pool defines the sharing boundary for all agents in that pool. In Azure DevOps Services, agent pools are scoped to the Azure DevOps Services organization, which means that you can share an agent pool across projects. To learn more about agent pools, see Create Agent Pools and Queues.
Add a Personal Access Token (PAT) for Azure Stack
Create a Personal Access Token to access Azure DevOps Services.
Sign in to your Azure DevOps Services organization and select your organization profile name.
Select Manage Security to access token creation page.
Copy the token.
Save the token information. This information isn't stored and won't be shown again when you leave the web page.
Install the Azure DevOps Services build agent on the Azure Stack hosted Build Server
- Connect to your Build Server that you deployed on the Azure Stack host.
Download and Deploy the build agent as a service using your personal access token (PAT) and run as the VM Admin account.
Navigate to the folder for the extracted build agent. Run the config.cmd file from an elevated command prompt.
When the config.cmd finishes, the build agent folder is updated with additional files. The folder with the extracted contents should look like the following:
You can see the agent in Azure DevOps Services folder.
Endpoint creation permissions
By creating endpoints, a Visual Studio Online (VSTO) build can deploy Azure Service apps to Azure Stack. Azure DevOps Services connects to the build agent, which connects to Azure Stack.
- Sign in to VSTO and navigate to the app settings page.
- On Settings, select Security.
In Azure DevOps Services Groups, select Endpoint Creators.
On the Members tab, select Add.
In Add users and groups, enter a user name and select that user from the list of users.
- Select Save changes.
In the Azure DevOps Services Groups list, select Endpoint Administrators.
On the Members tab, select Add.
- In Add users and groups, enter a user name and select that user from the list of users.
- Select Save changes.
Now that the endpoint information exists, the Azure DevOps Services to Azure Stack connection is ready to use. The build agent in Azure Stack gets instructions from Azure DevOps Services, and then the agent conveys endpoint information for communication with Azure Stack.
Create an Azure Stack endpoint
You can follow the instructions in Create an Azure Resource Manager service connection with an existing service principal article to create a service connection with an existing service principal and use the following mapping:
- Environment: AzureStack
- Environment URL: Something like
- Subscription ID: User subscription ID from Azure Stack
- Subscription name: User subscription name from Azure Stack
- Service Principal client ID: The principal ID from this section in this article.
- Service Principal key: The key from the same article (or the password if you used the script).
- Tenant ID: The tenant ID you retrieve following the instruction at Get the tenant ID.
Now that the endpoint is created, the VSTS to Azure Stack connection is ready to use. The build agent in Azure Stack gets instructions from VSTS, and then the agent conveys endpoint information for communication with Azure Stack.
Develop your application build
In this part of the tutorial you'll:
- Add code to an Azure DevOps Services project.
- Create self-contained web app deployment.
- Configure the continuous deployment process
Your Azure Stack environment needs the correct images syndicated to run Windows Server and SQL Server. It must also have App Service deployed. Review the App Service documentation "Prerequisites" section for Azure Stack Operator Requirements.
Hybrid CI/CD can apply to both application code and infrastructure code. Use Azure Resource Manager templates like web app code from Azure DevOps Services to deploy to both clouds.
Add code to an Azure DevOps Services project
Sign in to Azure DevOps Services with an organization that has project creation rights on Azure Stack. The next screen capture shows how to connect to the HybridCICD project.
Clone the repository by creating and opening the default web app.
Create self-contained web app deployment for App Services in both clouds
Edit the WebApplication.csproj file: Select Runtimeidentifier and then add
win10-x64.For more information, see Self-contained deployment documentation.
Use Team Explorer to check the code into Azure DevOps Services.
Confirm that the application code was checked into Azure DevOps Services.
Create the build pipeline
Sign in to Azure DevOps Services with an organization that can create a build pipeline.
Navigate to the Build Web Applicaiton page for the project.
In Arguments, add -r win10-x64 code. This is required to trigger a self-contained deployment with .Net Core.
Run the build. The self-contained deployment build process will publish artifacts that can run on Azure and Azure Stack.
Use an Azure hosted build agent
Using a hosted build agent in Azure DevOps Services is a convenient option for building and deploying web apps. Agent maintenance and upgrades are automatically performed by Microsoft Azure, which enables a continuous and uninterrupted development cycle.
Configure the continuous deployment (CD) process
Azure DevOps Services and Team Foundation Server (TFS) provide a highly configurable and manageable pipeline for releases to multiple environments such as development, staging, quality assurance (QA), and production. This process can include requiring approvals at specific stages of the application life cycle.
Create release pipeline
Creating a release pipeline is the final step in your application build process. This release pipeline is used to create a release and deploy a build.
- Sign in to Azure DevOps Services and navigate to Azure Pipelines for your project.
On the Releases tab, select [ + ] and then pick Create release definition.
On Select a Template, choose Azure App Service Deployment, and then select Apply.
On Add artifact, from the Source (Build definition) pull-down menu, select the Azure Cloud build app.
On the Pipeline tab, select the 1 Phase, 1 Task link to View environment tasks.
On the Tasks tab, enter Azure as the Environment name and select the AzureCloud Traders-Web EP from the Azure subscription drop-down list.
Enter the Azure app service name, which is "northwindtraders" in the next screen capture.
For the Agent phase, select Hosted VS2017 from the Agent queue drop-down list.
In Deploy Azure App Service, select the valid Package or folder for the environment.
In Select File or Folder, select OK to Location.
Save all changes and go back to Pipeline.
On the Pipeline tab, select Add artifact, and choose the NorthwindCloud Traders-Vessel from the Source (Build Definition) drop-down list.
On Select a Template, add another environment. Pick Azure App Service Deployment and then select Apply.
Enter "Azure Stack" as the Environment name.
On the Tasks tab, find and select Azure Stack.
From the Azure subscription drop-down list, select "AzureStack Traders-Vessel EP" for the Azure Stack endpoint.
Enter the Azure Stack web app name as the App service name.
Under Agent selection, pick "AzureStack -bDouglas Fir" from the Agent queue drop-down list.
For Deploy Azure App Service, select the valid Package or folder for the environment. On Select File Or Folder, select OK for the folder Location.
On the Variable tab, find the variable named VSTS_ARM_REST_IGNORE_SSL_ERRORS. Set the variable value to true, and set its scope to Azure Stack.
On the Pipeline tab, select the Continuous deployment trigger icon for the NorthwindCloud Traders-Web artifact and set the Continuous deployment trigger to Enabled. Do the same thing for the "NorthwindCloud Traders-Vessel" artifact.
For the Azure Stack environment, select the Pre-deployment conditions icon set the trigger to After release.
Save all your changes.
Some settings for release tasks may have been automatically defined as environment variables when you created a release pipeline from a template. These settings can't be modified in the task settings. However, you can edit these settings in the parent environment items.
Create a release
Now that you have completed the modifications to the release pipeline, it's time to start the deployment. To do this, you create a release from the release pipeline. A release may be created automatically; for example, the continuous deployment trigger is set in the release pipeline. This means that modifying the source code will start a new build and, from that, a new release. However, in this section you will create a new release manually.
On the Pipeline tab, open the Release drop-down list and choose Create release.
Enter a description for the release, check to see that the correct artifacts are selected, and then choose Create. After a few moments, a banner appears indicating that the new release was created, and the release name is displayed as a link. Choose the link to see the release summary page.
The release summary page for shows details about the release. In the following screen capture for "Release-2", the Environments section shows the Deployment status for the Azure as "IN PROGRESS", and the status for Azure Stack is "SUCCEEDED". When the deployment status for the Azure environment changes to "SUCCEEDED", a banner appears indicating that the release is ready for approval. When a deployment is pending or has failed, a blue (i) information icon is shown. Hover over the icon to see a pop-up that contains the reason for delay or failure.
Other views, such as the list of releases, will also display an icon that indicates approval is pending. The pop-up for this icon shows the environment name and more details related to the deployment. It's easy for an administrator see the overall progress of releases and see which releases are waiting for approval.
Monitor and track deployments
This section shows how you can monitor and track all your deployments. The release for deploying the two Azure App Services websites provides a good example.
On the "Release-2" summary page, select Logs. During a deployment, this page shows the live log from the agent. The left pane shows the status of each operation in the deployment for each environment.
You can choose a person icon in the Action column for a Pre-deployment or Post-deployment approval to see who approved (or rejected) the deployment, and the message they provided.
After the deployment finishes, the entire log file is displayed in the right pane. You can select any Step in the left pane to see the log file for a single step, such as "Initialize Job". The ability to see individual logs makes it easier to trace and debug parts of the overall deployment. You can also Save the log file for a step, or Download all logs as zip.
Open the Summary tab to see general information about the release. This view shows details about the build, the environments it was deployed to, deployment status, and other information about the release.
Select an environment link (Azure or Azure Stack) to see information about existing and pending deployments to a specific environment. You can use these views as a quick way to verify that the same build was deployed to both environments.
Open the deployed production app in your browser. For example, for the Azure App Services website, open the URL
- To learn more about Azure Cloud Patterns, see Cloud Design Patterns.