Introduction to Azure Container Registry and Kubernetes Service

ACR-AKS

In one of my post of the .NET migration strategy series, we went through the exercise of adding docker and container orchestration support to our ASP.NET Core API solution. In this post we would like to perform an exercise to publish the docker images to Azure Container Registry (ACR) and then pull down the images from ACR and deploy to Azure Container Instances using Azure Kubernetes Service (AKS). Before we go further, let us have a generic overview what ACR and AKS is.

A bit knowledge on ACR and AKS

If you are new to ACR and AKS like me, then this post will most likely help you to get started. However, I will try not to go in depth to the working of these services and cover only the overview and essential concepts associated with this post.

What is Azure Container Registry (ACR)

ACR allows to build, store and manage images for all types of container deployments.

ACR has four key concepts which we need to know –

Registry – A stateless, highly scalable server side application in Azure that stores docker images and have a distributed pipeline for these images

Repository – One or more group of container images in the registry

Image – Read-only snapshot of Docker container as image which are pushed to the registry

Container – Package containing the application and its dependencies wrapped in complete file system which has the code, runtime, system tools and libraries

What is Azure Kubernetes Service (AKS)

AKS is managed Kubernetes cluster offering from Microsoft Azure hosted as a service which is responsible to manage containerized applications

Azure monitor plays a major role here for AKS collecting memory and processor metrics from containers, nodes in order to determine the container health.

I would recommend you to go through the documentation of ACR and AKS which will guide you to get more in-depth concepts.

Solution Design

Primary Objective

Our primary objective is to use the capabilities of Azure Container Registry and Azure Kubernetes Services to deploy and publish docker images in Azure.

Having said that, we need to design our solution in such a way that following tasks can be established –

Phase 1: A source code repository like GitHub which will have the source codes along with docker file and docker compose (.YAML) file. We have that already

Phase 2: Create a Azure Container Registry (ACR) where the docker images will be stored.

Phase 3: Create Azure Kubernetes Service (AKS) which will manage the containers after the docker images are published.

Phase 4: Publish the docker images to Azure Container Registry (ACR)

Phase 5: Deploy the container to multi-container AKS cluster application

Phase 6: Automate the above steps of triggering the creation of docker images, publish it to ACR and then deploy to AKS cluster.

Architecture

image

We already have completed Phase #1, using GitHub as our source control. Phase #2 where we are going to create an Azure Container Registry.

Phase #2 – Create Azure Container Registry (ACR)

ACR can be created by any means like Portal, Azure CLI as well as Azure PowerShell. However, here I am going to use Azure CLI to create the ACR.

Step 1: Download and install Azure CLI from here.

Step 2: Open Windows PowerShell ISE and use the command az login which will redirect you to login to your azure account.

Step 3: Once you have successfully logged in, create an Azure Container Registry Instance to your resource group using the below command.
[powershell]
az acr create –resource-group netcoremigration –name acrnetmigration –sku Basic
[/powershell]
image

Step 4:  Verify that the Container Registry has been successfully created in the portal.

image

Simple isn’t it.

Phase #3 – Create Azure Kubernetes Service (AKS)

Now let us create AKS cluster in Azure. We will do this using portal.

Step 1: Login to https://portal.azure.com and search for Kubernetes Service in the Azure marketplace.

image

Step 2:  Provide the required information like the Resource group (use the same where all your resources are there in this post), Region (some machines are not available in all region, hence I have selected East US which is closer to me), DNS name prefix (can be the same name as the cluster name). Select the number of nodes you want. I have kept it to 1. Click Review and Create.

image

Step 3: Next select Authentication where you can create a new service principal and also enable RBAC for Kubernetes. I am not enabling the RBAC.

image

Step 4: Configure the networking section. Set up HTTP application routing to Yes to integrate ingress controller with automatic public DNS and Network Configuration to Basic.

image

Step 5: In Monitoring section, keep Enable Container monitoring to Yes and select an existing or new Log Analytics workspace.

image

Step 6: Click Create. You can download the template for Automation purpose in future. Wait for the deployment to complete.

image

Awesome. Till now we have both completed our exercise of creating and having the ACR and AKS ready. Let us go ahead with our Phase #4 and Phase #5

Phase #4 – Building and pushing docker images to ACR

Let us have series of steps to publish docker images to ACR.

Step 1: Run Docker Toolbox

First of all, let me run Docker Toolbox in order to make docker environment available for executing docker commands. You can review my docker introductory post which will give you some details about docker and how to create images and containers.

Step 2: Verify the availability of docker images

Run the command in command prompt to view list of images available.

docker images

If you are creating the image for the first time, just follow this post which will give you step-by-step instructions of creating docker images.

image

Step 3: Tag the latest image with ACR

Run the following docker command to tag the image with a fully qualified path to registry.

docker tag {Image Name or Image ID} {Azure Container Registry/Image Name}

For e.g.

docker tag 901561ea73c5 acrnetmigration.azurecr.io/employeemanagementapi

image

Step 4: Push the image to ACR

In order to push the docker images to Azure Registry, we need to ensure that we are authorized to execute this step.

Run below Azure CLI command with your container registry name to get authenticated to your Azure account

[powershell]
az acr login –name {container registry name}
[/powershell]
image

Now run the below Docker command which will start the process of publishing the latest docker image to ACR

[powershell]
docker push {azure container registry host}/{image name}
[/powershell]

image

Step 5: Verify the docker image has been successfully uploaded

Log into Azure portal and open your container registry. Click Repositories to find the docker image that has been uploaded to registry.

image

You can even verify whether the image has been uploaded to ACR by running the below command

[powershell]
az acr repository list –name {container registry name} –output table
[/powershell]
image

Till here our task to upload the docker image to ACR is done. Our next step is to deploy the application to AKS.

Phase #5 – Deploy application to AKS

In this phase we are going to deploy our application to AKS. We have already created Kubernetes Service Cluster in Phase #3.

Step 1: Install Kubernetes CLI and set environment variables

Run the below command to install kubectl (which is Kubernetes command-line client)

[powershell]
az aks install-cli
[/powershell]
image

Based on the above message, we need to set the path of kubectl downloaded and installed in my environment variables.

image

image

Run the below command which is going to get the credentials required to connect with AKS cluster and update the config file in your .kube directory.

[powershell]
az aks get-credentials –resource-group {resource group name} –name {kubernetes cluster name}
[/powershell]

Here netcoremigration is my resource group name where my cluster netcoremigrationakscluster has been installed.

image

image

Open Windows PowerShell and run the below command to verify the connection to cluster

[powershell]
kubectl get nodes
[/powershell]

image

Step 2: Create or validate Kubernetes Manifest file

Kubernetes manifest file is a YAML file that defines the deployment and management of the application, deployed to the cluster. Basically, it contains information about images and containers, network ports to publish, etc. to name a few. Below is how the manifest file (employeemanagementportal.yaml) looks like. This file is accompanied with the solution here.

image

apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: employeemanagementapi
spec:
replicas: 1
template:
metadata:
labels:
app: employeemanagementapi
spec:
containers:
- name: employeemanagementapi
image: acrnetmigration.azurecr.io/employeemanagementapi
imagePullPolicy: Always
ports:
- containerPort: 8080
imagePullSecrets:
- name: regsecret
---
apiVersion: v1
kind: Service
metadata:
name: employeemanagementapi
spec:
ports:
- protocol: TCP
port: 80
targetPort: 8080
selector:
app: employeemanagementapi
type: LoadBalancer

As you can see, containers have name: employeemanegementapi which is the name of the container and image: acrnetmigration.azurecr.io/employeemanagementapi is the image published in ACR. The script is going to deploy the application to AKS cluster with the port 8080

Verify that ACR server name is same as mentioned like acrnetmigration.azurecr.io.

Run the following command in azure CLI or powershell to get the server name

[powershell]
az acr list –resource-group {resource group name} –query "[].{acrLoginServer:loginServer}" –output table
[/powershell]

image

Step 3: Deploy the application using the manifest file

In PowerShell, run the following command to create the Kubernetes objects in the cluster as specified in the file

[powershell]
kubectl apply -f {kubernetes manifest YAML file}
[/powershell]

For e.g.
[powershell]
kubectl apply -f employeemanagementportal.yaml
[/powershell]

image

Step 4: Verify the application

This is the final step where you would like to check that the application is up and running from AKS.

First check the status of the app by running the following command in PowerShell

[powershell]
kubectl get service {application name} –watch
[/powershell]

image

Browse the external IP generated from the command which in my case is 40.87.94.16. If everything looks good, you should be able to view the app in browser.

Some issues found and resolutions

Unfortunately, I am unable to get the app. So I went ahead to execute few steps that I would like to share here which might help you if you facing similar issues.

Run the following command in PowerShell to see if you are able to pull the container image.

[powershell]
kubectl get pods
[/powershell]

image

It is saying that the status of my container image is ImagePullBackOff, which means there is some issue happening. Microsoft documentation says that it might be due to invalid registry permission or having a wrong container image.

Following links Authenticate with Azure Container Registry from Azure Kubernetes Service and 10 Most Common Reasons Kubernetes Deployments Fail might be really handy to debug this issue.

Ok, so now my next step is to review the issue that is happening.

I used the below command in PowerShell to review what is causing the issue. As you can see employeemanagementapi-59484bdc4-2z745 is the pod name I got from the previous command

[powershell]
kubectl describe pod employeemanagementapi-59484bdc4-2z745
[/powershell]

image

Checking the event log, I do see that somehow pulling the image is not working

image

Next step is to check if I am able to pull down the image locally from ACR. So, I ran the below command and it seems to be giving authentication error.

[powershell]
docker pull acrnetmigration.azurecr.io/employeemanagementapi
[/powershell]

image

I went ahead to authenticate for ACR and then found that I am able to download the image, which clearly states that I need to provide AKS permission to download the image from ACR. This is just my assumption and I might be wrong too.

image

Run the following command to get the Id of the service principal configured for AKS

[powershell]
az aks show –resource-group netcoremigration –name netcoremigrationakscluster –query "servicePrincipalProfile.clientId" –output tsv
[/powershell]

image

Run the following command to get ACR registry resource id

[powershell]
az acr show –name acrnetmigration –resource-group netcoremigration –query "id" –output tsv
[/powershell]

image

Use the values of service principal ID and ACR registry resource id to run the below command to create role assignment

[powershell]
az role assignment create –assignee 8e58a2a4-f629-4a83-975f-8d32339d7a23 –role Reader –scope /subscriptions/94e96215-c87d-4548-819f-8c29436c44db/resourceGroups/netcoremigration/providers/Microsoft.ContainerRegistry/registries/acrnetmigration
[/powershell]

image

Create a reader role assignment with a scope of ACR resource by running the following command. Here netcoreadmin is my service principal name.

[powershell]
az ad sp create-for-rbac –name netcoreadmin –role Reader –scopes /subscriptions/94e96215-c87d-4548-819f-8c29436c44db/resourceGroups/netcoremigration/providers/Microsoft.ContainerRegistry/registries/acrnetmigration –query password –output tsv
[/powershell]

image

Get the service principal client id by running the below command.

[powershell]
az ad sp show –id http://netcoreadmin –query appId –output tsv
[/powershell]

image

Use the following command in PowerShell where efaa4271-5783-4044-ad41-02e0b9db8220 is the service principal client id and 5f828976-ed29-435f-ad86-efbc40b74fe8 is Service Principal Password generated by above statements. acrauth is the Kubernetes secret created. You can give any name you want.

[powershell]
kubectl create secret docker-registry acrauth –docker-server acrnetmigration.azurecr.io –docker-username efaa4271-5783-4044-ad41-02e0b9db8220 –docker-password 5f828976-ed29-435f-ad86-efbc40b74fe8
[/powershell]

image

Update the Kubernetes manifest YAML file to have the imagePullSecrets secret name as acrauth

image

After the Manifest modification, run the PowerShell command again which will modify the kubernetes objects created.

[powershell]
kubectl apply -f employeemanagementportal.yaml
[/powershell]

image

Run the below command again to check the status of the container. It will be on Running state

[powershell]
kubectl get pods
[/powershell]

image

Take the name of the pod and run the command to ensure that the container is running.

[powershell]
kubectl describe pod employeemanagementapi-65cb5764f6-nkhb8
[/powershell]

image

Once verified, run the below command to get the external IP address that you will browse to run the app. Keep it running

[powershell]
kubectl get service employeemanagementapi –-watch
[/powershell]

image

This should solve the problem.

Well, that’s it for now. In our next post we will cover Phase #6 which will deal on implementing proper CI/CD processes and automating the deployment using Jenkins and Azure DevOps.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.