Volume 33 Number 4
Deploying Containerized ASP.NET Core Applications to Azure
Azure Key Vault is a cloud-based service that organizations can leverage to securely store sensitive business information. In the last issue of MSDN Magazine (msdn.com/magazine/mt845653), I explored a scenario in which insurance policies for vehicles generated by an agency could be stored securely in Azure Key Vault as secrets, and showed how additional features like asymmetric encryption with keys and built-in versioning could be used to maintain an audit trail of access to insurance policies. The applications that used Azure Key Vault were deployed to Azure App Service as Web apps. In this issue, I’ll be deploying the same applications to Azure Container Services for Kubernetes (AKS). Azure Container Services provides the ability to create and deploy Docker container-enabled applications to Azure.
There are two ASP.NET Core 2.0 Web applications in the solution accompanying this article, an admin portal used by the insurance companies, agencies and brokers, and a customer portal used by either the consumers who purchase the vehicle insurance policies or by regulatory authorities to ascertain the validity of the insurance policy. Refer to the previous article for more details on the business scenario addressed by the solution, and to learn how Azure Key Vault helped me meet those requirements.
Architecture of the Solution
Figure 1 represents the architecture of the solution, with minor changes from the previous article. Instead of Azure App Service, a single AKS cluster is used to host both Web applications on Linux, using Docker containers. Azure Application Gateway is used to expose an SSL-enabled endpoint to clients running in the browser and to the native Xamarin app, and routes requests to the Web applications deployed in AKS. Azure Active Directory (Azure AD) is used to authenticate the users of the admin portal while Azure Active Directory B2C (Azure AD B2C) is used for the consumers accessing the customer portal. Azure SQL Database stores the metadata information pertaining to the insurance policies created in the solution, and Azure Key Vault holds the sensitive information that will be used to ascertain the validity and authenticity of each insurance policy. There are some other options, apart from AKS, for deploying containerized applications, like Azure Container Instances (ACI) and Azure Web Apps for Containers, which are also covered in this article, though not depicted in Figure 1.
Figure 1 Solution Architecture
Modifying the Solution to Suit the New Architecture
Of course, changes to the architecture mean the solution must change. Let’s take a look at how I modified the solution.
Enabling the Web Applications for Docker Containers Visual Studio Tools for Docker provides a turnkey implementation to enable an ASP.NET 2.0 Core Application for both Windows and Linux Containers. Installing this tool gives you a context-driven menu option in your Visual Studio 2017 project that generates all the artifacts required to create a Docker container for the application. The admin and consumer (external) portal applications in the solution were packaged for Docker Linux containers. Before you can use the tool in Visual Studio 2017, you must install Docker for Windows and perform the configuration steps described at bit.ly/2F6YBRb. I created the Docker container images using the “Release” configuration in Visual Studio 2017 for each of the Web application projects.
Running the Docker commands in the console windows displays two container images, one for each portal application, as shown in Figure 2.
Figure 2 Docker Images of the Web Applications
Uploading Container Images to a Private Registry The container images created earlier were first uploaded to an Azure Container Registry (ACR), from where they would be consumed in Azure Container Services. The ACR instance created for this deployment is “contosoinsacr.” After signing into the registry using the Azure CLI, I executed Docker commands to upload the container images to this registry:
az acr login --name contosoinsacr --username <username> --password <password> docker tag contosoinsauthorityadminportal contosoinsacr.azurecr.io/contosoinsauthorityadminportal:web1v1 docker push contosoinsacr.azurecr.io/contosoinsauthorityadminportal:web1v1 docker tag contosoinsextportal:latest contosoinsacr.azurecr.io/contosoinsextportal:web2v1 docker push contosoinsacr.azurecr.io/contosoinsextportal:web2v1 az acr repository list --name contosoinsacr --output table
The final Docker command lists the container images from the ACR after they were uploaded. Refer to the documentation at bit.ly/2BZ1rdv, which details how to create an ACR and push a Docker image to it.
Deploying Containerized Web Applications
With the admin and external (customer) portal applications packaged as containers, there are multiple options available in Azure to deploy them. Let’s take a look.
Deploying to Azure Container Instances ACI provides the quickest way to run a container-based application in Azure, without your having to provision any virtual machines to host them or deal with container orchestration to handle more complex scenarios. You simply use the Azure Portal experience to create a new ACI and provide the access credentials and reference to the container images uploaded to the ACR in the steps covered earlier. On completion, the container instance gets provisioned and assigned a public IP address for accessing the Web application. These steps would be performed for both the admin and customer portal applications. Refer to the documentation available bit.ly/2CmuNhK to use the Azure Portal to create an ACI and deploy an application to it for more information.
Before these applications can be used, you need to configure the “redirect url” in the application registration pages in Azure AD for the admin portal and in Azure AD B2C for the consumer portal. Figure 3 shows the reply URL that’s configured for a Web application deployed to ACI or AKS.
Figure 3 Configured Reply URLs—Azure AD App Registration
Deploying to Azure Web App for Containers Deploying an application to Azure Web App for Containers is similar to deploying to Azure Container Instances in that there are no virtual machines to provision and no orchestrator for dealing with more complex scenarios. Instead, the containers are deployed to a managed Azure App Service Instance endpoint in Azure.
Figure 4 shows the settings required to create an Azure Web App for Containers instance in the Azure Portal. The URL to the Docker container image uploaded to the Azure container registry is captured as part of the configuration.
Figure 4 Azure Web App for Containers
Deploying to Web App for Containers provides other handy features that are available with Azure App Service, like the ability to scale out the Web app, configure auto scaling, and use deployment slots for staging and production.
Deploying to Azure Container Services for Kubernetes (AKS) The first step here is creating and configuring an AKS cluster. Before you can deploy the application to AKS from your local developer machine, you must have the “kubectl” command tools for Windows installed.
While the procedure can also be performed from the Azure Portal, the steps I’ll describe here are to provision an AKS cluster in Azure using the Azure CLI. Note that at this time, while ACS is generally available across all the Azure regions, AKS, which provides managed Kubernetes clusters with enhanced capabilities not available in ACS, and which is currently in Preview, is available in only a few regions around the world. In this case, I’m creating the cluster in West Europe. Here are the commands I use to do so:
az group create --name contosoinsacsrg --location westeurope az aks create -g contosoinsacsrg --name contosoinsacsportal --generate-ssh-keys --admin-username <username> --node-count 1 az aks get-credentials -g contosoinsacsrg -n contosoinsacsportal
To enable the AKS cluster to access the Azure container registry in order to pull the container images, the service principal of the AKS cluster is given a “Reader” role; that is, it’s given read access to the ACR instance hosting the images. Refer to the documentation at bit.ly/2ErvcBq for more details on this. Here are the CLI commands you use to perform these actions:
# Get the id of the service principal configured for AKS az aks show --resource-group contosoinsacsrg --name contosoinsacsportal --query "servicePrincipalProfile.clientId" --output tsv # Get the ACR registry resource id az acr show --name contosoinsacr --resource-group contosoInsAuthRG --query "id" --output tsv # Create role assignment az role assignment create --assignee <ServicePrincipalId> --role Reader --scope <resourceid>
Now let’s deploy the application to the AKS cluster. The steps I’ll explain here involve the use of kubectl commands on my development workstation running Windows and Docker.
I’ll deploy the application using “YAML” files. (YAML is a data serialization language often used for configuration files.) Figure 5 shows the YAML file used to deploy the admin portal in the solution. As an outcome of this step, the container image of the admin portal is pulled from ACR, provisioned in the AKS cluster and exposed through an Azure load balancer and public IP address.
Figure 5 The contosoinsportal.yaml File for Deploying the Admin Portal in the AKS Cluster
apiVersion: apps/v1beta1 kind: Deployment metadata: name: contosoinsadminv1 spec: replicas: 1 template: metadata: labels: app: contosoinsadminv1 spec: containers: - name: contosoinsadminv1 image: contosoinsacr.azurecr.io/contosoinsauthorityadminportal:web1v1 ports: - containerPort: 80 imagePullSecrets: - name: regsecret2 --- apiVersion: v1 kind: Service metadata: name: contosoinsadminv1 spec: ports: - port: 80 selector: app: contosoinsadminv1 --- apiVersion: v1 kind: Service metadata: name: contosoinsadminv1lb spec: type: LoadBalancer ports: - port: 80 selector: app: contosoinsadminv1
To allow access to the container image in ACR, the credentials must be provided in the YAML file using “pull secrets.” The following kubectl command generates a secret file called “regsecret2,” which is downloaded to the local machine. This file is referenced in the YAML file used to deploy the application:
kubectl create secret docker-registry regsecret2 --docker-server <acr-login-server> --docker-username <service-principal-ID> --docker-password <service-principal-password> --docker-email <email-address>
Running the next kubectl command deploys the admin portal to the AKS cluster, based on the YAML file passed as an argument. Browse the Kubernetes dashboard to view the deployed applications, as shown in Figure 6. These steps would be repeated for the external portal, after which both applications would be deployed to the AKS cluster, each with its own load-balanced, public-facing endpoints:
kubectl create -f contosoinsportal.yaml az aks browse --resource-group contosoinsacsrg --name contosoinsacsportal
Figure 6 Kubernetes Dashboard Showing the Deployed Applications
Now let’s look at the process for deploying application updates. When the next version of your project is available in Visual Studio 2017, the container image in Docker on the local machine is updated. Tag the image in ACR with the new version “web2v2” and push the update to it using the commands that follow. The last command uses kubectl to update the pods in the Kubernetes cluster with the new container image uploaded:
docker tag contosoinsextportal:latest contosoinsacr.azurecr.io/contosoinsextportal:web2v2
docker push contosoinsacr.azurecr.io/contosoinsextportal:web2v2
kubectl set image deployment contosoinsusersv1 contosoinsusersv1=contosoinsacr.azurecr.io/contosoinsextportal:web2v2
Figure 7 shows the landing page of the admin portal deployed to AKS.
Figure 7 The Admin Portal Running in AKS
CI/CD Automation Pipeline for Integration with Azure Container Services
Visual Studio Team Services can be used to implement a continuous integration and deployment pipeline for Docker-enabled applications running in Azure Container Services.
Visual Studio Team Services supports both Team Foundation Server and Git-based repositories for code check-in and version control. For code residing in external repositories like GitHub, a Web hook can be configured in Visual Studio Team Services that would trigger a build process when the code is checked in to the repository.
In the CI pipeline, using the “Docker Image creation” activity would create a new Docker image containing the application updates and push it to Azure Container Registry.
In the CD pipeline, using the “Deploy to Kubernetes” activity—and based on a YAML file—the updated container image could be pushed to an Azure Container Service cluster running Kubernetes.
When using Azure Web App for Containers, the Azure Portal lets you configure the CI/CD pipeline from the settings blade of the Web App. This configuration handles the generation of a new Docker image of the application when the code is checked in and the build process triggered, and lets the updated Web application be deployed and tested in the staging slot first, prior to pushing the image to the production slot.
Enabling SSL on the Web Applications
At this time, with AKS, the Web applications deployed are available using an HTTP endpoint only. To enable the endpoints for HTTPS instead, one of the options available is to deploy Azure Application Gateway, which would expose an HTTPS URL, perform SSL termination, and route the requests to the admin and customer portals.
Azure Application Gateway uses a custom probe to periodically monitor the health of the Web applications in the back-end pool. In order for the health probe to access a page in the Web application to check for application health, minor changes were made to both the portal applications by disabling authentication on the /home page, which doesn’t contain business-critical information. This page was then configured in the custom probe definition in Application Gateway to be used for the health check.
Alternatively, the Nginx Ingress Controller for Kubernetes supports TLS termination and can be used to SSL-enable access to the Web applications.
Deploying the Solution in Your Subscription
If you’d like to try out this solution on your own, you can download the source files and scripts from the GitHub repository at bit.ly/2DRvwdh. You’ll need the following software to implement this solution:
- Visual Studio 2017 Preview, Community or Enterprise Edition with Update 3
- An Azure subscription
- A Windows PowerShell script editor
- Azure CLI (bit.ly/2w3J00u)
- Docker Community Edition for Windows (dockr.ly/2mnfX7M)
- Visual Studio Tools for Docker (bit.ly/2F6YBRb)
- The Kubectl command tool for Windows (bit.ly/2swZVLJ)
The GitHub repository contains the source files for the admin and customer portals used in the solution. For this article, the single solution that contained the ASP.NET Core 2.0 MVC projects for both Web applications were separated into two individual solution projects so they could be packaged and deployed to containers separately. However, these individual solution files haven’t been added to the GitHub repository.
Minor code changes were made in both the projects to suit this article. In the previous article, I used .pfx files in the certificate store on the local machine, which the client embeds in its request to authenticate itself with the Azure Key Vault Service. In this issue, for simplicity, the client secret is used instead, along with the application ID, to authenticate the Web application with Azure Key Vault. The recommended approach is to use certificates in the request for authentication.
To deploy the two solution files to your Azure subscription, refer to the code snippets and reference documentation provided in this article.
Azure Key Vault is an effective mechanism that allows businesses to securely manage their sensitive business information using industry standard algorithms and techniques to perform cryptographic operations. Azure provides you with SDKs to consume this service on a variety of platforms in the language of your choice. Without having to make any significant code changes to your application, you could choose to deploy your solutions either as Web applications in Azure App Services or package them as Docker-enabled applications to Azure Container Services or Azure Web Apps for Containers. Visual Studio 2017 tooling for Docker provides a turnkey implementation to Docker-enable a Web application, hiding all the complexity and letting you focus on building business functionality. Azure Container Service gives you access to best-in-class, open source tooling support with Kubernetes for container orchestration. This, combined with the integrated tooling support for continuous integration and deployment with Visual Studio Team Services, ensures organizations have the right tools for agile software delivery across all the phases of a project lifecycle.
Srikantan Sankaran is a principal technical evangelist from the One Commercial Partner team in India, based out of Bangalore. He works with numerous ISVs in India and helps them architect and deploy their solutions on Microsoft Azure. Reach him at firstname.lastname@example.org.
Thanks to the following Microsoft technical expert for reviewing this article: Anil Dwarakanath
Anil Dwarakanath is a cloud solution architect at Microsoft and is based out of India.