Kubernetes

Arindam BaidyaArindam Baidya
30 min read

Table of contents

πŸš€ From Container to Production: The Need for Orchestration

So, you've containerized your application using Dockerβ€”awesome! πŸŽ‰
But now comes the real challenge:

How do you run that application in production?

Let’s say your app depends on other services like a database, messaging queue, or authentication backend. What if thousands of users show up? You’ll need to scale your app up. What if demand drops? You’ll want to scale down and save resources.

This is where container orchestration comes into play.


πŸ”§ What is Container Orchestration?

Container orchestration is the automated management of containerized applicationsβ€”handling deployment, scaling, networking, and health monitoring.

With orchestration tools, you can:

  • 🧩 Manage multi-container apps seamlessly

  • πŸ”— Connect containers across services

  • πŸ“ˆ Automatically scale with traffic spikes

  • ⚠️ Recover from hardware or service failures

  • πŸ“ Use declarative YAML configs to define system behavior


βš™οΈ The Tools of the Trade

There are several container orchestration platforms available:

ToolDescriptionEase of UseFeatures
Docker SwarmNative orchestration tool from Dockerβœ… Easy❌ Limited
Apache MesosPowerful but complex❌ Hardβœ… Advanced
KubernetesThe gold standard in orchestration⚠️ Moderate🌟 Feature-rich

🌐 Why Kubernetes Stands Out

Kubernetes (aka K8s), originally developed by Google, is now the most widely adopted container orchestration platform in the worldβ€”and for good reason:

  • 🧠 Highly customizable deployments

  • ☁️ Runs on all major clouds (AWS, GCP, Azure)

  • 🌍 Massive open-source community

  • πŸ“¦ Supports complex microservice architectures

Kubernetes isn't just a toolβ€”it's an entire ecosystem for managing modern apps.


🎯 Key Benefits of Kubernetes

FeatureBenefit
πŸ” Self-HealingAutomatically replaces failed containers
βš–οΈ Load BalancingDistributes traffic across running containers
πŸ“¦ Auto-ScalingDynamically adjusts resources based on demand
🧱 Service AbstractionExposes apps via internal or external services
πŸ“œ Declarative ConfigsInfrastructure as Code using YAML
πŸ“‘ Rolling UpdatesDeploy new versions with zero downtime

Kubernetes allows you to run hundreds or thousands of containers reliably across clustersβ€”without breaking a sweat. πŸ’ͺ


πŸ—οΈ Kubernetes Architecture: The Building Blocks of a Cluster

Before diving into setting up a Kubernetes cluster, it’s crucial to understand its core components and how they work together. This foundational knowledge helps make sense of the key terms and processes you'll encounter throughout your Kubernetes journey.


🧱 What is a Node?

A Node is a physical or virtual machine on which Kubernetes is installed. It acts as a worker machineβ€”this is where your containers actually run.

🧠 Fun fact: Nodes were once referred to as Minions.

But here’s the catch:
What happens if the node running your application fails?

πŸ‘‰ Your application goes down.
To avoid this, Kubernetes clusters are designed with multiple nodesβ€”so if one fails, another steps in. This ensures high availability and load distribution.


πŸ‘₯ What is a Cluster?

A Cluster is a group of nodes working together as a unified system. This allows:

  • Resilience: If one node fails, others continue serving the application.

  • Load Sharing: Requests are distributed across nodes to prevent overload.


πŸ‘‘ Enter the Master Node (Control Plane)

A cluster of worker nodes must be managed and coordinated. That’s the job of the Master Node, also known as the Control Plane.

The Master node is responsible for:

  • Monitoring the health of nodes

  • Managing deployments

  • Rescheduling containers if a node goes down


βš™οΈ Core Components of Kubernetes

When you install Kubernetes, you're actually installing a collection of components. Here's what powers the cluster:

πŸ”Œ API Server

Acts as the front door to the cluster.
All communicationβ€”whether from users, tools, or CLIsβ€”goes through the API Server.

kubectl cluster-info  # View cluster info via the API server

πŸ“¦ etcd (Key-Value Store)

A distributed, reliable key-value store used to persist the cluster state.

  • Stores all configuration data

  • Ensures consistency across nodes and masters

  • Helps in managing logs and consensus in distributed environments


🧠 Scheduler

The Scheduler decides where new containers should run by:

  • Analyzing resource availability

  • Assigning workloads to the best-fit node


🧬 Controllers

Controllers are the brain behind orchestration.

They:

  • Detect changes or failures

  • Take corrective action (e.g., restart containers, rebalance workloads)

Think of them as automated managers ensuring desired state is always maintained.


🐳 Container Runtime

The software responsible for running containers. Common runtimes include:

RuntimeDescription
DockerMost widely used (used in this course)
containerdLightweight Docker alternative
CRI-OKubernetes-native runtime
RocketNow deprecated, but once popular

πŸ›°οΈ Kubelet

An agent that runs on every worker node.

  • Communicates with the Master

  • Ensures containers are running as expected

  • Executes commands sent from the Control Plane


🧭 Master vs Worker Node – What’s the Difference?

ComponentMaster NodeWorker Node
kube-apiserverβœ…βŒ
controller-managerβœ…βŒ
schedulerβœ…βŒ
etcd (optional)βœ…βŒ
kubeletβŒβœ…
container runtime (e.g. Docker)βŒβœ…

🧰 Meet kubectl: Your Command Line Superpower

kubectl (pronounced "kube control") is the primary CLI tool for interacting with a Kubernetes cluster.

Some essential commands:

kubectl run hello-minikube       # Deploy an app to the cluster
kubectl cluster-info             # View cluster information
kubectl get nodes                # List all nodes in the cluster

With kubectl, you can manage deployments, inspect logs, scale services, and moreβ€”all from your terminal.


🐳 Docker vs Containerd + CLI Tools (ctr, nerdctl, crictl)


πŸ”₯ The Rise of Docker

In the early days of containerization, Docker became the dominant container tool due to its simplicity and complete developer experience. It bundled everything:

  • CLI tools

  • Image building capabilities

  • Volume and networking support

  • Security features

  • The container runtime itself (powered by Containerd and runc)

Kubernetes was initially designed to orchestrate Docker containers.


πŸ“ˆ The Kubernetes Evolution

As Kubernetes gained popularity, there was demand to support other container runtimes beyond Dockerβ€”such as rkt (Rocket).

This led Kubernetes to introduce the Container Runtime Interface (CRI)β€”a standard interface that allows Kubernetes to work with any OCI-compliant runtime.


πŸ“¦ What is OCI?

OCI stands for Open Container Initiative, which defines:

  • πŸ—οΈ Image Spec – how container images should be built

  • βš™οΈ Runtime Spec – how runtimes should behave


🧩 Enter CRI and Docker Shim

Since Docker was developed before CRI existed, it did not natively support CRI.

To continue supporting Docker, Kubernetes introduced the "Docker Shim", a workaround that allowed Docker to work with Kubernetes via a compatibility layer.

However, this was only a temporary solutionβ€”and Kubernetes eventually deprecated Docker support in favor of CRI-compatible runtimes like Containerd and CRI-O.


🧠 Docker vs Containerd

FeatureDockerContainerd
PurposeComplete container platformLightweight container runtime
IncludesCLI, image builder, networking, volumes, runtimeOnly the container runtime layer
CRI-Compatible❌ (via shim only)βœ…
Works with KubernetesYes (deprecated)βœ… (native)
CLI Toolsdockerctr, nerdctl

πŸ› οΈ CLI Tools Explained


1. βš™οΈ ctr – Containerd's Native CLI

  • Comes built-in with Containerd

  • Low-level CLI primarily for debugging

  • Not user-friendly or suitable for production use

ctr images pull docker.io/library/redis:alpine
ctr run docker.io/library/redis:alpine redis

2. πŸš€ nerdctl – Docker-like CLI for Containerd

  • Developed by the Containerd community

  • User-friendly, supports Docker-like syntax

  • Enables advanced features not available in Docker:

    • Encrypted container images

    • Lazy pulling

    • P2P image distribution

    • Image signing and verification

    • Kubernetes namespaces

nerdctl run --name redis redis:alpine
nerdctl run --name webserver -p 80:80 -d nginx

3. πŸ” crictl – CRI Debug Tool

  • CLI tool developed by the Kubernetes community

  • Interacts with CRI-compatible runtimes (e.g., Containerd, CRI-O)

  • Used for inspecting, debugging, and monitoring

  • Not used for creating or managing containers directly

crictl pull busybox
crictl images
crictl ps -a
crictl exec -i -t <container_ID> ls
crictl logs <container_ID>
crictl pods

πŸ”š Summary Table

ToolPurposeDeveloped ByWorks With
ctrLow-level CLI for ContainerdContainerd communityOnly Containerd
nerdctlDocker-like CLI for ContainerdContainerd communityOnly Containerd
crictlDebug/Inspect CRI runtimesKubernetes communityAny CRI-compatible runtime

βš™οΈ Setting Up Kubernetes: A Beginner’s Guide

There are multiple ways to set up a Kubernetes clusterβ€”ranging from local development setups to full-scale production environments in the cloud.


πŸš€ Kubernetes Setup Options

EnvironmentTools/ServicesUse Case
πŸ–₯️ Local MachineMinikube, MicroK8s, KindDevelopment & learning
🏒 ProductionkubeadmManual setup for real-world deployments
☁️ CloudGKE (Google), EKS (AWS), IBM Cloud, etc.Managed clusters in the cloud

🌟 Getting Started with Minikube

For beginners, the easiest way to spin up a Kubernetes cluster on your laptop is with Minikube.


🧠 What is Minikube?

Minikube is a lightweight tool that creates a single-node Kubernetes cluster on your local machine.

πŸ” It’s designed for:

  • Learning Kubernetes

  • Testing clusters

  • Local app development


βš™οΈ How Does Minikube Work?

Minikube bundles all of Kubernetes’ core components into a pre-packaged image, providing a ready-to-go cluster in minutes.

Components it includes:

  • Master Node Services:

    • kube-apiserver

    • etcd key-value store

    • controller-manager

    • scheduler

  • Worker Node Services:

    • kubelet (agent)

    • container runtime (like Docker or Containerd)

πŸ’‘ Instead of manually setting up each of these components across different machines, Minikube provides a pre-configured ISO image that includes everything.


πŸ–₯️ Minikube Installation Requirements

To get Minikube up and running, you’ll need:

RequirementDescription
πŸ–₯️ HypervisorA virtualization platform like Oracle VirtualBox or VMware
πŸ”§ kubectlKubernetes CLI tool to interact with the cluster
πŸ“¦ MinikubeThe Minikube executable to install and run the local cluster

Once installed, you can run commands like:

minikube start            # Start a local Kubernetes cluster
kubectl get nodes         # View node(s) in the cluster
kubectl get pods --all-namespaces

Pods

πŸ“¦ What is a Pod in Kubernetes?

A Pod is the smallest thing you can run in Kubernetes.
It usually contains one containerβ€”your app.


🧠 Simple Setup: One Cluster β†’ One Node β†’ One Pod

You start with:

  • 🧩 Cluster (Kubernetes)

  • πŸ–₯️ Node (Machine where apps run)

  • πŸ“¦ Pod (Your app wrapped in a container)

🧾 Command to create a Pod:

kubectl run myapp --image=nginx

This command:

  • Creates a Pod named myapp

  • Runs the Nginx web server inside it

πŸ” Check the Pod:

kubectl get pods

πŸ“ˆ Scale Up: Add More Pods

As traffic grows, we want to run multiple copies of the app (Pods).
We do this by creating a Deployment that manages scaling.

🧾 Create a Deployment with one replica:

kubectl create deployment myapp --image=nginx

🧾 Scale to 3 Pods (replicas):

kubectl scale deployment myapp --replicas=3

πŸ” Check running Pods:

kubectl get pods

You should see 3 pods like:

myapp-xxxxxxx-abcde
myapp-xxxxxxx-fghij
myapp-xxxxxxx-klmno

πŸ“‰ Scale Down: Reduce to 1 Pod

When traffic is low, reduce the number of Pods to save resources.

🧾 Scale down to 1 Pod:

kubectl scale deployment myapp --replicas=1

πŸ” Check again:

kubectl get pods

Now only one Pod should be running.


Pods With YAML - Creating Pods using a YAML based configuration file

Kubernetes uses YAML files as inputs for the creation of objects such as pods, replicas, deployments, services. All of this follows a similar structure. A Kubernetes defination file always contains four top-level fields, the apiVersion, kind, metadata, and spec. These are the top level or root level properties.

apiVersion: This is the version of the kubernetes API we are using to create the object. Depending on what we are trying to create, we must use the right API version. For now, since we are working on pods, we will set the API version as v1. Few other possible values for this field are apps/v1, beta, extensions/v1, etc.

kind: Kind refers to the type of object we are trying to create. Which in this case happened to be a Pod. Some other possible values here could be ReplicaSet, Deployment, or Service.

metadata: Metadata is the data about the object, like its name, labels, etc. Under the metadata what we put a dictionary. Name and Label are the child of metadata. Under the metadata, the name is a string value, like name: myapp-pod. And the Label is further a dictionary (Label is a dictionary within the metadata dictionary).

Note: Under metadata we can only specify name or label or anything else that Kubernetes expects to be under metadata. But under Labels, we can add any kind of key-value pairs.

spec (Specification section): Depending on the object we are going to create, this is where we would provide additional information to Kubernetes pertaining to that object. Spec is a dictionary, so we added a property under it called containers. Containers is a list or an array. The reason this property is a list because the pods can have multiple containers within them. (Although we are adding a single item in the list).

Once the file is created, run the command kubectl create -f <file-name> and Kubernetes creates a pod.

kubectl get pods use to see list of pod available.

kubectl describe pod <pod-name> to see detailed information about pod when it was created.

Example: pod.yaml

After creating yaml file, Need to create the pod object, and for that we can use, create or, apply command. Both work as same.

kubectl create -f pod.yaml or, kubectl apply -f pod.yaml


☸️ Kubernetes Controllers

Controllers are the brain behind Kubernetes.
They are background processes that monitor Kubernetes objects and respond accordingly to maintain the desired state.


πŸ”„ Replication Controller

One important controller is the Replication Controller.


❓ What is a Replica? Why Use a Replication Controller?

Let’s go back to our first scenario where we had a single Pod running our application.

πŸ”Ή What if the application crashes and the Pod fails?
πŸ”Ή Users will no longer be able to access the application.

To prevent downtime, we need to have more than one instance (or Pod) running at the same time.
That way, if one fails, others keep the application alive.


βœ… Role of the Replication Controller

  • Helps run multiple instances of a single Pod.

  • Ensures high availability of your application.

  • Monitors and maintains the desired number of Pods at all times.

  • Even if one Pod fails, it automatically replaces it with a new one.


πŸ€” Can It Be Used for Just One Pod?

Yes!

Even if you want to run just one Pod, the Replication Controller is useful because:

  • It ensures the Pod is recreated if it fails.

  • You don’t have to manually restart it.


πŸ“ˆ Scaling & Load Balancing

The Replication Controller helps:

  • Create multiple Pods to handle more users.

  • Balance load across different Pods and nodes in the cluster.

  • Automatically deploy more Pods when demand increases.

  • Distribute Pods across multiple nodes if needed.


πŸ†• ReplicaSet vs Replication Controller

πŸ”Ή Both serve the same purpose: maintaining a desired number of Pods.
πŸ”Ή But Replication Controller is the older technology.

  • ReplicaSet is the newer and recommended controller.

  • There are minor differences in how they work internally.

  • Going forward, we will stick to ReplicaSets in all demos and implementations.


Replication Controller

Any Kubernetes definition file, we have four sections, apiVersion, kind, metadata, and spec. The API version is specific to what we are creating. In this case, Replication Controller is supported in Kubernetes API version v1. The kind is ReplicationController, So far it is very similar to how we created a Pod in the previous section. Spec (Specification) is the most crucial part. For any Kubernetes definition file, the spec section defines what’s inside the object we are creating. In this case, we know the Replication Controller creates multiple instances of a Pod. But what Pod? We create a template under spec to provide a Pod template to be used by the Replication Controller to create replicas. For that we can use all of our previous definition file written for Pod creation except apiVersion, and kind.

We have nested two definition files together. The Replication Controller being the parent and the Pod defination being the child. But still we didn’t mentioned how many replicas we need in the Replication Controller. For that we need to add another property to the spec called replicas and input the number of replicas under it.

  • Now, Creating Replication Controller, kubectl create -f rc-definition.yml

  • To view list of created replication controller, kubectl get replicationcontroller

  • To see the pods created by the replication controller, kubectl get pods

Let’s Now look into ReplicaSet

It is very similar to the Replication Controller, But Look into the apiVersion, We need to set it apps/v1, Otherwise there will be an error in ReplicaSet. One more thing is ReplicaSet requires a selector definition. The selector section helps the replica set identify what pods fall under it.

But why we need to specify what pods fall under it, if we providing the contents of the pod definition file itself in the template?

β†’ It’s because ReplicaSet can also manage Pods that were not created as part of the ReplicaSet creation. For example, there are pods created before the creation of the ReplicaSet that match labels specified in the selector. The ReplicaSet also take those pods into consideration when creating the replicas.

The selector is one of the major differences between ReplicationController and ReplicaSet. Selector is not a required field in case of ReplicationController, but it is still available. When we skip this, as we did in the previous example, it assumes it to be the same as the labels provided in the Pod definition file.

In case of ReplicaSet, User input is required for the property, and it has to be written in the form of matchLabels. The match labels selector simply matches the labels specified under it to the labels on the Pod. (Also there are other options in selector for ReplicaSet which are not available in ReplicaController).

Similar command to creating and viewing Pods

  • kubectl create -f replicaset-difination.yml

  • kubectl get replicaset

  • kubectl get pods

  • kubectl delete replicaset myapp-replicaset, to delete the ReplicaSet as well as all Underlying PODs

  • kubectl describe replicaset myapp-replicaset, to get more information about replicaset


Labels and Selectors

Why do we label our Pods and objects in Kubernetes ?

Let us look at a simple scenario, Say we deployed three instances of our front end web application as three Pods. We would like to create a ReplicationController of ReplicaSet to ensure that we have three active Pods at any time. And that is one of the use cases of ReplicaSets, we can monitor existing Pods if we have them already created as it. In case they are not created, the ReplicaSet will create them for us. The ReplicaSet is to monitor the Pods and if any of them were to fail, deploy new ones. The ReplicaSet is infact a process that monitor the Pods.

Now how does the ReplicaSet know what Pods to monitor?

There colud be hundreds of other Pods in the Cluster running different applications. This is where labeling our Pods during creation comes in handy.

We could now provide these labels as a filter for ReplicaSet. Under the Selector section we use the matchLabels filter and provide the same label that we have used while creating the Pods. This way ReplicaSet know which Pod need to monitor. The same concept of labels and selectors is used in many other places throughout the Kubernetes.


In the ReplicaSet specification section, we learned that there are three sections, template, replicas, and selector. We need three replicas and we have updated our selector based on the previous discussed section.

Suppose we have the same scenario where we have three existing Pods that were created already. And we need to create a ReplicaSet to monitor the Pods to ensure there are a minimum of three running at all times.

When a replication controller is created, it is not going to deploy a new instance of pod as three of them with matching labels are already created. In that case do we really need to provide a template section in the ReplicaSet specification since we are not expecting the ReplicaSet to create a new pod on deployment?

β†’ Yes we do, Because in case on of the pods were to fail in the future, the ReplicaSet need to create a new one to maintain the desired number of pods. And for the ReplicaSet to create a new pod, the template definition section is required.


Scale Replica Set

Let’s now look how we can scale ReplicaSet. Say we started with three replica, and in the future we decided to scale to six.

Option 1:

We can update the number of replicas in the ReplicaSet definition file, and then run the following command

  • kubectl replace -f replicaset-definition.yml

    or,

  • kubectl edit replicaset myapp-replicaset It will opens up the running configuration of the replicaset in a text editor.

Option 2:

  • kubectl scale --replicas=6 -f replicaset-definition.yml, This will scale to 6 but not update in the definition file.

Option 3:

  • kubectl scale --replicas=6 replicaset myapp-replicaset, this is TYPE/NAME format, where replicaset = TYPE and myapp-replicaset = NAME. For TYPE, we can use rs in place of replicaset.

Kubernetes Deployments

Deploying an Application in a Production Environment using Kubernetes

When deploying a web server in a production environment, we often need multiple instances of the application running simultaneously β€” not just one β€” for reasons like load balancing, high availability, and fault tolerance.

Additionally, when new versions of the application become available on a Docker registry, we’d like to upgrade these Docker instances seamlessly. However, upgrading all instances at once can disrupt users who are currently accessing the application. To prevent this, we prefer to upgrade them gradually, one after the other. This controlled upgrade mechanism is known as a Rolling Update.

Rolling Updates

With rolling updates, new versions of the application are deployed incrementally, replacing the old versions one pod at a time. This ensures minimal downtime and provides the opportunity to monitor the system for any issues during the rollout.

Rollbacks

Sometimes, a newly rolled-out update may result in unexpected errors. In such cases, we need the ability to roll back to the previous stable version quickly. Kubernetes makes this easy using its rollback feature.

Pausing and Resuming Deployments

There may be scenarios where we want to apply multiple changes to our environmentβ€”such as:

  • Upgrading the web server version

  • Scaling the number of instances

  • Modifying resource allocations (CPU, memory, etc.)

Rather than applying each change immediately, Kubernetes allows us to pause the deployment, make all necessary changes, and then resume it so that all changes are rolled out together. This prevents intermediate states and ensures a clean deployment transition.


Kubernetes Deployment: High-Level Overview

So far, we’ve discussed Pods, which are the smallest deployable units in Kubernetes and encapsulate containers.

To run multiple pods, we use:

  • ReplicaSets: Ensure a specified number of pod replicas are running at all times.

  • ReplicationControllers: An older version of ReplicaSets.

But for higher-level management, Kubernetes provides the Deployment object.

Why Use Deployments?

Kubernetes Deployments offer powerful capabilities:

  • Manage ReplicaSets automatically

  • Enable rolling updates

  • Support rollbacks

  • Allow pausing and resuming deployments


Creating a Deployment

To create a deployment:

  1. Prepare a deployment definition YAML file.
    The structure is similar to a ReplicaSet file, except:

    • The kind is set to "Deployment" instead of "ReplicaSet".
  2. Use the kubectl create command to apply the file:

     kubectl create -f deployment-definition.yaml
    
  3. To verify the deployment:

     kubectl get deployments
    
  4. The deployment automatically creates a ReplicaSet, which can be viewed using:

     kubectl get replicaset
    
  5. The ReplicaSet then creates the pods, which can be listed with:

     kubectl get pods
    
  6. To view all the related resources at once:

     kubectl get all
    

    -β†’ One line command to create a Deployment

    kubectl create deployment <dep-name> --image=<image-name> --replicas=3


Kubernetes Deployments: Update and Rollback

πŸ”„ Understanding Rollouts and Versioning

When we first create a Deployment, Kubernetes triggers a rollout, which in turn creates a Deployment revision.

  • The first deployment is considered Revision 1.

  • When the application is upgraded (e.g., a new container version is deployed), a new rollout is triggered, and a new revision is created β€” e.g., Revision 2.

This versioning system helps track changes made to the deployment and allows us to roll back to any previous version if necessary.

Useful Commands:

  • 🟒 Check rollout status

      kubectl rollout status deployment/myapp-deployment
    
  • πŸ“œ View rollout history

      kubectl rollout history deployment/myapp-deployment
    

πŸ› οΈ Deployment Strategies

Assume we have 5 replicas of our web application running.

1. Recreate Strategy

  • All old pods are terminated first.

  • Then, new pods with the updated version are created.

  • This causes downtime β€” the app is unavailable during the transition.

  • ⚠️ Not the default strategy.

2. Rolling Update Strategy (βœ… Default)

  • One pod at a time is terminated and replaced with a new one.

  • Ensures zero downtime during the update process.

  • Provides a seamless user experience.


πŸ”§ Updating a Deployment

You can update deployments in several ways:

1. Edit the Deployment YAML

  • For changes such as:

    • Container image version

    • Labels

    • Number of replicas

    • Resource limits

kubectl apply -f deployment-definition.yaml
  • This command triggers a new rollout, creating a new ReplicaSet behind the scenes.

2. Update Image via CLI

To update the image directly using kubectl:

kubectl set image deployment/myapp-deployment nginx-container=nginx:1.9.1

⚠️ Note: This updates the deployment in Kubernetes, but does not update your local YAML file. Keep this in mind for version control.


πŸ” Viewing Deployment Details

Use the following command to inspect the details of a deployment:

kubectl describe deployment myapp-deployment

This provides:

  • Rollout history

  • Strategy used

  • ReplicaSets managed

  • Events and status


βš™οΈ How Updates Work Internally

  1. When you create a deployment (e.g., with 5 replicas), Kubernetes:

    • Creates a ReplicaSet

    • Which in turn creates 5 pods

  2. When you update the deployment:

    • Kubernetes creates a new ReplicaSet

    • Begins deploying updated pods there

    • Simultaneously, starts terminating old pods from the previous ReplicaSet (rolling update)

You can observe these changes using:

kubectl get replicasets

βͺ Rolling Back a Deployment

If a newly deployed update is found to be faulty, you can undo the deployment and revert to the previous version:

kubectl rollout undo deployment/myapp-deployment

Kubernetes will:

  • Terminate the pods in the new ReplicaSet

  • Spin up pods from the previous ReplicaSet

This ensures that your application returns to its last known good state quickly and efficiently.

kubectl create -f deployment.yaml --record To record the cause of change.

kubectl edit deployment myapp-deployment --record To edit in a running deployment.

kubectl describe deployment myapp-deployment To see the details of deployment.


πŸ”Œ Kubernetes Networking Basics

🧩 Single Node Cluster

Let’s begin by understanding networking in a single-node Kubernetes cluster.

  • Suppose your node (e.g., a VM or minikube instance) has an IP address: 192.168.1.2.

  • If you're using Minikube, this IP refers to the VM inside your hypervisor, not your actual laptop IP (which might be something like 192.168.1.10).

  • Inside this node, you create a Pod, which hosts a container.

βœ… Important Distinction:
In Docker, containers are assigned individual IPs.
In Kubernetes, IPs are assigned to Pods, not directly to containers.

For example:

  • Your pod may get an IP like 10.244.0.2 β€” this is from an internal virtual network Kubernetes creates (e.g., 10.244.0.0/16).

  • Every Pod gets a unique internal IP, and Pods can communicate with one another via these IPs within the same node.

However:

  • Pod IPs are ephemeral (i.e., they may change when Pods are recreated).

  • Therefore, relying directly on Pod IPs for communication is not recommended.


🌐 Kubernetes Cluster Networking Goals

Kubernetes networking has core principles:

  1. All Pods can communicate with each other without NAT (Network Address Translation).

  2. All nodes can communicate with all Pods and vice versa without NAT.


πŸ–§ Multi-Node Networking Challenges

Let’s scale up to a multi-node cluster (e.g., two nodes):

  • Node 1 IP: 192.168.1.2

  • Node 2 IP: 192.168.1.3

Initially, if both nodes assign Pods IPs from the same internal network range (e.g., 10.244.0.0), there will be:

  • IP conflicts

  • Broken communication across nodes

This is because:

  • Kubernetes does not set up inter-node networking by default.

  • It's the responsibility of the cluster administrator to install a Container Network Interface (CNI) plugin that fulfills Kubernetes’ networking requirements.


πŸ› οΈ Network Plugins (CNI Solutions)

To solve networking issues in a Kubernetes cluster, we use network plugins like:

PluginDescription
CalicoPowerful and widely used, supports network policy
FlannelSimple and easy to configure
Weave NetCommon in learning environments like Play-with-K8s
CiliumAdvanced security and observability with eBPF
VMware NSX-TSuitable for VMware environments
Cisco ACI, Big Cloud FabricEnterprise networking solutions

βœ… In many hands-on labs and demo setups (like Mumshad Mannambeth's course), Calico is used.


πŸ—ΊοΈ How Cluster Networking Works with Calico

Once a plugin like Calico is installed:

  • Each node is assigned a unique Pod network range, e.g.:

    • Node 1 β†’ 10.244.1.0/24

    • Node 2 β†’ 10.244.2.0/24

  • Pods within each node are assigned unique IPs from these subnets:

    • 10.244.1.2 on Node 1

    • 10.244.2.2 on Node 2

Calico handles:

  • IP address assignment

  • Routing traffic between nodes

  • Enabling Pod-to-Pod communication across the cluster

The result:

  • A virtual network spanning all Pods and nodes

  • No NAT is required

  • Direct communication is possible using Pod IPs


πŸ“‘ Kubernetes Services Explained

πŸ” What is a Kubernetes Service?

Kubernetes Services enable communication between various components of an application β€” both internally (within the cluster) and externally (from outside the cluster).

In a microservices architecture, we may have:

  • A frontend pod group (serving web pages),

  • A backend pod group (handling business logic),

  • And a database or external system connection.

➑️ Services help connect these components:

  • Frontend to backend

  • Backend to database

  • External users to frontend

Thus, Services enable loose coupling between microservices.


🌐 Accessing Pods Externally

Let’s take a typical scenario:

  • A web application runs inside a Pod.

  • The Pod has an internal IP like 10.244.0.2 (not accessible from your laptop on, say, 192.168.1.10).

  • The Kubernetes node hosting the Pod has an IP 192.168.1.2.

Now, how do you, as an external user, access the web page?

You can’t directly access 10.244.0.2 because it’s inside the cluster’s virtual network. You could SSH into the node and curl http://10.244.0.2, but that’s not ideal.

βœ… Solution: Kubernetes Service

A Service acts as a bridge, mapping requests from outside to the internal Pod.


🧱 Kubernetes Service Types

TypeDescription
NodePortExposes the Pod via a port on the node, accessible from outside the cluster
ClusterIPInternal-only service to connect Pods within the cluster
LoadBalancerProvisions an external load balancer (cloud providers only)

πŸ”€ NodePort Service (External Access)

βš™οΈ How it works:

  • The web server inside the Pod listens on port 80 β†’ this is the targetPort.

  • The Service listens on an internal port (also usually 80).

  • The Node listens on a NodePort (e.g., 30008), which is open to external users.

External Request --> Node IP:NodePort --> Service Port --> Pod TargetPort
                 --> 192.168.1.2:30008 --> 80 --> 80

🎯 Valid NodePort range: 30000–32767


πŸ“„ NodePort Service YAML Example

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  type: NodePort
  selector:
    app: myapp
  ports:
    - port: 80         # Port on the Service
      targetPort: 80   # Port inside the Pod
      nodePort: 30008  # Exposed Port on the Node

πŸ”‘ Note:

  • If targetPort is omitted, it's assumed to be the same as port.

  • If nodePort is omitted, Kubernetes will assign a random port within range.


πŸ”— Linking Service to Pods

  • Services use labels and selectors to identify which Pods to route traffic to.

  • Example:

      selector:
        app: myapp
    
  • All Pods with this label (app: myapp) become endpoints of the service.


πŸ“Š Service Load Balancing

If you have multiple Pods running the same application (for scalability and high availability), and they share the same labels, the Service:

  • Automatically selects all of them

  • Distributes traffic randomly among them

  • Acts as a built-in load balancer

No extra config is needed from you!


🌍 Multi-Node Cluster

Imagine you have:

  • Three nodes (192.168.1.2, 192.168.1.3, 192.168.1.4)

  • Pods with the same label (app: myapp) distributed across them

When you create a NodePort service:

  • Kubernetes automatically exposes the same NodePort (e.g., 30008) on all nodes

  • You can now access your app via any node in the cluster:

      curl http://192.168.1.2:30008
      curl http://192.168.1.3:30008
      curl http://192.168.1.4:30008
    

βœ… Summary:

  • Works with one Pod, multiple Pods, or Pods across multiple nodes

  • No additional config required

  • Highly resilient and scalable


πŸ” Service Commands

PurposeCommand
Create a servicekubectl apply -f service-definition.yaml or, kubectl create -f <File.yaml>
View all serviceskubectl get services or, kubectl get svc
Get detailed infokubectl describe service myapp-service
Test accesscurl http://<NodeIP>:<NodePort>
Tells you the node IP = 192.168.49.2kubectl get nodes -o wide
Returns http://192.168.49.2:30008minikube service myapp-service --url

🧩 Kubernetes Services – ClusterIP

πŸ” What is ClusterIP?

ClusterIP is the default type of Kubernetes service.

It enables internal communication between components within the cluster (Pod-to-Pod communication). It’s not accessible externally from outside the cluster.

πŸ“¦ Use Case Example:

  • Frontend Pods need to call Backend Pods.

  • Backend Pods need to connect to a Redis or MySQL service.

  • All these are handled internally via ClusterIP services.

🧠 Problem:

Pod IPs are dynamic β€” they change when Pods restart. So we can’t rely on direct Pod IPs for internal communication.

βœ… Solution: Use a ClusterIP Service

  • It groups all relevant Pods under a common internal IP and DNS name.

  • Any Pod inside the cluster can use that service name or ClusterIP to access those Pods.

🧱 ClusterIP Service YAML Example

apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  type: ClusterIP
  selector:
    app: myapp
    tier: backend
  ports:
    - port: 80         # Port exposed by the service (used internally)
      targetPort: 80   # Port exposed inside each backend Pod

πŸ”— Selector connects the Service to Pods with matching labels:

app: myapp
tier: backend

πŸ“˜ Access from other Pods:

curl http://backend-service:80

or just:

curl http://backend-service

πŸ“Š Built-in Load Balancing:

ClusterIP also distributes traffic randomly across all Pods that match the selector β€” just like NodePort β€” enabling internal load balancing.

πŸ§ͺ Commands:

PurposeCommand
Create ClusterIPkubectl apply -f clusterip-service.yaml
View Serviceskubectl get services
Describe Servicekubectl describe service backend-service

☁️ Kubernetes Service – LoadBalancer

🌍 What is LoadBalancer?

  • LoadBalancer exposes your service externally to the internet.

  • It works only in supported cloud providers (e.g., GCP, AWS, Azure).

  • Automatically provisions a cloud-based load balancer with an external IP.

πŸ“¦ Use Case:

You want users to access your app publicly at a domain like:

http://myapp.com

🧠 How It Works:

LoadBalancer β†’ NodePort β†’ Service Port β†’ Pod TargetPort
External IP (cloud LB) β†’ NodePort (internal) β†’ Pod

πŸ›  LoadBalancer YAML Example:

apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  type: LoadBalancer
  selector:
    app: myapp
    tier: frontend
  ports:
    - port: 80         # Port exposed via the LoadBalancer
      targetPort: 80   # Port inside the Pod

πŸ“˜ Output of kubectl get svc:

NAME              TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
frontend-service  LoadBalancer   10.96.105.30    35.232.101.22   80:30082/TCP   3m

πŸ’‘ DNS Setup:

Point your domain (myapp.com) to the EXTERNAL-IP using a DNS provider.

πŸ”— If you're on local setup and want LoadBalancer-like behavior:

  • Use MetalLB or minikube tunnel to simulate a LoadBalancer.

πŸ§ͺ Commands:

PurposeCommand
Create LoadBalancer svckubectl apply -f loadbalancer-service.yaml
View Serviceskubectl get services
Test external accesscurl http://<EXTERNAL-IP>

βœ… Kubernetes Service Types – Recap

TypeScopeAccessCloud RequiredUse Case
ClusterIPInternal onlyWithin cluster (Pods)❌ NoFrontend β†’ Backend, DB access
NodePortExternalNodeIP:Port (fixed range)❌ NoExternal dev/test environment
LoadBalancerExternalPublic IP from Cloud LBβœ… YesProduction public access
0
Subscribe to my newsletter

Read articles from Arindam Baidya directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Arindam Baidya
Arindam Baidya