Kubernetes: Fundamentals

Master the core building blocks of Kubernetes including Pods, Deployments, Services, and cluster architecture.

Getting Started with Kubernetes

Before diving into commands and configurations, it helps to understand what Kubernetes actually does. Think of it as a distributed operating system: just as your laptop’s OS manages programs, memory, and files on a single machine, Kubernetes manages containers, resources, and storage across many machines.

Why does this matter? When you run kubectl apply -f myapp.yaml, you are not just starting a container. You are telling Kubernetes: “Here is what I want my application to look like. Make it happen and keep it that way.” Kubernetes then handles container placement, networking, restarts, and scaling automatically.

This guide walks you through the fundamentals, building from your first deployment to production-ready configurations.

Quick Start Guide

The fastest way to understand Kubernetes is to use it. This section gets you deploying an application in minutes.

Requirements

  • Container technology knowledge (Docker)
  • Kubernetes cluster access (minikube, kind, k3s, or cloud provider)
  • kubectl CLI v1.28+ installed
  • Optional: Helm 3.x for package management

Your First Deployment

Let us deploy a web server and see Kubernetes in action:

# Deploy nginx and expose it
kubectl create deployment hello-world --image=nginx:alpine
kubectl expose deployment hello-world --type=LoadBalancer --port=80

# Verify it is running
kubectl get pods
kubectl get services

Now try the self-healing feature that makes Kubernetes valuable:

# Scale to 3 replicas and delete one pod
kubectl scale deployment hello-world --replicas=3
kubectl delete pod <pod-name>
kubectl get pods  # A new pod automatically replaces the deleted one

Clean up when done:

kubectl delete deployment hello-world
kubectl delete service hello-world

Core Concepts at a Glance

Before going deeper, here is how the key pieces fit together:

Concept What It Is Analogy
Pod Smallest deployable unit; wraps one or more containers An apartment unit in a building
Deployment Manages pod replicas and updates A property manager ensuring units are occupied
Service Stable network address for pods The building’s front desk that routes visitors
Node A machine (physical or virtual) running pods An apartment building
Cluster A group of nodes managed together The entire apartment complex

The key insight: You rarely work with pods directly. Instead, you tell a Deployment “I want 3 copies of my app” and it creates and manages the pods for you. Services then route traffic to those pods, regardless of which nodes they run on.

The rest of this guide explores each concept in depth, showing you how to build production-ready systems.

Understanding Kubernetes: From Containers to Orchestration

Consider the following evolution in how we run applications:

Era Approach Trade-off
Bare Metal One application per server Wasted resources; most servers idle
Virtual Machines Multiple VMs per server Better utilization but heavy overhead
Containers Many containers per server Lightweight but manual management at scale
Orchestration Kubernetes manages containers Automated, scalable, self-healing

Each step solved the previous era’s problems while creating new challenges. Containers solved VM overhead but introduced complexity: How do you run hundreds of containers across dozens of servers? How do you ensure they stay healthy? How do you update them without downtime?

Kubernetes answers these questions with a declarative approach and automated operations.

What Kubernetes Provides

Rather than listing features, consider what problems each capability solves:

Challenge Kubernetes Solution Benefit
“My container crashed” Self-healing Automatic restart and replacement
“How do services find each other?” Service discovery Built-in DNS and load balancing
“I need to deploy without downtime” Rolling updates Gradual replacement of old pods
“Traffic is spiking” Horizontal scaling Add replicas automatically or manually
“I need to store passwords securely” Secrets Encrypted storage with access controls
“Different apps need different storage” Storage classes Abstract storage provisioning

Core Concepts

Now that you understand why Kubernetes exists, let us explore how it works. The architecture consists of two main parts: the control plane that makes decisions and the worker nodes that run your applications.

Consider the following: When you run kubectl apply -f deployment.yaml, your request travels through several components. The API Server receives it, stores the desired state in etcd, the Scheduler decides which node should run the pods, and the Controller Manager ensures reality matches your specification. Understanding this flow helps you troubleshoot when things go wrong.

Architecture Overview

Kubernetes follows a master-worker architecture. The control plane manages the cluster while worker nodes run your applications.

Control Plane API Server Gateway etcd State Store Scheduler Pod Placement Controller Manager Controllers Cloud Controller Manager Worker Nodes Node 1 kubelet kube-proxy Container Runtime Pods Node 2 Node 3

Control Plane Components

API Server: Central management point, exposes Kubernetes API
etcd: Distributed key-value store for cluster state
Scheduler: Assigns pods to nodes based on resource requirements
Controller Manager: Runs controller processes
Cloud Controller Manager: Integrates with cloud provider APIs

Node Components

kubelet: Ensures containers are running in pods
kube-proxy: Maintains network rules for pod communication
Container Runtime: Docker, containerd, or CRI-O

Kubernetes Objects: The Building Blocks

With the architecture understood, let us explore the objects you will work with daily. Each object type solves a specific problem, and choosing the right one depends on your application’s needs.

When to use each object type:

Object Use Case Example
Pod Rarely used directly; foundation for other objects Testing, debugging
Deployment Stateless applications that can scale horizontally Web servers, APIs
StatefulSet Stateful applications needing stable identity Databases, message queues
DaemonSet Run one pod per node Log collectors, monitoring agents
Job Run-to-completion tasks Database migrations, batch processing
CronJob Scheduled tasks Nightly backups, report generation

Let us examine each object type, starting with the foundation.

Pods

The smallest deployable unit in Kubernetes:

Pod Container 1 Container 2 Shared Network & Storage
Pod Definition
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.21
    ports:
    - containerPort: 80
Key Features:
One or more containers
Shared network and storage
Ephemeral by design
Unique IP address

Deployments

Manages replica sets and provides declarative updates:

Deployment ReplicaSet Pod Pod Pod Replicas: 3
Deployment Definition
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
Features:
Rolling Updates

Zero-downtime deployments

Rollback

Revert to previous versions

Scaling

Adjust replica count

Self-healing

Automatic pod recovery

Services

Provides stable network endpoint for pods:

Service Types
ClusterIP Internal Only
NodePort Node IP:Port
LB LoadBalancer External LB
ExternalName DNS Maps to DNS
Service Definition
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
  type: LoadBalancer
**Choosing a Service Type**: The right service type depends on how your application needs to be accessed: | Service Type | Accessible From | Use Case | Cost | |--------------|-----------------|----------|------| | **ClusterIP** | Inside cluster only | Internal microservices | Free | | **NodePort** | Node IP + port (30000-32767) | Development, testing | Free | | **LoadBalancer** | External IP via cloud LB | Production web apps | Cloud provider charges | | **ExternalName** | DNS alias | Accessing external services | Free | **When to use each**: Start with ClusterIP for internal services. Use LoadBalancer for production internet-facing services. NodePort is useful for development but rarely appropriate for production due to port limitations. #### ConfigMaps and Secrets: Managing Application Configuration As your applications grow, you'll need to manage configuration separately from your container images. This separation allows you to deploy the same image across different environments (development, staging, production) with different configurations. ConfigMaps handle non-sensitive data, while Secrets manage sensitive information like passwords and API keys. **ConfigMap Example:** ```yaml apiVersion: v1 kind: ConfigMap metadata: name: app-config data: database_url: "postgres://localhost:5432/mydb" api_key: "public-api-key" ``` **Secret Example:** ```yaml apiVersion: v1 kind: Secret metadata: name: db-secret type: Opaque data: username: YWRtaW4= # base64 encoded password: cGFzc3dvcmQ= # base64 encoded ```

Namespaces

Logical isolation within a cluster:

Kubernetes Cluster default User Apps kube-system System Pods development Dev Apps production Prod Apps
Namespace Definition
apiVersion: v1
kind: Namespace
metadata:
  name: development
Default Namespaces:
default Default namespace for objects
kube-system Kubernetes system objects
kube-public Publicly accessible data
kube-node-lease Node heartbeat data

Workload Resources: Beyond Basic Deployments

Deployments work well for stateless applications, but real-world systems have varied requirements. Kubernetes provides specialized controllers for different workload patterns.

Consider the following decision tree:

  • Need to scale horizontally with identical replicas? Use a Deployment
  • Need stable identity and persistent storage per pod? Use a StatefulSet
  • Need exactly one pod on every node? Use a DaemonSet
  • Need to run a task to completion? Use a Job
  • Need to run tasks on a schedule? Use a CronJob

Deployment vs StatefulSet vs DaemonSet

Characteristic Deployment StatefulSet DaemonSet
Pod identity Random names Ordered names (app-0, app-1) One per node
Scaling Any order Sequential (0, 1, 2…) Tied to node count
Storage Shared or none Dedicated per pod Usually none
Network Random IPs Stable DNS per pod Per-node
Use case Web apps, APIs Databases, Kafka Logging, monitoring

StatefulSets: When Order and Identity Matter

StatefulSets solve the “pets vs cattle” problem. While Deployments treat pods as interchangeable (cattle), StatefulSets give each pod a stable identity (pets). This matters for applications like databases that need to know their role in a cluster.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres
  replicas: 3
  selector:
    matchLabels:
      app: postgres
  template:
    spec:
      containers:
      - name: postgres
        image: postgres:13
  volumeClaimTemplates:
  - metadata:
      name: postgres-storage
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 10Gi

What StatefulSets guarantee:

  • Pods named sequentially: postgres-0, postgres-1, postgres-2
  • Each pod gets its own persistent volume
  • Pods created in order (0 before 1 before 2) and deleted in reverse
  • Stable DNS: postgres-0.postgres.default.svc.cluster.local

DaemonSets: One Pod Per Node

Some workloads need to run everywhere: log collectors that capture output from all containers, monitoring agents that track node health, or network plugins. DaemonSets ensure exactly one pod runs on each node automatically.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
spec:
  selector:
    matchLabels:
      app: fluentd
  template:
    spec:
      containers:
      - name: fluentd
        image: fluentd:v1.14

Common DaemonSet applications:

  • Logging: Fluentd, Filebeat collecting container logs
  • Monitoring: Node Exporter, Datadog agent
  • Networking: Calico, Cilium CNI plugins
  • Storage: CSI node plugins

Jobs and CronJobs: Task Automation

Not all workloads run continuously. Jobs handle run-to-completion tasks, while CronJobs run tasks on a schedule.

Job - runs once until successful:

apiVersion: batch/v1
kind: Job
metadata:
  name: db-migration
spec:
  template:
    spec:
      containers:
      - name: migrate
        image: myapp:latest
        command: ["./migrate.sh"]
      restartPolicy: OnFailure
  backoffLimit: 3  # Retry up to 3 times

CronJob - runs on a schedule (standard cron syntax):

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-backup
spec:
  schedule: "0 2 * * *"  # 2 AM daily
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: backup-tool:latest
          restartPolicy: OnFailure

Real-world Job use cases: database migrations, data imports, report generation, sending batch emails, cleanup tasks.

Networking: Connecting Your Applications

Kubernetes networking follows a simple principle: every pod gets its own IP address, and all pods can communicate with each other without NAT. This flat network model makes it easy to reason about connectivity.

Consider the following networking layers:

Layer Purpose Kubernetes Object
Pod-to-Pod Direct communication Flat network (automatic)
Pod-to-Service Stable endpoint for pods Service
External-to-Service Traffic from outside cluster Ingress, LoadBalancer
Service-to-External Outbound connections NetworkPolicy (egress)

Ingress: Your Cluster’s Front Door

While Services handle internal routing, Ingress manages external HTTP/HTTPS traffic. Instead of creating multiple LoadBalancer services (each with its own IP and cost), Ingress provides a single entry point that routes to different services based on hostnames and paths.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80

When to use Ingress vs LoadBalancer:

  • Use Ingress when you have multiple services that need HTTP/HTTPS routing
  • Use LoadBalancer for non-HTTP traffic or single services
  • Ingress typically requires an Ingress Controller (nginx, traefik, or cloud-provided)

Network Policies: Microsegmentation for Security

By default, all pods can communicate freely. Network Policies let you restrict this, implementing defense-in-depth by controlling which pods can talk to each other.

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

This policy says: “Only allow traffic to the API pods from frontend pods on port 8080.”

Important: Network Policies require a CNI plugin that supports them (Calico, Cilium, Weave Net). The default kubenet does not enforce policies.