Demystifying Kubernetes: A Closer Look at Pods, Namespaces, Deployments, Services, Secrets, and ConfigMaps
Table of contents
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:
On the Master node create a directory named "projects" and cd into it and create a file named "pod.yml"
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
On the Master node write the below command to create a pod :
kubectl apply -f pod.yml
On the Master node write the below command to see the pods :
kubectl get pods
On the Worker node type the below command to see the running containers :
sudo docker ps
Write the below command on the worker node:
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:
On the master node type to see the existing namespace:
kubectl get namespace
To create a namespace type on the master node :
kubectl create namespace my-django-app
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
Now write the following command :
kubectl apply -f pod.yml
Now to see the created pod :
kubectl get pods -n=my-django-app
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:
Pod Management: A deployment manages a set of identical pods, ensuring that the specified number of replicas are created and maintained.
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.
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.
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.
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:
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
Write the following command to create the deployment:
kubectl apply -f deployment.yml
Let's see the pods created in the namespace: my-django-app
kubectl get pods -n=my-django-app
To scale the deployment :
kubectl scale deployment my-django-app-deployment --replicas=10 -n my-django-app
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 :
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
Type the following command to create the service :
kubectl apply -f service.yml
Now make sure you have set inbound rules for port 30010 of the worker node :
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:
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"
Now write the below command :
kubectl apply -f configMap.yml
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 :
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
Now write the secret file as follows :
apiVersion: v1 kind: Secret metadata: name: mysql-secret type: Opaque data: password: aG93YXJleW91Cg==
Write the kubectl apply command to create secret :
kubectl apply -f secret.yml
ConfigMap and Secrets in action :
*) Now let's create the deployment :
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