Demystifying Kubernetes: A Closer Look at Pods, Namespaces, Deployments, Services, Secrets, and ConfigMaps

Demystifying Kubernetes: A Closer Look at Pods, Namespaces, Deployments, Services, Secrets, and ConfigMaps

By - GJS

What is Pod?

In Kubernetes, a pod is the smallest unit of deployment, representing a single instance of a running process. It can encapsulate one or more containers with shared resources. Containers within a pod communicate over localhost, scheduled and deployed together on a cluster node for efficient interaction. Pods are ephemeral, easily created, destroyed, or replaced, providing scalability and flexibility for containerized applications. They serve as the basic building blocks for higher-level abstractions like deployments and replica sets, managing pod lifecycles, scaling, availability, and network exposure.

Refer to my blog on creating a Kubernetes cluster using Kubeadm

Creating a Pod:

  1. On the Master node create a directory named "projects" and cd into it and create a file named "pod.yml"

  2. On the Master write the below commands in the pod.yml file

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

  3. On the Master node write the below command to create a pod :

      kubectl apply -f pod.yml
    

  4. On the Master node write the below command to see the pods :

      kubectl get pods
    

  5. On the Worker node type the below command to see the running containers :

     sudo docker ps
    

  6. Write the below command on the worker node:

  7. Now write the curl command :

     curl -L http://127.0.0.1:8000
    

    you will see that everything is running fine.

What is a Namespace?

In Kubernetes, namespaces provide a mechanism for isolating groups of resources within a single cluster. Names of resources need to be unique within a namespace, but not across namespaces. Namespace-based scoping is applicable only for namespaced objects (e.g. Deployments, Services, etc) and not for cluster-wide objects (e.g. StorageClass, Nodes, PersistentVolumes, etc).

Creating a pod inside a namespace:

  1. On the master node type to see the existing namespace:

      kubectl get namespace
    

  2. To create a namespace type on the master node :

     kubectl create namespace my-django-app
    

  3. Modify the pod.yml file to the one given below :

     apiVersion: v1
     kind: Pod
     metadata:
       name: django-app
       namespace: my-django-app
     spec:
       containers:
       - name: django-app
         image: trainwithshubham/django-todo:latest
         ports:
         - containerPort: 8000
    
  4. Now write the following command :

     kubectl apply -f pod.yml
    

  5. Now to see the created pod :

     kubectl get pods -n=my-django-app
    

  6. To delete the created pod :

     kubectl delete pod django-app -n my-django-app
    

What is a Deployment?

In Kubernetes, a deployment is a high-level object that defines the desired state for your application or service and manages the deployment and scaling of your application pods. It is one of the key resources provided by Kubernetes for managing containerized applications.

A deployment ensures that a specified number of replica pods are running and available at all times. It abstracts away the underlying infrastructure and handles the process of creating, updating, and scaling the pods based on the desired state defined in the deployment configuration.

Here are some key features and functionalities provided by a Kubernetes deployment:

  1. Pod Management: A deployment manages a set of identical pods, ensuring that the specified number of replicas are created and maintained.

  2. Rolling Updates and Rollbacks: Deployments support rolling updates, allowing you to update your application without downtime by gradually replacing pods with new versions. If any issues are detected, you can perform rollbacks to the previous version.

  3. Scalability: You can easily scale the number of pods up or down to meet the changing demands of your application using the deployment's scaling capabilities.

  4. Health Checks and Self-healing: Deployments monitor the health of pods using readiness and liveness probes. If a pod fails the checks, the deployment automatically replaces it with a new one, ensuring the desired state is maintained.

  5. Versioning and History: Deployments keep a history of revisions, allowing you to track and roll back to previous versions if needed.

By using a deployment, you can abstract away the complexity of managing individual pods and focus on defining the desired state of your application. Kubernetes takes care of the rest, ensuring that your application remains available, scalable, and resilient.

Creating a Deployment:

  1. In the project directory create the deployment.yml file

     vim deployment.yml
    
     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: my-django-app-deployment
       namespace: my-django-app
       labels:
         app: django-app
     spec:
       replicas: 2
       selector:
         matchLabels:
           app: django-app
       template:
         metadata:
           labels:
             app: django-app
         spec:
           containers:
           - name: django-app-container
             image: trainwithshubham/django-todo:latest
             ports:
             - containerPort: 8000
    
  2. Write the following command to create the deployment:

     kubectl apply -f deployment.yml
    

  3. Let's see the pods created in the namespace: my-django-app

     kubectl get pods -n=my-django-app
    

  4. To scale the deployment :

     kubectl scale deployment my-django-app-deployment --replicas=10 -n my-django-app
    

  5. Now, let's see whether the pods have been scaled or not :

What are Services?

In Kubernetes, a Service is an abstraction that defines a stable network endpoint for accessing a group of pods. It provides a way to expose and connect to your application running in pods, regardless of their underlying IP addresses or locations within the cluster. Services enable communication and load balancing between pods, allowing for reliable and scalable network connectivity within a Kubernetes cluster.

Key features and functionalities of Kubernetes Services include:

  • Provide a stable network endpoint for accessing groups of pods.

  • Enable load balancing and even distribution of network traffic.

  • Facilitate service discovery and dynamic connectivity between application components.

  • Support internal and external access, with different types available such as Cluster IP, NodePort, and LoadBalancer

Creating a Service :

  1. Create a service.yml file :

     vim service.yml
    
     apiVersion: v1
     kind: Service
     metadata:
       name: my-django-app-service
       namespace: my-django-app
     spec:
       type: NodePort
       selector:
         app: django-app
       ports:
         - port: 80
           targetPort: 8000
           nodePort: 30010
    
  2. Type the following command to create the service :

      kubectl apply -f service.yml
    

  3. Now make sure you have set inbound rules for port 30010 of the worker node :

  4. Now in the browser, type <Woker node's Public IPv4 address>:30010

What are Config Maps:

  • Store non-sensitive configuration data, such as environment variables or configuration files.

  • Enable decoupling of configuration from container images, facilitating easy modification and management of configuration.

  • Can be mounted as files or used as environment variables within pods.

  • Promote portability and maintainability of applications by providing a flexible and centralized configuration management mechanism.

Creating a Config Map:

  1. cd into the /django-todo-app/k8s/MYSQL-DB & create configmap.yml file with the following content :

     kind: ConfigMap 
     apiVersion: v1 
     metadata:
         name: mysql-config 
         labels:
             app: todo 
     data:
         MYSQL_DB: "todo-db"
    
  2. Now write the below command :

     kubectl apply -f configMap.yml
    

  3. To check the config map created :

     kubectl get configmap
    

What are Secrets :

Secrets in Kubernetes are resources designed to store and manage sensitive information, such as passwords, API keys, and TLS certificates. They provide a secure way to store and distribute this sensitive data to applications running within the cluster. Secrets are base64-encoded and can be mounted as files or exposed as environment variables to be securely accessed by pods. By utilizing Secrets, sensitive information can be stored and managed in a more protected manner within a Kubernetes environment.
In short secrets :
1. Store sensitive information such as passwords, API keys, and TLS certificates.
2. Securely encode and store sensitive data using base64 encoding.
3. Can be mounted as files or used as environment variables in pods.
4. Provide a secure way to supply sensitive data to applications running within the cluster.

Creating secrets :

  1. Create a secret.yml file :

     vim secret.yml
    

    NOTE:

    The below commands show how to encrypt/decrypt text using base64 :

     echo "hello@1234" | base64
    
     echo "aGVsbG9AMTIzNAo=" | base64 --decode
    

  2. Now write the secret file as follows :

     apiVersion: v1
     kind: Secret
     metadata:
       name: mysql-secret
     type: Opaque
     data:
       password: aG93YXJleW91Cg==
    
  3. Write the kubectl apply command to create secret :

     kubectl apply -f secret.yml
    

ConfigMap and Secrets in action :

*) Now let's create the deployment :

  1.         vim deployment.yml
    
     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: mysql
       labels:
         app: mysql
     spec:
       replicas: 1
       selector:
         matchLabels:
           app: mysql
       template:
         metadata:
           labels:
             app: mysql
         spec:
           containers:
           - name: mysql
             image: mysql:8
             ports:
             - containerPort: 3306
             env:
             - name: MYSQL_ROOT_PASSWORD
               valueFrom:
                 secretKeyRef:
                   name: mysql-secret
                   key: password
             - name: MYSQL_DATABASE
               valueFrom:
                 configMapKeyRef:
                   name: mysql-config
                   key: MYSQL_DB
    
     kubectl apply -f deployment.yml
    
     kubectl get pods
    

    *) If the pod crashed then use this command to create the secret and then create the deployment :

     kubectl get secret
    
     kubectl delete secret mysql-secret
    
     kubectl create secret generic mysql-secret --from-literal=password=howareyou
    
     kubectl get secret
    

    *) Now install MySQL on the worker node :

     sudo apt install mysql-client-core-8.0
    

    *) Now we go to the master node and connect to MySQL using the below command:

     kubectl exec -it <pod-name> -- /bin/sh
    

    *) Now connect the MySQL using username root and password from Secret :

     mysql -u root -p${MYSQL_ROOT_PASSWORD}
    

    Thank you :

    Dear readers,

    I want to express my heartfelt gratitude for your continuous support and engagement with my blog. Your readership and valuable feedback have been instrumental in shaping the content and direction of my writing. Thank you for being a part of this journey and for inspiring me to keep sharing my thoughts and ideas. Your presence means the world to me, and I am truly grateful for your unwavering support.

    Warmest regards, Gaurav Ji Srivastava