Sunday 6 January 2019

Deploying ASP.NET Core App to Azure Kubernetes Services (AKS)–Setting Up Azure DevOps Pipeline Manually–Step By Step Guide–Part 2

In the part 1 of this post, enabling Docker support for ASP.NET Core app and building and pushing the Docker image to Azure Container Service, using Azure DevOps build pipeline with simple steps was described. The image is tagged with the build Id and it is pushed to the Azure Container Registry, so that it can be later deployed to a container orchestrator to run the container. Helm is used to get he deployment done to AKS via Azure DevOps when creating a an ASP.NET Core App, Container Registry and AKS, then getting it deployed automatically with few clicks using Azure Projects as described in the post “Deploy ASP.NET Core App to AKS with Azure DevOps Project”. Let’s look at getting the container image in Azure Container Registry deployed to AKS with three simple steps without using Helm, with Azure Pipelines.

As the first step we need to get an Azure Kubernetes Service cluster created in Azure, as described in the post here. Then create a release pipeline in Azure DevOps. Select the build created in the Part1, to build and push Docker image as an artifact to enable triggering the release when a new build is available.image

Enable continuous trigger (this is not mandatory and you can opt to create the release manually on demand).image

To deploy to AKS as the fist step you can create a namespace in AKS cluster. Namespaces in Kubernetes are described here. For this purpose we should create a YAML file and add the following YAML code to it. Then in the deployment pipeline we can use the YAML file in the Kubernetes deployment task to get the namespace created in AKS. Following should be the content of the YAML file. It says to use apiVersion v1, the type or the king is a namespace. Then in metadata tag you can specify the Namespace name. Here we have use __ prefix and suffix with KubNamespace to create a token in the YAML file. This token can be replaced at the time of deployment, which would allow the same YAML file to be used in deploying in multiple environments, such as Dev –> QA –> Staging –> Production in a deployment pipeline.

apiVersion: v1
kind: Namespace
metadata:
  name: __KubNamespace__

We need another, YAML file to describe how to get the Docker image deployed in the AKS cluster and then how to run the ASP.NET Core app in the container deployed as a service in Kubernetes. First part of this YAML file defines how the deployments should happen. You can see in the metadata in the deployment section, the AppName is tokenized so that it can be replaced at the time of deployment. As the container name also AppName is used. Container image location is tokenized so that at the deployment time the Azure Container Registry, Login Server info and the container image name and the tag (build version) can be replaced. Container port as hardcoded here to 80 as that is how it the port used in the Docker file to expose the ASP.NET Core app in the Part1. This port also can be tokenized if required. The SecretName token is used so that pulling the container image from the Azure Container Registry (ACR) in the Kubernetes (AKS) can be authenticated and authorized. If this is not provided, then Kubernetes will fail to pull the image from ACR with an access denied error. More details on setting this will be described in the deployment step later in this post. The second section specifies how to run the container in AKS. As the name of service the APPName is used and it is tokenized. The type is set to use the LoadBalancer in AKS. AppName token is provided as the app and port 80 is hardcoded to run the service but it also can be tokenized as mentioned earlier.

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: __AppName__
spec:
  template:
    metadata:
      labels:
        app: __AppName__
    spec:
      containers:
      - name: __AppName__
        image: __ACR__/__ImageName__:__buildversion__
        ports:
        - containerPort: 80
      imagePullSecrets:
      - name: __SecretName__   
---
apiVersion: v1
kind: Service
metadata:
  name: __AppName__
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: __AppName__

Add both the YAML files to the code repo you have used in the Part1.image

Then in the release pipeline add the repo as an artifact source so that the YAML files can be used in the release steps of the pipeline.image

image


Add the variables as shown below to the release pipeline. App name can be different from the container image name. Secret name can be any value of your preference which would be used to store service principle based ACR access details in Kubernetes cluster to enable obtaining images from ACR for deployment. Image name should be same image name that we have used in Part1. Since we linked the build from Part1 as primary artifact of the release pipeline we can use Build.BuildId predefined variable to get the tag of the Docker image. Provide a name for the Kubernetes namespace name variable KubNamesapce.image

ACR variable refers to Azure Container Registry login server as described in the deployment section of the YAML above. It can be obtained from the overview tab of the Azure Container Registry in the Azure portal.image

Create a release stage and provide a name for example Dev. Add an Agent phase and select Hosted2017 pool t run the deployment.image

Add replace token step coming with the marketplace extension here, Set the artifact path from repo as root directory and target files as *.yml to replace tokens in the YAML files described earlier. The prefix and suffix should be set as __ and this will make the YAML files to be updated with the values defined in the release pipelines, as the first step of the release.image

As the next step add a Deploy to Kubernetes task coming with extension available in marketplace, then click the Manage link near Azure subscription to add a service connection as described in Part1 and in this article. Connect the resource group you have created the AKS cluster in the service connection. Then select it for the Azure subscription in the Deploy to Kubernetes step as shown below. Once the subscription selected you would be able to select the resource group  and the AKS cluster in the step. Make sure to keep the namespace as empty in this step which is used to create the Kubernetes namespace if it does not exist in the AKS cluster. The namespace name would be found via the YAML file as described below and providing non existing namespace here would cause the deployment to fail, as it will try to use a namespace if provided to execute the action.image

Scroll down in the Deploy to Kubernetes step which is used for creating namespace, in the Commands section for the command set apply as the value. Select Use configuration files and for the configuration file provide the YAML file artifact path which  we added to the repo for namespace deployment. the YAML file token for namespace is already replaced with variable values by previous step replace tokens. Note that we do not have to secret information here as we are not yet deploying image to AKS. We do not have to update any other section of this step as we only create the namespace in this step.image

Add another Deploy to Kubernetes step which would be used to deploy the image to AKS. Then select the AKS cluster Azure subscription service connection, the resource group and the AKS cluster. Make sure to set the namespace variable in Namespace field this time as we are deploying the app in the newly created namespace in the previous step.image

In the Commands section for the command set apply as command and select the use configuration file option. for the Configuration file pick the deployment YAML file we created earlier. The tokens in this YAML will be replaced with the variable values we set in the pipeline, such as build Id for tag of docker image, docker image name, app name etc. Expand the secrets section and select the Type of secret as docker Registry. Then for Container registry type select Azure Container Registry. Select the service connection we have added in the Part1, which is having the connection to ACR we created in the Part1 to store the Docker image. Then Select the Azure Container Registry from drop down  which is having the Docker image. For the secret name provide the variable name we have set earlier. Select Force update secret option, which would always keep the secret updated in the Kubernetes cluster allowing it to access the selected ACR which is containing the Docker image to obtain it for deployment.image

With this you can save the release pipeline and create a new release. image

You can view Kubernetes dashboard as described here, and in the Kubernetes dashboard you would be able to see newly created namespace deployed with the app. In the Services of the Kubernetes dashboard you would be able to find the external endpoint of the app that is deployed to the cluster. image

When you click on in you would be able to view the ASP.NET Core app running in the AKS cluster.image

With the above steps we have completed the simple implementation of deployment to AKS via Azure DevOps which is simple and clear to manage. However, helm based deployment using Azure pipelines to AKS would be more enterprise ready, have much more flexibility as well as robustness to implement deployments targeting AKS. We can explore more on  them in the coming posts.

No comments:

Popular Posts