Tuesday 14 May 2024

Deploying Microservices Application on Kubernetes

This article extends my notes from an Udemy course "Kubernetes for the Absolute Beginners - Hands-on". All course content rights belong to course creators. 

The previous article in the series was Microservices Application Stack on Docker | My Public Notepad.

In the previous article in Kubernetes series we deployed the voting application on Docker. In this article we'll see how to deploy it on Kubernetes.

The goal is to:
  • deploy these applications as containers on a Kubernetes cluster
  • enable connectivity between the containers so that the applications can access each other and the databases
  • enable external access for the external facing applications which are the Voting and the Result app so that the users can access the web browser
The smallest object that we can create on a Kubernetes cluster is a pod so we must first deploy these applications as a pod on our Kubernetes cluster or we could deploy them as ReplicaSets or Deployments. We can first deploy containers as pods directly and later we can convert this to using Deployments.

Once the pods are deployed, the next step is to enable connectivity between the services. Let's review the connectivity requirements (which application requires access to which services and which application needs to be accessed externally).
  • Redis database
    • accessed by the Voting app and the Worker app. The Voting app saves the vote to the Redis database, and the worker app reads the vote from the Redis database.
    • has a service that listens on Port 6379
  • PostgreSQL database
    • accessed by the Worker app to update it with the total count of votes, and it's also accessed by the Result app to read the total count of votes to be displayed in the resulting web page in the browser.
    • has a service that listens on Port 5432
  • The Voting app
    • is accessed by the external users, the voters
    • has a Python web server that listens on port 80
  • The Result app
    • accessed by the external users to view the results
    • has a Node.js based server that listens on Port 80
  • The Worker app 
    • not being accessed by anyone. None of the other components or external users are accessing the Worker app. The Worker app simply reads the count of votes from the database and then updates the total count of votes on the PostgreSQL database. None of the other components nor the external users ever access the Worker app
    • has no service because it's just a worker and it's not accessed by any other service or external users.
How to make one component accessible by another? 

For example, how to make the Redis database accessible by the Voting app? The voting app should not use the IP address of the Redis pod because the IP of the pod can change if the pod restarts. 

In Kubernetes ClusterIP Service | My Public Notepad we learned that the right way is to use a ClusterIP service which is used to expose an application to other applications and in Kubernetes NodePort Service | My Public Notepad we learned that we should use NodePort service to expose an application to users for external access.

Let's first create ClusterIP services for those applications that should not be accessed outside the cluster:
  • a service for the Redis so that it can be accessed by the Voting app and the Worker app
    • will name it a redis service and it will be accessible anywhere within the cluster by the name of the service redis. The source code within the Voting app and the worker app are hardcoded to point to a Redis database running on a host by the name redis so so it's important to name our service as redis.
  • a service for the PostgreSQL pod so that the PostgreSQL DB can be accessed by the Worker and the Result app. 
    • named db because in the source code of the Result app and the Worker app, they are looking for a database at the address db 
    • while connecting to the database, the Worker and the Result apps are passing a username and password to connect to the database, both of which are set to postgres. So when we deploy the Postgres DB pod, we must make sure that we set the these credentials for it as the initial set of credentials to while creating the database.
Let's now create NodePort services for those applications for which we need to enable external access:
  • a services for Voting app 
  • a service for the Result app
When we create these services we can decide on what port we are going to make them available on and it would be a high port with a port number greater than 30000. 

We will be deploying five pods in total and we have four services. We have no service for the Worker pod and this is because it is not running any service that must be accessed by another application or external users. It is just a worker process that reads from one database and updates another so it does not require a service. A service is only required if the application has some kind of process or database service or web service that needs to be exposed, that needs to be accessed by others.

Deploying Microservices Application stack via Pods and Services

Here is the code of the Kubernetes project which deploys Voting app via Pods and Services: kubernetes-demo/minikube/voting-app at main · BojanKomazec/kubernetes-demo

Images used in the project above were derived from these:

And here is a similar implementation, via Docker only: https://github.com/dockersamples/example-voting-app

Deploying applications directly as pods has drawbacks as application cannot scale easily. If we wanted to add more instances of a particular service, and if we wanted to update the application like an image that was used in the application, then your application will have to be taken down while the new pod is created so that that may result in a downtime.

So the right approach is to use Deployments to deploy an application.

Deploying Microservices Application stack via Deployments and Services

We choose deployments over ReplicaSets as deployments:
  • automatically create ReplicaSets as required
  • help us perform rolling updates and rollbacks and maintain a record of revisions and record the cause of change
Project repo from the Udemy course: kodekloudhub/example-voting-app-kubernetes

My project repo: kubernetes-demo/minikube/voting-app-via-deployments at main · BojanKomazec/kubernetes-demo - it also contains instructions how to scale deployment of the Voting web app.


No comments: