Skip to content
Home
Kubernetes Basics: Pods, Deployments, Services & Config Management

Kubernetes Basics: Pods, Deployments, Services & Config Management

Developer Tools Developer Tools 8 min read 1530 words Beginner ExcellentWiki Editorial Team

Kubernetes (K8s) is the industry standard for container orchestration. It automates deployment, scaling, and management of containerized applications across clusters of machines. While Docker Compose handles single-host deployments, Kubernetes manages multi-host clusters with features like auto-scaling, self-healing, rolling updates, and service discovery. Kubernetes was originally designed by Google based on their internal Borg system, which has run Google’s infrastructure for over a decade. This guide covers Kubernetes fundamentals — the core concepts you need to understand before running production workloads.

Architecture Overview

A Kubernetes cluster consists of a control plane and worker nodes. The control plane manages the cluster state; nodes run the actual workloads.

Control Plane Components

The API Server (kube-apiserver) exposes the Kubernetes API. Every operation — creating a pod, scaling a deployment, querying logs — goes through the API server. It validates and processes RESTful requests, storing the cluster state in etcd.

The Scheduler (kube-scheduler) assigns pods to nodes based on resource requirements, constraints, and policies. It considers CPU and memory requests, node affinity rules, taints and tolerations, and data locality.

The Controller Manager (kube-controller-manager) runs controllers that reconcile the desired state with the actual state. The deployment controller ensures the correct number of pods are running. The node controller monitors node health. The endpoint controller connects services to pods.

etcd is a distributed key-value store that holds the entire cluster state — all configurations, secrets, and resource specifications. etcd uses the Raft consensus algorithm for consistency and requires an odd number of members (typically 3 or 5) for fault tolerance.

Worker Node Components

kubelet is the primary node agent. It communicates with the API server to receive pod specifications, ensures containers are running and healthy, and reports node and pod status back to the control plane.

kube-proxy manages network rules on each node, implementing Service abstraction through iptables, IPVS, or userspace mode. It handles load balancing across pods in a service.

Container Runtime (containerd, CRI-O, or Docker) pulls images and runs containers. Kubernetes uses the Container Runtime Interface (CRI) to support multiple runtime implementations.

Pods: The Atomic Unit

A pod is the smallest deployable unit in Kubernetes. It wraps one or more containers that share storage, network namespace, and a specification for how to run. Containers in the same pod share the same IP address, port space, and can communicate via localhost.

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
    tier: frontend
spec:
  containers:
    - name: nginx
      image: nginx:1.25
      ports:
        - containerPort: 80
      resources:
        requests:
          memory: "64Mi"
          cpu: "250m"
        limits:
          memory: "128Mi"
          cpu: "500m"
      livenessProbe:
        httpGet:
          path: /healthz
          port: 80
        initialDelaySeconds: 3
        periodSeconds: 3
      readinessProbe:
        httpGet:
          path: /ready
          port: 80
        initialDelaySeconds: 3
        periodSeconds: 3

Resource Requests and Limits

Resource requests guarantee a minimum amount of CPU and memory for the pod. The scheduler uses requests to place pods on nodes with sufficient capacity. Resource limits cap the maximum resources a container can consume. CPU is compressible — exceeding the limit throttles the container. Memory is incompressible — exceeding the limit crashes the container (OOMKill).

Probes

Liveness probes determine if a container is running properly. If a liveness probe fails, kubelet kills the container and restarts it. Readiness probes determine if a container is ready to serve traffic. If a readiness probe fails, the service removes the pod from its endpoints. Startup probes protect slow-starting containers from being killed by liveness probes before initialization completes.

Deployments: Declarative Pod Management

Deployments provide declarative updates for pods and ReplicaSets. You describe the desired state — how many replicas, which container image, resource requirements — and the deployment controller ensures the actual state matches.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: app
          image: myapp:1.0.0
          ports:
            - containerPort: 3000
          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: url

Rolling Updates and Rollbacks

Deployments support rolling updates with configurable surge and unavailable limits:

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

maxSurge: 1 allows one extra pod during the update. maxUnavailable: 0 ensures all pods remain available — zero-downtime deployment.

# Trigger a rolling update
kubectl set image deployment/web-app app=myapp:1.2.0

# Check rollout status
kubectl rollout status deployment/web-app

# Pause and resume
kubectl rollout pause deployment/web-app
kubectl rollout resume deployment/web-app

# Rollback to previous version
kubectl rollout undo deployment/web-app

# Rollback to a specific revision
kubectl rollout undo deployment/web-app --to-revision=2

# View rollout history
kubectl rollout history deployment/web-app

Services: Stable Network Endpoints

Pods are ephemeral — they can be created, destroyed, or rescheduled to different nodes. Services provide stable network endpoints that abstract away pod churn. A service selects target pods using label selectors and load-balances traffic across them.

Service Types

ClusterIP (default) exposes the service on a cluster-internal IP. Only reachable from within the cluster. Use for internal communication between services.

NodePort exposes the service on each node’s IP at a static port (30000-32767). Access from outside the cluster at <node-ip>:<node-port>. Use for development and debugging.

LoadBalancer provisions a cloud provider load balancer (AWS ELB, GCP TCP/UDP Load Balancer, Azure Load Balancer) that forwards traffic to the NodePort. This is the standard way to expose services to the internet in production.

ConfigMaps and Secrets

ConfigMaps store non-confidential configuration data as key-value pairs:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  APP_ENV: production
  LOG_LEVEL: info
  config.json: |
    {"features": {"dark_mode": true, "beta_api": false}}

Mount ConfigMaps as environment variables or files. Secrets are similar but base64-encoded and intended for sensitive data like passwords and API keys. Use RBAC to restrict secret access.

Storage and Persistence

Containers are stateless by default — data written to the container filesystem is lost when the pod restarts. Persistent Volumes (PVs) and Persistent Volume Claims (PVCs) provide durable storage:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

StatefulSets manage stateful applications with stable network identities and ordered deployment. Databases, message queues, and distributed systems use StatefulSets.

Advanced Workload Management

DaemonSets

DaemonSets ensure that every node in the cluster runs a copy of a pod. They are ideal for cluster-wide services like log collectors (Fluentd, Filebeat), monitoring agents (Prometheus Node Exporter, Datadog Agent), and networking plugins (Calico, Cilium):

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
spec:
  selector:
    matchLabels:
      name: fluentd
  template:
    metadata:
      labels:
        name: fluentd
    spec:
      containers:
        - name: fluentd
          image: fluent/fluentd:v1.16
          volumeMounts:
            - name: varlog
              mountPath: /var/log
      volumes:
        - name: varlog
          hostPath:
            path: /var/log

When a new node joins the cluster, the DaemonSet automatically schedules a pod on it. When a node is removed, the pod is garbage collected without manual intervention.

Jobs and CronJobs

Batch workloads run to completion rather than indefinitely. Jobs execute one or more pods and track completion:

apiVersion: batch/v1
kind: Job
metadata:
  name: data-migration
spec:
  completions: 1
  parallelism: 1
  template:
    spec:
      containers:
        - name: migration
          image: myapp:latest
          command: ["node", "migrate.js"]
      restartPolicy: Never

CronJobs schedule Jobs on a time-based schedule:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: db-backup
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: backup
              image: postgres:16-alpine
              command: ["pg_dump", "-U", "admin", "-f", "/backup/db.sql", "myapp"]
          restartPolicy: OnFailure

CronJobs support time zones, concurrency policies (Allow, Forbid, Replace), and starting deadlines for delayed schedules.

Network Policies

Network Policies control traffic flow between pods. By default, all pods can communicate freely — network policies restrict this:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-allow-frontend
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              tier: frontend
      ports:
        - port: 3000

This policy restricts incoming traffic to the API pods: only pods with label tier: frontend can connect on port 3000. All other ingress traffic is dropped.

Frequently Asked Questions

What is the difference between a pod and a container?

A pod is the Kubernetes abstraction — it wraps one or more containers sharing the same network namespace and storage volumes. Containers in the same pod are always co-located and co-scheduled on the same node. Single-container pods are most common; multi-container pods are used for sidecar patterns.

How does Kubernetes handle service discovery?

Kubernetes has built-in DNS-based service discovery. Each service gets a DNS name matching the service name in the namespace. Pods resolve service-name.namespace.svc.cluster.local to the service’s ClusterIP. kube-proxy on each node forwards traffic to healthy pod endpoints.

What is Horizontal Pod Autoscaling?

The Horizontal Pod Autoscaler (HPA) automatically scales deployment replicas based on CPU utilization, memory usage, or custom metrics. It reads metrics from the Metrics Server and adjusts the replica count within configured min/max bounds. Combined with cluster autoscaling, it handles traffic spikes without manual intervention.

How do I debug a crashing pod?

Start with kubectl describe pod pod-name to check events and status. Use kubectl logs pod-name --previous to see logs from the previous container instance (crashed containers generate new instances). Check liveness probe configuration — overly aggressive probes cause unnecessary restarts.

Can I run stateful databases on Kubernetes?

Yes, but with caveats. Use StatefulSets for stable identities, PersistentVolumeClaims for storage, and ConfigMaps for configuration. The Kubernetes Operator pattern (e.g., Zalando’s Postgres Operator, Strimzi for Kafka) automates backups, failovers, and upgrades. Stateful workloads require careful planning around storage performance, backup strategies, and disaster recovery.

Related Articles

Section: Developer Tools 1530 words 8 min read Beginner 756 articles in section Report inaccuracy Back to top