Kubernetes Basics for Developers: Running Containers Beyond One Machine
Container Management Beyond One Server
Modern applications are no longer always deployed as one simple file on one server. A real production application may have a frontend, backend API, database connection, cache, background worker, authentication service, logging system, monitoring setup, and multiple running copies of the same service.
Docker helps developers package an application into a container. A container includes the application code, runtime, libraries, and required environment so that the application can run more consistently across different machines.
Docker Compose helps run multiple containers together on a single machine. For example, a developer may use Docker Compose to run a backend, frontend, database, and Redis cache during local development.
But production is more complex than local development.
A company may need to run containers across many machines. It may need automatic restart when containers fail. It may need scaling when traffic increases. It may need safe updates without downtime. It may need traffic routing, service discovery, health checks, configuration management, secrets, storage, and monitoring.
This is where Kubernetes becomes important.
Kubernetes is a platform used to manage containerized applications across a cluster of machines. It helps developers and DevOps teams run, scale, update, and recover applications in a more controlled way.
Kubernetes is not the first DevOps tool beginners need to learn. Before Kubernetes, it is better to understand Linux basics, Git, Docker, Dockerfile, Docker Compose, networking basics, CI/CD, cloud deployment, and monitoring. But once an application grows beyond one machine, Kubernetes becomes an important concept.
Why Kubernetes Exists
Running one container manually is simple.
A developer can run:
docker run nginx
This starts one Nginx container.
But a production system needs more than starting one container.
A production team may ask:
How many copies of the backend should run?
What happens if one copy crashes?
How does traffic reach the correct container?
How can a new version be deployed without downtime?
How can the application scale during high traffic?
How can the team roll back if a release fails?
Where should configuration and passwords be stored?
How can logs and health checks be monitored?
These are operational questions.
Kubernetes exists to solve these problems. It does not write your application code. It manages how your containerized application runs in production-like environments.
A simple way to understand Kubernetes:
Docker packages the application.
Kubernetes manages the application containers in a cluster.
Docker answers, “How do I build and run this container?”
Kubernetes answers, “How do I keep this containerized application running, scaling, updating, and recovering across machines?”
Link to:Web application security
The Core Idea: Desired State
The most important Kubernetes idea is desired state.
In Kubernetes, you describe what you want. Kubernetes tries to keep the system matching that description.
For example, you may say:
Run three copies of my backend.
Use this container image.
Expose the application on port 80.
Restart failed containers.
Send traffic only to healthy pods.
Kubernetes continuously compares the current state with the desired state.
If you want three backend pods and one crashes, Kubernetes creates another one. If a node fails, Kubernetes can move workloads to another available node. If a new image is deployed, Kubernetes can gradually replace old pods with new ones.
This is different from manually managing containers.
Instead of repeatedly starting containers by hand, you define the desired state and let Kubernetes maintain it.
Kubernetes Cluster
A Kubernetes cluster is a group of machines used to run containerized applications.
A cluster usually has two major parts:
Control plane
Worker nodes
The control plane manages the cluster. It makes decisions, watches the cluster state, and coordinates resources.
Worker nodes run the actual application workloads. These workloads run inside pods, and pods contain containers.
For local learning, tools like Minikube or Kind can create a small Kubernetes cluster on your computer. In production, a cluster may run on cloud providers such as AWS, Google Cloud, Azure, or private infrastructure.
A small cluster may have one worker node. A production cluster may have many worker nodes.
Control Plane
The control plane is the brain of Kubernetes.
It does not usually run normal application traffic in production setups. Its job is to manage the cluster.
The control plane checks what should be running and what is actually running. If something is missing, unhealthy, or not matching the desired state, it takes action.
For example, if a Deployment says three pods should run and only two are currently running, the control plane works to create another pod.
This management role is what makes Kubernetes powerful.
Worker Node
A worker node is a machine that runs application workloads.
A worker node can be a virtual machine, cloud instance, or physical server. It provides CPU, memory, networking, and storage resources for pods.
When you deploy an application, Kubernetes schedules pods onto available worker nodes. It considers available resources and cluster rules before deciding where pods should run.
If one node becomes unhealthy, Kubernetes can reschedule workloads to other nodes depending on the setup.
For a beginner, remember this:
Control plane manages.
Worker nodes run applications.
Pod
A pod is the smallest deployable unit in Kubernetes.
A pod usually contains one container. In some advanced cases, a pod may contain multiple closely related containers that need to share the same network and storage context.
Most beginner projects use one container per pod.
Example:
A Spring Boot backend container runs inside a backend pod.
A React frontend container runs inside a frontend pod.
A Python worker container runs inside a worker pod.
Pods are temporary. They can be created, deleted, restarted, or replaced. Because of this, production systems usually do not depend directly on individual pod IP addresses.
Developers normally manage pods through higher-level objects such as Deployments.
Link to:Authentication Password SecurityContainer Inside a Pod
Kubernetes does not remove the need for containers.
Your application still runs inside a container. Kubernetes manages that container through a pod.
For example, a backend application may be packaged as a Docker image:
my-backend:v1
Kubernetes can run that image inside a pod.
The container runs the application. The pod provides the Kubernetes environment around it, including networking, lifecycle management, and optional storage.
This is one of the most important beginner points:
Docker creates container images.
Kubernetes runs those images inside pods.
Deployment
A Deployment is a Kubernetes object used to manage application pods.
A Deployment defines:
Which container image should run
How many replicas should exist
Which labels identify the pods
How updates should happen
For example, you can create a Deployment that says:
Run three backend pods using image backend:v1.
If one pod crashes, Kubernetes creates another pod. If you change the image to backend:v2, Kubernetes can perform a rolling update.
Deployments are commonly used for stateless applications such as APIs, frontend services, and background workers.
Link to: AI Agent
Replica
A replica is one running copy of an application pod.
If a backend Deployment has three replicas, Kubernetes runs three backend pods.
Multiple replicas help with availability and traffic handling. If one pod fails, the other pods can still serve requests. If traffic increases, more replicas can be added.
Example:
1 replica = useful for learning
3 replicas = better availability
10 replicas = higher traffic handling
The number depends on traffic, resources, and application design.
Stateless Applications
A stateless application does not store important permanent data inside the running container.
Examples include:
Backend API
Frontend service
Authentication service
Notification worker
File processing worker
Stateless applications are easier to run in Kubernetes because pods can be restarted or replaced without losing important data.
For example, a backend API should not store user orders inside the container file system. It should store them in a database or external storage system.
Kubernetes works especially well with stateless services.
Link to: AI Hallucination
Stateful Applications
A stateful application stores important data or depends on stable identity.
Examples include:
Database
Message broker
Storage system
Distributed database cluster
Stateful workloads are more complex because data must be preserved when pods restart or move.
Kubernetes supports stateful workloads using StatefulSets, Persistent Volumes, and Persistent Volume Claims. However, for many beginner and small production projects, using a managed database service outside Kubernetes is easier and safer.
A good beginner rule:
Run your app services in Kubernetes first.
Be careful before running production databases inside Kubernetes.
Service
A Service gives stable network access to pods.
Pods are temporary. Their IP addresses can change when they restart or get replaced. If another application connects directly to a pod IP, that connection can break.
A Service solves this by providing a stable name and stable access point.
Example:
A backend Deployment has three backend pods.
A backend Service sends traffic to those pods.
The frontend connects to the Service instead of individual pod IP addresses.
A Service selects pods using labels.
This is how Kubernetes makes networking reliable between changing pods.
Link to : Rag AI
ClusterIP Service
ClusterIP is the default Service type.
It exposes the Service only inside the Kubernetes cluster.
Example:
A frontend pod can call an internal backend Service.
A backend pod can call an internal payment Service.
A worker pod can call an internal queue Service.
ClusterIP is useful for internal communication.
It is not directly accessible from outside the cluster.
For beginners, remember:
ClusterIP = internal access inside the cluster
NodePort Service
NodePort exposes a Service on a port of each worker node.
This allows external traffic to reach the Service using the node IP and port.
NodePort is useful for learning and local testing. For example, with Minikube, you can expose a sample application and open it in a browser.
But in production, NodePort is usually not the cleanest approach. Production systems often use Ingress or a cloud LoadBalancer.
For beginners:
NodePort = simple external access for practice
LoadBalancer Service
A LoadBalancer Service asks the cloud provider to create an external load balancer.
This is common in managed Kubernetes environments.
The load balancer receives public traffic and forwards it to the Kubernetes Service.
Example:
User visits your application.
Cloud load balancer receives traffic.
Traffic is sent to the Kubernetes Service.
Service forwards traffic to healthy pods.
LoadBalancer is useful in production, but it can add cloud cost because external load balancers are usually paid resources.
Link to: AI vs Rule based systems
Ingress
Ingress manages external HTTP and HTTPS traffic into the cluster.
It can route traffic based on domain names and paths.
Example:
example.com -> frontend service
example.com/api -> backend service
example.com/admin -> admin service
Ingress is commonly used for web applications because it provides cleaner routing than exposing every Service separately.
Ingress can also help with HTTPS, domain-based routing, and path-based routing.
However, Ingress needs an Ingress Controller to work.
Ingress Controller
An Ingress resource only defines routing rules. An Ingress Controller actually applies those rules and handles traffic.
Common Ingress controllers include:
Nginx Ingress Controller
Traefik
Cloud-specific Ingress controllers
Without an Ingress Controller, Ingress rules alone will not route traffic.
For beginners, this is an important confusion point:
Ingress = routing rules
Ingress Controller = component that makes the rules work
ConfigMap
A ConfigMap stores non-sensitive configuration values.
Examples:
Application mode
Log level
Public API URL
Feature flag
Service name
Application profile
ConfigMaps help separate configuration from the container image.
For example, the same backend image can run in development, staging, and production with different configuration values.
ConfigMap should not store passwords, tokens, or private keys. Sensitive values should be stored in Secrets.
Link to: Fine Tuning AI
Secret
A Secret stores sensitive values.
Examples:
Database password
API key
JWT secret
Private token
Cloud access credential
Secrets help keep sensitive configuration separate from application images.
However, Kubernetes Secrets still need careful access control. Developers should not expose Secrets in logs, screenshots, public repositories, or article examples with real values.
A safe teaching example should use fake values only.
Environment Variables in Kubernetes
Kubernetes can pass ConfigMap and Secret values into containers as environment variables.
Example:
The backend image stays the same.
The database URL comes from a ConfigMap.
The database password comes from a Secret.
The application profile comes from an environment variable.
This makes deployments flexible.
Instead of rebuilding the Docker image for every environment, you can change the runtime configuration.
Volumes and Persistent Storage
By default, container storage is temporary. If the container is restarted or replaced, data inside the container may disappear.
A Volume provides storage to a pod.
For simple stateless applications, volumes may not be needed. But for applications that process files, store temporary data, or run stateful workloads, volumes become important.
A Persistent Volume is storage that can exist beyond the life of a pod.
A Persistent Volume Claim is a request for storage.
Example:
A database pod needs 10GB storage.
The pod uses a Persistent Volume Claim.
Kubernetes connects the claim to available storage.
Storage in Kubernetes should be planned carefully, especially for production.
YAML Manifest
Kubernetes resources are usually defined using YAML files.
A YAML manifest describes the desired state.
You can define resources such as:
Deployment
Service
ConfigMap
Secret
Ingress
Persistent Volume Claim
This makes infrastructure configuration repeatable and version-controlled.
Instead of clicking buttons manually, the team can store YAML files in Git and apply them whenever needed.
Practical Example: Creating a Deployment
Let us create a simple Nginx Deployment.
Create a file named sample-deployment.yaml.
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-app
spec:
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: sample-container
image: nginx:1.25
ports:
- containerPort: 80
This file tells Kubernetes to run three pods. Each pod runs the Nginx container on port 80.
Apply the file:
kubectl apply -f sample-deployment.yaml
Check the Deployment:
kubectl get deployments
Check the pods:
kubectl get pods
If one pod fails, the Deployment tries to create another pod to maintain three replicas.
This is the desired-state model in action.
Practical Example: Creating a ClusterIP Service
Now create a Service so the pods can be accessed through a stable internal address.
Create a file named sample-service.yaml.
apiVersion: v1
kind: Service
metadata:
name: sample-service
spec:
type: ClusterIP
selector:
app: sample-app
ports:
- port: 80
targetPort: 80
Apply the Service:
kubectl apply -f sample-service.yaml
Check Services:
kubectl get services
Describe the Service:
kubectl describe service sample-service
This Service selects pods with the label app: sample-app. If pods are replaced, the Service still forwards traffic to the correct matching pods.
Practical Example: Exposing the App with NodePort
For local practice, NodePort is easy to understand.
Create a file named sample-nodeport-service.yaml.
apiVersion: v1
kind: Service
metadata:
name: sample-nodeport-service
spec:
type: NodePort
selector:
app: sample-app
ports:
- port: 80
targetPort: 80
nodePort: 30080
Apply it:
kubectl apply -f sample-nodeport-service.yaml
Check it:
kubectl get svc
If you are using Minikube, open the service:
minikube service sample-nodeport-service
NodePort is useful for practice. For production web applications, Ingress or LoadBalancer is usually better.
Useful kubectl Commands
kubectl is the command-line tool used to interact with Kubernetes.
Common commands:
kubectl get pods
Shows running pods.
kubectl get deployments
Shows deployments.
kubectl get services
Shows services.
kubectl describe pod <pod-name>
Shows detailed information about a pod.
kubectl logs <pod-name>
Shows application logs from a pod.
kubectl delete -f sample-deployment.yaml
Deletes resources defined in a YAML file.
These commands help beginners move from theory to practice.
Link to: Embeddings AI
Deployment Update with a New Image
In real projects, applications are updated frequently.
For example, a backend image may change from:
backend:v1
to:
backend:v2
In Kubernetes, you can update the image in the Deployment YAML and apply it again.
Example:
containers:
- name: backend-container
image: my-backend:v2
Then run:
kubectl apply -f backend-deployment.yaml
Kubernetes can gradually replace old pods with new pods using a rolling update.
This helps reduce downtime.
Rolling Update
A rolling update gradually replaces old pods with new pods.
Example:
Your backend has three pods running version 1.
You deploy version 2.
Kubernetes starts one new pod with version 2.
When it is ready, Kubernetes removes one old pod.
This continues until all pods are updated.
This is safer than stopping all old pods at once.
Rolling updates are useful because users can continue accessing the application while the update happens.
Link to: Types of Machine Learning
Rollback
A rollback means returning to a previous working version.
If a new deployment causes errors, Kubernetes can roll back to an older ReplicaSet.
Check rollout history:
kubectl rollout history deployment sample-app
Roll back:
kubectl rollout undo deployment sample-app
Rollback is useful, but it is not magic. If your application update includes database changes, rollback must be planned carefully.
A good production deployment considers both application code and database compatibility.
Readiness Probe
A readiness probe checks whether a pod is ready to receive traffic.
A container may be running, but the application may not be ready yet.
For example, a backend service may need time to connect to the database or load configuration.
If readiness probe fails, Kubernetes does not send traffic to that pod.
Example:
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
Readiness probes help prevent users from reaching an application that is still starting.
Liveness Probe
A liveness probe checks whether a container is still alive.
Sometimes an application may become stuck but the process does not exit. A liveness probe can detect this and restart the container.
Example:
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 20
Liveness probes are useful for self-healing.
However, they should be configured carefully. If the check is too strict, Kubernetes may restart healthy containers unnecessarily.
Startup Probe
Some applications take longer to start.
A startup probe helps Kubernetes understand that the application is still starting and should not be killed too early.
Example:
startupProbe:
httpGet:
path: /
port: 80
failureThreshold: 30
periodSeconds: 10
Startup probes are useful for applications with slow startup, such as large Java services or applications that load many resources before becoming ready.
Resource Requests and Limits
Kubernetes allows you to define how much CPU and memory a container needs.
A request tells Kubernetes the expected minimum resource requirement.
A limit defines the maximum resource usage allowed.
Example:
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
Requests help Kubernetes schedule pods properly.
Limits prevent one container from consuming too many resources.
But limits should be realistic. If memory limit is too low, the application may be killed frequently.
Horizontal Pod Autoscaler
Horizontal Pod Autoscaler, or HPA, automatically adjusts the number of pod replicas based on metrics such as CPU usage.
Example:
If CPU usage increases, Kubernetes can add more backend pods.
If traffic decreases, Kubernetes can reduce the number of pods.
Autoscaling helps applications handle changing traffic.
Example command:
kubectl autoscale deployment sample-app --cpu-percent=70 --min=2 --max=10
This tells Kubernetes to keep CPU usage around 70% by scaling between 2 and 10 pods.
Autoscaling is powerful, but it should be tested carefully. More pods may increase database connections, memory use, and cloud cost.
ConfigMap Example
Create a file named app-config.yaml.
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_MODE: "production"
LOG_LEVEL: "info"
Apply it:
kubectl apply -f app-config.yaml
Use it in a Deployment:
env:
- name: APP_MODE
valueFrom:
configMapKeyRef:
name: app-config
key: APP_MODE
This keeps non-sensitive configuration separate from the container image.
Secret Example
Create a Secret using kubectl:
kubectl create secret generic app-secret --from-literal=DB_PASSWORD=fakepassword123
Use it in a Deployment:
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: DB_PASSWORD
In real projects, do not expose real secrets in public repositories, tutorials, or screenshots.
Secrets should be managed carefully with proper access control.
Full Stack Application in Kubernetes
A full stack application in Kubernetes may contain:
Frontend Deployment
Frontend Service
Backend Deployment
Backend Service
ConfigMap
Secret
Ingress
Monitoring
Logging
Example flow:
A user visits the domain.
Ingress receives the request.
Frontend service serves the UI.
Frontend calls backend API.
Backend service routes traffic to backend pods.
Backend reads configuration from ConfigMap.
Backend reads database password from Secret.
Database may run outside the cluster as a managed service.
This structure is common in modern cloud-native applications.
Kubernetes for Microservices
Kubernetes is often used with microservices.
A microservice application may include:
User service
Order service
Payment service
Notification service
Inventory service
Each service can have its own Deployment and Service.
This allows teams to scale services separately. For example, payment service may need fewer replicas, while product search service may need more replicas during high traffic.
Kubernetes provides service discovery, internal networking, rolling updates, and scaling for these services.
However, microservices also increase complexity. Kubernetes helps manage the infrastructure, but teams still need good logging, monitoring, API design, security, and communication between services.
Kubernetes in DevOps
Kubernetes is important in DevOps because it supports automation and reliability.
A CI/CD pipeline can build a Docker image, push it to a registry, update the Kubernetes Deployment, and monitor rollout status.
Example deployment flow:
Developer pushes code to Git.
CI pipeline runs tests.
Docker image is built.
Image is pushed to registry.
Kubernetes Deployment is updated.
Rolling update starts.
Monitoring checks application health.
This makes deployment more repeatable than manual server updates.
Kubernetes and Docker Compose Difference
Docker Compose is simpler and useful for local development or small single-server setups.
Kubernetes is more powerful and designed for clusters.
Docker Compose is good when:
You are learning containers.
You want to run frontend, backend, and database locally.
You have a simple deployment on one machine.
Kubernetes is useful when:
You need scaling.
You need self-healing.
You need rolling updates.
You run many services.
You manage production workloads across multiple machines.
A beginner should not jump into Kubernetes before understanding Docker and Docker Compose.
When Kubernetes Is Useful
Kubernetes is useful when applications need:
Multiple replicas
Self-healing
Rolling updates
Service discovery
Autoscaling
Cluster-level container management
Microservice deployment
Cloud-native operations
Production-like reliability
For a growing product, Kubernetes can bring structure and automation.
For example, an e-commerce backend may need multiple API replicas during festival sales. A fintech application may need safe updates and health checks. A SaaS product may need several internal services communicating reliably.
Kubernetes is valuable when the operational need is real.
Link to: Vector Database
When Kubernetes May Be Too Much
Kubernetes is not always needed.
A small blog, simple portfolio, early-stage API, or small business website may run well on normal hosting, VPS, Docker Compose, or managed platforms.
Kubernetes adds complexity. It needs cluster management, monitoring, security, resource planning, deployment strategy, and debugging knowledge.
Using Kubernetes only because it is popular can waste time.
A good developer chooses tools based on the project need.
Simple project: simple deployment.
Growing production system: Kubernetes may help.
This practical decision-making is more important than tool hype.
Link to: Token AI
Beginner Confusion: localhost in Kubernetes
One common beginner confusion is using localhost incorrectly.
Inside a Kubernetes pod, localhost means the same pod, not your laptop and not another service.
If a backend pod needs to connect to a database service, it should use the Kubernetes Service name, not localhost.
Example:
Wrong in many cases:
localhost:5432
Better inside cluster:
database-service:5432
Understanding this saves a lot of debugging time.
Beginner Confusion: latest Image Tag
Using latest image tag may feel easy, but it can cause confusion in production.
Example:
image: my-backend:latest
The problem is that latest does not clearly show which version is running.
A better approach is to use versioned tags:
image: my-backend:v1.2.3
Versioned tags make rollback, debugging, and release tracking easier.
Beginner Confusion: Secrets in Plain YAML
Beginners sometimes put passwords directly inside YAML files.
That is risky, especially if the file is pushed to GitHub.
Bad practice:
DB_PASSWORD: "mypassword123"
A safer approach is to use Kubernetes Secrets, external secret managers, and proper access control.
Even with Kubernetes Secrets, teams should avoid exposing sensitive values in logs, screenshots, public demos, or tutorials.
Kubernetes Debugging Mindset
When something fails in Kubernetes, do not guess immediately.
Start with simple checks.
Check pods:
kubectl get pods
Describe the pod:
kubectl describe pod <pod-name>
Check logs:
kubectl logs <pod-name>
Check services:
kubectl get svc
Check events:
kubectl get events
Many Kubernetes issues are caused by image pull errors, wrong ports, failed health checks, missing environment variables, resource limits, or incorrect service selectors.
A calm debugging process is better than random changes.
Production Mindset for Kubernetes
Kubernetes can run applications, but production readiness needs more than YAML files.
A production Kubernetes setup should consider:
Monitoring
Logging
Security
Resource limits
Health probes
Rollback strategy
Backup plan
Secret management
Network access rules
Cost control
CI/CD pipeline
Alerting
Kubernetes gives the platform, but the team still needs good engineering practices.
A cluster without monitoring is risky. A Deployment without resource limits can affect other workloads. A public dashboard without security can become dangerous. A database without backup can create serious loss.
Kubernetes is powerful, but it must be managed responsibly.
Practical Kubernetes Understanding
Kubernetes helps manage containers in a reliable and scalable way.
Pods run containers.
Deployments manage pods.
Services provide stable access.
Ingress routes external traffic.
ConfigMaps store non-sensitive configuration.
Secrets store sensitive values.
Volumes handle storage.
Probes check health.
Autoscaling adjusts capacity.
kubectl helps developers interact with the cluster.
For developers, Kubernetes becomes easier when every concept is connected to a real problem.
Pods solve container execution.
Deployments solve replica management and updates.
Services solve changing pod IPs.
Ingress solves web routing.
ConfigMaps and Secrets solve configuration separation.
Probes solve health checking.
Autoscaling solves changing traffic.
Kubernetes is not just a collection of difficult terms. It is a system designed to keep containerized applications running in real production environments.
A developer does not need to master every advanced feature on day one. The important first step is to understand how applications move from a single container to a managed cluster.


Post a Comment