Kubernetes Book by rakesh kumar jangid
Kubernetes Book by rakesh kumar jangid
Table of Contents
1. What is the Need for an Orchestration Tool like Kubernetes and Why is it Needed?
2. What is a Monolithic Application, and How Does it Differ from a Microservices-Based
Application?
2.1 Monolithic Architecture
Real-world examples of monolithic applications
2.2 Microservices Architecture
Real-world examples of microservices-based applications
3. What is a Cluster? Describe Kubernetes Architecture with Diagram
3.1 Master Node Components (Short and Detailed Description)
API Server
etcd
Kube-Scheduler
Kube-Controller Manager
3.2 Worker Node Components
Kubelet
Kube-Proxy
Container Runtime
3.3 Step-by-Step Workflow – How Kubernetes Processes a Client Request
3.4 Additional Important Tools You Should Know About
Kubectl
Kubeadm
CNI Networking
4. Kubernetes Commands
4.1 Basic Kubernetes Commands
List Available Kubernetes Resources
Generate a Token to Join Nodes
Explain a Kubernetes Resource
4.2 Configuration-Related Commands
View Kubeconfig Content
Shows the Currently Active Context
Lists All Users in the Kubeconfig File
Renames an Existing Context in the Kubeconfig
List All Contexts
Switch to a Different Context
Set Namespace for the Current Context
Set User for the Current Context
5. Deployment Strategy and Its Types
6. Create & Manage Kubernetes Resources
Command Line Method (CLI Method)
Direct Edit Method (etcd Database)
YAML Manifest Files (File Method)
7. Namespace in Kubernetes
What is a Namespace in Kubernetes?
Namespace-Dependent Resources vs. Independent Resources
8. Core Kubernetes Workloads
Pod
ReplicationController (RC)
ReplicaSet (RS)
Deployment
DaemonSet
Static Pod
Init Container
9. Kubernetes Pod Scheduling
What is Pod Scheduling in Kubernetes?
Why is Pod Scheduling Different from Default kube-scheduler Scheduling?
9.1 Types of Pod Scheduling
nodeName Based Pod Scheduling (Direct)
nodeSelector Based Pod Scheduling (Labels Based)
Taint & Tolerations
Cordon & Uncordon
Affinity & Anti-Affinity
10. Kubernetes Configuration Management
ConfigMap and Secrets in Kubernetes
11. Kubernetes Storage Management
Persistent Volumes (PV)
Persistent Volume Claims (PVC)
Storage Classes
12. Kubernetes Resource Quota
13. Kubernetes Sidecar Containers & BusyBox
14. Kubernetes Networking & Services
Service, kube-proxy & CNI
15. Kubernetes Security & Authentication
Creating an Authentication Configuration File in Kubernetes Using API and Custom
Certification Keys
RBAC (Role-Based Access Control)
16. Kubernetes Ingress
Ingress Controller & Ingress Resource
17. Setting Up Kubernetes v1.30.2 Cluster Using Kubeadm on Ubuntu 22.04 LTS
Stay Connected
LinkedIn: https://www.linkedin.com/in/rakeshkumarjangid
My Blog: https://rakamodify.store/
Lastly, I believe that I could only put this together because of the grace of Lord Krishna
and my Guru. In truth, they are the ones making everything happen.
Thank You
Rakesh Kumar Jangid
From Containers to Kubernetes: Understanding the Need
When we build an applica on, just wri ng the code is not enough. We also need to deploy it
properly so that it runs smoothly, scales when needed, and works without interrup on.
In the past, companies used a method called monolithic architecture, where the en re
applica on was built as a single unit. This approach had many problems. If even a small part of
the applica on had an issue, the whole system could fail. Scaling was difficult, and adding or
upda ng features took a lot of me and effort.
Later, container tools like Docker and Podman made applica on deployment easier by
packaging everything into lightweight containers. But there were s ll challenges. Managing
one or two containers was simple, but handling hundreds or thousands of them manually was
not prac cal.
What is need of Orchestra on tool like Kubernetes and why this is needed?
Why Do We Need Kubernetes?
1. Scalability
Kubernetes automa cally adjusts the number of containers based on your app's traffic
or workload. For example, if your app gets a traffic spike during a sale, Kubernetes can
instantly add more containers to handle the load and scale down when traffic decreases,
saving resources. Bytheway this type of scaling is known as Horizontal Scaling.
What is Horizontal Vs Ver cal Scaling?
horizontal and ver cal scaling in Kubernetes can indeed be understood and
implemented on two levels:
a) Host Server and Resource Level (Infrastructure Scaling)
Horizontal Scaling: Adds more physical or virtual machines (nodes) to the
cluster. Kubernetes automa cally distributes workloads across these
addi onal nodes. For example, if the cluster is running out of resources,
you can add another server to expand the available capacity.
Ver cal Scaling: Increases the resources (CPU, memory, disk) of exis ng
nodes in the cluster. This is done at the infrastructure level by upgrading
the hardware or resizing virtual machines.
b) Pod or Deployable Resource Unit Level (Applica on Scaling)
Horizontal Scaling: Adds more pods (replicas 2 to 5 ) of your applica on to
handle increased workload. This is managed through Kubernetes'
deployment scaling, where new pod instances are created to share the
load. There is No down me and this is more fault tolerance.
Ver cal Scaling: Increases the resource alloca on (CPU, memory) of
individual pods by adjus ng their resource limits and requests. Kubernetes
ensures that the pod has more resources to handle its tasks efficiently. Best
and simpler to manage for single-pod applica ons.
2. Resource Alloca on
Kubernetes ensures your hardware (servers) is used efficiently. It decides where to run
containers so that no server is overloaded while others are underused. This op mized
resource alloca on saves costs and improves performance.
3. Self-Healing
If a container crashes or has issues, Kubernetes detects it and replaces or restarts it
automa cally. It constantly monitors the health of your app to ensure everything runs
smoothly without requiring manual interven on.
4. Security
Kubernetes offers built-in security features such as:
o Isola on between containers to prevent one from affec ng others.
o Role-based access control (RBAC) to limit who can perform certain ac ons.
o Secret management for handling sensi ve informa on like API keys and
passwords securely.
5. Portability
Kubernetes runs on any environment (Dev, Test, Prod), whether it’s a cloud provider like
AWS, Azure, Google Cloud, or an on-premises server. This portability means you can
move your app between environments without making significant changes.
6. Up me
Kubernetes helps maintain near 100% up me for your app. Through features like load
balancing, rolling updates, and self-healing, it ensures your app stays online, even during
updates or unexpected failures.
7. Support for Microservices
Modern applica ons o en use microservices—small, independent services that work
together. Kubernetes makes managing these microservices easier by handling
networking, scaling, and service discovery (le ng containers find and talk to each
other).
8. DevOps Support
Kubernetes is a perfect fit for DevOps workflows. It integrates well with CI/CD
(Con nuous Integra on/Con nuous Deployment) pipelines, enabling teams to
automate deployments, tes ng, and rollbacks. It also supports collabora on between
development and opera ons teams, making it a key part of the DevOps culture.
What is a monolithic applica on, and how does it differ from a microservices
based applica on?
Monolithic Architecture
A monolithic architecture is built as one big, unified system where all applica on
dependencies, code, and layers work together as a single unit. If one part of the code or logic
fails, the en re applica on can go down. Any changes require redeploying the en re app,
which o en leads to significant down me and an increased chance of errors in the future.
Real-world examples of monolithic applica ons:
eBay (early versions): Everything was built as one large applica on, making it challenging
to scale and update.
WordPress (before mul -site support): Early versions were monolithic, where all
features were integrated ghtly together.
Shopify (ini al stages): Ini ally, it was a monolithic app before transi oning to
microservices as it grew.
Microservices Architecture
In contrast, a microservices architecture splits the applica on into smaller, independent parts,
o en running on separate systems like containers. Each part works independently, so if a
change is needed in one part, the rest of the applica on con nues running smoothly without
down me or added risk.
Real-world examples of microservices-based applica ons:
Ne lix: Moved from a monolithic architecture to microservices to handle the massive
scale of users and content.
Amazon: Uses microservices for different func ons like order management, payment
processing, and recommenda ons.
Uber: Uses microservices to manage different parts of its app like ride requests, driver
loca on tracking, and payment systems.
Monolithic: One big box, ghtly connected, prone to failure and down me when
changes are made.
Microservices: Many small boxes, independently running, allowing updates without
impac ng the rest of the app.
Note: In-Short:
A Kubernetes cluster has two main components and later sub-components:
1. Master Node(s) (Control Plane)
API Server
etcd
Kube-Scheduler
Kube-Controller Manager
API Server
The API Server is the central point of interac on for the en re Kubernetes system. It
processes all requests related to crea ng, upda ng, or dele ng resources, ensuring they
are routed to the correct parts of the system. The API Server also checks for user
authoriza on and enforces rules, ensuring that only authorized users can make changes
to the cluster. All other components communicate through the API Server to interact
with the cluster, making it the 'middleman' or 'hub' for communica on between all
other cluster arch-components.
etcd
etcd saved current state of the cluster. etcd is a key-value store used by Kubernetes to
hold its most cri cal data, including the current state of all resources within the cluster
(such as Pods, nodes, services, etc.). This distributed database ensures data consistency
across all nodes in the cluster and provides backup for the cluster’s state. If anything
goes wrong, etcd helps restore the cluster to its previous state.
Kube-Scheduler
The Kube-Scheduler is responsible for determining which worker node should run a new
Pod. It evaluates the resources available on the nodes (e.g., CPU and memory) and
considers any placement rules (such as affinity or taint tolera ons). The scheduler then
places the Pod on the most suitable node based on these factors. In short, the Kube-
Scheduler determines the ideal node for running a new Pod.
Kube-Controller Manager
The Kube-Controller Manager ensures that the Kubernetes cluster always remains in its
desired state. It con nuously monitors etcd for any changes, which are triggered by
requests from the API Server. Whenever the state of the cluster changes, the controller
works to restore the system to the desired as per requested state by taking correc ve
ac ons, such as scaling applica ons, replacing failed Pods, or ensuring node health. The
Kube-Controller Manager automa cally performs these tasks to keep the cluster in the
desired state
Kubelet
The Kubelet is an agent that runs on each worker node in the Kubernetes cluster. It
receives instruc ons from the API Server, which runs on the master node. The Kubelet
ensures that the Pods, the smallest deployable units in Kubernetes, are running as
expected. It also con nuously monitors the health of the node and its Pods, repor ng
the status back to the master node API Server to ensure the cluster remains in the
desired state.
Kube-Proxy
Kube-Proxy is the default networking component in Kubernetes responsible for
managing network traffic for Pods and Services. When you create a Service in
Kubernetes, Kube-Proxy automa cally manages the network rou ng and ensures that
traffic is correctly forwarded to the appropriate Pods as per dedicated services,
regardless of the nodes they are running on. It performs load balancing by distribu ng
traffic across mul ple Pods to prevent overloading any single Pod. Addi onally, Kube-
Proxy manages network rules using iptables or IPVS on each node, ensuring that
network traffic is routed efficiently and accurately.
While Kube-Proxy handles traffic rou ng and load balancing, it works alongside the
Container Network Interface (CNI), which handles the underlying networking setup and
IP assignment for Pods. Essen ally, Kube-Proxy ensures seamless communica on
between services and Pods, enabling proper network traffic management within the
cluster.
Container Run me
The Container Run me is the main so ware behind, responsible for running and
crea ng containers inside Pods. It performs tasks such as pulling container images,
star ng and stopping containers, and managing the overall lifecycle of containers.
Examples of container run mes include containerd and CRI-O. For instance, Docker uses
containerd as its container run me, while Podman uses CRI-O. The Container Run me
runs on all worker nodes and receives instruc ons from the Kubelet.
kubectl
kubectl is the command-line tool used to interact with a Kubernetes cluster. It allows
you to run commands against the Kubernetes API server, which manages the cluster.
With kubectl, you can perform various opera ons such as:
Crea ng, upda ng, and dele ng resources: like Pods, Deployments, Services, etc.
Monitoring and debugging: viewing the status of resources, logs from Pods, and
other informa on.
Managing configura ons: applying and modifying configura ons in the cluster.
Essen ally, kubectl acts as the primary way for administrators and developers to
communicate with and control the Kubernetes cluster.
Kubeadm
kubeadm is a tool for easily se ng up a Kubernetes cluster. It provides commands to
help you ini alize the master node, join worker nodes to the cluster, and manage certain
cluster configura ons. It automates the process of se ng up the control plane
components (API server, controller manager, scheduler) and helps in crea ng a secure,
produc on-grade cluster. But you s ll need to configure and manage the network and
storage components separately, that is not the part of kubeadm cluster setup.
CNI Networking
CNI (Container Network Interface) is a specifica on and a set of plugins used for
configuring networking in Kubernetes. It is responsible for providing networking
features that allow containers and Pods to communicate with each other and with the
outside world, even when running across mul ple worker nodes and within a single
deployment resource.
CNI plugins manage things like:
Assigning IP addresses to containers and Pods.
Enabling Pod-to-Pod communica on across nodes.
Configuring network policies to control traffic between Pods.
In Kubernetes, CNI ensures that Pods can communicate with each other within the
cluster and with external services, and it can integrate with different network plugins
(like Calico, Flannel, Weave, etc.) to provide various networking features.
Kubernetes commands
Basic Kubernetes Commands:
1. List Available Kubernetes Resources
This command displays all the Kubernetes resource types (like Pods, Services,
ConfigMaps) along with their API version, short name, kind, and whether they are
namespaced. It helps in understanding what resources are available and how they are
grouped. This is an important command for wri ng and learning YAML for Kubernetes
resources.
Command: # kubectl api-resources
2. Generate a Token to Join Nodes
As we know, kubeadm is a cluster setup command-line tool and this command
generates a token for adding new worker nodes to a cluster and provides the join
command to execute on the nodes. It’s useful for scaling your cluster by adding more
nodes.
Command: # kubeadm token create --print-join-command
For your informa on, it’s important to know that most deployment strategies in Kubernetes
share a common YAML syntax, including fields like apiVersion, kind, metadata, and spec. You
can use the kubectl explain command followed by the resource name to get help in wri ng
the complete or required YAML manifest files as per your need.
¶ Although Command Line Method (CLI Method) is not the standard way
to work, because we don’t have any working history with that but this
method is quick for smaller tasks or when working with predefined
configura ons.
Just like in Docker or Podman, you can run two separate applica ons
without conflicts. How does that happen? Because each container runs in
its own namespace, which logically isolates the environment. Similarly, in
Kubernetes, you can isolate applica on-related resources like Pods,
Deployments, Services, Secrets, Volumes, and even access controls by using
namespaces. You can create your own namespace, and use accordingly.
How to set namespace in config file without open config file directly?
Modifies the current context to use a specific namespace by default. This eliminates the
need to specify the namespace for every command.
¶ Note: you can create a manifests file from cli using --dry run=client. The
dry-run method validates and generates a YAML manifest from the
provided CLI op ons without crea ng the actual resource.
¶ Later, the -o op on specifies the output format, such as YAML (-o yaml),
JSON (-o json), or other formats. You can redirect this output to a file for
future use.
Check the status of Pod in detailed (including node name and labels)
Command: # kubectl get po –show-labels
Run this and Verify its crea on. In custom namespace “grras”
Command: # kubectl create -f ./pod1.yml
Command: # kubectl get po -o wide --show-labels
Inspec ng a Pod
Command: # kubectl describe po <pod-name>
Accessing a Pod’s Shell
Command: # kubectl exec -it <pod-name> -- /bin/sh
A er tes ng, clean up the resources you created. In custom namespace “grras”(Note:
No HA feature available)
Command: # kubectl delete pod <pod-name>
Command: # Kubectl delete -f pod-file.yml ##------ Using manifests file method
Command: # kubectl get po
No Scaling:
Pods cannot automa cally scale up or down to handle future high demand for
applica on services. Scaling requires a system that dynamically adjusts
the number of Pods based on the load on the applica on. However, with Pods alone,
this process cannot happen automa cally—you have to monitor the load manually
and scale Pods yourself. This can be a tedious and error-prone task, o en leading to
down me and disrup ons in service.
No Persistent Storage:
Data stored in a Pod is ephemeral by default. If the Pod restarts, all data is lost unless
persistent storage is configured.
No Rollback or Rollout:
In today’s real-world scenarios, having the ability to roll out new versions or roll back
to a previous stable state is cri cal. Pods by themselves lack these features, making
them unsuitable for modern, reliable deployments.
Pod Removal: If there are more Pods than the desired count, the Replica on Controller
iden fies and removes the unnecessary ones. However, before removing excess Pods, it
first takes control of any orphan Pods to bring them under its management.
¶ Since 2 Pods with the label app: web already exist, the Kubernetes
controller will create only 2 addi onal Pods to reach the desired total of
4 replicas, as specified in the replicas field of the Replica onController.
¶ For monitoring purpose. If you will describe the pod this me, you will
see they are managed by “web-controller” Replica onController.
Because this me they are not orphan, they have parents.
Answer:
Create the Pods using an online raw YAML file. (The YAML file has been uploaded to my GitHub
account. You can download that file from wget )
Command: # kubectl create -f \
h ps://raw.githubusercontent.com/rakesh08061994/k8s-prac ce/refs/heads/master/rc4pod.yml
Check now: Pods are being created on random nodes as scheduled by the kube scheduler. You
can verify this by describing the Pods to confirm that they are for now not managed by the
Replica onController.
Command: #kubectl get po -o wide --show-labels
Describe the pod
Command: # kubectl describe po <pod-name>
¶ Info: In the Pod's logs, at the end, you can see that the kube-scheduler
is responsible for selec ng the best node for the Pod (We are not
choosing any nodes, its kube-scheduler), while the kube-controller
ensures that the desired state matches the requested state in any
condi on, that you gives as replicas=value.
Now create a Replica onController named web-controller with a requested replicas value of 4
and the label dev=wp. This will allow it to take control of the exis ng orphan Pods already
running in the cluster that match the specified label.
¶ Note: If you want to scale up or scale down the number of Pod replicas,
the kube-controller-manager will manage the desired state, while the
kube-scheduler will schedule Pods accordingly.
¶ If you increase the replicas, new Pods with the label app:wp will be
created. If you decrease the replicas, extra Pods will be removed, and
the system will ensure the desired state matches the requested state.
This is the process behind scaling in Kubernetes.
¶ When you delete some Pods with matching labels, and the number falls
below the requested replicas, the Replica onController will
automa cally create the exact number of Pods needed to restore the
requested = desired number of replicas. This is managed by the kube-
scheduler and the controller manager.
¶ Create four Pods with different labels like app=wp, env=test, and
app=db, env=prod. A Replica onController (RC) can only manage Pods
with one specific label using matchLabels, and it doesn’t support
features like rolling updates or rollbacks.
¶ On the other hand, a ReplicaSet (RS) can manage Pods with mul ple
labels using matchExpressions, making it more flexible and be er for
advanced scenarios.
Create four pods and check the labels
Command: # kubectl create -f \
h ps://raw.githubusercontent.com/rakesh08061994/k8s-prac ce/refs/heads/master/rs4pod.yml
Important: Avoid Operator Selectors Overlaps in ReplicaSets: Don't Let Them Fight Over Pods!
If you run mul ple ReplicaSets with overlapping operator selectors (like In, NotIn, and Exists)
that match the same Pods, they will fight over those Pods because Kubernetes doesn't know
which ReplicaSet should "own" them. Here's what happens:
1. Conflict:
Each ReplicaSet will try to manage the Pods to match its desired replica count. For
example:
o One ReplicaSet might create a Pod because it thinks a Pod is missing.
o Another ReplicaSet might delete the same Pod because it thinks there are too
many Pods.
2. Unpredictable Results:
You can't be sure which ReplicaSet will actually manage the Pods. Some Pods might
end up managed by both ReplicaSets, which is confusing.
3. Troubleshoo ng is Hard:
If you're trying to understand why Pods are being created or deleted, it will be difficult
because mul ple ReplicaSets are involved, and their ac ons overlap.
What is a Rollback?
A rollback is a safety net for when something goes wrong during or a er an update. It
lets you quickly go back to the previous version of your app that was working fine.
Here’s an example:
1. You update your app to a new version using a rolling update with proper
networking and high availability management without down me because your
pods may run or distribute on mul ple nodes.
2. A er the update, users start repor ng problems (maybe a bug in the new
version).
3. Kubernetes allows you to “roll back” to the old version automa cally, so your
app works again without needing manual fixes.
A Deployment resource in Kubernetes is a powerful tool for managing and upda ng your
applica on consistently over me. It ensures that your app runs efficiently by handling rolling
updates, scaling to meet demand, and maintaining high availability, so your applica on stays
up and running without interrup ons.
This resource type is more advanced than previous container and pod management resources
like Replica onController and ReplicaSet, offering addi onal features like automated rollbacks,
be er control over updates, and seamless scaling.
But in this we have to know that To achieve automa c scaling based on workload, you
need to configure the Horizontal Pod Autoscaler (HPA). HPA automa cally adjusts the
number of Pods in your Deployment based on metrics such as CPU u liza on, memory
usage, or custom metrics. This means that when your applica on experiences higher
traffic or resource demand, HPA will automa cally scale up the number of Pods, and
when the load decreases, it will scale down the Pods.
Load Balancing: When mul ple Pods are running, Kubernetes evenly distributes
incoming traffic among them. This helps to prevent any single Pod from being
overloaded, improving the overall reliability and performance of your applica on.
Replica Control: Kubernetes ensures that the right number of Pods (based on the desired
state you set) are running at all mes. If a Pod crashes, Kubernetes automa cally creates
a new one to replace it, ensuring that your app always has the correct number of
replicas.
Automated Rolling Updates: With a Deployment, updates are done gradually, one Pod
at a me. This ensures that your applica on remains available while the update is being
applied, minimizing the risk of down me during updates. The update behavior is
controlled using two key se ngs: MaxSurge and MaxUnavailable.
o MaxSurge determines how many Pods can be created above the desired number
of Pods during an update (i.e., the extra Pods that can be temporarily added). You
can specify this as either a fixed number (e.g., 2) or a percentage (e.g., 25%).
o MaxUnavailable specifies how many Pods can be unavailable during the update
process. Similar to MaxSurge, you can define this in either a fixed number (e.g.,
1) or as a percentage (e.g., 50%).
These se ngs give you fine-grained control over the update process, allowing
Kubernetes to manage the update in a way that keeps your applica on running smoothly
without down me.
Automated Rollback: If something goes wrong during an update (like bugs or
unexpected issues), Kubernetes allows you to automa cally roll back to the previous,
stable version of your app. This ensures that any poten al issues don't disrupt your
users. Just like with rolling updates, the rollback also follows the MaxSurge and
MaxUnavailable se ngs to minimize down me.
Label Management: Labels are used to organize and select Pods based on specific
criteria (such as app version or environment). This helps Kubernetes manage Pods more
efficiently, as you can target specific Pods for scaling, upda ng, or other opera ons
based on their labels.
¶ The Deployment adds a hash value to each ReplicaSet. This hash helps
manage the Pods and their updates by making sure it doesn’t get mixed
up with older Pods (orphan Pods). Even if the labels (key-value pairs)
match, the hash ensures that old Pods are not included, and only the
ones managed by the current ReplicaSet are kept.
o Using the Manifest File: Update the replicas count directly in the YAML file and
reapply it by “kubectl apply -f ”. Because you have to apply these change to the
actual cluster. Only change the YAML is not sufficient.
o Using the Edit ETCD Database method: Modify the Deployment informa on in
the etcd database (not recommended in produc on).
¶ maxSurge: This tells Kubernetes how many extra Pods it can create
temporarily during an update or rollback. For example, if you have 4
replicas and set maxSurge to 25% in deployment, then it will allow 1
extra Pod to be created to prevent down me. Because 25% of 4 is 1. This
helps prevent down me because newly created Pods need me to be
ready, join the network, and be managed by services before the old Pods
are terminated. So this se ng is like all pods make available in every
condi on.
¶ maxUnavailable: This tells Kubernetes how many Pods can be taken
down (or become unavailable) during the update or rollback. If you set
maxUnavailable to 25% for 4 replicas, Kubernetes can make 1 Pod
unavailable at a me.
3. Rolling Update the image version to nginx:1.27.3. (One more RepliaSet with new
version)
So you can do this using any of the three methods: command line, edi ng the
manifests file, or directly edi ng the deployment to the etcd.
In reality When you perform a rolling update on a Deployment with a newer version,
actually the Deployment creates a new ReplicaSet in the background with the updated
version nginx:1.27.3. As a result, the Deployment now manages two ReplicaSets: one
with the previous version 1.27.2 and another with the new version 1.27.3. This ensures
a smooth transi on between versions while maintaining applica on availability. Later, if
needed, you can roll back to the previous version using the rollback feature. At that me,
the exis ng ReplicaSets created during the update process will be u lized to revert to
the stable version.
Command: # kubectl set image deployment/web-deployment nginx=nginx:1.27.3
B. Go to a specific revision: (First, check the rollout history to iden fy the revision
you need)
Command: # kubectl rollout history deployment/web-deployment
C. Then, rollback to a specific revision by specifying its number:
Command: # kubectl rollout undo deployment/web-deployment --to
revision=<revision-number>
Daemon Set
In the series of Kubernetes deployment strategies, let's talk about DaemonSet, a resource type
with its own specific use cases. Unlike Deployments, DaemonSets are not used for replicas,
high availability, rolling updates, or rollback features—Deployments are be er suited for those
scenarios.
¶ When a new worker node is added to the cluster using the kubeadm join
command, DaemonSet Pods are automa cally scheduled on that node.
2. Apply the YAML file to the cluster using the kubectl apply -f command.
3. Verify the status of the DaemonSet and ensure it is running on all applicable nodes.
¶ Note: You might be wondering why the DaemonSet is only running on 2
nodes (the worker nodes) and not on the master node, even though we
have a 3-node cluster. However, if you check the kube-proxy and weave-
net DaemonSets, you’ll see they are running on all nodes, including the
master node.
¶ Hmmm… That’s a valid ques on! The reason lies in taints and
tolera ons, which are advanced pod scheduling mechanisms. Don’t
worry, we’ll cover these in detail in a later session.
¶ For now, here’s a quick explana on: in the kube-proxy and weave-net
DaemonSets, tolera ons are configured. These tolera ons allow the
pods to bypass the taints on the master node, effec vely removing the
restric ons and le ng them run on all nodes.
Sta c Pod
A sta c pod in Kubernetes is a type of pod that is directly managed by the kubelet service on
a specific node, rather than being controlled by the Kubernetes API server, controller manager,
or scheduler. Unlike regular pods, a sta c pods are not part of the Kubernetes control manager
object like “Pod, RC, RS, Deployment, Daemon-Set” etc
Sta c pods are defined using configura on files (YAML or JSON) placed in a designated
directory on the node, such as /etc/kubernetes/manifests/. The kubelet monitors this directory
and automa cally creates and manages the pods based on the configura on.
¶ You’ve decided to deploy a sta c pod with the following specifica ons:
¶ Namespace: grras
Now Try to delete this pod from control-node using kubectl. See this is mirror copy
Command: #kubectl delete pod <pod-name>
And see your logs are genera ng by sta c-pod successfully By running this
command: #watch kubectl logs <pod-name> -n <namespace>
INIT CONTAINERS
What is an Init Container in Kubernetes?
An init container is a special type of container in Kubernetes that runs before the main
applica on containers (called service containers) in a pod. It is designed to perform
ini aliza on tasks required to prepare the environment or fulfill specific condi ons for the
service containers.
How Init Containers Work
A pod can have one or more init containers, defined in its specifica on.
Init containers run sequen ally, one a er another. Each init container must complete
successfully before the next one starts.
A er all init containers complete, the main service containers in the pod are started.
Why Use Init Containers?
1. Fulfil Mul ple Condi ons:
o Init containers can ensure that specific precondi ons are met before the main
applica on starts.
Examples:
Wai ng for a database to be ready.
Downloading configura on files or secrets.
Se ng up temporary resources.
2. Separa on of Concerns:
o Tasks like environment setup or dependency resolu on are separated from the
main applica on logic, improving modularity.
3. Reliability:
o If an init container fails, Kubernetes retries it automa cally. The pod does not
transi on to the "Running" state un l all init containers succeed.
The default Kubernetes scheduler is the built-in system that handles this task automa cally. It
looks at factors like:
How much CPU and memory the pod needs.
Which nodes have enough resources available.
Any special rules you’ve set, like which node the pod must or must not run on.
In Short
¶ Info: If no node in the cluster has the required labels, the deployment
will remain in a wai ng state, as this is a hard type of scheduling and the
pod cannot be scheduled elsewhere.
Use Case:
Ideal for ensuring workloads run on nodes with specific label characteris cs, such as
hardware types, environments (e.g., produc on), or region labels, which are provided earlier
by the cluster administrator.
Syntax of nodeSelector with a eching only one key=value pairs:
Note: nodeSelector support AND opra on, means both labes should present on singe node.
Two nodes labels not support in nodeSelector.
¶ Info: In this image, you will see that labels are already a ached to the
specific nodes.
On node1 = env=test & region=india
On node2 = env=prod & region=usa
¶ And node1 has all the required labels as per requirement
Create deployment Manifests file men oning nodeSelector with preferred key=labels:
Command: # vim web-deploy.yml
And check the pods status (Pods will deployed on node1-k8s only because of labels)
Some of you might wonder if it's possible to use both types of scheduling (nodeName
& nodeSelector) in a single manifest file. The answer is yes. You can specify both
nodeName and nodeSelector in the same manifest file, but nodeName will always take
precedence over nodeSelector.
Why this happened:
Because nodeName directly forcefully specifies the exact node where the pod must
be scheduled, bypassing the kube-scheduler en rely. On the other hand,
nodeSelector relies on the kube-scheduler to match key value labels of nodes and
determine where the pod should run.
Q1: Assign the label env=test to node1 and env=prod to node2. Then, schedule a pod using
nodeSelector in such a way that the pod can run on both labeled nodes instead of just one.
Your ques on is “can you use operators with nodeSelector” Pod Scheduling ??
Answer:
NO, nodeSelector does not support using operators like In, Equal, Exists, etc. It only
supports single key-value matching.
To cover mul ple labels or achieve more complex scheduling logic, you need to use
taints and tolera ons instead.
Hardware Differences:
Some nodes may have high-performance GPUs for AI or machine learning workloads.
Others may have high CPU and RAM for compute-intensive tasks and some nodes may
have SSD storage for fast data access, while others use SATA disks for general-purpose
storage.
Regional Varia ons:
Nodes may be distributed across different regions or availability zones, such as:
region=north-india, south-india, east-india, west-india
region=usa, russia, australia, japan,
region=south-asia
Specialized Nodes:
Some nodes may be dedicated to specific workloads, such as database services or
caching systems. So, In this diverse environment, not all pods can or should run on all
nodes. For example:
Node Labels:
o Assign labels to nodes as per the node specifica on.
o Labels are simple key-value pairs that describe the a ributes of nodes.
o Example:
region=india
hardware=gpu
storage=ssd
o These labels help iden fy the characteris cs of nodes, making it easier to
match pods to the right nodes. if you remember in previous part where in
nodeSelector based Pod scheduling we use these labels for provide
condi ons. That run this pod only on that node that have storage=ssd etc.
Limita on: Labels alone don’t restrict pod placement. They work passively to define
a ributes but don’t enforce rules.
o Tolera ons: A kind of bypass entry card act as permissions in pods that allow them
to bypass the node’s restric ons and authorize to schedule on node.
We can understand now that, Taints and tolera ons work together to provide strict
control over pod placement.
In Kubernetes, taints are applied to nodes to control which pods can run on them. They act
like special rules that determine whether a pod can be scheduled on a node based on
whether it has the proper tolera on (like a special card that lets the pod bypass the rule).
Kubernetes provides three types of taints, each serving a specific purpose:
1) NoSchedule
2) PreferNoSchedule
3) NoExecute
1) NoSchedule
This taint tells Kubernetes:
o “Don’t schedule any new pods on this node unless the pod has the special card
(tolera on) to bypass this rule.”
o Pods already running on the node will not be affected—they can stay.
Example: It’s like a VIP area with a sign that says, "Only those with a special card can
enter." Exis ng guests (pods) are allowed to stay, but new guests must have the special
card to get in.
2) PreferNoSchedule
This taint is less strict and means:
o “Try not to schedule new pods here, but if there’s no other place, it’s okay to let
them in.
o I mean avoid myself ASAP for pod scheduling, but if required then schedule on
me”
Example: Think of it as a sign that reads, "Preferably, don’t enter unless it's necessary."
Kubernetes will try to avoid scheduling new pods here, but will let them in if no other
op ons are available.
How to remove “PreferNoSchedule” taint from node? (Only add - at the last of
command )
Command: #kubectl taint node node1-k8s key=value:PreferNoSchedule-
3) NoExecute
This is the strictest taint. It works in two ways:
o “Do not schedule new pods unless they have the special card to bypass this
taint.”
o “Evict (remove) any exis ng pods that don’t have the special card to stay here.”
Example: Imagine a sign that says, "No entry without a special card—if you're already
inside without one, you need to leave immediately." Only pods with the special card
are allowed to remain or be scheduled on this node.
How to remove “NoExecute” taint from node? (Only add - at the last of command )
Command: #kubectl taint node node1-k8s key=value:NoExecute-
Types of Tolera ons: (Only the right Key will able to open the right lock)
Tolera ons are used on pods to match the taints on nodes. Similar to taints, tolera ons also
have three types. They work as follows:
1. NoSchedule: Allows the pod to run on a node with a NoSchedule taint.
2. PreferNoSchedule: The pod avoids nodes with this taint but can run there if no other
nodes are available.
3. NoExecute: Allows the pod to stay on or run on a node with a NoExecute taint,
preven ng evic on.
Operators with tolera ons:
In Kubernetes, tolera ons use two main operators: Equal and Exists. The Equal operator
matches a taint's key and value exactly with the tolera on's key and value. It ensures that only
taints with the same key-value pair will be tolerated.
On the other hand, the Exists operator ignores the value and only requires the key to match.
This means any taint with the specified key will be tolerated, regardless of its value. These
operators help fine-tune which nodes a pod can be scheduled on based on the taints applied
to the nodes.
If you do not use operators in tolera ons, Kubernetes will assume the Equal operator by
default. This means that the tolera on will only match taints that have both the same key and
value as the tolera on. Without specifying an operator, Kubernetes will look for taints that
exactly match the key-value pair, and the pod will only be scheduled on nodes that have a taint
with that specific combina on.
And same thing will work for other taint and tolera ons included “PreferNoSchedule & NoExecute”
Node Affinity:
Simple Explana on: A Pod or Deployment wants to schedule its replicas only on
specific nodes that have already a par cular label.
Example: If we want our Pods to run only on nodes with the label env=dev, we will
apply Node Affinity with env=dev.
Rule Meaning: "I want to stay only with you" or "I want to be only near you."
Result: Pods will be scheduled only on Node 4 & Node 5.
Node An -Affinity:
Simple Explana on: A Pod or Deployment wants to avoid certain nodes based on their labels.
Example: If we apply Node An -Affinity to env=dev, the Pods will not be scheduled on
Node 4 & Node 5.
Rule Meaning: "I don’t want to be with you."
Result: Pods will be scheduled only on Node 1, Node 2, and Node 3, avoiding Node 4 &
Node 5.
Hard and So Rules in Affinity & An -Affinity
Affinity and An -Affinity rules apply at two levels:
1 Node Level (Node Affinity & Node An -Affinity)
2 Pod Level (Pod Affinity & Pod An -Affinity)
Each level has Hard (Required) and So (Preferred) rules.
Example:
"I want to schedule my backend Pods only on nodes with label env=prod."
If no node has env=prod, the backend Pods won’t be created.
Example:
"I prefer to schedule my backend Pods on nodes with env=prod, but if not available,
place them anywhere."
If no node has env=prod, the backend Pods can run on other nodes.
Example:
"I don’t want to schedule my frontend Pods on nodes with env=dev."
If all nodes have env=dev, the frontend Pods won’t be created.
Example:
"I prefer to avoid scheduling frontend Pods on nodes with env=dev, but if no other
node is available, they can be placed there."
If no other node is free, Kubernetes will s ll schedule the Pod on env=dev nodes.
Example:
"I want to deploy log Pods only on nodes where logic Pods (app=logic) are running."
If no node has app=logic, log Pods won’t be scheduled.
Example:
"I prefer to deploy log Pods on nodes where logic Pods (app=logic) are running, but
if not available, deploy anywhere."
If no app=logic Pod exists, the log Pods can run on other nodes.
Example:
"I don’t want to deploy web Pods on nodes where database Pods (app=database)
are running."
If all nodes have database Pods, web Pods won’t be scheduled.
So Pod An -Affinity (Preferred)
Pod should not be scheduled on the same node as another specific Pod type, but if
needed, it can be.
Example:
"I prefer to avoid web Pods on nodes where database Pods (app=database) are
running, but if no choice, they can be scheduled there."
If no other node is free, Kubernetes will s ll schedule web Pods on database nodes.
YAML File
Node Affinity (Pod runs only on Nodes with a specific label)
apiVersion: v1
kind: Pod
metadata:
name: node-affinity-example
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecu on:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- us-west-1
containers:
- name: nginx
image: nginx
Real-World Assignment
Imagine you are a Kubernetes administrator managing a cloud-based e-commerce
applica on. The system has three major components:
1. Frontend: A web interface for customers.
2. Backend: Handles business logic and API calls.
3. Database: Stores customer data and transac ons.
Your challenge:
Ensure that the backend and frontend run on the same Node for be er performance.
Ensure that database Pods do not run on the same Node for fault tolerance.
Ensure that backend Pods are not scheduled on Nodes with low memory.
Ensure that at least one replica of each component runs in each availability zone.
Steps:
1. Define Labels for Nodes: Label some Nodes as high-memory, low-memory, zone-a, and
zone-b.
2. Apply Node Affinity: Ensure the backend only runs on high-memory Nodes.
3. Apply Pod Affinity: Ensure the frontend and backend run together.
4. Apply Pod An -Affinity: Ensure the database Pods do not run on the same Node.
5. Use topologyKey to distribute workloads across different zones.
Use the provided YAML templates and modify them to meet the assignment goals.
1. Introduction
In Kubernetes, we need to store some settings and data, such as:
Non-Sensitive Data – Application settings, URLs, log levels, etc.
Sensitive Data – Passwords, API Keys, tokens, certificates etc.
To store these types of data, Kubernetes provides ConfigMap and Secret.
Note: Secrets are only Base64 encoded, not encrypted. To secure them, use etcd encryption and
RBAC.
3. Ways to Create ConfigMap and Secret
Both can be created using:
1. kubectl command
2. YAML file
Secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
DB_USER: YWRtaW4= # Base64 encoded "admin"
DB_PASS: cGFzczEyMw== # Base64 encoded "pass123"
Now Mounting Entire File in a Pod (Using ConfigMap and Secret as Volumes)
D. Using as Volumes
You can attach and mount the entire ConfigMap or Secret as a volume.
Mounting ConfigMap as a Volume
apiVersion: v1
kind: Pod
metadata:
name: configmap-volume-pod
spec:
containers:
- name: my-container
image: busybox
volumeMounts:
- name: config-volume
mountPath: /config # Mount point
volumes:
- name: config-volume
configMap:
name: my-config
When a Pod is created in Kubernetes, it gets temporary storage. If that Pod is deleted or crashes, its
data is also lost. However, sometimes we need storage that is persistent and keeps data safe. To
solve this issue, Kubernetes provides Persistent Volumes (PV) and Persistent Volume Claims
(PVC).
2. What are Persistent Volume (PV) and Persistent Volume Claim (PVC)?
PVs are independent of Pods, meaning that even if a Pod is deleted, the PV remains.
When a developer needs storage, they request a claim for one of the available drives.
Similarly, in Kubernetes, an admin pre-creates PVs, and developers submit PVCs for them.
Dynamic Provisioning (Automatically Creating Storage)
When a user creates a PVC and selects a StorageClass (e.g., fast-storage), Kubernetes
automatically provisions a new PV.
When a user creates a PVC, Kubernetes finds an available PV and binds them together.
If no suitable PV is found, the PVC remains unbound until a new PV becomes available.
When a PVC is deleted, what happens to the PV depends on its Reclaim Policy:
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: standard
hostPath:
path: "/mnt/data"
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain # "Recycle" is deprecated, use "Retain" or "Delete"
storageClassName: slow
nfs:
path: /mnt/nfs-share1
server: 172.17.0.2
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: standard
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
volumeMounts:
- mountPath: "/data"
name: storage
volumes:
- name: storage
persistentVolumeClaim:
claimName: my-pvc
5. What is StorageClass?
StorageClass is used in Kubernetes to define different types of storage and enable Dynamic
Provisioning.
StorageClass Example
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-storage
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
fsType: ext4
allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: dynamic-storage
provisioner: kubernetes.io/aws-ebs # Cloud provider storage
parameters:
type: gp2
fsType: ext4
allowVolumeExpansion: true
Note:
This does not specify accessModes because it is determined at the PVC level.
The PVC specifies the required access mode.
Kubernetes will provision a PV that satisfies this request.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dynamic-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi # Requesting 10Gi storage
storageClassName: dynamic-storage
Step-3: The Provisioned PersistentVolume (PV)
Once the PVC is created, Kubernetes dynamically provisions a PV with the same access
mode:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pvc-12345678
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce # This is inherited from PVC
persistentVolumeReclaimPolicy: Delete
storageClassName: fast-storage
csi:
driver: ebs.csi.aws.com
volumeHandle: vol-xyz123
The CSI (Container Storage Interface) section in the PersistentVolume (PV) manifest is used
when Kubernetes dynamically provisions storage using a CSI driver.
Breaking It Down
csi: → This section tells Kubernetes that the storage is provisioned using the CSI
driver instead of traditional methods like nfs, hostPath, or awsElasticBlockStore.
driver: ebs.csi.aws.com → Specifies the CSI driver handling the storage. In this case,
it's the AWS EBS CSI driver, which allows Kubernetes to manage AWS Elastic Block
Store (EBS) volumes dynamically.
volumeHandle: vol-xyz123 → A unique identifier for the actual backend storage
volume (in AWS, this would be the EBS volume ID). Kubernetes uses this to attach and
detach the volume to/from nodes.
The access mode is set automatically based on the PVC's request.
7. Access Modes of PV
ReadWriteOncePod
Can be used for Read/Write by a single Pod only.
(RWOP)
8. Reclaim Policies
If you need more storage, you can expand a PVC (if allowVolumeExpansion: true is set).
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: expandable-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi # Previously 5Gi, now increased to 10Gi
storageClassName: fast-storage
Kubernetes provides different types of storage volumes based on various use cases. Some volumes
are created directly within the pod, while others require Persistent Volume (PV) and Persistent
Volume Claim (PVC) for management.
emptyDir
hostPath
2. Object Level Quota – Limits the number of Pods, Deployments, Services, PVCs, etc.
Example:
2. Object Quota – Limits the number of Kubernetes objects like Pods, Deployments, Services,
PVCs, etc.
A Object Quota sets a limit on the maximum resources that can be used in a Namespace. It controls
computing resource like CPU, RAM, storage, and the number of objects (Pods, Services,
Deployments, etc.).
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
spec:
hard:
pods: "10" # Maximum 10 Pods
services: "5" # Maximum 5 Services
deployments: “10” # Maximum 10 deployments
secrets: "15" # Maximum 15 Secrets
requests.cpu: "2" # Max 2 CPU requests
requests.memory: "4Gi" # Max 4GB RAM requests
limits.cpu: "4" # Max 4 CPU usage
limits.memory: "8Gi" # Max 8GB RAM usage
requests.storage: "100Gi" # Max 100GB Storage
persistentvolumeclaims: "5" # Max 5 PVCs
What Does This Mean for the Namespace? When this Resource Quota is applied:
Error: exceeded quota: team-a-quota, requested: pods=1, used: pods=10, limited: pods=10
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
spec:
hard:
requests.cpu: "2" # Minimum 2 CPU required
requests.memory: "4Gi" # Minimum 4GB RAM required
limits.cpu: "4" # Maximum 4 CPU allowed
limits.memory: "8Gi" # Maximum 8GB RAM allowed
Important:
Meaning:
Example: If a Pod requests more than 2 CPUs or tries to use more than 4 CPUs, Kubernetes will
block the request and show an error.
Error: exceeded quota: compute-quota, requested: cpu=3, used: cpu=2, limited: cpu=2
Meaning: The request exceeds the allowed CPU limit in this Namespace.
Priority-Based Quota – High-Priority Pods
Sometimes, important Pods need extra resources. For this, Priority-Based Quota is used.
Imagine you are running a shared Kubernetes cluster where multiple teams and applications use
the same resources. Some applications are more important than others. For example:
To ensure that critical applications always get the resources they need, Priority-Based Quota is
used.
Real-Life Example
1. High-Priority (Business Class) – Always gets a seat, even if the flight is full.
2. Medium-Priority (Premium Economy) – Gets a seat if available.
3. Low-Priority (Economy Class) – May be denied a seat if the flight is overbooked.
Similarly, Kubernetes ensures high-priority applications always run, while low-priority applications
may be limited if resources are tight.
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-high # Resources reserved for high-priority applications
spec:
hard:
cpu: "1000" # High-priority apps can use up to 1000 CPUs
memory: "200Gi" # Can use up to 200GB RAM
pods: "10" # Only 10 high-priority pods allowed
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["high"] # Applied only to high-priority pods
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-medium # Resources reserved for medium-priority applications
spec:
hard:
cpu: "10" # Medium-priority apps can use up to 10 CPUs
memory: "20Gi" # Can use up to 20GB RAM
pods: "10" # Only 10 medium-priority pods allowed
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["medium"] # Applied only to medium-priority pods
- apiVersion: v1
kind: ResourceQuota
metadata:
name: pods-low # Resources reserved for low-priority applications
spec:
hard:
cpu: "5" # Low-priority apps can use up to 5 CPUs
memory: "10Gi" # Can use up to 10GB RAM
pods: "10" # Only 10 low-priority pods allowed
scopeSelector:
matchExpressions:
- operator: In
scopeName: PriorityClass
values: ["low"] # Applied only to low-priority pods
Meaning:
High-Priority Pods get their own limits.
Up to 10 High-Priority Pods are allowed.
High-priority apps always get resources first.
Low-priority apps may be paused if resources are low.
Ensures fair and efficient resource usage in Kubernetes.
apiVersion: v1
kind: Pod
metadata:
name: medium-priority-pod
namespace: example-namespace
spec:
priorityClassName: medium-priority # Assigning medium-priority
containers:
- name: app-container
image: nginx
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
For example, if you want to limit the number of GPUs used in a Namespace, you can define a
quota like this:
apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota
spec:
hard:
requests.cpu: "4" requests.memory: "16Gi"
requests.nvidia.com/gpu: "4" # Maximum 4 GPUs can be used in namespace
Meaning:
The Namespace where this quota is applied cannot use more than 4 GPUs.
This feature is useful for workloads that require machine learning, AI processing, or high-
performance computing while ensuring fair resource distribution.
exist.
Compute Quota: Controls how much CPU, Memory, and special resources (like GPU)
can be used.
Storage Quota: Controls how much storage (Persistent Volume Claims - PVCs) can
be used.
apiVersion: v1
kind: ResourceQuota
metadata:
name: my-resource-quota
namespace: my-namespace # Replace with your actual namespace
spec:
hard:
pods: "10" # Max 10 Pods allowed
services: "5" # Max 5 Services allowed
persistentvolumeclaims: "5" # Max 5 PVCs allowed
requests.cpu: "2" # Max 2 CPU requests
requests.memory: "4Gi" # Max 4GB RAM requests
limits.cpu: "4" # Max 4 CPU usage
limits.memory: "8Gi" # Max 8GB RAM usage
requests.storage: "100Gi" # Max 100GB total storage usage
configmaps: "10" # Max 10 ConfigMaps allowed
secrets: "15" # Max 15 Secrets allowed
requests.cpu: "4"
limits.cpu: "8"
requests.memory: "8Gi"
limits.memory: "16Gi"
pods: "5"
Currently, the team has already created 5 Pods, but there is still CPU and Memory available.
Can they create an additional Pod? Why or why not?
Create an Object Count Quota (Pods, Services, PVCs) from Command Line
kubectl create resourcequota object-quota --namespace=<namespace> \
--hard=pods=10,services=5,persistentvolumeclaims=5,secrets=15
Creates a quota that limits the number of Kubernetes objects like Pods, Services, PVCs, and Secrets.
Sometimes, along with the main container, we need an extra container to help it. This extra container
is called a Sidecar Container. It runs alongside the main container and provides additional features
to improve performance and functionality of main container without losing main containers quality
and performance.
If your main container is designed to do only one job but needs extra features, instead of modifying
it, you can add a Sidecar Container.
Example: If a container is running a web app, but you need to store log files, you can use a separate
Sidecar Container for log storage.
You can add new features without modifying the main container
It improves microservices architecture
Helps create scalable and repeatable solutions
Makes logging, monitoring, and security easier
To check logs:
kubectl logs -f sidecar-example -c sidecar-container
BusyBox is a very lightweight Linux-based utility tool that includes basic Unix commands like ls, cp,
mv, echo, cat, grep, wget, etc. without any heavy program or utility tools. It is called "The Swiss Army
Knife of Embedded Linux" because it provides multiple Unix commands in a single binary. It has
1mb size max. so this is lightweight and fast.
containers:
- name: sidecar-container
image: busybox
command: ["/bin/sh", "-c", "while true; do cat /var/log/app.log; sleep 10; done"]
Problems
If the Main Container (e.g., Nginx, PostgreSQL) handles logging, monitoring, or networking,
maintenance becomes difficult.
The Single Responsibility Principle (SRP) suggests that each container should do only one
job.
If you only need to change log forwarding or monitoring, you can update the Sidecar
instead of modifying the Main Container.
BusyBox is less than 1MB in size, while Base OS images (Ubuntu, Alpine, Debian) can be
100MB+.
A smaller image means faster loading, less storage, and lower RAM usage.
BusyBox includes essential Unix tools (ls, cat, ping, wget, grep, sh).
Defiantly we can, but BusyBox is the best and simplest option. Why because of its size and
minimalist nature with complete required tools options.
If you need Shell Access and Basic Commands in a lightweight container, BusyBox is the best
choice!
My Conclusion
Sidecar Containers help improve the functionality of the Main Container without modifying
it.
They are used for logging, monitoring, proxy, data sync, and security.
Kubernetes Sidecar Containers are defined in a YAML file with shared volumes.
BusyBox is a lightweight Linux-based image, ideal for debugging, networking, file
processing, and Sidecar Containers.
It is fast, minimal, and secure, making it the best choice for Kubernetes and Docker
environments.
Using the Sidecar Pattern keeps containers modular, scalable, and easy to manage.
Practice-1: Create an Nginx web server pod with a sidecar container that prints logs every 2
seconds. This will demonstrate how a sidecar container can be used for log processing in
Kubernetes.
Answer:
Step-1 Here’s the YAML configuration to create a Pod with two containers:
1. Nginx container - Runs the web server and stores logs in /var/log/nginx.
2. BusyBox sidecar container - Reads and prints the logs from /var/log/nginx every 2
seconds.
# vim sidecar-pod-example.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx-sidecar-pod
spec:
containers:
- name: nginx-container
image: nginx
volumeMounts:
- name: log-volume
mountPath: /var/log/nginx
- name: log-sidecar
image: busybox
command: ["/bin/sh", "-c"]
args: ["while true; do cat /var/log/nginx/access.log; sleep 2; done"]
volumeMounts:
- name: log-volume
mountPath: /var/log/nginx
volumes:
- name: log-volume
emptyDir: {}
BusyBox Sidecar: Reads the logs from the shared volume and prints them every 2
seconds.
Now question may come, “If logs are already stored in a volume, you can view them directly
from the volume mount point. So, why do we need a sidecar container to print logs using:
So answer would be “You are right If you just need to view logs, use kubectl logs or kubectl
exec but If you need to automatically process, filter, stream, or forward logs, a sidecar
container is useful.”
How It Works?
The application reads configuration from /etc/app/config/config.yaml.
The sidecar updates this file every 60 seconds.
Now, verify that all your sidecar containers are correctly configured and functional!
What is a service ?
A Service in Kubernetes helps expose an application running in your cluster by providing a single,
stable network endpoint. This ensures that even if your application runs in multiple Pods (which may
change dynamically), clients can always access it reliably.
2. Consistent Access – If an application has multiple backend Pods, a Service provides a fixed
way to reach them.
Clients can use this identity to interact with the backend Pods.
For example, assume we have a backend application running in 3 Pods. Instead of connecting to
individual Pods, we create a Service that directs traffic to all healthy backend Pods.
Types of Services
1. ClusterIP (Default)
Exposes the Service only within the cluster.
Not accessible from outside.
Example: Internal communication between microservices.
Example YAML:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-backend
ports:
- protocol: TCP
port: 80
targetPort: 9376
Here, all Pods with label app=my-backend will be reachable at port 80 via the Service.
2. NodePort
Exposes the Service on a specific port of each Node.
Accessible from outside the cluster using NodeIP:NodePort.
Useful for debugging or basic external access.
Example YAML:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: my-backend
ports:
- port: 80
targetPort: 9376
nodePort: 30007 # This port is accessible on every node
If the cluster node has IP 192.168.1.10, then you can access the service at:
http://192.168.1.10:30007
3. LoadBalancer
Used when running Kubernetes on cloud providers (AWS, GCP, Azure).
It provisions an external load balancer to distribute traffic.
Suitable for public-facing applications.
Example YAML:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: LoadBalancer
selector:
app: my-backend
ports:
- port: 80
targetPort: 9376
If the cloud provider assigns 192.0.2.127 as the external IP, users can access it via:
http://192.0.2.127
4. ExternalName
Maps a Service to an external DNS name.
No traffic is routed inside the cluster; instead, it resolves to an external resource.
Example YAML:
apiVersion: v1
kind: Service
metadata:
name: my-database
spec:
type: ExternalName
externalName: db.example.com
When applications inside the cluster query my-database, they get redirected to
db.example.com.
Other Important Concepts
1. Multi-Port Services
Services can expose multiple ports for different functionalities.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-backend
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377
This allows HTTP traffic on port 80 and HTTPS traffic on port 443.
2. Headless Services
A Service without a ClusterIP (clusterIP: None).
apiVersion: v1
kind: Service
metadata:
name: my-headless-service
spec:
clusterIP: None
selector:
app: my-backend
ports:
- port: 80
targetPort: 9376
Applications query DNS and get direct Pod IPs instead of a single service IP.
3. Service Discovery
There are two ways clients inside the cluster can discover Services:
2. DNS Resolution: Services are registered in the cluster’s DNS and can be accessed using my-
service.default.svc.cluster.local.
1. kube-proxy – It ensures that traffic from a Service reaches the correct Pod.
2. CNI Plugin (Container Network Interface) – It enables internal networking between Pods,
even when they are on different nodes.
Without these two networking components, a Service would not be able to route traffic to
application Pods, and Pods wouldn’t be able to communicate across the cluster. Let’s break them
down in simple terms.
1. What is kube-proxy?
kube-proxy is a network service that makes sure traffic from a Service reaches the right Pod. It
acts like a traffic controller inside the Kubernetes cluster.
When a request comes to a Service, kube-proxy finds a healthy Pod behind that Service.
If a Pod goes down, kube-proxy automatically redirects traffic to another healthy Pod.
Example: Imagine a website where users visit www.myapp.com. This request reaches a Service
in Kubernetes. The kube-proxy decides which backend Pod should handle the request and
forwards the traffic accordingly.
It ensures that all Pods can communicate with each other, even if they are running on
different nodes.
It makes sure that all same-label Pods (like replicas of a Deployment) can talk to each
other easily.
Example: If you have multiple replicas of a backend application (app: backend), the CNI plugin
makes sure they can talk to each other smoothly.
Technology Uses iptables or IPVS Uses plugins like Flannel, Calico, etc.
By understanding these two, you can better manage Kubernetes networking and troubleshoot
connectivity issues easily.
1. Diagram of ClusterIP and NodePort Service
2. Diagram of ClusterIP and NodePort Service
3. Diagram of Kube-Proxy and CNI plugin
My Final Thoughts
Services ensure stable and reliable communication between Pods.
Load balancing, service discovery, and networking policies enhance Kubernetes' power.
kube-proxy is like a traffic manager that connects Services to the right Pods.
CNI Plugin ensures that all Pods can communicate internally, just like how computers in
a network talk to each other.
If user has specific role or cluster-role level authorization, it will list all Kubernetes nodes.
Otherwise, it will show below message that showing that “User” are not able to list the resource.
Which mean this is user authentication issue. This is Kubernetes role authorization issue.
The new user rakesh is now successfully configured to interact with the Kubernetes cluster using
kubectl. This setup ensures secure authentication through certificate-based authentication.
Introduction
Role-Based Access Control (RBAC) is a security mechanism in Kubernetes that helps administrators
control who can access cluster resources and what actions they can perform. It provides a way to
assign permissions to users, groups, and service accounts to ensure secure operations in a
Kubernetes environment.
RBAC allows fine-grained access management by defining roles and bindings that determine which
resources can be accessed and modified. It is essential for maintaining security and preventing
unauthorized access to critical components in a cluster.
B. Resources in RBAC
Resources are the Kubernetes objects on which actions can be performed. Some key resources are:
This command creates a Role named gip-admin in the gip namespace, granting full permissions on
all resources.
Creating a RoleBinding for a User
This binds the gip-admin Role to the user rakesh, allowing him to perform all actions in the gip
namespace.
This binds the gip-admin Role to the group devops-team, allowing all users in that group to perform
This binds the gip-admin Role to the Service Account monitoring-sa in the monitoring namespace.
This binds the cluster-admin-role to the user rakesh, giving him full cluster-wide access.
This binds the cluster-admin-role to the group devops-team, allowing all users in that group
to have full cluster-wide access.
This binds the cluster-admin-role to the Service Account monitoring-sa in the monitoring
namespace, allowing it full cluster-wide access.
This grants read-only access to pods and services in the myproject namespace.
This lets a user view and update ConfigMaps and Secrets in myproject namespace.
5. Service Account
A. What is a Service Account?
A Service Account is a special type of account in Kubernetes. It is used by applications running inside
Pods to communicate securely with the Kubernetes API server.
B. How is a Service Account Different from a Normal User Role/ClusterRole?
User accounts are for humans (like developers, administrators).
Service accounts are for applications inside Pods.
Service accounts can have Roles/ClusterRoles, but they are mainly used by Pods to access
Kubernetes resources.
C. Can We Assign a Role/ClusterRole to a Service Account?
Yes! You can assign a Role (namespace-level) or a ClusterRole (cluster-wide) to a service account
using RoleBinding or ClusterRoleBinding.
D. Is a Service Account Namespace-Based or Cluster-Based?
By default, a service account is namespace-based.
A service account from one namespace cannot be used in another namespace unless granted
access using ClusterRoleBinding.
E. Why Do We Need a Service Account?
1. To allow Pods to securely access the API server.
2. To control permissions for specific workloads (applications).
3. To automate tasks without using user credentials.
One way to expose services is by using NodePort, which assigns a unique port on every node.
However, this approach has a major drawback—each service requires an open port, increasing
security risks by making cluster nodes directly accessible from the internet. Another option is using
a LoadBalancer, which provides external access by creating a dedicated cloud-based load balancer
for each service. While this method is effective, it becomes expensive and difficult to manage as the
number of services grows.
Ingress acts as a single entry point that routes external requests to the appropriate services based
on defined rules. Instead of assigning a separate LoadBalancer or NodePort for each service,
Ingress allows controlled and secure access while simplifying traffic management, reducing costs,
and improving security.
Ingress Controller – This is the actual component that processes incoming traffic and
enforces the routing rules defined in Ingress Resources. Kubernetes does not come with an
Ingress Controller by default, so you need to install and configure one separately.
Ingress Resource – This is a Kubernetes object that defines the rules for routing traffic, such
as which requests should be sent to which service based on domain names or URL paths.
However, an Ingress Resource alone does not handle traffic; it requires an Ingress Controller
to function.
Without an Ingress Controller, Ingress Resources are just configurations that Kubernetes cannot act
upon. In the next section, we will dive deeper into both Ingress Controller and Ingress Resource to
understand how they work together to manage external traffic efficiently.
I have created an image diagram below to visually explain how Ingress and Ingress Controller
function with two deployment services inside your Kubernetes cluster.
Ingress Controller is a special pod that reads Ingress Resources and routes traffic
accordingly.
https://docs.nginx.com/nginx-ingress-controller/installation/installing-nic/installation-with-
manifests/
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: project-ingress # Name of the Ingress resource
namespace: amazon # Namespace where this Ingress is applied
spec:
rules:
- host: www.grras.com # When a request comes for this domain
http: # Rule 1: Handles traffic for www.grras.com
paths:
- path: / # Routes all traffic ("/" means root path)
pathType: Prefix # Ensures the path-based routing
backend:
service:
name: svc2 # Traffic is forwarded to the service "svc2"
port:
number: 80 # The service port it should use
- host: www.rakammodify.store # When a request comes for this domain
http: # Rule 2: Handles traffic for www.rakammodify.store
paths:
- path: / # Routes all traffic for this domain
pathType: Prefix # Path-based routing
backend:
service:
name: svc1 # Traffic is forwarded to the service "svc1"
port:
number: 80 # The service port it should use
What is Prerequisites
Ubuntu 22.04 LTS installed on all nodes
Internet access
User with sudo privileges
Step 1: Disable Swap on All Nodes
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
On worker nodes, run the output command received from the master.