kubernetes Fundamental with project

In this blog post, we’ll walk you through the step-by-step process of deploying applications on Kubernetes, the popular container orchestration platform.

What is Kubernetes?

Kubernetes is an open-source Orchestration tool(clustering of any number of containers running on different networks) or we can say container management tool which automates container deployment, container scaling, load balancing of containerized application.

It schedules, runs and manages isolated containers which are running on virtual/physical/ cloud machines.

Kubernetes main role managing containers.

Let’s deploy our django application using kubernetes.

Note: Please follow the steps for deployment

Step 1: Pre-requisites:

Installation of Kubernetes on master and worker nodes:

Scripts/k8sss.sh at main · RishikeshOps/Scripts``````````

Step 2: Clone a repository

https://github.com/Hemantjangir53/django-todo-cicd.git

Let’s look into the docker file in this repository:

FROM python:3 

WORKDIR /data

RUN pip install django==3.2  # Python framework 

COPY . .

RUN python manage.py migrate

EXPOSE 8000

CMD ["python","manage.py","runserver","0.0.0.0:8000"]

It’s a Django application running on port number 8000 and the entry point to the application is manage.py

What are Containers?

Containers hold the entire packages that is needed to run the application. In other words, we can say that the image is a template and the container is a copy if that template.

Containers are created from images.

Step 3: Build an Image from Dockerfile

docker build . -t hemantjangir/django-todo-cicd:latest
  • Go to the repository cd django-todo and run the above command to create an image.

  • Run the docker images command to get the list of images.

Step 4: Push the docker image to a Registry

  • Login to the docker hub
docker login

After running the command it will prompt for username and password. Enter the details and you are successfully logged in.

  • Push the image to registry
docker push hemantjangir/django-todo-cicd:latest
  • Verify whether we have successfully been able to push the docker image to the registry.

There are primary two ways to create and manage resources:

  1. Command-Line Interface

  2. YAML Manifests

Command-Line Interface:

The Kubernetes CLI referred to as kubectl is a tool that allows you to interact with the Kubernetes Cluster. It provides a set of commands to create, modify, and manage Kubernetes resources

For example:

kubectl create to create a resource, kubectl edit or kubectl patch to modify the resource and kubectl delete to delete any resources, kubectl get pods to get all the pods in the default namespace. There are many more commands.

YAML Manifests:

YAML can stand for "yet another markup language" or "YAML ain't markup language". It's more human-readable and concise. YAML represents data as key-value pairs. YAML manifests are configuration files written in YAML. These files define the desired state of Pods, Deployments, ConfigMaps, Secret, and many more.

We will be using YAML Manifests to deploy our application.

What is Pods?

The code of our application runs inside containers, which are encapsulated within Pods in Kubernetes.

In Kubernetes, a pod is the smallest deployable unit. It's a group of one or more containers that run instances of an application. A Pod can contain one or more containers, and all the containers share the same resources such as CPU, memory, and storage.

  • Pods have their own unique IP address within the cluster, enabling other Pods or services to communicate with them.

  • Pods in Kubernetes are considered ephemeral, meaning they can be created, scaled, or terminated dynamically based on the desired state of the system.

1 Pod = 1 container is recommendand as best practices.

Task 1: Create your First Pod.

We will be creating a single pod using the YAML Manifests.

pod.yml

apiVersion: v1
kind: Pod
metadata:
  name: django-app
spec:
  containers:
  - name: django-app
    image: hemantjangir/django-todo-cicd:latest
    ports: 
    - containerPort: 8000

In pod.yml file,

  • apiVersion: v1 specifies the Kubernetes API version being used.

  • kind: Pod indicates that you are creating a Pod object.

  • metadata contains metadata about the Pod, including its name.

  • spec defines the desired state of the Pod.

  • containers is an array of container objects running inside the Pod. In this case, there is only one container.

  • name: django-app sets the name of the container to "django-app".

  • image: hemantjangir/django-todo-cicd:latest specifies the Docker image to be used for the container. In this case, it uses the image "hemantjangir/django-todo-cicd" with the "latest" tag.

  • ports defines the network ports that the container exposes. In this example, it exposes port 8000.

kubectl apply -f pod.yml

Run this command, Kubernetes will read our YAML file, and update any resources in our cluster accordingly. To see the newly created pod in action, you can run kubectl get pods. You should see the pod running.

Worker nodes are the machines in the Kubernetes cluster where Pods are scheduled and containers are run

  • Connect to Worker Node to verify if the container is successfully created.
docker ps

  • Let’s go inside the container and execute the curl command
docker exec -it 3551dae bash

Hey ! We have successfully been able to create containers via pod using YAML Manifests

Namespaces

Namespace is a logical entity which allow you to isolated your resources. They allow multiple teams or applications to co-exist in the same cluster.

Each namespace has its own set of resources, including Pods, Services, Deployments, ConfigMaps, and more.

  • By default, Kubernetes provides a default namespace where resources are created if no specific namespace is specified.

  • You can define RBAC (Role-Based Access Control) policies to grant different levels of access to resources based on namespaces.

Step 5: Create a Namespace

kubectl create namespace my-django-app

We will be creating my-django-app namespace for our application to include all the pods, services, deployment, and containers in this namespace.

Task 2: Create a Pod inside the Namespace

pod.yml

apiVersion: v1
kind: Pod
metadata:
  name: django-app
  namespace: my-django-app
spec:
  containers:
  - name: django-app
    image: hemantjangir/django-todo-cicd:latest
    ports: 
    - containerPort: 8000
  • To create the pod run the following command:
kubectl apply -f pod.yml
  • To verify the pods created inside the namespace
kubectl get pods -n=my-django-app

Deleting a Pod

kubectl delete -f pod.yml

Here, the pod will be deleted from the namespace my-django-app .

As we have added a namespace added in the metadata.

We just learned to create a pod inside the namespace.

Deployment

deployment is a tool that manages the performance of a pod. It is a desire state of pod.

Our app runs inside kubernetes cluster. Application consists of multiple pods, each representing a component of the application. Instead of manually creating and managing individual pods for your application, you can use a deployment.

  • It ensures that the desired number of replicas of each component is always available and handles any necessary updates or scaling.

  • Kubernetes monitors the health of the Pods managed by a Deployment. If a Pod fails or becomes unresponsive, Kubernetes automatically replaces it to maintain the desired number of replicas.

Step 6: Create a Deployment

deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: todo-deployment
  namespace: my-django-app
  labels:
    app: todo-app
spec:
  replicas: 3
  selector:      # 3 replicas make on the which basic it define by selectors 
    matchLabels:
      app: todo-app
  template:
    metadata:
      labels:
        app: todo-app
    spec:
      containers:
      - name: todo-app
        image: hemantjangir/django-todo-cicd:latest
        ports:
        - containerPort: 8000

In Manifest, we have declared

kind: Defines the type of resource, which is a Deployment in this case.

selector: filter that help identify objects with labels. Specifies the labels used to select which Pods are part of this Deployment.

labels: a type of metadata that are attached to objects like services and pods. They are key-value pairs that are used to describe identifying aspects of the object.

  • matchLabels: Defines the labels that Pods must have to be considered part of the Deployment. In this case, Pods with the label app: django-app will be included.

  • replicas: Defines the desired number of replicas (Pods) to maintain, set to 3 in this example.

  • template: It is a blueprint for creating pods. The template section includes metadata, such as labels, and the pod's specification.

  • spec: Specifies the specifications for the Pods created from the template.

kubectl apply -f deployment.yml  # run the deployment
kubectl get pods -n=my-django-app  # get the list of pods in namespace

You can then use the kubectl apply command to create or update the Deployment in your Kubernetes cluster.

To get the pods created inside a namespace kubectl get pods -n=my-django-app .

Scale

It is used to scale number of replicas(Pods) in the Deployments

Task 3: Create 10 replicas using Kubernetes CLI commands

kubectl scale deployment todo-deployment --replicas=10 -n=my-django-app
  • --replicas=10: Sets the desired number of replicas (Pods) to 10. This means that Kubernetes will adjust the number of Pods in the Deployment to match this value.

It has created 10 pods in Cluster

Service

You have a deployment with multiple pods running a web application. Each pod has its own IP address, which can change dynamically. If you expose these pods directly to clients, the clients would need to keep track of each pod’s IP address and handle potential changes. This approach becomes impractical as the number of pods scales up or down. To solve this problem, you can create a service.

It provides a way to expose your application running in Pods to other services or external users within the cluster.

Step 7: Expose your application to external users

service.yml

apiVersion: v1
kind: Service
metadata:
  name: todo-service
  namespace: my-django-app
spec:
  type: NodePort
  selector:
    app: todo-app
  ports:
    - port: 80    # cluster ip
      targetPort: 8000   # django port
      nodePort: 30007  # external port outseide the cluster

NodePort: Exposes the Service on a port across each cluster node’s IP. Allows external access to the Service. We are using NodePort (30000–32767) range of IP allowed.

  • port: Specifies the port number on the Service itself. In this case, it is set to 80.

  • targetPort: Specifies the port number on the Pods that the Service should forward traffic to. In this example, it is set to 8000

  • nodePort: 30007 : it is set to 30007, meaning that traffic arriving at nodeIP:30007 will be directed to the Service.

kubectl apply -f service.yml

Edit the inbound rule in the security group of the EC2 instance and click on save rules.

Access the Application

To access the application: http://<public_ip_of_instance>:30007

Well, Done! we have successfully deployed a todo application on Kubernetes Cluster.

To Delete the Deployment

kubectl delete -f deployment.yml