Kubernetes Basics: Getting Started Guide for Developers
Kubernetes (often abbreviated as K8s) has become the industry standard for container orchestration. Whether you are deploying microservices, scaling a web application, or managing complex distributed systems, Kubernetes provides a powerful platform that automates deployment, scaling, and operations of application containers. This guide covers the fundamental concepts every developer needs to understand before working with Kubernetes in 2026.
What is Kubernetes?
Kubernetes is an open-source container orchestration platform originally developed by Google and now maintained by the Cloud Native Computing Foundation (CNCF). It manages containerized workloads and services, providing declarative configuration and automation. Instead of manually deploying containers on individual servers, Kubernetes handles scheduling, networking, storage, and health monitoring automatically.
Key problems Kubernetes solves:
- Service discovery and load balancing - Kubernetes can expose a container using a DNS name or its own IP address and load-balance traffic across replicas
- Storage orchestration - Automatically mount local storage, cloud providers, or network storage systems
- Automated rollouts and rollbacks - Describe the desired state and Kubernetes changes the actual state at a controlled rate
- Self-healing - Restarts failed containers, replaces and reschedules containers when nodes die
- Secret and configuration management - Deploy and update secrets and application configuration without rebuilding images
- Horizontal scaling - Scale your application up or down with a single command, a UI, or automatically based on CPU usage
Core Concepts and Architecture
Cluster Architecture
A Kubernetes cluster consists of two main components: the Control Plane (master) and Worker Nodes. The Control Plane manages the overall state of the cluster, while Worker Nodes run your application workloads.
- Control Plane - Runs the API server, scheduler, controller manager, and etcd (key-value store for cluster data)
- Worker Nodes - Run the kubelet agent, container runtime (containerd or CRI-O), and kube-proxy
- kubectl - The command-line tool used to interact with the Kubernetes API server
Pods
A Pod is the smallest deployable unit in Kubernetes. It represents one or more containers that share storage, network, and a specification for how to run. In most cases, a Pod runs a single container, but multi-container Pods are used for sidecar patterns like logging agents or service meshes.
# pod.yaml - A simple Pod definition
apiVersion: v1
kind: Pod
metadata:
name: my-app
labels:
app: my-app
environment: development
spec:
containers:
- name: app
image: node:20-alpine
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
env:
- name: NODE_ENV
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-urlDeployments
Deployments are the recommended way to manage Pods in production. A Deployment describes a desired state (e.g., 3 replicas of your app), and the Deployment controller changes the actual state to match. Deployments support rolling updates, rollbacks, and scaling.
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
labels:
app: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web
image: my-registry/web-app:v1.2.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "1000m"Services
A Service exposes a set of Pods as a network service. Since Pods are ephemeral (they can be created and destroyed at any time), Services provide a stable endpoint for communication. Kubernetes supports several Service types:
- ClusterIP (default) - Exposes the Service on an internal IP, accessible only within the cluster
- NodePort - Exposes the Service on each node's IP at a static port (30000-32767)
- LoadBalancer - Provisions an external load balancer (cloud provider specific)
- ExternalName - Maps the Service to a DNS name
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: web-app-service
spec:
type: LoadBalancer
selector:
app: web-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
# Internal service for database
apiVersion: v1
kind: Service
metadata:
name: database-service
spec:
type: ClusterIP
selector:
app: postgres
ports:
- protocol: TCP
port: 5432
targetPort: 5432Essential kubectl Commands
kubectl is the primary command-line tool for managing Kubernetes clusters. Here are the commands you will use most frequently:
# Cluster information
kubectl cluster-info
kubectl get nodes
kubectl get namespaces
# Working with Pods
kubectl get pods # List all pods in default namespace
kubectl get pods -n my-namespace # List pods in specific namespace
kubectl get pods -o wide # Show additional details (node, IP)
kubectl describe pod my-app # Detailed pod information
kubectl logs my-app # View pod logs
kubectl logs my-app -f # Stream logs in real-time
kubectl logs my-app -c sidecar # Logs from specific container
kubectl exec -it my-app -- /bin/sh # Shell into a pod
# Working with Deployments
kubectl get deployments
kubectl create deployment web --image=nginx:latest
kubectl scale deployment web --replicas=5
kubectl set image deployment/web web=nginx:1.25
kubectl rollout status deployment/web
kubectl rollout history deployment/web
kubectl rollout undo deployment/web # Rollback to previous version
# Apply configuration files
kubectl apply -f deployment.yaml
kubectl apply -f ./k8s/ # Apply all files in directory
kubectl delete -f deployment.yaml
# Resource management
kubectl top pods # CPU/memory usage
kubectl top nodes
kubectl get events --sort-by=.metadata.creationTimestampConfigMaps and Secrets
ConfigMaps store non-confidential configuration data as key-value pairs. Secrets store sensitive data like passwords, tokens, and TLS certificates. Both can be injected into Pods as environment variables or mounted as files.
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: "production"
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"
config.json: |
{
"feature_flags": {
"new_dashboard": true,
"beta_api": false
}
}
---
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
stringData:
database-url: "postgresql://user:pass@db:5432/myapp"
api-key: "sk-abc123def456"
---
# Using ConfigMap and Secret in a Pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 2
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- configMapRef:
name: app-config
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
volumeMounts:
- name: config-volume
mountPath: /app/config
volumes:
- name: config-volume
configMap:
name: app-config
items:
- key: config.json
path: config.jsonNamespaces
Namespaces provide a way to divide cluster resources between multiple users or teams. They are useful for organizing environments (dev, staging, production) or isolating teams within a shared cluster.
# Create namespaces
kubectl create namespace development
kubectl create namespace staging
kubectl create namespace production
# Deploy to a specific namespace
kubectl apply -f deployment.yaml -n staging
# Set default namespace for kubectl
kubectl config set-context --current --namespace=development
# Resource quotas per namespace
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: development
spec:
hard:
pods: "20"
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "8"
limits.memory: "16Gi"Ingress Controllers
Ingress manages external HTTP and HTTPS access to services within a cluster. An Ingress controller (like NGINX Ingress or Traefik) reads Ingress resources and configures the load balancer accordingly. This allows path-based and host-based routing, TLS termination, and more.
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- myapp.example.com
- api.example.com
secretName: app-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
- host: api.example.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: api-v1-service
port:
number: 8080
- path: /v2
pathType: Prefix
backend:
service:
name: api-v2-service
port:
number: 8080Local Development with Minikube
Minikube runs a single-node Kubernetes cluster on your local machine. It is the easiest way to learn and experiment with Kubernetes without needing a cloud provider.
# Install minikube (macOS)
brew install minikube
# Start a local cluster
minikube start --driver=docker --cpus=4 --memory=8192
# Enable useful addons
minikube addons enable ingress
minikube addons enable metrics-server
minikube addons enable dashboard
# Open Kubernetes dashboard
minikube dashboard
# Access a LoadBalancer service locally
minikube tunnel
# Stop and delete cluster
minikube stop
minikube deleteHealth Checks and Probes
Kubernetes uses probes to determine the health of a container. Configuring probes correctly is critical for reliable deployments and self-healing behavior.
- Liveness probe - Determines if a container is running. If it fails, Kubernetes restarts the container
- Readiness probe - Determines if a container is ready to accept traffic. If it fails, the Pod is removed from Service endpoints
- Startup probe - Used for slow-starting containers. Disables liveness and readiness checks until the container has started
spec:
containers:
- name: app
image: my-app:latest
ports:
- containerPort: 8080
# Liveness: restart if /healthz fails
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
failureThreshold: 3
# Readiness: stop sending traffic if /ready fails
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 3
# Startup: allow up to 5 minutes for slow startup
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 10Best Practices for Beginners
- Always set resource requests and limits - Prevents a single Pod from consuming all node resources and helps the scheduler make better decisions
- Use Deployments, not bare Pods - Deployments handle rolling updates, rollbacks, and self-healing automatically
- Configure health probes - Readiness and liveness probes enable Kubernetes to route traffic correctly and restart unhealthy containers
- Use namespaces for isolation - Separate environments and teams with namespaces and resource quotas
- Store configuration in ConfigMaps - Never hardcode configuration in container images; use ConfigMaps and Secrets for environment-specific values
- Use labels consistently - Labels like app, version, environment enable powerful selection, monitoring, and automation
- Pin image versions - Never use the
latesttag in production; always specify exact image versions for reproducibility - Enable RBAC - Use Role-Based Access Control to limit what users and service accounts can do
- Monitor with metrics-server - Install metrics-server for
kubectl topand Horizontal Pod Autoscaler - Start with managed Kubernetes - Use EKS, GKE, or AKS for production instead of managing your own control plane
Frequently Asked Questions
What is the difference between Docker and Kubernetes?
Docker is a container runtime that builds and runs individual containers. Kubernetes is an orchestration platform that manages many containers across many machines. Docker creates the containers; Kubernetes decides where to run them, how many to run, how to network them together, and how to handle failures. In modern Kubernetes, containerd (a component of Docker) is typically used as the container runtime.
When should I use Kubernetes?
Kubernetes is ideal when you need to run multiple services that must scale independently, require high availability, or need automated deployment workflows. If you have a single small application, simpler solutions like Docker Compose, a PaaS (Heroku, Railway), or serverless might be more appropriate. Kubernetes adds operational complexity, so evaluate whether the benefits justify the overhead.
How does Kubernetes handle scaling?
Kubernetes supports both horizontal and vertical scaling. Horizontal Pod Autoscaler (HPA) automatically adjusts the number of Pod replicas based on CPU utilization, memory usage, or custom metrics. Vertical Pod Autoscaler (VPA) adjusts resource requests and limits. Cluster Autoscaler adds or removes nodes from the cluster based on pending Pod demands.
What is Helm and should I use it?
Helm is a package manager for Kubernetes that bundles related YAML manifests into reusable charts. It simplifies deploying complex applications (databases, monitoring stacks, ingress controllers) with a single command. Helm is recommended once you move beyond simple deployments and need to manage multiple environments or share configurations across teams.
How do I debug a failing Pod?
Start with kubectl describe pod <name> to see events and status conditions. Check logs with kubectl logs <name>. If the container is crash-looping, usekubectl logs <name> --previous to see logs from the last terminated container. For deeper debugging, use kubectl exec -it <name> -- /bin/sh to shell into the running container and inspect the filesystem, network, and processes.