Understanding of Docker and Kubernetes - key technologies in deployment and management of the application

    Even though this is the second time I have learned Docker and Kubernetes, this is the first time I applied them to a project (idraiske food delivery application, GitHub). This totally changed my mind about building and deploying nature applications via Vercel. These technologies require more action than just finishing the application and clicking on "Deploy" on Vercel and don't care about further consequences. For example, assume you work for a big company, and you have to reach a high-quality web application since your application will not only handle HTTP requests but respond to them as fast as possible. Let's say, your application has 1000 of accessing at a time, which means about 1000 requests at the same time. Your application will collapse immediately since it can not handle too much at a time. So what is the solution?

There comes the concept of dividing traffic from Kubernetes. This blog is to demonstrate my understanding and application of Kubernetes and Docker in our lives. It might take your time to develop the website, but the result is valuable. 

Firstly, about Docker.

Source: Internet

    Docker is an open-source platform designed to simplify the process of developing, shipping, and running applications by using containerization. Containers are lightweight, portable, and self-sufficient units that bundle an application with all its dependencies, libraries, and configurations, ensuring that it runs consistently across different environments. Unlike traditional virtual machines, Docker containers share the host operating system's kernel, making them faster and more resource-efficient. With Docker, developers can create a standardized development environment, streamline application deployment, and facilitate scaling in cloud or on-premises infrastructures.
     Docker can solve a problem in teamwork: dependency mismatch. For example, I used version A in my local, and it worked well, however, in another teammate's local, it will not work. The reason is the mismatch in the dependency of the machine. To solve this, we can use Docker because Docker creates a standardized development environment, so it makes sure code will run in every environment. 
   In the Idraiske food delivery app, I used docker to create 5 containers to host 5 back-end microservices: Restaurant-listing, Food Catalogue, userInfo, order placement, and eureka server (a service to monitor all available microservices). Then I use Kubernetes as an orchestration to manage those containers. 

Second, about Kubernetes. 

Source: Internet

    Kubernetes is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. Orchestration involves managing the lifecycle of containers, including their deployment, scaling, networking, storage, and monitoring. Therefore, Kubernetes is a control plane that automates and coordinates these tasks, ensuring that the desired state of the application/system is maintained, which is kinda like a manager of that container.

    Kubernetes is so important to CI/CD progress because it simplifies deployment. If we deploy our application by ourselves on some servers, we have to prepare QA tests, and IT tests and manage the application on the server, which is difficult. Otherwise, Kubernetes will take care of those processes for you, and then your team can focus on the development process, such as application logic, and API enhancement. Kubernetes also automates scaling and load balancing. For example, Suppose a restaurant Microservice needs 3 replica sets. In that case, Kubernetes duplicates your container into 3, deploys them, and when requests come, it will be equally divided into 3 pods, so that 1 pod will not crash due to lots of requests bombarding it. Otherwise, Kubernetes is self-healing and fault-tolerant. It will periodically check containers to see whether there are any pods down or not. If there is any, Kubernetes will create 1 instance of it, and replace that faulty one. 

    There are 9 components of the Kubernetes concept: Node, Pods, Services, Ingress, ConfigMaps, Secrets, Volumes, Deployments, Stateful set. This picture makes me feel easy to approach these concepts of Kubernetes:

Source: Udemy course

1. Node

Let's say you deploy your application on a physical server, which is a virtual machine. That machine is also called a worker node or Node. This node will handle requests to the front-end application and fetch food catalog lists for a particular restaurant or a list of restaurants. Therefore, everything will happen inside that node. Another virtual machine called the master node, will manage worker nodes. 

2. Pods

In Kubernetes, a Pod is the smallest deployable unit and the basic building block of the platform. For example, in idraiske-food-delivery-application, I created a microservice (e.g.: userInfo), and then I dockerized it by a Docker container. Then, Kubernetes will wrap this container with 1 more layer called Pod, then deploy this pod on a Node. Each pod has its own IP address, and each pod can communicate using these IP addresses. 

3. Services

Service is the one that helps pods to interact with each other. For example, in the idraiske-food-delivery application, the Restaurant listing service needs the food catalogs of a restaurant, which also means that the Restaurant-listing Microservice communicates with the Food Catalogue Microservice. 

There are 3 types of services: ClusterIP, NodePort, and LoadBalancer. ClusterIP: Default service type. It exposes the service on an internal IP within the cluster, and it is only accessible from within the cluster, not outside. NodePort: This type exposes the service on a specific port of each cluster node's IP address. It makes the service accessible from outside the cluster by using the node's IP address and the assigned NodePort. Load Balancer: This type provisions an external load balancer (e.g., from a cloud provider) that directs traffic to the service. It automatically assigns an external IP address, making the service accessible from outside the cluster. => This has to be provided by cloud (AWS ALB)

4. Ingress

Ingress is an API object in Kubernetes that defines rules for routing external traffic to internal services ~ entry points for external requests. It means that ingress defines routing traffic rules, based on hostnames, paths, or other criteria to direct incoming traffic to appropriate services within the cluster. 

5. Config Maps

Configmap is used to store configuration data that can be consumed by containers running in pods. For example, in the idraiske-food-delivery application, I built back-end services that can support endpoint requests. Each Microservice uses some properties to connect to the real database, such as URL, username, and password. If we store them locally in the application.yml file (or application-dev.yml if we use Spring Boot profiling). If we store those credentials in the application.yml files, each time we change a property, we have to go to those application.yml files, change that property, rebuild the application, push the repository image to Docker, pull the new image to the pod, restart the pod. This is too complex. Therefore, we have the configmap file to decouple that process. In the project, I used a configmap file to store the URLs of databases (AWS RDS and MongoDB).

Configmap provides a way to decouple the configuration from the application code, allowing for easy configuration changes without modifying the container image. From it, we can separate configuration concerns from application logic, so that we can easily manage those credentials, and update configuration independently of the container images. Configmap promotes flexibility, maintainability,y and portability in a Kubernetes environment. 

6. Secrets

Secrets are files similar to configmap files, but the difference between them is that it is used to store secret data credentials and they are stored not in plain text format, but in base64 encoded format. Secret is used to store and manage sensitive information, such as passwords, API keys, tokens, or certificates. => Secrets provide a way to securely store and distribute sensitive data to containers running in pods. In the project, I used a secret file to store the credentials of databases (usernames and passwords). 

It is similar to the env variable in JavaScript. env is also used to store sensitive/confidential credentials, that can not be exposed to users. It also separates those data from application logic (just need to remember that, if you need that variable, call for env.xxx variable)

7. Volumes

Volumes are a way to provide persistent storage to containers running in pods. It plays a crucial role in managing and persisting data in Kubernetes. They enable containers to work with shared and persistent storage, allowing for data integrity, data sharing between containers, and reliable data storage beyond the lifecycle of individual containers. If your DB Pod crashes, your data is safe in volumes (because they are now stored in volumes). These are backup storage for the database in Pods. 

8. Deployments

Deployment in Kubernetes is like a blueprint or set of instructions for running and managing your application. Deployment is similar to a manager of my application since it ensures that the required number of copies of my application is always running, even if a pod or node fails. If I want to scale up the application, I can simply tell the Deployment to add more replicas, and it will automatically create and manage those new replicas for me. 

The deployment file or manifest file is like a blueprint that tells Kubernetes how to set up and manage different parts of your application or system. It is written in a format called YAML or JSON. In the project, I created 4 manifest files for managing 4 Microservices: Restaurant listing, food catalog, userInfo management, and order placement service. In those files, I declared the name of the pod, label, number of replicas for this deployment, Docker container image, and docker image credentials.  

9. Stateful set

StatefulSets also ensures that each pod has its own persistent storage so that data can be stored and retrieved even if the pod is terminated or moved to a different node. During the Idraiske food delivery application, I used Statefulset to deploy the Eureka Server, since the name of the pod will not change once the pod restarted. In the dev profile of each other pod, I used the service name of the Eureka server, which means that it should not be a random name or changed each time the Eureka pod restarts, or other Microservice will crash since it can not find the Eureka service. This means that the Eureka pod name should be constant (not changed), and StatefulSet can help me with this problem. 

Differentiate statefulSet and Deployments.


StatefulSet

Deployment

Similar

- Both are Kubernetes workload resources and define the action of deploying and managing pods. They are not types of pods themselves but are mechanisms for controlling how pods are created, managed, and maintained. 

Purpose

- Manage stateful pods

- Ensures pods have stable network identities and persistent storage.

- Suitable for applications requiring stable pod names or data persistence (e.g., databases, distributed systems).

- Manage stateless applications

- Ensures that the desired number of pod replicas are running.

- Automatically handles scaling, rolling updates, and self-healing (e.g., restarting failed pods).


Actions

- Deploy application

- Pods are named predictably based on the StatefulSet's name and their ordinal index.

<statefulset-name>-<ordinal-index>

E.g: app-name: my-service

=> my-service-0


=> Pod names are stable and persistent.

- Deploy application

- Generate new pod names if they failed or updated

<deployment-name>-<replica-set-hash>-<random-suffix>

E.g: app-name: my-app-deployment

=> my-app-deployment-6f23423-abcde

=> my-app-deployment–6f23423-bejdk

=> Names of pods are dynamically changed due to 1 action to the pod 

=> No stable identity

Service Relation

Service provides stable DNS for each pod.

Service provides stable access, but pod names are dynamic.

Communication

Pods can directly address each other using their predictable names. (ClusterIP)

Pods communicate indirectly through a Service, which acts as the stable endpoint. (NodePort, Load Balancer)

Example

Eureka (because in our Eureka MS: we do not use local, we use a specific URL for eureka, so when using DNS for this, the pod’s name is based on the URL - eureka-0 

Food-catalogue, Restaurant-listing, Order, UserInfo, Front-end

    Finally, to summarize the relationship between Docker and Kubernetes, Docker dockerizes/packages our application into a containerized application or a container (easy to deploy to any server) and Kubernetes deploys/monitors/maintains those containers. 



Comments