Continuous Delivery To Azure App Services With VSTS

Introduction and Background

It has been quite a while since I last published anything about Microsoft Azure. So, here is my next post about Microsoft Azure. The subject itself could've been for the last post in the DevOps category, however this seems to be one of the initial concepts in the category. So, what I want to cover in this post is that many times, Continuous Delivery comes in handy when you really want to make things a bit automated. However, CD is not that simple to consider. Most of the time, there is authentication required on the machines where your application is going to be delivered etc. Continuous Integration, on the other hand, is just the process to trigger the build for every change in the system. 

Continuous Delivery gives the most trouble to any DevOps practitioners. The reason behind that is that CD requires not just the release information, but the location where to deploy the application when most systems require authentication/authorization in order to deploy or update the applications. That is why, this topic is the toughest in DevOps, I believe. 

To keep things simple, I will just create a simple ASP.NET Core application, and then I will deploy that application to Visual Studio Team Services environment, where it will be -

  1. Built using ASP.NET Core build system;
  2. Deployed to Azure App Service "Deployment Slot";
  3. Swapped to the default web app slot.

These are the steps that we are going to take in this post. To learn how we can solve the CD problem with VSTS for Azure and ASP.NET Core web applications, please follow the steps given ahead.

Deploying a simple web app

So, open up the terminal and type the following commands.

  1. $ cd your_preferred_directory  
  2. $ dotnet new -t web  
  3. $ dotnet restore   

What this will do - if you don't know - is that it will create a new project, and setup the development environment for you locally. After this step, I recommend using Visual Studio Code. You should open the IDE and start programming in it.

  1. $ code .   

I will initially upload the default web application, and then later, I will shift the content to the slots and deploy the latest changes to the production.

So, let us just go ahead and create a  Git repository inside the same directory. Later on, we will publish the project to a remote repository of our VSTS account's project. You would require to execute the following commands for that, 

  1. $ git add .  
  2. $ git commit -m "Committing the changes to repository".  
  3. $ git push https -//git.yourserver.com/repository_path.git   

I did the same, and targeted my VSTS project repository to publish the code. Once the code was published, the build system was triggered automatically. 


Figure 1 - Publishing the changes to VSTS repository.

That content gets uploaded to the VSTS repository.


Figure 2 - Content of online repository in VSTS.

Now, since our code has been modified, the continuous integration system triggers and starts to build the project as there were changes. 


Figure 3 - Build triggered and running in VSTS.

This is currently the build that our change triggered and queued upon. Now, this build system is for the ASP.NET Core provided by Microsoft in the VSTS. We can use other build systems, or create our own build systems based on the frameworks, or languages that we are using. However, since ASP.NET Core was the default here, I used that. 


Figure 4 - Build results for the latest changes in the repository.

After a few steps that are required in the build system, it would finally publish the built executables and other resources to an artifact folder from where other processes can copy the content easily. 

Now, since we are using the CD system, the trigger of a successful build would also trigger the deployment to a location where we have told it to. 

Using Deployment Slots

The reason why you should prefer using Deployment Slots is that, they are wonderful! Only Azure supports Deployment Slots, whereas on the other vendors, you are required to have two separate machines and connect them across. Whereas in Azure, things are different.

  1. Deployment slots are submachines in your own machine -- or service. 
  2. They provide an identical environment and configurations for your application to work. 
  3. Deployment slots mimic the production environment, so it is as if you were testing the application on the production environment.
  4. The swapping process takes zero downtime! Load balancers allow Azure to switch the IP address mapping to the virtual machines or services internally. 
  5. No requests are dropped in the swapping process. 

Thus, I also used the deployment slots in Azure, as they allow a lot of stuff to be managed easily. And it is my own recommendation to never deploy the applications directly to the production environment, as there needs to be some testing system that confirms that everything runs perfectly on the production environment as well, and not just on the testing environment. 

So, that is what I did. I created a deployment slot in the testing App Service for this post. 


Figure 5 - Deployment Slot made active in the application to store and stage the latest version of application for testing purposes, and booting purposes.

Then, once that was done, I went onwards to modify the release system and ensure that the release was performed to deploy the application to the deployment slot, instead of the production slot. 


Figure 6 - Release settings for our Azure App Service.

The "Deploy to slot" option configures whether to deploy to a slot, or to the production slot. So, now that our release is also managed the next step in the toolchain was to deploy it; and since our build was successful, the VSTS automatically triggered to deploy the application to the Azure Deployment Slot.


Figure 7 - Release processing the latest build and deploying the application to Azure.

Pay close attention to the picture above.

  1. It got triggered automatically (see the Description column).
  2. The build that was used to fetch the artifacts is also shown. 
  3. Time and the author is also shown. 

After this, the application gets deployed to the Server. 

Preview of the application

The first preview of the application is the following one.


Figure 8 - Deployment Slot application preview.

This is the preview of the application under deployment slots. If you look at the URL, you will notice "-deployment" appended to the URL, which means that this is the preview of our slot, and not the application itself. 

Benefits? Quite a few...

  1. We can run all sort of tests to check whether the latest build work properly or not. 
  2. All of the dependencies get loaded up before serving any user. "Warms up the slots"
  3. Users don't feel that the website was updated, instead they just see what's improved! 
  4. To update the production slot, all we need to do is, click a button. 
  5. In case of any problem, we can roll back the latest build... Even from a production slot! 

These are a few of the benefits that I have found in using Deployment Slots and which is why I personally recommend using Deployment Slots instead of the production slot, each time. Secondly, you can provide multiple slots to different teams and every team will work separately on their own environment testing their own stuff. 

Updating the application

Now, that our application is running, let us see how quickly can we update the application after a change. So, what I would be doing is updating the navigation header for the site. 

  1. <div class="container">  
  2.     <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">  
  3. <span class="sr-only">Toggle navigation</span>  
  4. <span class="icon-bar"></span>  
  5. <span class="icon-bar"></span>  
  6. <span class="icon-bar"></span>  
  7. </button> <a asp-controller="Home" asp-action="Index" class="navbar-brand">Updated!</a> </div>  
  8.     <div class="navbar-collapse collapse">  
  9.         <ul class="nav navbar-nav">  
  10.             <li><a asp-controller="Home" asp-action="Index">Home</a></li>  
  11.             <li><a asp-controller="Home" asp-action="About">About</a></li>  
  12.             <li><a asp-controller="Home" asp-action="Contact">Contact</a></li>  
  13.         </ul> @await Html.PartialAsync("_LoginPartial") </div>  
  14. </div>   

You might have noticed what I changed. (Look for "Updated!" in the middle of the code above).


Figure 9 - Committing the latest changes to the local repository.

This would update the local repository and then we can update the remote repository, to reflect the changes in our project's repository. That step was similar to what did previously, just publish the changes to the remove repository. 


Figure 10 - Pushing the changes to the server for deployment.

So, that change was pushed to the server and that change then triggered our toolchain for build, release and deployment for the ASP.NET Core web application. What this did was, that it

  1. Updated the remote repository.
  2. Triggered the build automatically – Continuous Integration.
  3. Triggered the release automatically, if the build succeeds – Continuous Deployment.
  4. Finally, publishes the application where it has to go live.

So, the rest of the stuff was similar to what we had previously. Same build procedures, same release cycles and then finally everything goes to the Deployment Slots. 

Swapping - Deployment Slots to Production Slots

At this moment, our application is properly running in the deployment slot! However, we need to swap the slots and then our users would be able to see the live updates. First of all, let us see how the updates changed our website then we will move onwards to update the website itself. 


Figure 11 - Latest updates on the Deployment Slot.

That is the deployment slot, and now, we can move onwards to apply the changes to the production slot. For that, we can select the Swap option from the Deployment Slots blade, which lets us choose which slot goes where. 


Figure 12 - Swapping the slots blade.

This order matters a lot. The Source should be loacted at where your recent updates are, and the Destination should be located where they should go! Now remember, although internally there is just a traffic shift from one source to another but in reality, if the order gets messed up, the results are undefined. I have tried to play around myself with it and it gets messed up really very much. So, do remember, that order is everything!

Finally, when we go back to our application website. You will see that the changes are now living there. 


Figure 13 - Preview of the production slot on Azure.

And the Deployment Slot gets the content of this application itself -- the default Azure App Service page. 

Summary

So, in this post, we solved a few things. First of all, we saw how CD gets to be the toughest IT part in DevOps (IT because there are some other tasks, such as user management where you get to face a headache of customer requirements and error management etc. -D). Then, we moved onwards to manage the Visual Studio Team Services in order to apply the automation across the steps and stages of App Life Cycle. 

Then, we saw how Azure Deployment Slots can help us get the most out of the testing systems and make sure that everything, I repeat, everything is working properly. 

What's next?

Here is the assignment. Notice that I mentioned, you can swap the Deployment Slots. There is a way to automate that as well - Using Powershell. You can easily use Azure PowerShell on Visual Studio Team Services to automate the swapping process as well. That way, you can run some tests on the production environment and then let the cmdlets do the rest of the job for you.

Azure PowerShell would let you migrate the website back also if you feel that the website is not performing well.