In this article, let’s see how can we deploy an application on kubernetes cluster. In this article, we will try to deploy an application using kubernetes deployment locally.
The Sample Application
We will create an ASP .NET Core application. We will try to deploy the application on Azure Kubernetes cluster. We will also have little fun to see how kubernetes can help you to create fault tolerant applications.
The application’s home controller in ASP.NET Core application will expect the instance of IHostApplicationLifetime. The constructor should look like below:
public HomeController(ILogger<HomeController> logger, IHostApplicationLifetime hostApplicationLifetime)
{
_logger = logger;
this.hostApplicationLifetime = hostApplicationLifetime;
}
This instance it will use in the crash action to stop the web application. Below is the Crash action from the Home Controller.
public IActionResult Crash()
{
hostApplicationLifetime.StopApplication();
return Ok("stopping application");
}
The home page of the application shows the machine name. The sample code for the Index view is shown below:
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<h1>Machine Name: @Environment.MachineName </h1>
</div>
Let’s begin the Action !
Below is the step by step process to deploy the application.
Please refer this blog from the docker series to create the instance of AKS service. Please refer this blog from this series to create Azure container registry
Create Docker Image of Application
Add the dockerfile to your application. If you are using visual studio, you can right click on the project and select add new item and then select add docker support. The dockerfile should look like below:
Refer my previous blog to understand this file.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
WORKDIR /src
COPY ["SampleApplication/SampleApplication.csproj", "SampleApplication/"]
RUN dotnet restore "SampleApplication/SampleApplication.csproj"
COPY . .
WORKDIR "/src/SampleApplication"
RUN dotnet build "SampleApplication.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "SampleApplication.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "SampleApplication.dll"]
Assuming that you have Docker Desktop installed locally on your development machine, you can go to command prompt, navigate to the directory where solution file resides and run the below command to create the image.
# to create the image
docker build -t sampleapp-f SampleApplication/Dockerfile .
# to see the newly created image
docker image list
# to run the application
docker run -p 8080:80 --name mysampleapp sampleapp
The last command will run the application in docker container. If you try to access the application on https://localhost:8080 you should be able to see the host name of the container.
Also if you navigate to https://localhost:8080/home/crash, the application would stop working. The docker container is tied to this running process, if application stops, it will also stop.
In real world, your application may go in faulted state or may crash, but then will you really want human intervention to identify and correct the application instance?
There comes kubernetes. Coming steps will help us know how.
Push the Image to Azure Container Registry
Push the image to azure container registry. Use below commands to push the image. Please refer my previous blog to understand the steps.
# login to azure
az login
# login to azure container registry
az acr login --name mysamples
# tag the registry with image
docker tag sampleapp mysamples.azurecr.io/sampleapp
# push the image to registry
docker push mysamples.azurecr.io/sampleapp
# to get list of images at your registry
az acr repository list --name mySamples --output table
Create the deployment (YML document)
Below is the YML document, which suggests to create 2 replicas of the service.
apiVersion: apps/v1
kind: Deployment
metadata:
name: sampleapp-deployment
labels:
app: sampleapp
spec:
replicas: 2
template:
metadata:
name: sampleapp
labels:
app: sampleapp
spec:
containers:
- name: sampleapp
image: mysamples.azurecr.io/sampleapp
imagePullPolicy: IfNotPresent
restartPolicy: Always
selector:
matchLabels:
app: sampleapp
---
apiVersion: v1
kind: Service
metadata:
name: sampleapp-service
spec:
selector:
app: sampleapp
ports:
- port: 80
type: LoadBalancer
Save this file as deploysampleapp.yml.
Deploy the application.
Now docker desktop comes with kubernetes. Assuming that you have enabled kubernetes in the docker settings.
By default, if you run kubectl, it will be interacting with local kubernetes cluster. You can change it to point to the AKS cluster using below command.
# point kubectl to Azure Kubernetes Cluster
# Azure kubernetes cluster name is my-cluster
az aks get-credentials --name my-cluster --resource-group samples
Run below command to deploy the YML file on your Azure cluster. While running this file please make sure that file is present in the directory from where this command is executed.
kubectl apply -f deploysampleapp.yml
That’s it. You just deployed your application on Kubernetes cluster.
How to access application?
Check the pods by using below commands and make sure that they are in running status.
kubectl get pods
If they are not in running status then there may be many reasons why pod could not be started. You can run pod describe command to find the reason.
One of the most common reason why pod is not running may be because your container registry is not attached with kubernetes cluster. You can run below command to attach existing container registry with existing kubernetes cluster.
# cluster name is my-cluster
# resource group is samples
# registry name is mysamples
az aks update -n my-cluster -g samples --attach-acr mysamples
Run below command to know if the external IP address has been assigned.
kubectl get service
Once you see the external IP address assigned to service, you can access the application in browser using the IP on http protocol.
If you refresh page multiple times, you will be able to see that requests are going to different pods because you have load balancer in between.
Before we conclude
If you try to access the crash url at http://publicIP/home/crash, the pod will stop, as application stops. This is same as what we observed when the application was running as docker container.
But remember yml file ? There we specified that there should always be 2 instances running. So, kubernetes cluster, without any human intervention, restarts the pod. If you run kubectl get pods, you should be able to see number of restarts increase after you visit crash url.
That is how powerful kubernetes is when it comes to orchestration. The most important thing is it manages the state of application based on declarative syntax in yml file. You do not need to write steps on how exactly the intended state should be achieved.
I hope you find this article informative. Let me know your thoughts.