Skip to content
StackPractices
beginner By Mathias Paulenko

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 TypeDescriptionUse Case
ClusterIPInternal cluster IP onlyInternal communication
NodePortExposes on each node’s IP at a static portDirect external access
LoadBalancerExposes externally using cloud provider’s LBProduction ingress
ExternalNameMaps to external DNS nameExternal 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:

ProbePurposeAction on Failure
LivenessIs the app running?Restart container
ReadinessIs the app ready to accept traffic?Remove from Service endpoints
StartupHas 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 projects
  • dev, 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 :latest in 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 latest image 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 default namespace 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.