Monday, February 15, 2021

Build CI/CD Pipeline For Azure Kubernetes

Ahsan Siddique

 


Introduction

 
In my recent three articles, I developed a REST API with Azure Functions using SQL database and containerized Azure Functions Apps using Docker Desktop and created a CI/CD pipeline for my containerized Azure Functions App. In this article, I will create CI/CD pipeline for the Azure Kubernetes cluster because I want to do an automatic build and release process. If any developer wants to make a change in the code, then my pipelines will run automatically based on the branch name trigger. I already have pushed this application source code to Azure Repo. This is a public repo and anyone can access and clone the code. I will use the Azure Container Registry service for docker image hosting and I will use Azure Kubernetes service for container deployments.
  1. Develop A REST API With Azure Functions Using SQL
  2. Containerized Azure Functions Apps
Prerequisites
 
You are required to have intermediate-level knowledge of Azure Container Registry and Azure Kubernetes services and Azure DevOps.
 
Scheme
  • Create Azure Resource Group
  • Create Azure Container Registry
  • Create Azure Kubernetes Cluster
  • Create a Pipeline For Deployment to Kubernetes
Let's get started,
 
Log in to the Azure portal or log in through Azure CLI. I will show you both ways. Open your command prompt and use the following command in order to login to Azure. Make sure you already have installed the Azure CLI on your local.
 
az login
 
After logging in, you can see your all active subscriptions in the output and you need to set the subscription for this current context to do so use the following command. I have multiple subscriptions and I will use my Azure pass sponsorship for this context.
 
Build CI/CD Pipeline For Azure Container Instances
 
az account set --subscription "Azure Pass - Sponsorship"
 
Step 1 - Create an Azure Resource Group
 
As you know, we already logged in using CLI. Now we will create a resource group for our docker images and Kubernetes cluster. We will keep our all resources in this resource group that we are creating. Use the following command in order to create the resource group. If you don't have Azure CLI installed on your local you can follow the Azure Portal steps as shown below.
 
az group create --name "azurefunction-rg" --location "centralus"
 
Build CI/CD Pipeline For Azure Container Instances
 
Build CI/CD Pipeline For Azure Container Instances
 
az group list --output table
 
Step 2 - Create Azure Container Registry
 
We have created a resource group. Now for every new resource, we will add to this resource group. Use the following command to create the Azure container registry for hosting docker images. This is a paid service, but you can also use a free hosting service like Docker Hub.
 
(Azure Container Registry Name : azurefuncAcr)
 
az acr create --resource-group azurefunction-rg --name azurefuncAcr --sku Basic
 
Build CI/CD Pipeline For Azure Container Instances
 
Build CI/CD Pipeline For Azure Container Instances
 
As shown above, you can see that we have successfully created the Azure container registry.
 
Build CI/CD Pipeline For Azure Container Instances
 
Build CI/CD Pipeline For Azure Container Instances
 
Step 3 - Create Azure Kubernetes Cluster
 
Click on create a resource and choose Kubernetes Service. 
 
 
Select your subscription and resource group. Enter your cluster name and other options leave it to default, and then simply click on Review and Create.
 
 
We successfully created our Azure Kubernetes cluster.
 
 
Step 4 - Create a Pipeline For Deployment to Kubernetes
 
Login to your DevOps accounts and create a new project with the name Azure Function App.
 
Build CI/CD Pipeline For Azure Container Instances
 
Open this newly created project and add source code to this project repo. You can also use the existing source code that I mention on top of this article. I already have the source code in this project.
 
Build CI/CD Pipeline For Azure Container Instances
 
Next, click on the Pipeline tab and then choose the pipelines. This pipeline will build the source code and then create the docker image and will push to the Azure container registry that we created in the last step and create a new deployment to the Azure Kubernetes cluster. Click on create pipeline and choose the source code option. As I mentioned earlier that, I am using Azure Repos for my source code. I will select the Azure repo git option.
 
Build CI/CD Pipeline For Azure Container Instances
 
Select your repository and then branch. In my case, I will choose Azure Function App.
 
Build CI/CD Pipeline For Azure Container Instances
 
Next, select the Deploy to Azure Kubernetes Service (build and push the image to Azure Container Registry; Deploy to Azure Kubernetes Service) option from the Configure your pipeline page.
 
Build CI/CD Pipeline For Azure Container Instances
 
Next, select your active subscription from pop up and hit continue. In my case, I have two subscriptions and I select the (Azure Pass - Sponsorship). Enter your Azure account credentials and click sign in.
 
Build CI/CD Pipeline For Azure Container Instances
 
Next, select your Cluster name from the dropdown and choose the Namespace (existing or new), and select the container registry and enter the image name that you want to use. The service Port option leaves it with a default value. Finally, click on validate and configure.
 
 
Next, you will see an azure-pipelines.yml file that is a predefined template for building and pushing images to the Azure container registry and deploying them to the Kubernetes cluster. Just update the branch trigger name main to master or any branch name that you want to use for this build pipeline. Now we are good to go and we can save this pipeline as-is. Click on save and run.
  1. # Deploy to Azure Kubernetes Service  
  2. # Build and push the image to Azure Container Registry; Deploy to Azure Kubernetes Service  
  3. # https://docs.microsoft.com/azure/devops/pipelines/languages/docker  
  4.   
  5. trigger:  
  6. - master  
  7.   
  8. resources:  
  9. - repo: self  
  10.   
  11. variables:  
  12.  
  13.   # Container registry service connection established during pipeline creation  
  14.   dockerRegistryServiceConnection: '65de1c2f-d191-4f20-b6cb-15201e44d415'  
  15.   imageRepository: 'azurefunctionapp'  
  16.   containerRegistry: 'learningimagescontainerregistry.azurecr.io'  
  17.   dockerfilePath: '**/Dockerfile'  
  18.   tag: '$(Build.BuildId)'  
  19.   imagePullSecret: 'learningimagescontainerregistry1592bca3-auth'  
  20.  
  21.   # Agent VM image name  
  22.   vmImageName: 'ubuntu-latest'  
  23.     
  24.   
  25. stages:  
  26. - stage: Build  
  27.   displayName: Build stage  
  28.   jobs:    
  29.   - job: Build  
  30.     displayName: Build  
  31.     pool:  
  32.       vmImage: $(vmImageName)  
  33.     steps:  
  34.     - task: Docker@2  
  35.       displayName: Build and push an image to container registry  
  36.       inputs:  
  37.         command: buildAndPush  
  38.         repository: $(imageRepository)  
  39.         dockerfile: $(dockerfilePath)  
  40.         containerRegistry: $(dockerRegistryServiceConnection)  
  41.         tags: |  
  42.           $(tag)  
  43.             
  44.     - upload: manifests  
  45.       artifact: manifests  
  46.   
  47. - stage: Deploy  
  48.   displayName: Deploy stage  
  49.   dependsOn: Build  
  50.   
  51.   jobs:  
  52.   - deployment: Deploy  
  53.     displayName: Deploy  
  54.     pool:  
  55.       vmImage: $(vmImageName)  
  56.     environment: 'AzureFunctionApp-1436.default'  
  57.     strategy:  
  58.       runOnce:  
  59.         deploy:  
  60.           steps:  
  61.           - task: KubernetesManifest@0  
  62.             displayName: Create imagePullSecret  
  63.             inputs:  
  64.               action: createSecret  
  65.               secretName: $(imagePullSecret)  
  66.               dockerRegistryEndpoint: $(dockerRegistryServiceConnection)  
  67.                 
  68.           - task: KubernetesManifest@0  
  69.             displayName: Deploy to Kubernetes cluster  
  70.             inputs:  
  71.               action: deploy  
  72.               manifests: |  
  73.                 $(Pipeline.Workspace)/manifests/deployment.yml  
  74.                 $(Pipeline.Workspace)/manifests/service.yml  
  75.               imagePullSecrets: |  
  76.                 $(imagePullSecret)  
  77.               containers: |  
  78.                 $(containerRegistry)/$(imageRepository):$(tag)  
 
Here you will see in the output popup the three files will be added to our repository (azure-pipeline, deployment.yml, service.yml) choose the commit directly to the master branch option and hit Save and Run.
 
 
After Save and Run, you will see two stages. In the first stage, our code will be built and the docker image will be created and pushed to the Azure container registry. In the second stage, it will be deployed to the Kubernetes cluster.
 
 
The process of building an image and pushing it to the Azure container registry is in progress.
 
 
The stage of building an image and pushing it to the Azure container registry is done.
 
 
The process of deploying to the Kubernetes cluster is in progress. 
 
 
The stage of deploying to the Kubernetes cluster is done.
 
 
Open your Kubernetes cluster and from the left panel click on Services and ingresses. Here you will see a new service named azurefuncapp is running under the default namespace with its External IP address that we will use for the public.
 
 
Grab the External IP address of your service and open it in any browser. Amazing, the Azure Kubernetes cluster is up and running in the Azure portal. So, this was the process of building a CI/CD pipeline for Azure Kubernetes Cluster.
 

Friday, February 5, 2021

Containerized Azure Functions Apps

Ahsan Siddique


Introduction

 
In the previous article, I developed a REST API with Azure Functions using SQL database. So, In this article, I will show you how to containerized Azure Functions Apps using Docker Desktop.
 
Prerequisites
 
You are required to have basic knowledge of Azure Functions and beginner level knowledge of Docker.
 
Required Tools
  1. Azure Functions Core Tools
  2. Azure Functions SDK
  3. Docker Desktop
Road Map of Article
  • Create a Docker File
  • Create Container Image
  • Run Image Inside Container
  • Testing APIs with Postman
Let's Get Started 
 
I will use my existing Azure function app that was created in my last article.
Step 1 - Create a Docker File
 
Let's open your function app project and go to the Tools tab and select Command Line and then select Developer Command Prompt.
 
 
 
 
 
After opening the window like shown above on your local, right now you are the outside of your source code files, so let's go inside source code files. This is because we will create a docker file inside the main folder where all files live like our classescsproj file, etc. In the command prompt, write the dir command and hit enter. Now you can see all the files and folders that your application contains. Here, you can see a folder named RESTApiWithAzureFunction, so this is our main folder where we will create our docker file. To go inside this folder, write the cd {Your folder Name} command and hit enter. As shown below, I highlighted the commands. 
  1. dir                            //to check the folders and files inside the current directory  
  2. cd RESTApiWithAzureFunction   //to change the current directory      
 
Now we are in the right place and here we will use Azure Functions Core Tools to generate the docker file. Run the following command. This command will create a new docker file with all of its dependent base images.
  1. func init --docker-only  
 
 
 
 
Step 2 - Create a Container Image
 
We have added a Docker file inside our function app. Finally, it's time to create a container image with its dependent environments. Write the following command in order to create the image. If you already have all the dependent base images on your local, then it will take a very short time. However, if you are creating it for the first time, then it will take a bit longer because at first, Docker will pull all the base images from the Docker hub that the Azure function-core tool mentions inside the docker file. In the following command, you can see the docker build instruction and after that -t will specify the tag that specifies in the command with colon azurefuncimage:v1, and at the end, you can see a simple dot or period that indicates the current directory.
 
(Image Name = azurefuncimage)
  1. docker build -t azurefuncimage:v1 .  
 
 
 
 
Step 3 - Run Image Inside Container
 
We already built our Azure function app docker image. Run the following command to see all images that we have in Docker.
  1. docker images  
Now, we will run this image inside a new container. I will also add an environment variable in the command that will create and run the container because I want to add my SQL database connection string while creating a new container. Run the following command to get a new container up and running.
  1. docker run -e SqlConnectionString "Server=tcp:development.database.windows.net,1433;Initial Catalog=learning;Persist Security Info=False;User ID={Your ID};
  2. Password= {Your Password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" -p 8080:80 azurefuncimage:v1  
 
 
The docker run command will run the container based on the image that I specify at the end of the command. -n  tag specifying the name of the container and -e tag specifying the environment variable and -p tag will map the port that we want to expose to the outside of the container in my case, I am exposing 8080 port for public accessing and the 80 port is the internal port of the container. At the end of this command, you can see the image name with a tag that we created in the last step.
 
Run the following command to see all containers that we have in Docker.
  1. docker ps  
Now if you want to stop your running container, then run the following command in order to stop the container. At the end of this command, add the container Id that you can get using the docker ps command.
  1. docker ps stop containerId
Step 4 - Testing API’s with Postman
 
Open Postman and hit the following URL:
 
Post Request  - Create a new task:
 
 
Get Request - Get Task By Id: 
 
https://localhost:8080/api/task/id 
 
 
 
Get Request - Get Tasks List:
 
https://localhost:8080/api/task
 
 
 
Azure Function Logs Inside Container:
 
 
 
What Next?
 
In the next part of this article, I will demonstrate how to run containers inside Azure. Also, I will explain all steps of how to implement continuous integration and continuous deployment for Azure Function applications. Stay Tuned! Develop A REST API With Azure Functions Using SQL