Kubernetes Revision
Kubernetes is designed to orchestrate containers.
Why is Container Orchestration Needed?
Imagine you have:
An application split into multiple services (e.g., frontend, backend, database), each running in its own container.
Multiple instances of these containers to handle high traffic.
A need to ensure these containers stay healthy and restart if they fail.
Managing this manually for dozens or hundreds of containers would be overwhelming. Container orchestration automates these tasks.
Example: Running a Web App with Kubernetes
Let’s say you have a web application with three components:
Frontend (React or Angular)
Backend API (Node.js, Python)
Database (MySQL)
Without Orchestration:
You manually start containers for each service.
You restart failed containers yourself.
You update each container manually during a new release.
With Kubernetes:
Define Your Application in a YAML File
Deploy to Kubernetes:
Kubernetes Handles the Rest
- A cluster is a collection of machines (physical or virtual) working together to run applications using Kubernetes. It consists of one master node and multiple worker nodes. Think of it as a team: the master node is the manager, and the worker nodes are the employees doing the tasks.
Master Node Components
API Server:
Significance: Acts as the central communication hub for the cluster.
Function:
Receives commands from users (
kubectl
or other tools).Passes those instructions to the other components.
Example: When you type
kubectl apply -f deployment.yaml
, the API server processes this request and instructs the cluster to deploy your application.
Scheduler:
Significance: Decides which worker node will run a specific task or application.
Function:
Analyzes the available resources on worker nodes (CPU, memory).
Places tasks on the most suitable node.
Example: If worker node 1 is busy, it assigns the job to worker node 2.
etcd:
Significance: The brain's memory—a distributed key-value store.
Function:
Stores all the cluster’s state and configuration data.
Ensures consistency across the cluster.
Example: If a node fails, Kubernetes consults
etcd
to determine what was running there and reschedules it on another node.
Controller Manager:
Significance: Handles the cluster's overall health and operations.
Function:
Manages controllers.
Examples of controllers:
Node Controller: Monitors worker nodes and replaces failed ones.
Replica Controller: Ensures the correct number of app instances are running.
Example: If 3 replicas of your app are required, but 1 crashes, the Controller Manager restarts it automatically.
Worker Node Components
Kubelet:
Significance: The worker node's agent that follows orders from the master node.
Function:
Ensures the containers on the worker node are running as instructed by the master.
Reports the node's status back to the master.
Example: The Kubelet ensures the frontend container is running and will restart it if it crashes.
Kube-proxy:
Significance: Manages networking for apps in the cluster.
Function:
Routes traffic to the right container or pod.
Allows communication between containers, worker nodes, and the outside world.
Example: If a user accesses your app,
kube-proxy
directs their request to the appropriate container.
Container Runtime:
Significance: The software that runs your containers.
Function:
Responsible for starting, stopping, and managing the lifecycle of containers.
Examples: Docker, containerd.
Example: If your app's container is built with Docker, the runtime runs it on the worker node.
How They Work Together
You issue a command:
kubectl apply -f app-deployment.yaml
.The API Server receives the request and updates the desired state in etcd.
The Scheduler assigns the task to a suitable worker node.
The Controller Manager ensures that the required number of app instances are running.
On the worker node:
Kubelet ensures the assigned containers are running.
Kube-proxy routes network traffic to the correct containers.
The Container Runtime (e.g., Docker) runs the containers.
What is kubectl
?
kubectl
(pronounced cube-control) is a command-line tool used to interact with a Kubernetes cluster. It acts as the interface between the user and the Kubernetes API Server, allowing you to manage, monitor, and troubleshoot applications and resources in your cluster.
What is a Pod in Kubernetes?
A Pod is the smallest and most basic unit of deployment in Kubernetes. It represents a single instance of a running process in your cluster. It can run one or more containers and share the same resources.
How Kubernetes Helps with Scalability, Load Balancing, High Availability, Rollouts, and Rollbacks?
Scalability:
Adds or removes instances when needed. Example:
Imagine you run an online store, and during a sale, many users visit your site.
You start with 2 instances of your app. As traffic increases, Kubernetes automatically scales up to 10 instances.
When traffic drops, it scales back down to save resources.
Load Balancing:
Spreads traffic evenly across instances. Example:
Your app has 3 pods running.
A user visits your site; Kubernetes sends their request to Pod 1.
Another user visits; their request is routed to Pod 2, and so on.
High Availability:
Keeps your app running, even during failures. Example:
You have 5 pods running your app.
If one pod crashes, Kubernetes automatically creates a new pod to replace it.
If a worker node fails, Kubernetes reschedules the pods to other nodes.
Rollouts:
Updates your app without downtime. Example:
You release a new version of your app (v2).
Kubernetes starts replacing the old pods (v1) with new ones (v2), one at a time.
Users don’t experience downtime because the old pods keep running until the new ones are ready.
Rollbacks:
Reverts to a stable version if things go wrong. Example:
Your new version (v2) has a bug.
Kubernetes quickly rolls back to the previous version (v1).
Users won’t notice because the rollback happens smoothly.
What is a Kubernetes Cluster?
A Kubernetes cluster is a group of computers (nodes) that work together to run and manage applications automatically. It has a control plane (brain) that makes decisions and worker nodes that run the applications.
Common Methods to Build a Kubernetes Cluster:
Minikube – For local, single-node clusters (good for learning).
Kubeadm – For setting up production-ready clusters manually.
Cloud-managed services (EKS, AKS, GKE) – Fully managed Kubernetes in AWS, Azure, or Google Cloud.
K3s – A lightweight Kubernetes version for small environments.
What is minikube?
A tool to run a Kubernetes cluster locally on your computer.
It's like a mini Kubernetes lab for testing and learning.
It sets up a small, single-node Kubernetes cluster on your machine.
It’s ideal for experimenting and development without needing a full-fledged cloud setup.
What is Kubeadm?
Kubeadm is a tool used to set up real Kubernetes clusters on actual servers.
✅ Use Case:
If you want to set up a full Kubernetes cluster in the cloud or on physical/virtual machines.
Good for production or multi-node clusters (where you have multiple computers working together).
✅ How it Works:
Helps you initialize a Kubernetes cluster on multiple machines.
Doesn't install extra tools like Minikube does—just the basic Kubernetes components.
Needs some manual setup, like configuring networking and joining worker nodes.
Key Differences :
Feature | Minikube | Kubeadm |
Purpose | For learning & testing (local or cloud) | For setting up real Kubernetes clusters |
Where it Runs | On a local PC/laptop, VM, or cloud | On cloud, physical, or VM servers |
Cluster Type | Single-node (by default) but can simulate multi-node | Single-node or multi-node (production-ready) |
Ease of Use | Very easy (one command setup) | Requires manual setup and configuration |
Extra Features | Has built-in Kubernetes tools & addons (e.g., dashboard) | Only installs core Kubernetes, no extras |
How Minikube Simulates Multi-Node Clusters ?
Minikube doesn’t create real separate nodes like a full Kubernetes cluster. Instead, it runs multiple worker nodes as separate containers or VMs within a single machine. This helps test multi-node behavior without needing multiple physical servers.
Example Command:
To start a Minikube cluster with 3 nodes (1 control plane + 2 worker nodes):
minikube start --nodes 3
Reality: All nodes run inside the same Minikube VM/container.
Limitation: Unlike a real multi-node Kubernetes setup, all nodes share the same underlying OS and resources.
Kubernetes Control Plane Ports and Their Purpose :
Protocol | Direction | Port Range | Purpose | Used By |
TCP | Inbound | 6443 | Kubernetes API server – the main entry point for cluster management requests | All components interacting with the API server |
TCP | Inbound | 2379-2380 | etcd server client API – responsible for storing the Kubernetes cluster state | kube-apiserver, etcd |
TCP | Inbound | 10250 | Kubelet API – enables the control plane to manage worker nodes | Control plane, self |
TCP | Inbound | 10259 | kube-scheduler – assigns pods to nodes | Self |
TCP | Inbound | 10257 | kube-controller-manager – manages controllers that regulate cluster state | Self |
Note:
By default, etcd (which stores the cluster data) runs as part of the control plane and uses specific ports (2379-2380).
However, you can set up etcd on separate servers (outside the control plane) or change its port numbers if needed.
"Self" means that the component communicates with itself or is used internally within the same node.
For example:
- Kubelet API (10250): Used by the control plane to communicate with Kubelet, but Kubelet may also use it internally.
Kubernetes Worker Node Ports and Their Purpose
Protocol | Direction | Port Range | Purpose | Used By |
TCP | Inbound | 10250 | Kubelet API – enables the control plane to manage and monitor worker nodes | Control plane, self |
TCP | Inbound | 10256 | kube-proxy – manages network rules for Kubernetes services | Self, load balancers |
TCP | Inbound | 30000-32767 | NodePort services – exposes Kubernetes services externally on worker nodes | All |
Note:
The default port range for NodePort services is 30000-32767, but it can be customized.
Default port numbers can be changed, and if custom ports are used, those specific ports must be opened instead of the defaults listed here.
Why did we study about ports in detail above ?
Kubeadm requires manual setup, so understanding these ports is important when configuring firewalls, networking, and security rules.
Minikube, on the other hand, is an automated setup meant for local environments, and it handles these configurations internally.
However, if you're running Minikube in a custom setup (like a VM or cloud instance), knowing these ports can still be useful for troubleshooting or network access.
Now, let’s start our kubernetes cluster journey with minikube , since it’s much easier to setup as compared to kubeadm. Follow this guide to setup minikube : https://cloudvesna.com/step-by-step-guide-running-kubernetes-on-aws-ec2-with-minikube-3997d7aab6a4 .
Deployment of nginx for practicing Kubernetes :
At first , we create deployment ; then, we view the deployments and also the pods.
By default, Nginx listens on port 80 inside the container, but this port is inside the Pod's network namespace, not accessible directly from your local machine.
To make the Nginx service available outside the Pod, we can run the command :
kubectl expose deployment my-nginx --port=80 --type=LoadBalancer
This creates a Service in Kubernetes. A Service provides a stable network endpoint to access your Pods.
--port=80
: Exposes the Pod's internal port 80 to the Service.--type=LoadBalancer
: Requests a cloud load balancer (or Minikube simulates one) to expose the Service externally.
Justification: A Service is necessary because Pods are ephemeral (they can restart or move to another node). A Service ensures a consistent way to access your Nginx app, regardless of where the Pod runs.
To check if the Service was created successfully, we can use the command : kubectl get services
This displays the list of Services, including:
ClusterIP
: The internal IP assigned to the Service (accessible within the cluster).External-IP
: The external endpoint (if applicable).Port
: The port exposed by the Service.
Then we run the command minikube service my-nginx
. Minikube translates the Kubernetes Service's external endpoint into a URL that you can access on your local machine. We can use minikube service my-nginx --url
to obtain the accessible URL
On visiting the URL , through our local machine, we get :-
What is Minikube Dashboard?
Minikube Dashboard is a web-based user interface (UI) that allows you to visually interact with the resources running in your Minikube Kubernetes cluster. It provides a graphical view of various Kubernetes objects like Pods, Deployments, Services, ReplicaSets, and other components within your Minikube environment.
Demo WebApp Project :
At first, we will dockerize a simple react app by following the steps mentioned in my previous blog : https://iamkishaloy.hashnode.dev/docker-revision . Then we will build its image by a command like docker build -t kishaloy01/webapp-demo:02 .
(since my Dockerhub username is kishaloy01). Then we will use docker login
and enter our credentials properly ; then finally we will push the image like docker push kishaloy01/webapp-demo:02
Then we can use the command : kubectl create deployment webapp --image=IMAGEID
(In my case, it was kubectl create deployment webapp --image=kishaloy01/webapp-demo:02 )
We can then check with get deployments and get pods commands :
We can then expose the PORT using service :
NOTE: We can also delete the undesirable deployments using the “delete” command.
For example :
NOTE: 1) The kubectl logs
command is used to view the logs of a pod's container. It is helpful for debugging issues such as crashes, errors, or unexpected behavior within containers.
- The
kubectl describe
command provides a detailed overview of a resource (such as a pod, deployment, or service) in the cluster. It includes metadata, status, events, and other useful information that helps to debug problems and understand resource configurations.
Concept of Rollout in Kubernetes:
In Kubernetes, "rollout" refers to the process of updating a deployment to use a new version of an application or configuration. Kubernetes manages the rollout automatically to ensure that your application remains available during the update.
Let use see an example :
1. Create a Deployment
Let’s create a deployment with version 1 of the application.
kubectl create deployment my-app --image=nginx:1.20
Check the pods:
kubectl get pods
2. Update the Deployment
Now, update the application to a new version (nginx:1.21
).
kubectl set image deployment/my-app nginx=nginx:1.21
3. Rollout Status
You can track the progress of the rollout with:
kubectl rollout status deployment/my-app
This shows whether the update was successful or if there are any issues.
After the update, new pods will run nginx:1.21
, while the old ones are terminated.
4. Rollback if Needed
If the new version has issues, you can rollback to the previous version.
kubectl rollout undo deployment/my-app
This restores the previous version (nginx:1.20
).
Rollout Benefits
Zero Downtime: Old pods are gradually replaced with new ones to ensure continuous availability.
Rollback: Quickly revert to a stable version if something goes wrong.
Control: Manage updates at your own pace using commands like
pause
andresume
.
Rollback in Kubernetes
A rollback in Kubernetes reverts a deployment to a previous version if a newer version has issues like bugs, misconfiguration, or instability. Kubernetes maintains a history of revisions for each deployment, making it easy to switch back to an earlier version. Example: Point 4 above .
Self-Healing in Kubernetes
Self-healing in Kubernetes means the system automatically detects and fixes problems with your application to ensure it remains healthy and available. Kubernetes uses built-in mechanisms to monitor your application's state and restore it if something goes wrong.
Kubernetes monitors your application's desired state (defined in your deployment) and compares it to the actual state:
Desired State: The state you want.
Actual State: The state Kubernetes observes in the cluster.
If the actual state doesn't match the desired state (e.g., a pod crashes), Kubernetes automatically:
Restarts failed pods.
Reschedules pods on different nodes if a node fails.
Recreates pods if they are deleted accidentally.
Example : Self-Healing in Action :-
Step 1: Create a Deployment
Deploy an application with 3 replicas:
Check the pods:
Step 2: Simulate a Failure
Manually delete one of the pods:
Check the pods again:
- What Happened? Kubernetes noticed one pod was missing (actual state ≠ desired state) and created a new pod to maintain 3 replicas. (Note: In the above example , we can see the AGEs of the pods to understand the phenomenon).
YAML Configuration for Deployment and Service in Kubernetes
In Kubernetes, YAML files are used to define configurations for deploying applications and exposing them as services. These configurations describe what Kubernetes should do and the desired state of your application. Using YAML configurations for Kubernetes deployments and services streamlines application management by making it simpler, consistent, and scalable. It allows developers and DevOps teams to focus on innovation rather than managing infrastructure manually.
Step 1: Deployment YAML
This file creates a deployment with 2 replicas of an Nginx application:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: my-nginx
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Key Points:
replicas: 2
: Runs 2 instances of the app.selector
: Matches pods with theapp: my-nginx
label.containers
:image: nginx:latest
: Pulls the Nginx image from Docker Hub.containerPort: 80
: Exposes port 80 inside the pod.
Step 2: Service YAML
This file exposes the pods created by the deployment:
apiVersion: v1
kind: Service
metadata:
name: my-nginx-service
spec:
selector:
app: my-nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
Key Points:
selector
: Matches pods with theapp: my-nginx
label.ports
:port: 80
: The port the service listens on.targetPort: 80
: The port the pods listen on.
type: LoadBalancer
: Exposes the service to the internet.
How to Apply These Files
Save the deployment YAML as
deployment.yaml
and the service YAML asservice.yaml
.Apply them using
kubectl
:kubectl get deployments
andkubectl get services
.
Note: We can see above : my-nginx-deployment and my-nginx-service
SDN-Based Networking:
SDN stands for Software-Defined Networking (SDN). SDN in Kubernetes separates networking from physical hardware and automates it. The networking part is managed using software.
Understanding SDN in Kubernetes:
Kubernetes follows a flat network model where:
Every pod gets a unique IP address.
Pods can communicate with each other as if they are on the same network.
Services expose applications internally or externally without needing manual network setup.
This is achieved using Container Network Interface (CNI) plugins, which implement SDN in Kubernetes.
How SDN Works in Kubernetes :
1️⃣ Control Plane Handles Networking Rules
The Kubernetes API server and controllers manage networking rules.
These rules determine how pods communicate, how services are exposed, and how external users access apps.
2️⃣ SDN Implements the Rules
Instead of relying on physical routers/switches, SDN uses software to control traffic flow.
SDN tools like CNI plugins (Calico, Flannel, Cilium) implement these rules dynamically.
3️⃣ Network Policies Manage Traffic
Kubernetes uses Network Policies to define which pods/services can talk to each other.
For example, you can block database pods from being accessed by all other pods except the backend.
Different SDN Implementations in Kubernetes (CNI Plugins)
Kubernetes does not manage networking on its own. Instead, CNI (Container Network Interface) plugins handle SDN.
CNI Plugin | How It Works | Best For |
Flannel | Creates a simple overlay network | Easy networking setup |
Calico | Uses BGP (Border Gateway Protocol) for direct routing | Performance & security |
Cilium | Uses eBPF for faster networking {Extended Berkeley Packet Filter (eBPF)} | Advanced networking policies |
Weave | Simple & automatic networking | Easy multi-cluster networking |
Analogy between AWS and Kubernetes :
AWS Component | Kubernetes Equivalent | Explanation |
EC2 Instance | Pod | An EC2 instance runs applications, just like a Kubernetes Pod runs one or more containers. |
EBS (Elastic Block Store) | Persistent Volume (PV) | EBS provides persistent storage for EC2 instances, similar to how Persistent Volumes store data for Kubernetes pods. |
ALB (Application Load Balancer) | Service (LoadBalancer/ClusterIP/NodePort) | ALB routes external traffic to EC2 instances, just like a Kubernetes Service routes traffic to Pods. |
Route 53 (DNS Service) | CoreDNS | Route 53 manages DNS for AWS resources, while CoreDNS provides internal DNS resolution in a Kubernetes cluster. |
What is a Namespace in Kubernetes?
A Namespace is like a separate workspace inside a Kubernetes cluster.
It helps in organizing, isolating, and managing resources (pods, services, deployments, etc.).
Real-World Analogy:
Imagine a shopping mall .
Inside the mall, there are different stores (namespaces) like Electronics, Clothing, and Food.
Each store manages its own inventory (pods, services) without affecting others.
Why Use Namespaces?
✅ Logical separation – Different teams/projects can work in different namespaces.
✅ Resource isolation – You can limit CPU, memory, and storage per namespace.
✅ Better security – Users can have access only to specific namespaces.
✅ Easy management – Helps prevent naming conflicts (e.g., multiple nginx
pods in different namespaces).
Default Namespaces in Kubernetes:
By default, Kubernetes has four namespaces:
Namespace | Purpose |
default | Used when no namespace is specified. |
kube-system | Used for Kubernetes internal components (e.g., scheduler, controller). |
kube-public | Readable by everyone, used for cluster-wide information. |
kube-node-lease | Manages node heartbeat leases for health monitoring. |
Creating a New Namespace
Method 1: Command Line
Create a namespace using:
kubectl create namespace my-namespace
Check existing namespaces:
kubectl get namespaces
Method 2: YAML File
apiVersion: v1
kind: Namespace
metadata:
name: my-namespace
Apply it using:
kubectl apply -f my-namespace.yaml
Deploying a Pod Inside a Namespace:
If you want to create a pod in my-namespace, modify the YAML:
apiVersion: v1
kind: Pod
metadata:
name: my-nginx-pod
namespace: my-namespace
spec:
containers:
- name: nginx-container
image: nginx
Apply it:
kubectl apply -f my-nginx-pod.yaml
List pods inside the namespace:
kubectl get pods -n my-namespace
Deleting a Namespace (Caution!) :
To delete a namespace and everything inside it:
kubectl delete namespace my-namespace
This will remove all pods, services, and deployments inside my-namespace
.
Some common Kubernetes errors :-
1. Err Image Pull
What is it?
- Err Image Pull happens when Kubernetes (via the Kubelet on your worker nodes) is unable to pull (download) the container image for a Pod from a container registry (like Docker Hub, AWS ECR, Google Container Registry, etc.).
Why does this happen?
The most common reasons for this error are:
Incorrect image name: If the image name specified in your pod definition (YAML file) is wrong or misspelled, Kubernetes will fail to find and pull the image.
Wrong tag: If the image tag (version) specified doesn't exist in the registry, the pull will fail.
No access to the registry: If Kubernetes doesn't have permission to access the container registry (for example, using a private registry without proper credentials), it can't pull the image.
Network issues: Sometimes, the network connection between the Kubernetes node and the container registry is interrupted or has issues, preventing the image from being pulled.
How to Troubleshoot "Err Image Pull"?
Check the image name and tag: Ensure that the name of the image is correct and the tag (like
nginx:latest
) is valid.Verify credentials: If the image is in a private registry, make sure Kubernetes has the right credentials. You can create a Kubernetes Secret to store the credentials and reference it in your deployment.
Check network: Ensure your nodes have internet access and can reach the registry.
2. CrashLoopBackOff
What is it?
- CrashLoopBackOff is an error where a container inside a Pod continuously crashes and tries to restart over and over. Kubernetes will attempt to restart the container but if it keeps failing, it will eventually stop trying after several failed attempts, and the Pod enters a CrashLoopBackOff state.
Why does it happen?
Misconfigured application: The most common cause is that the application inside the container crashes due to a bug or misconfiguration. For example, an app might expect a file or environment variable that isn’t present, causing it to crash.
Out of memory or CPU: If the app uses more resources (like CPU or memory) than the node can provide, it might get killed by the operating system.
Incorrect command or entry point: If the command or entry point specified for the container is incorrect or the executable is missing, the container will crash.
Dependencies missing: The app might depend on other services or components that are not yet ready or are misconfigured.
How to Troubleshoot "CrashLoopBackOff"?
Check logs: Use
kubectl logs <pod-name>
to see the logs from the container and look for any errors that might indicate why the application is failing.This will show you any error messages output by the application inside the container.
Check resource usage: Ensure that the container has enough memory and CPU. If not, you can adjust the resource limits in your YAML file (like increasing memory limits).
Use
kubectl describe pod
: This can give more detailed information about the container's state and events that occurred, including whether the container was killed due to resource limits or crashed.
ReplicaSet:
What is a ReplicaSet?
A ReplicaSet is a Kubernetes controller that ensures a specific number of identical Pods are running in the cluster. If some Pods crash or get deleted, the ReplicaSet automatically replaces them.
Example in Kubernetes YAML :
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend-replicaset
spec:
replicas: 3 # Ensure 3 frontend Pods exist
selector:
matchLabels:
tier: frontend # Find existing Pods with this label
template:
metadata:
labels:
tier: frontend # New Pods will have this label
spec:
containers:
- name: my-app
image: nginx
How ReplicaSet Works Step by Step
Step 1️⃣: Searching for Pods with Label tier=frontend
When the ReplicaSet starts, it searches the entire cluster for existing Pods that have Label: tier=frontend
(just like the manager checks which employees already have a "frontend" badge).
Step 2️⃣: Checking If These Pods Are Already Managed
If the found Pods are already managed by another controller (like a Deployment), the ReplicaSet ignores them.
If the Pods are NOT managed by anyone, the ReplicaSet takes control of them.
Step 3️⃣: Ensuring Exactly 3 Pods Exist
The ReplicaSet checks how many Pods it found with the label tier=frontend
:
If 3 Pods are already there → Great! No action needed.
If only 2 Pods exist → The ReplicaSet creates 1 new Pod to reach the total of 3.
If 0 Pods exist → The ReplicaSet creates 3 new Pods to meet the requirement.
Checking in Kubernetes
1️⃣ Get all ReplicaSets
kubectl get rs
This shows how many Pods each ReplicaSet is managing.
2️⃣ Get all Pods
kubectl get pods --show-labels
This lists all Pods along with their labels.
Observations:
Naming Convention in Kubernetes:
Example
Consider this Deployment YAML file for an Nginx application:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
What Happens When We Apply This?
When you run: kubectl apply -f deployment.yaml
We get :
Kubernetes creates:
Deployment:
Name:
nginx-deployment
This is the controller that ensures 3 Pods are always running.
ReplicaSet:
Name:
nginx-deployment-54c98b4f84
This is automatically created by the Deployment.
The hash (
54c98b4f84
) is based on the pod template and ensures uniqueness.
Pods:
Names:
nginx-deployment-54c98b4f84-j6rr5 nginx-deployment-54c98b4f84-s6qfs nginx-deployment-54c98b4f84-t6nt6
Each Pod name consists of:
<Deployment Name>-<ReplicaSet Hash>-<Unique Pod ID>
SUMMARY :
Kubernetes Object | Purpose | Naming Convention | Example |
Deployment | Ensures a specified number of Pods are running and handles updates. | <deployment-name> | nginx-deployment |
ReplicaSet | Ensures the right number of Pods exist at all times. Created automatically by Deployment. | <deployment-name>-<replicaset-hash> | nginx-deployment-86dcfdf4c6 |
Pod | Smallest deployable unit in Kubernetes, containing a containerized app. | <replicaset-name>-<unique-id> | nginx-deployment-86dcfdf4c6-9d9mc |
What Happens When You Update the Deployment?
Let's say you update the image in the Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.20 # Updated from latest to 1.20
Run: kubectl apply -f deployment.yaml
What will happen?
A new ReplicaSet (e.g.,
nginx-deployment-75b9fd87c5
) is created because the Pod template changed.The old ReplicaSet (
nginx-deployment-86dcfdf4c6
) will be scaled down to 0 Pods.The new ReplicaSet (
nginx-deployment-75b9fd87c5
) will create 3 new Pods.
Probes: Ensuring Application Health Inside Pods:
A Pod might be running, but the application inside it could be stuck, slow, or unresponsive.
To monitor application health inside the Pod, Kubernetes provides three types of probes:
1. Startup Probe: Checking If an App Has Started
Used only during application startup.
If the app takes a long time to start, Kubernetes waits until the app is ready instead of assuming it has failed.
Once the Startup Probe succeeds, it stops checking further.
🔵 Example of a Startup Probe in Kubernetes YAML:
apiVersion: v1
kind: Pod
metadata:
name: slow-app
spec:
containers:
- name: slow-container
image: myapp
startupProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10 # Wait 10 sec before first check
periodSeconds: 5 # Check every 5 sec
failureThreshold: 5 # Fail after 5 failed attempts
Here, Kubernetes waits 10 seconds before the first health check.
If the app starts slowly, Kubernetes waits longer before marking it as failed.
2. Readiness Probe: Checking If an App Is Ready to Receive Traffic
Used to decide when a Pod should receive traffic.
Even if the Pod is running, the app inside might not be ready yet.
If the Readiness Probe fails, Kubernetes removes the Pod from the load balancer until it recovers.
🔵 Example of a Readiness Probe in Kubernetes YAML:
apiVersion: v1
kind: Pod
metadata:
name: web-app
spec:
containers:
- name: web-container
image: mywebapp
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5 # Wait 5 sec before first check
periodSeconds: 3 # Check every 3 sec
If the app inside isn’t ready, Kubernetes removes it from the load balancer.
Once it becomes ready, traffic resumes.
3. Liveness Probe: Checking If an App Is Still Alive
Used to check if an app has crashed or is stuck.
If the Liveness Probe fails, Kubernetes automatically restarts the Pod.
🔵 Example of a Liveness Probe in Kubernetes YAML:
apiVersion: v1 kind: Pod metadata: name: backend-app spec: containers: - name: backend-container image: mybackend livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 5 # Wait 5 sec before first check periodSeconds: 10 # Check every 10 sec failureThreshold: 3 # Restart Pod after 3 failures
- If the app hangs or crashes, Kubernetes restarts the Pod.
Summary of Probes:
Component | Purpose | What It Checks? |
Startup Probe | Checks if the application has started | If the app takes too long to start |
Readiness Probe | Checks if the app is ready to receive traffic | If the app is initialized and can serve requests |
Liveness Probe | Checks if the app is still running | If the app freezes or crashes |
Microservice Traffic Flow in Kubernetes:
What is Microservice Traffic Flow?
Microservice traffic flow refers to how data moves between different microservices inside a Kubernetes cluster. { NOTE : Microservices in Kubernetes are a software development approach that breaks down an application into small, independent services. These services are then deployed using Kubernetes}.
1️⃣ How External Traffic Enters the Cluster
When a user opens a website (example.com
)., the request goes through several steps:
🔹 Step 1: DNS Resolution
- CoreDNS resolves
example.com
to an IP address, directing traffic to the right service.
🔹 Step 2: Traffic Reaches Kubernetes via Ingress or Load Balancer
Ingress Controller or Load Balancer routes traffic to the right microservice.
If the app is public, a Load Balancer (AWS ELB, Azure LB, etc.) is used.
If it’s inside Kubernetes, Ingress handles routing.
✅ Ingress Example (Routes traffic based on URL):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ecommerce-ingress
spec:
rules:
- host: example.com
http:
paths:
- path: /shop
backend:
service:
name: shop-service
port:
number: 80
- path: /cart
backend:
service:
name: cart-service
port:
number: 80
If the user accesses
example.com/shop
, it goes toshop-service
.If the user accesses
example.com/cart
, it goes tocart-service
.
🔹 Step 3: Service Routes Traffic to the Correct Pod
Since Pods have dynamic IPs, a Kubernetes Service gives them a stable IP.
Types of Services:
ClusterIP – Default, used for internal traffic.
NodePort – Exposes a service on a specific port.
LoadBalancer – Exposes a service externally.
✅ Service Example (Routes traffic to the correct microservice):
apiVersion: v1
kind: Service
metadata:
name: shop-service
spec:
selector:
app: shop
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
The service ensures requests reach the correct Pods, even if their IPs change.
2️⃣ How Microservices Communicate Internally
Once inside Kubernetes, microservices often need to communicate with each other.
🔹 Scenario: Checkout Service Needs Product Details
The
checkout-service
needs to callinventory-service
to check stock.DNS-Based Service Discovery happens using
service-name.namespace.svc.cluster.local
.Example:
curl
http://inventory-service.default.svc.cluster.local:80
The
checkout-service
can call theinventory-service
using the internal ClusterIP.
3️⃣ Securing Microservice Traffic
To ensure safe and controlled communication, Kubernetes provides:
Security Feature | Purpose | Example |
Network Policies | Restrict which Pods can talk to each other | Firewalls inside a mall, allowing only certain employees to enter restricted areas |
Service Mesh (Istio, Linkerd) | Adds encryption, retries, monitoring to traffic | Mall security cameras tracking visitor movement |
TLS Encryption (mTLS) | Encrypts traffic between services | A secure vault in a bank |
Example: Network Policy (Only Allows Checkout to Call Inventory)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-checkout-to-inventory
spec:
podSelector:
matchLabels:
app: inventory
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: checkout
- This ensures that only
checkout-service
can talk toinventory-service
, blocking unauthorized services.
DaemonSet in Kubernetes:
What is a DaemonSet?
A DaemonSet ensures that a specific Pod runs on every node in a Kubernetes cluster.
🔹 Why Do We Need DaemonSets?
Some system-level services should run on all nodes, such as:
✅ Log collectors (e.g., Fluentd, Filebeat) – To collect logs from all nodes.
✅ Monitoring agents (e.g., Prometheus Node Exporter) – To track node performance.
✅ Security tools (e.g., Falco) – To monitor system activity for security threats.
Think of it like:
If Kubernetes is a city, a DaemonSet is like having a security guard at every building instead of just one main security office.
🔹 How Does a DaemonSet Work?
It automatically creates a Pod on every node.
When a new node is added, it adds a Pod on that node.
If a node is removed, the Pod on that node is deleted.
Example: Running a Log Collector on Every Node
Imagine you have a Kubernetes cluster with three nodes, and you need Fluentd to collect logs from all nodes.
✅ DaemonSet YAML to Deploy Fluentd on All Nodes
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-daemonset
labels:
app: fluentd
spec:
selector:
matchLabels:
name: fluentd-pod
template:
metadata:
labels:
name: fluentd-pod
spec:
containers:
- name: fluentd
image: fluent/fluentd:v1.14
resources:
limits:
memory: 200Mi
cpu: 100m
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
hostPath:
path: /var/log
What This Does:
Creates a Fluentd Pod on every node.
Mounts
/var/log
to collect logs from all nodes.Automatically runs on new nodes if added to the cluster.
✅ Apply the DaemonSet in Kubernetes
kubectl apply -f fluentd-daemonset.yaml
✅ Check DaemonSet Status
kubectl get daemonset
Output:
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
fluentd-daemonset 3 3 3 3 3 <none> 10s
Means: Fluentd is running on all three nodes in the cluster.
🔹 Controlling Where DaemonSet Runs
By default, a DaemonSet runs on all nodes, but you can limit it to specific nodes using nodeSelector or nodeAffinity.
✅ Example: Run DaemonSet Only on Worker Nodes
spec:
template:
spec:
nodeSelector:
node-role.kubernetes.io/worker: "true"
This ensures Fluentd runs only on worker nodes and not on master nodes.
Quick Hands-On Commands :
✅ Check All DaemonSets
kubectl get daemonsets -A
✅ Describe DaemonSet Details
kubectl describe daemonset fluentd-daemonset
✅ Delete DaemonSet
kubectl delete daemonset fluentd-daemonset
Kubernetes StatefulSet:
Unlike Deployments, where Pods are identical and can be replaced freely, StatefulSet Pods have:
✅ Fixed names (e.g., pod-0
, pod-1
, pod-2
)
✅ Persistent storage that does not get deleted when a Pod restarts
✅ Ordered scaling (Pods start and stop in a defined sequence)
Think of it like:
A hotel where every room (Pod) has a fixed room number, and when a guest leaves, their room and belongings (Persistent Volume) are still reserved for them.
How StatefulSet Works:
1️⃣ Creates Pods with unique, ordered names (pod-0
, pod-1
, etc.)
2️⃣ Ensures stable network identities using a Headless Service (pod-0.app
, pod-1.app
)
3️⃣ Uses Persistent Volumes so data is not lost when a Pod restarts
4️⃣ Maintains order when scaling up/down (adds/removes Pods in sequence)
Example: Deploying MySQL with StatefulSet:
✅ Step 1: Create a Headless Service
A Headless Service gives each StatefulSet Pod a fixed DNS name.
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
clusterIP: None # Makes it headless
selector:
app: mysql
ports:
- port: 3306
📌 Why Headless? Because each Pod needs a stable hostname (e.g., mysql-0
, mysql-1
).
✅ Step 2: Create the StatefulSet for MySQL
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql # Uses the Headless Service
replicas: 3 # Three MySQL Pods
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "mypassword"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
What This Does:
✅ Creates 3 MySQL Pods (mysql-0
, mysql-1
, mysql-2
)
✅ Uses Persistent Volumes (mysql-data
) so data persists after restarts
✅ Ensures each Pod has a fixed hostname (mysql-0.mysql
, mysql-1.mysql
)
✅ Step 3: Deploy the StatefulSet and the service :
✅ Step 4: Check StatefulSet Status:
Hence, all 3 MySQL Pods are running.
✅ Check Persistent Volume Claims (PVC)
kubectl get pvc
Each Pod gets its own separate storage (mysql-data-mysql-0
, mysql-data-mysql-1
).
✅ Scale Up StatefulSet to 5 Pods
kubectl scale statefulset mysql --replicas=5
✅ Scale Down StatefulSet to 2 Pods
kubectl scale statefulset mysql --replicas=2
📌 Note: When scaling down, the last Pod is removed first (mysql-2
before mysql-1
).
Quick Hands-On Commands:
✅ Check All StatefulSets
kubectl get statefulsets -A
✅ Describe StatefulSet Details
kubectl describe statefulset mysql
✅ Delete StatefulSet (But Keep Storage)
kubectl delete statefulset mysql --cascade=orphan
✅ Delete StatefulSet (And Remove Storage)
kubectl delete statefulset mysql
kubectl delete pvc -l app=mysql
Init Containers:
What are Init Containers?
Init containers are special containers that run before the main container in a Pod. They are used for preparing environments before the actual application starts.
Why use Init Containers?
Preload data (e.g., fetch database schema).
Wait for dependencies (e.g., ensure the database is running before starting the app).
Set up configurations dynamically.
Practical: Using an Init Container
Create a file pod-with-init.yaml
:
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
initContainers:
- name: init-container
image: busybox
command: ['sh', '-c', 'echo "Initializing..."; sleep 5; echo "Done!"']
containers:
- name: main-container
image: nginx
command: ['sh', '-c', 'echo "Main container started"; sleep 3600']
🔹 Apply and Check
kubectl apply -f pod-with-init.yaml
kubectl get pods
kubectl describe pod init-demo
You will see that init-container runs first before the main container starts.
Resource Requests:
What are Resource Requests?
Resource requests in Kubernetes tell the scheduler how much CPU and memory a container needs at a minimum.
Why use Resource Requests?
Ensures a Pod gets at least the requested resources.
Helps Kubernetes schedule Pods efficiently.
Practical : Setting Resource Requests
Create a file pod-resource-request.yaml
:
apiVersion: v1
kind: Pod
metadata:
name: resource-pod
spec:
containers:
- name: app-container
image: nginx
resources:
requests:
memory: "256Mi" # Minimum memory required
cpu: "250m" # Minimum CPU required (250 millicores = 0.25 CPU)
Apply and Check
kubectl apply -f pod-resource-request.yaml
kubectl describe pod resource-pod
Kubernetes LimitRange:
What is LimitRange?
A LimitRange sets the minimum and maximum amount of CPU/memory a container can request in a namespace.
Why use LimitRange?
Prevents any container from consuming too many resources.
Ensures fair resource distribution.
Practical: Setting LimitRange
Create a file limit-range.yaml
:
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-mem-limits
spec:
limits:
- default:
memory: 512Mi
cpu: "500m"
defaultRequest:
memory: 128Mi
cpu: "250m"
type: Container
Apply and Check:
kubectl apply -f limit-range.yaml
kubectl get limitrange
kubectl describe limitrange cpu-mem-limits
Now, if a Pod does not specify its resource limits, Kubernetes will apply these defaults.
Observation:
Kubernetes Resource Quota:
What is a Resource Quota?
A Resource Quota restricts how much total CPU/memory/storage a namespace can consume.
Why use Resource Quota?
Prevents one team from consuming all cluster resources.
Ensures fair allocation across multiple teams.
Practical : Setting a Resource Quota
Create a file resource-quota.yaml
:
apiVersion: v1
kind: ResourceQuota
metadata:
name: my-quota
spec:
hard:
pods: "10" # Maximum 10 Pods in this namespace
requests.cpu: "2" # Max 2 CPU cores requested
requests.memory: "4Gi" # Max 4GB memory requested
limits.cpu: "4" # Max 4 CPU cores allowed
limits.memory: "8Gi" # Max 8GB memory allowed
Apply and Check
kubectl apply -f resource-quota.yaml
kubectl get resourcequota
kubectl describe resourcequota my-quota
Now, if someone tries to create more than 10 Pods, Kubernetes will block the request.
Multi-Container Pod in Kubernetes:
What is a Multi-Container Pod?
A Multi-Container Pod is a Kubernetes pod that contains more than one container. These containers share the same network (IP), storage (volumes), and lifecycle, allowing them to work together.
Why Use Multi-Container Pods?
One container helps another (e.g., logging, monitoring).
One container transforms data for another.
Acts as a proxy between services.
Example:
Imagine a food delivery app:
Main Container: Runs the app that processes orders (
order-service
).Sidecar Container: A separate container collects logs (
logging-service
).
Multi-Container Pod Example:
apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
spec:
containers:
- name: order-service
image: nginx # Main container
- name: logging-service
image: busybox
command: ["sh", "-c", "while true; do echo 'Logging Order Data'; sleep 5; done"]
How to Apply & Test
kubectl apply -f multi-container-pod.yaml
kubectl logs multi-container-pod -c logging-service # View logs of the sidecar container
Outcomes:
Kubernetes ConfigMap:
What is a ConfigMap?
A ConfigMap in Kubernetes is used to store configuration data separately from the application code. This helps in keeping the application flexible and easier to manage.
Think of ConfigMap as a settings file (like .env
in local development) that stores configuration details such as:
Database connection details
API keys (non-sensitive)
Environment-specific settings
Why Use ConfigMap?
Instead of hardcoding configurations inside your application, you can store them in a ConfigMap.
❌ Without ConfigMap (Hardcoded)
env:
- name: DATABASE_URL
value: "mysql://user:password@db-host:3306/mydb"
- Problem: If the database host or password changes, you need to modify and redeploy the application.
✅ With ConfigMap
envFrom:
- configMapRef:
name: my-config
- Advantage: If the database URL changes, you only update the ConfigMap without redeploying the application.
NOTE: A ConfigMap stores configuration data (key-value pairs) that can be injected into pods without changing the container image*.*
Create ConfigMap from YAML:
Let's define a ConfigMap named app-config
with some database settings.
🔹 ConfigMap YAML File
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DATABASE_HOST: "mysql"
DATABASE_PORT: "3306"
APP_ENV: "production"
🔹 Apply the ConfigMap
kubectl apply -f app-config.yaml
🔹 Verify the ConfigMap
kubectl get configmap app-config -o yaml
Outcomes:
Using ConfigMap as Environment Variables:
Now, let's use our app-config
ConfigMap inside a Pod.
🔹 Define a Pod using ConfigMap
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: app-container
image: nginx
envFrom:
- configMapRef:
name: app-config # Inject ConfigMap as environment variables
🔹 Apply the Pod
kubectl apply -f configmap-pod.yaml
🔹 Check if ConfigMap values are available in the container
kubectl exec -it configmap-pod -- env | grep DATABASE_
Expected Output:
DATABASE_HOST=mysql
DATABASE_PORT=3306
Outcomes:
Summary:
✅ ConfigMaps store configuration separately from application code.
✅ They can be used as environment variables or mounted as files in a Pod.
✅ Updating a ConfigMap does not require redeploying the Pod.
Short Summary:
Concept | Description | |
Pod Controller | Replication | Ensures the specified number of Pod replicas are running at all times. |
ReplicaSet | Manages the lifecycle of Pods, ensuring the desired number of replicas is maintained. A ReplicaSet is used by Deployments. | |
Deployment | Manages stateless applications by creating and updating Pods in a controlled manner, ensuring the desired state. | |
DaemonSet | Ensures that a copy of a Pod is running on each node (or a subset of nodes) in a Kubernetes cluster, often used for logging, monitoring, or networking. | |
StatefulSet | Manages stateful applications, ensuring each Pod has a stable, unique identity (e.g., database Pods). | |
Service | ClusterIP | Exposes the service on an internal IP within the cluster, only accessible within the cluster. |
Headless | A service with no ClusterIP, used to directly access the Pods via DNS records, typically used with StatefulSets. | |
NodePort | Exposes the service on a specific port on each node in the cluster, making it accessible externally at <NodeIP>:<NodePort> . | |
LoadBalancer | Exposes the service to external traffic using a cloud provider's load balancer, automatically provisioning an external IP. | |
ExternalName | Maps the service to a DNS name, allowing access to external services by their name, instead of IP or hostname. |
Ingress Controller:
What is an Ingress Controller?
An Ingress Controller is a component in Kubernetes (K8s) that manages ingress resources. It acts as a traffic manager or gatekeeper for HTTP and HTTPS traffic that comes into your Kubernetes cluster. Its main job is to route the external HTTP/HTTPS requests to the appropriate services inside the Kubernetes cluster.
How does it work?
Ingress Resource: This is a set of rules or configurations that define how the HTTP(S) requests should be routed to different services in your Kubernetes cluster.
Ingress Controller: It reads these rules (ingress resources) and configures the system to manage incoming traffic accordingly.
Key Concepts
Ingress Resource: Defines the rules for routing HTTP/HTTPS traffic. It can specify things like:
Which URLs map to which services
Whether or not to use SSL (HTTPS)
Path-based routing (e.g.,
/app1
goes to service A,/app2
goes to service B)
Ingress Controller: It's like a proxy that reads the ingress resource and makes sure the traffic is forwarded correctly to the services.
Practical Example
Let’s say we have two applications running in our Kubernetes cluster:
App1 (running on port 8081)
App2 (running on port 8082)
Step 1: Create an Ingress Resource
We define an Ingress resource to tell Kubernetes how traffic should be routed. For example, we could say:
All traffic coming to
http://mywebsite.com/app1
should go toApp1
(service1).All traffic coming to
http://mywebsite.com/app2
should go toApp2
(service2).
Here’s an example of an Ingress Resource configuration:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: default
spec:
rules:
- host: mywebsite.com
http:
paths:
- path: /app1
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 8081
- path: /app2
pathType: Prefix
backend:
service:
name: app2-service
port:
number: 8082
This resource defines that:
Requests to
/app1
will be sent toapp1-service
on port 8081.Requests to
/app2
will be sent toapp2-service
on port 8082.
Step 2: Install and Configure the Ingress Controller
To manage these ingress resources, we need to install an Ingress Controller (like NGINX Ingress Controller). This controller will listen for incoming requests and apply the routing rules defined in the Ingress resource.
You can install NGINX Ingress Controller using Kubernetes commands, for example:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
Once the Ingress Controller is installed and running, it automatically starts managing incoming HTTP/HTTPS traffic based on the ingress rules you’ve defined.
Step 3: Accessing Your Applications
Now, let's assume your DNS is set up to route mywebsite.com
to your Kubernetes cluster's external IP. When someone accesses http://mywebsite.com/app1
, the Ingress Controller will route this traffic to the app1-service
running on port 8081. Similarly, http://mywebsite.com/app2
will be routed to the app2-service
.
Why is it Useful?
Centralized Traffic Management: Instead of creating a separate load balancer for each service, you can have a single point (Ingress Controller) for managing all external traffic.
Simplified URL Routing: With path-based routing, you can easily manage different apps within the same domain (
mywebsite.com/app1
,mywebsite.com/app2
).SSL Termination: Ingress controllers can handle HTTPS and SSL termination, meaning they can manage the secure connection between external users and your services.
Cost-Efficient: Using an Ingress Controller reduces the need for multiple load balancers, saving costs.
Pod Autoscaling:
What is Pod Autoscaling?
In Kubernetes, a Pod is the smallest deployable unit. It represents a single instance of a running process in a cluster. Pod Autoscaling refers to the ability to automatically adjust the number of Pods running in a Kubernetes deployment based on the current demand or load. This helps ensure your application remains responsive and efficient, whether it's experiencing high traffic or low traffic.
Why do we need Pod Autoscaling?
Efficient Resource Management: Instead of manually scaling the number of Pods based on expected load, Kubernetes can automatically increase or decrease Pods as needed.
Cost Efficiency: Autoscaling ensures that you’re only running the number of Pods necessary at any given moment, which helps save resources (and costs) when the demand is low.
Performance Optimization: It ensures that your app can handle increased traffic by scaling up automatically when the load is high.
How does Pod Autoscaling work?
There are two primary types of Pod Autoscaling in Kubernetes:
Horizontal Pod Autoscaler (HPA): This automatically adjusts the number of Pods based on CPU or memory usage or other custom metrics.
Vertical Pod Autoscaler (VPA): This automatically adjusts the CPU and memory resources allocated to a Pod based on its usage.
However, in this explanation, we’ll focus mainly on Horizontal Pod Autoscaler (HPA) because it’s the most common one used.
Key Concepts of Horizontal Pod Autoscaler (HPA):
Metrics: The HPA uses metrics like CPU usage and memory usage to determine whether a Pod needs to be scaled up or down. For example, if CPU usage goes beyond 80% for a period, the HPA will create more Pods to handle the extra load.
Target Utilization: You set a target utilization value (like 50% CPU). The HPA will try to maintain the target CPU or memory usage by scaling the number of Pods.
Scaling Decision: If the current load exceeds the target utilization, HPA scales up (adds more Pods). If the load is less, it scales down (removes Pods).
How to Set Up Horizontal Pod Autoscaling?
Here’s a simple example to help you understand how it works in practice.
Step 1: Deploy Your Application
First, let’s say you have a simple web application running in a Kubernetes deployment with a single Pod.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1 # Initially we have one Pod
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app-container
image: my-app-image
resources:
requests:
cpu: "100m" # CPU request (in milliCPU)
memory: "128Mi"
limits:
cpu: "500m" # CPU limit
memory: "512Mi"
Step 2: Create an HPA Resource
Now, we define the Horizontal Pod Autoscaler. This will automatically scale the number of Pods based on the average CPU usage. We’ll set a target of 50% CPU utilization. If the average CPU usage of the Pods exceeds 50%, it will scale up the Pods, and if the usage falls below that threshold, it will scale down.
Here’s an example of the HPA resource:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 1 # Minimum number of Pods
maxReplicas: 5 # Maximum number of Pods
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50 # Target 50% CPU usage
Step 3: How the Autoscaler Works
Scaling Up: If the average CPU usage exceeds 50% for a sustained period, Kubernetes will add more Pods to handle the load. So if the load increases and the current Pod(s) are overworked, the system will automatically add new Pods.
Scaling Down: If the CPU usage falls below the 50% target for a sustained period, the HPA will scale down by removing excess Pods. For example, if the load decreases, the system might reduce the number of Pods from 3 to 1.
Step 4: Monitor the Autoscaling
To check the status of the HPA and see how many Pods are currently running, you can use the following command:
kubectl get hpa
This will show you something like this:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
my-app-hpa Deployment/my-app 50%/50% 1 5 3 5m
In this example, it shows that:
Target is 50% CPU utilization.
Current replicas is 3 (out of a possible 1–5).
The HPA is adjusting the replicas based on CPU usage.
Concept of Taint & Toleration in Kubernetes :
In Kubernetes, Taint & Toleration is a mechanism used to control which Pods can be scheduled on which Nodes. It helps in restricting or prioritizing certain workloads to specific nodes.
What is a Taint?
A Taint is a label (restriction) applied to a Node that prevents general Pods from being scheduled on it. A Node with a Taint will only allow Pods that have the matching Toleration.
Syntax of a Taint:
kubectl taint nodes <node-name> key=value:effect
key=value
→ The identifier for the tainteffect
→ Defines how the taint behaves (explained below)
Types of Effects:
NoSchedule → Prevents scheduling new Pods unless they have a matching toleration.
PreferNoSchedule → Tries to avoid scheduling Pods but does not strictly enforce it.
NoExecute → Evicts already running Pods that don’t tolerate the taint.
What is a Toleration?
Think of it as a "PASS CARD" that lets a Pod enter a restricted Node.
Syntax of a Toleration in a Pod's YAML:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
- The Pod will be scheduled on the Node only if the Taint and Toleration match.
PRACTICAL:
Scenario 1: Dedicated Nodes for Critical Applications
Imagine you have a Kubernetes cluster with 5 Nodes, and one of them has high-end hardware. You want only critical workloads (like a database) to run on that Node.
Step 1: Apply a Taint to the High-End Node
kubectl taint nodes high-performance-node critical=true:NoSchedule
This prevents all normal Pods from being scheduled on this node.
Step 2: Add a Toleration to the Critical Workload
Modify the Pod definition for your database:
apiVersion: v1
kind: Pod
metadata:
name: critical-db
spec:
tolerations:
- key: "critical"
operator: "Equal"
value: "true"
effect: "NoSchedule"
Now, only the critical-db
Pod can be scheduled on high-performance-node
, while other Pods are kept away.
Scenario 2: Temporary Maintenance on a Node
You have a Node node1 that needs maintenance, and you want to evict running Pods from it.
Step 1: Apply a Taint to Evict Pods
kubectl taint nodes node1 maintenance=true:NoExecute
All Pods without a toleration for this taint will be removed from this Node.
Step 2: Allow Certain Pods to Stay
If you want some system Pods (like monitoring agents) to continue running, you add a toleration:
tolerations:
- key: "maintenance"
operator: "Equal"
value: "true"
effect: "NoExecute"
Now, only these Pods will stay, while others will be evicted.
Real-world analogy: VIP lounge (tainted Node) only allows VIP guests (Pods with matching toleration).
What is a Static Pod?
Definition:
A Static Pod is a special type of Pod that is directly managed by the Kubelet on a specific Node, not by the Kubernetes API Server.
Key Characteristics:
They do not have a
ReplicaSet
orDeployment
.They are not managed by the Kubernetes Scheduler.
They run only on the node where they are defined.
If the Node crashes, the Pod will not restart on another Node automatically.
Analogy:
Think of Static Pods like system services (e.g., SSH, Nginx, or a database) installed directly on a machine. These services always run on that specific machine, regardless of external systems.
Example: Running a Static Pod
Step 1: Create a Static Pod YAML on a Node
A Static Pod is created by placing a YAML file in the /etc/kubernetes/manifests/
directory on a Node.
apiVersion: v1
kind: Pod
metadata:
name: static-web
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
Step 2: Move the YAML to the Static Pod Directory
mv static-pod.yaml /etc/kubernetes/manifests/
Step 3: Verify the Pod is Running
kubectl get pods -A
Since the Static Pod is not controlled by the API Server, it won't appear in kubectl get deployments
, but you can still see it in the pod list.
What is nodeName in Kubernetes?
Definition:
nodeName
is a hardcoded way to schedule a Pod on a specific Node.
Key Characteristics:
The Pod is only scheduled on the Node specified.
If the Node is unavailable, the Pod is stuck in
Pending
state.No failover to another Node unless re-created.
Analogy:
Think of nodeName
like manually assigning a delivery to a specific worker. If that worker is unavailable, the delivery doesn’t happen.
Example: Assigning a Pod to a Specific Node
Step 1: Get the Node Name
kubectl get nodes
Example output:
NAME STATUS ROLES AGE VERSION
node-1 Ready worker 10d v1.24.0
node-2 Ready worker 10d v1.24.0
Step 2: Create a Pod YAML with nodeName
apiVersion: v1
kind: Pod
metadata:
name: nginx-node1
spec:
nodeName: node-1
containers:
- name: nginx
image: nginx
Step 3: Apply the YAML
kubectl apply -f nginx-node1.yaml
Step 4: Verify the Pod is Running on the Specific Node
kubectl get pods -o wide
If node-1
is unavailable, the Pod will be stuck in Pending
state.
What is NodeAffinity?
Definition:
NodeAffinity is a mechanism in Kubernetes that allows you to control how Pods are scheduled onto Nodes based on specific conditions.
It works like an advanced version of nodeName
, where instead of hardcoding a specific Node, we define rules for selecting the Node dynamically.
Key Characteristics:
Unlike
nodeName
, it allows flexible Node selection.Works with Labels assigned to Nodes.
Helps in distributing workloads across Nodes based on their characteristics (e.g., CPU, memory, region).
Analogy:
Think of NodeAffinity like assigning students to classrooms based on their subjects.
A Math student should be in a Math classroom.
A Science student should be in a Science classroom.
Here, the subject is like a Node label, and the student is the Pod.
Example: Using NodeAffinity
Step 1: Label Nodes Based on Region
First, find available Nodes:
kubectl get nodes
Example output:
NAME STATUS ROLES AGE VERSION
node-1 Ready worker 100d v1.24.0
node-2 Ready worker 100d v1.24.0
Now, assign labels:
kubectl label nodes node-1 region=us-east
kubectl label nodes node-2 region=us-west
Step 2: Define a Pod with NodeAffinity
apiVersion: v1
kind: Pod
metadata:
name: nginx-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: region
operator: In
values:
- us-east
containers:
- name: nginx
image: nginx
Step 3: Apply the YAML
kubectl apply -f nginx-affinity.yaml
Step 4: Verify if the Pod is Scheduled on the Correct Node
kubectl get pods -o wide
If everything is correct, the Pod should be running on node-1
(us-east).
Types of NodeAffinity:
Type | Description |
requiredDuringSchedulingIgnoredDuringExecution | Strict rule - The Pod will only schedule on matching Nodes. |
preferredDuringSchedulingIgnoredDuringExecution | Soft rule - The Pod prefers a matching Node but will run elsewhere if needed. |
NOTE:
Concept | Description | Analogy |
ETCD | Stores all cluster data | A digital notebook where Kubernetes writes all cluster details |
ETCD Backup | Saves a snapshot of the cluster | Taking a backup of your phone data |
ETCD Restore | Recovers the cluster from backup | Restoring phone data after a reset |
Kubernetes LocalPath Storage:
LocalPath Storage in Kubernetes allows you to use a node's local disk storage to store data for your applications. It is commonly used for testing, development, and single-node clusters.
What is LocalPath Storage?
LocalPath Storage is provided by Rancher’s Local Path Provisioner, which dynamically creates PersistentVolumes (PVs) using local storage on the worker node where a Pod runs.
Think of it like this:
If your application needs storage, LocalPath will allocate a folder on the node’s local disk and mount it to your Pod.
The data will not move if the Pod is scheduled on another node (unlike cloud-based storage like EBS or NFS).
When to Use LocalPath Storage?
✅ For development & testing – Quick and easy storage setup.
✅ For single-node Kubernetes clusters – No need for external storage.
✅ For lightweight applications – When you don’t need persistent cloud storage.
🚫 When NOT to use it:
In production multi-node clusters (data won’t move with the Pod).
When you need high availability (node failure = data loss).
For distributed applications that require shared storage.
How Does LocalPath Storage Work?
1️⃣ Local Path Provisioner creates a folder on the node.
2️⃣ It mounts that folder into your Pod.
3️⃣ The Pod reads/writes data to that folder.
4️⃣ If the Pod moves to another node, the data does NOT follow it.
Example: Running a MySQL Database with LocalPath Storage
1️⃣ Install Local Path Provisioner
If you're using Rancher Desktop or k3s, LocalPath is pre-installed.
Otherwise, install it manually:
kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
Verify installation:
kubectl get storageclass
You should see:
2️⃣ Create a PersistentVolumeClaim (PVC)
This requests storage from LocalPath.
Create a file mysql-pvc.yaml
:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce # Only one Pod can use it at a time
resources:
requests:
storage: 1Gi
storageClassName: local-path
Apply it:
kubectl apply -f mysql-pvc.yaml
Check PVC status:
kubectl get pvc
Output:
3️⃣ Deploy MySQL with LocalPath Storage
Create a file mysql-deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "password123"
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql-storage
volumes:
- name: mysql-storage
persistentVolumeClaim:
claimName: mysql-pvc
Apply it:
kubectl apply -f mysql-deployment.yaml
Check pod and storage:
kubectl get pods -o wide
kubectl describe pod <pod_name>
4️⃣ Verify Data Persistence
Now, let’s test if the data is stored locally:
🔹 Step 1: Connect to MySQL Pod
kubectl exec -it $(kubectl get pods -l app=mysql -o jsonpath="{.items[0].metadata.name}") -- mysql -u root -p
Enter password: password123
🔹 Step 2: Create a Test Database
CREATE DATABASE testdb;
SHOW DATABASES;
You should see testdb
in the list.
🔹 Step 3: Delete the MySQL Pod
kubectl delete pod $(kubectl get pods -l app=mysql -o jsonpath="{.items[0].metadata.name}")
Wait for the Pod to restart.
🔹 Step 4: Check if Data is Still There
Reconnect and run:
SHOW DATABASES;
If testdb
is still there, LocalPath Storage is working!
How to Remove LocalPath Storage?
To delete all storage:
kubectl delete -f mysql-deployment.yaml
kubectl delete -f mysql-pvc.yaml
To remove Local Path Provisioner:
kubectl delete -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
Storage Network Volume in Kubernetes
What is it?
A Storage Network Volume in Kubernetes refers to storage that is accessible over a network, rather than being tied to a single node (server). It allows pods (containers) to read and write data even if they move between nodes.
Example:
Imagine you have an application running in Kubernetes that needs a shared database (like MySQL or PostgreSQL). If this database is running inside a pod and that pod crashes or moves to another node, you will lose data if it was stored only on the original node.
Solution:
Use a network-attached storage (NAS) like:
AWS EBS (Elastic Block Store)
Google Cloud Persistent Disk
NFS (Network File System)
CephFS (Distributed File System)
How it Works in Kubernetes?
You create a Persistent Volume (PV) and a Persistent Volume Claim (PVC) that requests storage from the network.
Example YAML:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-network-volume
spec:
accessModes:
- ReadWriteOnce # Only one pod can write, but many can read
resources:
requests:
storage: 5Gi
storageClassName: standard # This uses cloud storage (AWS/GCP)
Key Benefits:
✔ Data survives even if the pod dies
✔ Accessible from multiple nodes
✔ Works with cloud providers and on-prem solutions
Kubernetes RBAC (Role-Based Access Control)
What is it?
RBAC controls who can do what in your Kubernetes cluster.
Example Scenario
Imagine your team has:
Developers (Can deploy apps)
Ops Team (Can restart servers)
Security Team (Read-only access)
RBAC Key Components
Roles: Defines permissions (within a namespace)
ClusterRoles: Defines permissions for the entire cluster
RoleBinding: Grants a Role to a user or group
ClusterRoleBinding: Grants a ClusterRole to a user
Example 1: Create a Role for Read-Only Access
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: read-only-role
rules:
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list"]
- This allows users to only view pods and services in the
default
namespace.
Example 2: Bind Role to a User
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-only-binding
namespace: default
subjects:
- kind: User
name: john.doe # Replace with actual username
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: read-only-role
apiGroup: rbac.authorization.k8s.io
- Now, john.doe can only read pods and services.
Kubernetes Service Account
What is a Service Account?
A Service Account is an identity used by pods to interact with the Kubernetes API.
Similar to how users log in with user accounts, pods use service accounts to perform actions inside the cluster.
By default, every pod uses the default service account unless we specify a custom one.
Why Use Service Accounts?
✔ Control what a pod can access (RBAC permissions)
✔ Prevent unauthorized actions (e.g., a pod deleting resources)
✔ Better security (limit API access per application)
Example 1: Default Service Account
Every namespace has a default service account.
kubectl get serviceaccounts -n default
Output:
NAME SECRETS AGE
default 1 10d
- This means any pod created in the
default
namespace automatically gets this service account.
Example 2: Create a Custom Service Account
Instead of using the default one, let's create a custom service account.
Step 1: Define a Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
namespace: default
Apply it:
kubectl apply -f my-service-account.yaml
Step 2: Attach the Service Account to a Pod
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
serviceAccountName: my-service-account # Attach custom service account
containers:
- name: my-container
image: nginx
Now, this pod uses my-service-account instead of the default one.
Example 3: Grant Permissions to the Service Account
By default, a service account has no permissions. You must bind a Role or ClusterRole.
Step 1: Create a Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
- This role allows reading pod information.
Step 2: Bind the Role to the Service Account
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader-binding
namespace: default
subjects:
- kind: ServiceAccount
name: my-service-account
namespace: default
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Now, my-service-account can list pods but not delete them.
Kubernetes Security Context
What is a Security Context?
Security Context defines security settings for pods and containers.
It controls privileges, user permissions, and network security.
Why Use Security Context?
✔ Prevent containers from running as root
✔ Limit file access
✔ Control Linux capabilities (e.g., disable dangerous syscalls)
Example 1: Run a Pod as a Non-Root User
By default, containers run as root, which is risky.
apiVersion: v1
kind: Pod
metadata:
name: non-root-pod
spec:
securityContext:
runAsUser: 1000 # Run as user ID 1000 instead of root
runAsGroup: 3000 # Run with group ID 3000
fsGroup: 2000 # File system permissions
containers:
- name: my-container
image: nginx
- This ensures the pod does not run as root.
Example 2: Read-Only Root Filesystem
Prevent a container from modifying system files.
apiVersion: v1
kind: Pod
metadata:
name: read-only-pod
spec:
containers:
- name: my-container
image: nginx
securityContext:
readOnlyRootFilesystem: true # Prevents writing to the root filesystem
- This ensures the pod cannot modify its own files.
Example 3: Drop Linux Capabilities (Extra Privileges)
By default, containers inherit some Linux capabilities. Let’s drop them.
apiVersion: v1
kind: Pod
metadata:
name: restricted-pod
spec:
containers:
- name: my-container
image: nginx
securityContext:
capabilities:
drop:
- ALL # Drop all Linux capabilities
- This removes all extra privileges.
Example 4: Privileged Mode (Avoid This!)
Some containers need privileged mode to access host resources.
apiVersion: v1
kind: Pod
metadata:
name: privileged-pod
spec:
containers:
- name: my-container
image: nginx
securityContext:
privileged: true # Full root access (Not Recommended)
- ⚠️ WARNING: This gives full access to the node, which is a security risk.
Helm (Kubernetes Package Manager):
What is Helm?
Helm is like apt/yum (Linux) or npm (JavaScript) but for Kubernetes.
It simplifies the installation, management, and upgrading of Kubernetes applications. Instead of writing long YAML files, Helm uses charts (predefined templates) to deploy applications.
Why Use Helm?
✅ Saves Time – No need to write huge Kubernetes YAML files.
✅ Easy to Upgrade – Run one command to upgrade applications.
✅ Version Control – Roll back to a previous version if needed.
✅ Reusable – Share and reuse Helm charts.
The picture explains the concept well :
Example: Deploying Nginx with Helm
1️⃣ Install Helm
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
2️⃣ Add Helm Repo & Install Nginx
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install my-nginx bitnami/nginx
This deploys an Nginx web server on Kubernetes in seconds.
3️⃣ Check Deployment
kubectl get pods
kubectl get svc
4️⃣ Uninstall Nginx
helm uninstall my-nginx
🔹 Helm Chart Structure
A Helm chart is a folder with these files:
mychart/
├── Chart.yaml # Chart metadata (name, version, description)
├── values.yaml # Default configuration values
├── templates/ # Kubernetes YAML templates
│ ├── deployment.yaml
│ ├── service.yaml
To customize values:
helm install my-nginx bitnami/nginx --set service.type=LoadBalancer
This changes the service type from ClusterIP (default) to LoadBalancer.
Key Helm Concepts :
Concept | Meaning | Example |
Chart | A Helm package containing Kubernetes YAML templates | bitnami/nginx |
Release | A deployed instance of a Helm chart in a cluster | my-nginx |
Repository | A collection of Helm charts | https://charts.bitnami.com/bitnami |
Values.yaml | A file that stores configurable values for a Helm chart | service.type=LoadBalancer |
Templates/ | A directory where Helm stores Kubernetes YAML templates | deployment.yaml, service.yaml |
Common Helm Commands :
Command | Description |
helm repo add <repo-name> <repo-url> | Add a new Helm chart repository |
helm repo update | Update all Helm chart repositories |
helm search repo <chart-name> | Search for a chart in repositories |
helm install <release-name> <chart-name> | Install a Helm chart |
helm list | Show all installed Helm releases |
helm upgrade <release-name> <chart-name> | Upgrade a Helm release |
helm rollback <release-name> <revision> | Roll back to a previous version |
helm uninstall <release-name> | Uninstall a Helm release |
helm show values <chart-name> | Display default values of a chart |
WHY INGRESS CAME ?
Kubernetes Ingress is like a traffic cop for your Kubernetes cluster. It helps direct incoming traffic (like web requests) to the right services inside your cluster. Before Kubernetes, people used tools like Nginx, F5, or HAProxy to manage traffic on local VMs. These tools provided advanced features like ratio-based load balancing, sticky sessions, path-based routing, TLS termination, domain-based routing, white listing, back listing and more. But when Kubernetes first came out, its built-in load balancer was very basic and didn’t offer these advanced features. This disappointed people moving from traditional VMs to Kubernetes.
Additionally, Kubernetes initially had high costs for static public IPs used by load balancers. To solve these problems, the Kubernetes team introduced Ingress.
NOTE: Short explanations of the above mentioned features :
Ratio-Based Load Balancing: Distributes traffic to backend servers based on a predefined ratio (e.g., 70% to Server A, 30% to Server B).
Sticky Sessions: Ensures a user’s requests always go to the same backend server during their session.
Path-Based Routing: Routes traffic to different services based on the URL path (e.g.,
/api
goes to Service A,/app
goes to Service B).TLS Termination: Decrypts HTTPS traffic at the gateway and sends it as plain HTTP to backend services.
Domain-Based Routing: Routes traffic to different services based on the domain name (e.g.,
foo.com
to Service A,bar.com
to Service B).Whitelisting: Allows only specific IPs or users to access a service.
Blacklisting: Blocks specific IPs or users from accessing a service.
Ingress acts as a smart gateway, routing traffic based on rules you define.
How Does Ingress Work?
Ingress Resource: You define rules in a YAML file .
Ingress Controller: The controller reads these rules and configures itself (e.g., Nginx) to route traffic accordingly.
Simplest Example : Default Backend
This is the simplest Ingress setup. All traffic is routed to a single service.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
defaultBackend:
service:
name: test
port:
number: 80
- What it does: Any traffic coming to your cluster will be sent to the
test
service on port 80.
Let’s see an example of Host-Based Routing:
This routes traffic based on the domain name (host).
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-with-auth
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: http-svc
port:
number: 80
- host: example.bar.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: meow-svc
port:
number: 80
What it does:
If someone visits
foo.bar.com
, they’ll be routed to thehttp-svc
service.If someone visits
example.bar.com
, they’ll be routed to themeow-svc
service.
Let’s see a simple Ingress tutorial:
1. Enable Ingress in Minikube
Minikube doesn’t enable Ingress by default, so first, start Minikube and enable Ingress:
minikube start
minikube addons enable ingress
Verify that the Ingress controller is running:
kubectl get pods -n kube-system | grep ingress
You should see pods like ingress-nginx-controller
running.
2. Deploy a Sample App
Let's create a simple Nginx deployment and expose it as a service.
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
Apply this deployment:
kubectl apply -f nginx-deployment.yaml
Now, expose it as a service:
kubectl expose deployment nginx-deployment --port=80 --target-port=80 --type=ClusterIP
Check the service:
kubectl get svc
You should see a ClusterIP
service created for Nginx.
3. Create an Ingress Resource
Now, let’s define an Ingress resource to expose our Nginx service.
# nginx-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: nginx.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-deployment
port:
number: 80
Apply the Ingress resource:
kubectl apply -f nginx-ingress.yaml
Check if the Ingress is created:
kubectl get ingress
4. Test Ingress
Since Minikube runs in a VM, you need to update your /etc/hosts
file to resolve nginx.local
to Minikube’s IP.
Find Minikube’s IP:
minikube ip
If Minikube IP is 192.168.49.2
, update /etc/hosts
:
192.168.49.2 nginx.local
Now, test in your browser or with curl
:
curl http://nginx.local
You should see the default Nginx welcome page.