Kubernetes Basics for Application Developers
Learn the core Kubernetes concepts every developer needs: Pods, Services, Deployments, ConfigMaps, and basic kubectl commands.
Note: This guide follows English-language naming conventions and terminology standards common in international development teams. Examples use English identifiers and comments to maximize compatibility across codebases and tooling.
Kubernetes Basics for Application Developers
Introduction
Kubernetes (K8s) is an open-source container orchestration platform. It automates deployment, scaling, and management of containerized applications. As a developer, you need to understand the core abstractions to deploy and debug your applications well.
Key Concepts
Pod
A Pod is the smallest deployable unit in Kubernetes. It wraps one or more containers that share network and storage.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
Deployment
A Deployment manages a set of identical Pods, ensuring the desired number of replicas are running and enabling rolling updates.
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
Service
A Service exposes a set of Pods as a network service, providing load balancing and stable DNS names.
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: ClusterIP
| Service Type | Description | Use Case |
|---|---|---|
| ClusterIP | Internal cluster IP only | Internal communication |
| NodePort | Exposes on each node’s IP at a static port | Direct external access |
| LoadBalancer | Exposes externally using cloud provider’s LB | Production ingress |
| ExternalName | Maps to external DNS name | External dependencies |
Essential kubectl Commands
# Apply a manifest
kubectl apply -f deployment.yaml
# Get resources
kubectl get pods
kubectl get deployments
kubectl get services
# Describe a resource (detailed info + events)
kubectl describe pod myapp-xxx
# Execute a command in a pod
kubectl exec -it myapp-xxx -- sh
# View logs
kubectl logs -f myapp-xxx
kubectl logs -f deployment/myapp --tail=100
# Port-forward for local access
kubectl port-forward svc/myapp-service 8080:80
# Scale a deployment
kubectl scale deployment myapp --replicas=5
# Rollout status and history
kubectl rollout status deployment/myapp
kubectl rollout history deployment/myapp
kubectl rollout undo deployment/myapp
ConfigMaps and Secrets
ConfigMap
Store non-sensitive configuration data:
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
data:
LOG_LEVEL: "info"
API_TIMEOUT: "30"
# Use in a Pod
envFrom:
- configMapRef:
name: myapp-config
Secret
Store sensitive data (base64 encoded):
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password=secret123
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
Health Checks
Kubernetes uses probes to determine container health:
| Probe | Purpose | Action on Failure |
|---|---|---|
| Liveness | Is the app running? | Restart container |
| Readiness | Is the app ready to accept traffic? | Remove from Service endpoints |
| Startup | Has the app finished starting? | Disable other probes temporarily |
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
Namespaces
Namespaces provide logical separation within a cluster:
# Create a namespace
kubectl create namespace dev
# Set default namespace for context
kubectl config set-context --current --namespace=dev
# List resources in a namespace
kubectl get pods -n dev
Common namespace strategies:
default— small projectsdev,staging,prod— per-environment- Per-team or per-project isolation
What Works
- Set resource requests and limits on every container to prevent noisy neighbors
- Use readiness probes to prevent traffic from reaching unready Pods
- Use liveness probes to recover from deadlocks and hangs
- Never run as root — set
securityContext.runAsNonRoot: true. See container security. - Pin image tags — avoid
:latestin production - Use ConfigMaps for configuration, Secrets for credentials
- Set graceful termination — handle SIGTERM in your app (
terminationGracePeriodSeconds). See deployment strategies.
Common Mistakes
- Not setting resource requests/limits, causing cluster instability
- Using
latestimage tags, leading to unpredictable deployments - Missing readiness probes, causing 502 errors during rollouts
- Storing secrets in ConfigMaps instead of Secrets
- Not handling SIGTERM, causing abrupt shutdowns and data loss
- Deploying everything to the
defaultnamespace without isolation
Frequently Asked Questions
Q: What is the difference between a Pod and a Deployment? A: A Pod is a single instance. A Deployment is a controller that manages multiple Pod replicas, handles rolling updates, and self-heals if Pods fail.
Q: How do I access my application running in Kubernetes locally?
A: Use kubectl port-forward to forward a local port to a Pod or Service. For shared access, use a Service of type LoadBalancer or Ingress.
Q: What happens during a rolling update?
A: Kubernetes creates new Pods with the updated image, waits for readiness probes to pass, then gradually scales down old Pods. If the update fails, you can kubectl rollout undo.
How do I get started with this in an existing project?
Start with a small, isolated part of your codebase. Apply the concepts from this guide to one module or service. Measure the impact, then expand to other areas.
What tools do I need?
The tools mentioned throughout this guide are listed in each section. Most are open-source and widely adopted. Check the related resources for setup instructions.
How do I measure success after implementing this?
Define clear metrics before starting: performance benchmarks, error rates, or maintainability indicators. Compare before and after. Iterate based on the data, not on assumptions.
Advanced Topics
Scenario: Production K8s Deployment for E-commerce
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
namespace: production
labels: { app: payment-service }
spec:
replicas: 4
strategy:
rollingUpdate: { maxSurge: 1, maxUnavailable: 0 }
selector:
matchLabels: { app: payment-service }
template:
metadata:
labels: { app: payment-service }
spec:
containers:
- name: payment
image: registry.example.com/payment:v2.1.0
ports: [{ containerPort: 3000 }]
resources:
requests: { cpu: 200m, memory: 256Mi }
limits: { cpu: 500m, memory: 512Mi }
readinessProbe:
httpGet: { path: /health, port: 3000 }
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet: { path: /health, port: 3000 }
initialDelaySeconds: 15
periodSeconds: 20
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef: { name: db-secret, key: url }
# PodDisruptionBudget ensures availability during node drain
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector: { matchLabels: { app: payment-service } }
topologyKey: kubernetes.io/hostname
# hpa.yaml - Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata: { name: payment-service }
spec:
scaleTargetRef: { apiVersion: apps/v1, kind: Deployment, name: payment-service }
minReplicas: 4
maxReplicas: 20
metrics:
- type: Resource
resource: { name: cpu, target: { type: Utilization, averageUtilization: 70 } }
- type: Resource
resource: { name: memory, target: { type: Utilization, averageUtilization: 80 } }
# pdb.yaml - Pod Disruption Budget
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata: { name: payment-service }
spec:
minAvailable: 3
selector: { matchLabels: { app: payment-service } }
Production checklist:
| Item | Status |
|------|--------|
| Resource limits | Set |
| Readiness probe | Configured |
| Liveness probe | Configured |
| HPA | Enabled |
| PDB | minAvailable set |
| Anti-affinity | Spread across nodes |
| Secrets | From Secret Manager |
| Rolling update | maxUnavailable: 0 |
| Image tag | Pinned (not latest) |
| Namespace | Dedicated |
How do I debug a CrashLoopBackOff?
Check events: kubectl describe pod <name>. Check logs: kubectl logs <name> --previous (previous container crash). Common causes: missing env vars, wrong command, OOMKilled (increase memory limit), failed readiness probe (check path and port), permission issues (check service account and RBAC). Fix the root cause, do not just restart the pod.
Related Resources
Docker for Developers — A Complete Guide
Learn Docker from the ground up: images, containers, Dockerfiles, networks, volumes, and Docker Compose for local development.
GuideCI/CD Pipeline Guide
A practical guide to building CI/CD pipelines with GitHub Actions, testing, deployment strategies, and rollback procedures.
GuideSoftware Architecture Guide
A guide to designing software architecture: monoliths vs microservices, layered architecture, data flow, and technology selection criteria.
RecipeImplement Graceful Shutdown and Zero-Downtime Restarts
How to implement graceful shutdown and zero-downtime restarts for web servers, workers, and containers
RecipeDeploy Applications to Kubernetes with Helm Charts
Package, version, and deploy Kubernetes applications using Helm charts with value overrides, template functions, and release management for reproducible infrastructure
PatternExternal Configuration Store Pattern
Centralize application configuration outside of deployment artifacts to support live updates and multi-environment management.
GuideSystem Design Interview Guide: Key Concepts
A practical guide to system design interviews: scalability, databases, caching, load balancing, microservices, and how to structure your answer.