← Tutorials 🤖 AI 📓 Architect's Notebook ☁ AWS 📋 Cheatsheet 🗃 Databases 🚀 DevOps 🧩 DSA ❓ FAQ 🖥 Frontend ☕ Java 🍏 MongoDB 🐍 Python 🌿 Spring Boot 🏗 System Design 🏛 TOGAF
TutorialsDevOps › Kubernetes
★ marked topics are high-priority interview topics with in-depth explanations and visual diagrams. Other topics give concise, practical summaries.

Introduction to Kubernetes

☸️ Kubernetes · Foundations · 6 min read

Kubernetes (K8s) is an open-source container orchestration platform that automates deploying, scaling, and managing containerized applications across a cluster of machines. Originally built by Google and now governed by the CNCF, it has become the industry standard for running containers in production.

Why Kubernetes

Docker packages an app into a container; but running hundreds of containers across many servers — keeping them healthy, scaled, networked, and updated with zero downtime — is what Kubernetes solves.

  • Self-healing — restarts failed containers, reschedules them on healthy nodes.
  • Horizontal scaling — scale apps up/down automatically based on load.
  • Service discovery & load balancing — built-in DNS and traffic distribution.
  • Automated rollouts & rollbacks — ship new versions safely.
  • Declarative config — you describe the desired state; K8s makes it real and keeps it that way.

The Declarative Model

You don't tell K8s how to do things step by step. You declare the desired state in YAML ("run 3 replicas of this image"), and the control plane continuously reconciles reality toward it.

# the whole K8s mental model in one loop: desired state (your YAML) ──▶ controllers reconcile ──▶ actual state ▲ │ └────────────── watch & correct drift ◀────────────┘
💡 Interview one-liner: "Kubernetes is a declarative, self-healing container orchestrator that continuously reconciles the actual cluster state toward the desired state you declare."

Kubernetes Architecture

☸️ Kubernetes · Foundations · ★ Interview Topic · 12 min read

A Kubernetes cluster has two planes: the Control Plane (the brain that makes global decisions) and the Worker Nodes (where your containers actually run). Understanding which component does what is the single most-asked K8s interview question.

Cluster Anatomy — Visual

Control Plane (master) kube-apiserverfront door (REST) etcdcluster state store schedulerplaces pods on nodes controller-managerreconcile loops cloud-controller-manager Decides & stores; never runs your containers Worker Node 1 kubelet kube-proxy Podcontainers Pod+ runtime Worker Node 2 kubelet kube-proxy Pods (your workloads run here)

Control Plane Components

ComponentResponsibility
kube-apiserverThe front door — all reads/writes go through its REST API; validates & persists to etcd
etcdDistributed key-value store holding the entire cluster state (the source of truth)
kube-schedulerWatches for unscheduled pods and assigns each to the best node
kube-controller-managerRuns reconcile loops (node, replicaset, deployment controllers…)
cloud-controller-managerIntegrates with cloud provider APIs (load balancers, volumes, nodes)

Worker Node Components

ComponentResponsibility
kubeletAgent on each node; ensures the containers described in PodSpecs are running & healthy
kube-proxyMaintains network rules so Services route traffic to the right pods
Container runtimeActually runs containers (containerd, CRI-O)
💡 Memory aid — the request flow: kubectl applyAPI server validates & writes to etcdscheduler picks a node → kubelet on that node tells the runtime to start the pod → kube-proxy wires up networking. Name every component and you've nailed the architecture question.

Control Plane Components

☸️ Kubernetes · Foundations · 6 min read

The control plane is the cluster's brain — it makes global decisions and detects/responds to events. It never runs your application containers (in a typical setup); it manages everything that does.

The Five Components

  • kube-apiserver — the only component everything else talks to; exposes the Kubernetes REST API.
  • etcd — consistent, highly-available key-value store; the single source of truth. Back this up!
  • kube-scheduler — assigns pods to nodes based on resources, affinity, taints.
  • kube-controller-manager — bundles the core controllers (Node, ReplicaSet, Job, Endpoint…).
  • cloud-controller-manager — talks to the cloud provider for LBs, storage, and node lifecycle.
⚠️ etcd is the most critical component — if you lose it without a backup, you lose the cluster's entire state. Production clusters run etcd as a 3 or 5-node quorum and back it up regularly.

Worker Nodes

☸️ Kubernetes · Foundations · 5 min read

Worker nodes are the machines (VMs or physical) that actually run your application pods. Each node is managed by the control plane and runs three things.

Node Components

  • kubelet — the node agent. Receives PodSpecs from the API server and makes sure those containers are running and healthy; reports status back.
  • kube-proxy — implements the Service abstraction by managing iptables/IPVS rules for pod networking.
  • Container runtime — containerd or CRI-O; pulls images and runs containers via the CRI.

Inspecting Nodes

kubectl get nodes kubectl describe node <node-name> kubectl top node # resource usage (needs metrics-server)
💡 A node can be cordoned (no new pods) and drained (evict existing pods) for maintenance — key commands during cluster upgrades.

Kubernetes Cluster

☸️ Kubernetes · Foundations · 5 min read

A cluster is the complete unit: one (or more) control plane nodes plus a set of worker nodes, working together as a single logical platform on which you deploy applications.

Cluster Setup Options

ToolUse
minikube / kindLocal single-node clusters for learning & dev
kubeadmBootstrap a self-managed cluster
EKS / AKS / GKEManaged clusters (cloud runs the control plane)

Quick Local Start

minikube start kubectl cluster-info kubectl get nodes
💡 In production, the control plane is run in HA (3+ nodes) and is often managed for you (EKS/AKS/GKE) so you only worry about worker nodes and workloads.

Pods

☸️ Kubernetes · Workloads · ★ Interview Topic · 10 min read

A Pod is the smallest deployable unit in Kubernetes — a wrapper around one or more containers that share the same network namespace (IP & port space), storage volumes, and lifecycle. You almost never create pods directly; controllers (Deployments) create them for you.

What's Inside a Pod — Visual

Pod (shared IP 10.1.2.3) Container Aapp :8080 Sidecarlog shipper shared: network (localhost) · volumes · lifecycle

Pod Manifest

apiVersion: v1 kind: Pod metadata: name: myapp labels: { app: myapp } spec: containers: - name: app image: myrepo/myapp:1.0 ports: - containerPort: 8080 resources: requests: { cpu: "250m", memory: "256Mi" } limits: { cpu: "500m", memory: "512Mi" }

Key Facts

  • Containers in a pod share localhost and can share volumes — used for sidecar patterns.
  • Pods are ephemeral & mortal — they get a new IP each time; never rely on a pod's identity.
  • A pod is scheduled to one node as a unit (all its containers run together).
  • Manage pods via controllers (Deployment/StatefulSet), not directly.
kubectl get pods kubectl describe pod myapp kubectl logs myapp -c app kubectl exec -it myapp -- sh
💡 Interview gotcha: a Pod can hold multiple containers, but the common case is one container per pod. Multiple containers are for tightly-coupled helpers (sidecars) that must share the pod's network/storage.

Multi-Container Pods

☸️ Kubernetes · Workloads · 6 min read

Sometimes a pod runs more than one container that must work together — sharing network and volumes. There are well-known patterns for this.

The Patterns

PatternPurpose
SidecarHelper alongside the main app (log shipper, proxy, sync agent)
AmbassadorProxy that simplifies access to external services
AdapterTransforms the app's output to a standard format (e.g. metrics)
Init containerRuns to completion before app containers start (setup, migrations)

Init Container Example

spec: initContainers: - name: wait-for-db image: busybox command: ['sh','-c','until nc -z db 5432; do sleep 2; done'] containers: - name: app image: myapp:1.0
💡 Init containers run sequentially and must succeed before the main containers start — perfect for "wait for the database" or "run schema migration" steps.

ReplicaSets

☸️ Kubernetes · Workloads · ★ Interview Topic · 8 min read

A ReplicaSet ensures a specified number of identical pod replicas are running at all times. If a pod dies, the ReplicaSet creates a new one; if there are too many, it deletes extras. It's the self-healing & scaling engine beneath Deployments.

How It Reconciles — Visual

ReplicaSetdesired: replicas = 3 Pod (running) Pod (running) Pod (died) ↳ recreated automatically

How It Identifies Its Pods

A ReplicaSet uses a label selector to know which pods it owns. It constantly counts pods matching the selector and adds/removes to match the desired replica count.

apiVersion: apps/v1 kind: ReplicaSet metadata: { name: myapp-rs } spec: replicas: 3 selector: matchLabels: { app: myapp } # which pods it manages template: # pod blueprint metadata: { labels: { app: myapp } } spec: containers: - name: app image: myapp:1.0
💡 You rarely create ReplicaSets directly — Deployments manage ReplicaSets for you and add rolling updates/rollbacks on top. Knowing the relationship (Deployment → ReplicaSet → Pods) is a classic interview question.

Deployments

☸️ Kubernetes · Workloads · ★ Interview Topic · 10 min read

A Deployment is the most common way to run a stateless app. It manages ReplicaSets to provide declarative updates — rolling out new versions, rolling back, and scaling — all while keeping your app available.

Deployment → ReplicaSet → Pods — Visual

Deploymentmanages rollouts ReplicaSet v2active (3 pods) ReplicaSet v1old (0 pods, kept for rollback) Pod Pod Pod

Deployment Manifest

apiVersion: apps/v1 kind: Deployment metadata: { name: myapp } spec: replicas: 3 selector: matchLabels: { app: myapp } strategy: type: RollingUpdate rollingUpdate: { maxSurge: 1, maxUnavailable: 0 } template: metadata: { labels: { app: myapp } } spec: containers: - name: app image: myapp:1.0 ports: [ { containerPort: 8080 } ]

Everyday Commands

kubectl apply -f deployment.yaml kubectl set image deployment/myapp app=myapp:2.0 # trigger rolling update kubectl rollout status deployment/myapp kubectl rollout undo deployment/myapp # rollback kubectl scale deployment/myapp --replicas=5
💡 The hierarchy to memorize: Deployment manages ReplicaSets, ReplicaSets manage Pods. On each update, the Deployment creates a new ReplicaSet and scales it up while scaling the old one down — keeping the old one (scaled to 0) so you can roll back instantly.

StatefulSets

☸️ Kubernetes · Workloads · 6 min read

A StatefulSet manages stateful applications (databases, Kafka, Zookeeper) that need stable identity and storage — unlike Deployments where pods are interchangeable.

What It Guarantees

  • Stable, ordered namesmyapp-0, myapp-1, … (not random).
  • Stable persistent storage — each pod keeps its own PVC across restarts/rescheduling.
  • Ordered, graceful deploy/scale — pods created/deleted in order (0,1,2 …).
  • Stable network identity via a headless Service (myapp-0.svc).
💡 Use a Deployment for stateless apps; a StatefulSet for anything needing stable identity/storage. Interview test: "Postgres replica set → StatefulSet; web API → Deployment."

DaemonSets

☸️ Kubernetes · Workloads · 5 min read

A DaemonSet ensures a copy of a pod runs on every node (or a subset). As nodes join the cluster, they automatically get the pod; as nodes leave, the pods are removed.

Typical Uses

  • Log collectors (Fluentd, Filebeat) on every node.
  • Node monitoring agents (node-exporter, Datadog).
  • Storage/network plugins (CNI, CSI daemons).
kubectl get daemonset -A
💡 DaemonSet = "one pod per node." Perfect for node-level infrastructure that must be everywhere, not load-balanced replicas.

Jobs

☸️ Kubernetes · Workloads · 5 min read

A Job runs a pod (or several) to completion — for batch/one-off tasks like a data migration, backup, or report. Unlike Deployments, it's not meant to run forever; it finishes and stops.

apiVersion: batch/v1 kind: Job metadata: { name: db-migrate } spec: completions: 1 backoffLimit: 4 # retries before marking failed template: spec: restartPolicy: Never containers: - name: migrate image: myapp:1.0 command: ["java","-jar","app.jar","--migrate"]
💡 Use parallelism + completions for parallel batch processing. A Job tracks success and retries failed pods up to backoffLimit.

CronJobs

☸️ Kubernetes · Workloads · 5 min read

A CronJob runs Jobs on a schedule, using standard cron syntax — for recurring tasks like nightly backups, report generation, or cleanup.

apiVersion: batch/v1 kind: CronJob metadata: { name: nightly-backup } spec: schedule: "0 2 * * *" # every day at 02:00 jobTemplate: spec: template: spec: restartPolicy: OnFailure containers: - name: backup image: backup-tool:1.0
💡 Control history with successfulJobsHistoryLimit / failedJobsHistoryLimit, and prevent overlap with concurrencyPolicy: Forbid.

Namespaces

☸️ Kubernetes · Organization · ★ Interview Topic · 8 min read

Namespaces provide virtual clusters within a physical cluster — a way to divide resources between teams, environments, or projects. They give scope to names, enable resource quotas, and support access control (RBAC).

Logical Partitioning — Visual

One physical cluster devapp · db · quota: small stagingapp · db · quota: med prodapp · db · quota: large Same names (app, db) coexist — scoped per namespace · separate RBAC & quotas

Working with Namespaces

kubectl get namespaces kubectl create namespace dev kubectl apply -f app.yaml -n dev kubectl get pods -n dev kubectl config set-context --current --namespace=dev # set default

Key Points

  • Default namespaces: default, kube-system (control plane), kube-public.
  • Cross-namespace DNS: service.namespace.svc.cluster.local.
  • Not everything is namespaced — Nodes, PersistentVolumes, and StorageClasses are cluster-scoped.
  • Apply ResourceQuotas and LimitRanges per namespace to cap usage.
💡 Namespaces isolate names and policy, not the network by default — pods in different namespaces can still talk unless you add NetworkPolicies. Common pattern: one namespace per team or per environment.

Labels and Selectors

☸️ Kubernetes · Organization · 5 min read

Labels are key-value pairs attached to objects; selectors query objects by their labels. This loosely-coupled mechanism is how Services find pods, ReplicaSets own pods, and you filter resources.

metadata: labels: app: myapp tier: backend env: prod
kubectl get pods -l app=myapp,env=prod # equality kubectl get pods -l 'env in (prod,staging)' # set-based
💡 Labels drive almost every relationship in K8s — a Service's selector matching pod labels is exactly how traffic finds pods. Use consistent label conventions (app, tier, env, version).

Annotations

☸️ Kubernetes · Organization · 4 min read

Annotations attach non-identifying metadata to objects — info for tools and humans, not for selection. Unlike labels, you can't query by them.

Labels vs Annotations

LabelsAnnotations
PurposeIdentify & selectDescribe / configure tools
QueryableYes (selectors)No
Examplesapp: myappbuild info, ingress config, change-cause
💡 Many controllers read annotations as config — e.g. ingress controllers (nginx.ingress.kubernetes.io/rewrite-target) and Prometheus scrape settings.

Services

☸️ Kubernetes · Networking · ★ Interview Topic · 10 min read

Pods are ephemeral and get new IPs constantly. A Service provides a stable virtual IP and DNS name in front of a set of pods (selected by labels), with built-in load balancing — so clients have one reliable address regardless of pod churn.

Stable Front for Changing Pods — Visual

Clientmyapp:8080 Servicestable ClusterIP + DNS Pod 10.1.1.4 Pod 10.1.2.7 Pod 10.1.3.9 selects pods by label · load-balances

The Four Service Types

TypeExposesUse
ClusterIPInternal virtual IP (default)Pod-to-pod within the cluster
NodePortA port on every nodeBasic external access / dev
LoadBalancerCloud load balancerProduction external access
ExternalNameA CNAME to an external hostAlias to an external service
apiVersion: v1 kind: Service metadata: { name: myapp } spec: type: ClusterIP selector: { app: myapp } # matches pod labels ports: - port: 80 # service port targetPort: 8080 # container port
💡 The Service finds its pods via the selector → pod labels match, and kube-proxy programs the load-balancing rules. Layering: ClusterIP (internal) → NodePort (node port) → LoadBalancer (cloud LB) each builds on the previous.

ClusterIP

☸️ Kubernetes · Networking · 4 min read

ClusterIP is the default Service type. It exposes the Service on an internal virtual IP reachable only inside the cluster — ideal for internal microservice-to-microservice communication.

  • Reachable via the cluster IP or DNS name (myapp.default.svc.cluster.local).
  • Not accessible from outside the cluster.
  • A headless variant (clusterIP: None) returns pod IPs directly — used by StatefulSets.
💡 Use ClusterIP for backends (databases, internal APIs). Front-facing access goes through Ingress or LoadBalancer, which themselves route to ClusterIP Services.

NodePort

☸️ Kubernetes · Networking · 4 min read

NodePort exposes the Service on a static port on every node (range 30000–32767). External traffic to <NodeIP>:<NodePort> is routed to the Service, then to pods.

spec: type: NodePort selector: { app: myapp } ports: - port: 80 targetPort: 8080 nodePort: 30080 # optional; auto-assigned if omitted
⚠️ NodePort is fine for dev/testing but crude for production — you expose ports on every node and must manage an external LB/DNS yourself. Prefer LoadBalancer or Ingress in production.

LoadBalancer

☸️ Kubernetes · Networking · 4 min read

LoadBalancer provisions an external cloud load balancer (AWS ELB, GCP LB, Azure LB) that routes internet traffic to the Service. It's the standard way to expose a service externally on managed clusters.

spec: type: LoadBalancer selector: { app: myapp } ports: [ { port: 80, targetPort: 8080 } ]

The cloud provider assigns a public IP/hostname (kubectl get svc shows EXTERNAL-IP). Under the hood it builds on NodePort.

💡 One LoadBalancer per Service gets expensive. For many HTTP services, use a single Ingress (one LB) that routes by host/path to many backend Services instead.

ExternalName

☸️ Kubernetes · Networking · 4 min read

ExternalName maps a Service to an external DNS name via a CNAME record — no proxying, no selector, no pods. It lets in-cluster apps reach an external service through a stable internal name.

apiVersion: v1 kind: Service metadata: { name: external-db } spec: type: ExternalName externalName: db.prod.example.com
💡 Use it to abstract external dependencies: your app calls external-db, and you can later swap the real host (or move the DB into the cluster) without changing app config.

Ingress

☸️ Kubernetes · Networking · ★ Interview Topic · 9 min read

An Ingress manages external HTTP/HTTPS access to services in the cluster, providing host- and path-based routing, TLS termination, and a single entry point — so you don't need a separate LoadBalancer per service.

One Entry Point, Many Services — Visual

Internet Ingress + Controllerroutes by host/path · TLS /api → api-serviceapp.com/api / → web-serviceapp.com/ shop.com → shop-servicehost-based

Ingress Manifest

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: myapp-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: tls: - hosts: [app.example.com] secretName: app-tls # TLS cert from a Secret rules: - host: app.example.com http: paths: - path: /api pathType: Prefix backend: { service: { name: api-svc, port: { number: 80 } } } - path: / pathType: Prefix backend: { service: { name: web-svc, port: { number: 80 } } }
⚠️ Ingress is just a set of routing rules — it does nothing without an Ingress Controller (nginx, Traefik, AWS ALB) running in the cluster to implement them. Forgetting the controller is the #1 "why isn't my Ingress working" mistake.
💡 Ingress vs LoadBalancer: a LoadBalancer Service = one cloud LB per service (L4). An Ingress = one LB for many services with smart L7 (host/path) routing + TLS. Cheaper and more flexible for HTTP apps.

Ingress Controller

☸️ Kubernetes · Networking · 5 min read

An Ingress Controller is the actual pod (a reverse proxy) that watches Ingress resources and implements their routing rules. Kubernetes ships the Ingress API but not a controller — you install one.

Popular Controllers

ControllerNotes
ingress-nginxMost common, community standard
TraefikDynamic config, great DX
AWS Load Balancer ControllerProvisions ALB/NLB on EKS
HAProxy / Contour / KongHigh-performance / API-gateway features
# install ingress-nginx via Helm helm install ingress-nginx ingress-nginx/ingress-nginx
💡 The controller itself is usually exposed via a single LoadBalancer Service — that one cloud LB then fans out to all your Ingress-routed services.

Service Discovery

☸️ Kubernetes · Networking · 5 min read

Service discovery is how pods find and talk to each other without hardcoding IPs. Kubernetes provides it automatically through DNS and environment variables.

Two Mechanisms

  • DNS (preferred) — every Service gets a DNS name; pods resolve service-name (same namespace) or service.namespace.svc.cluster.local.
  • Environment variables — kubelet injects <SVC>_SERVICE_HOST/PORT for services existing at pod start (legacy, order-dependent).
# app in namespace "dev" reaching the db service: jdbc:postgresql://db:5432/app # same namespace jdbc:postgresql://db.prod.svc.cluster.local:5432/app # cross-namespace
💡 Always use DNS, not injected env vars — DNS works regardless of creation order and updates dynamically as services change.

DNS in Kubernetes

☸️ Kubernetes · Networking · 5 min read

Kubernetes runs an internal DNS server (CoreDNS) that gives every Service and pod a resolvable name, powering service discovery.

Naming Convention

# Service FQDN <service>.<namespace>.svc.cluster.local # examples myapp # same namespace (short) myapp.prod # cross-namespace myapp.prod.svc.cluster.local # fully qualified

Debugging DNS

kubectl run -it --rm dnstest --image=busybox -- nslookup myapp kubectl get pods -n kube-system -l k8s-app=kube-dns # CoreDNS pods
💡 DNS issues are a top cluster problem. If service discovery breaks, check CoreDNS pods in kube-system first.

Kubernetes Networking

☸️ Kubernetes · Networking · 6 min read

Kubernetes networking follows a flat model with four fundamental rules, implemented by a CNI plugin (Calico, Cilium, Flannel, AWS VPC CNI).

The Networking Model

  • Every pod gets its own IP.
  • Pods can communicate with all other pods without NAT.
  • Nodes can communicate with all pods.
  • The IP a pod sees itself as = the IP others use to reach it.

The Layers

CommunicationMechanism
Container ↔ container (same pod)localhost
Pod ↔ podCNI plugin (flat network)
Pod ↔ Servicekube-proxy (iptables/IPVS)
External ↔ ServiceNodePort / LoadBalancer / Ingress
💡 The CNI plugin is pluggable — clusters choose one (e.g. Cilium for eBPF-based performance & network policy). The model is the contract; the CNI is the implementation.

Network Policies

☸️ Kubernetes · Networking · 6 min read

By default, all pods can talk to all pods. A NetworkPolicy is a firewall for pods — it restricts ingress/egress traffic by pod/namespace selectors and ports, enabling zero-trust segmentation.

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: { name: db-allow-api } spec: podSelector: matchLabels: { app: db } # applies to db pods policyTypes: [Ingress] ingress: - from: - podSelector: matchLabels: { app: api } # only api pods may connect ports: - { protocol: TCP, port: 5432 }
⚠️ NetworkPolicies require a CNI that supports them (Calico, Cilium) — with some CNIs (e.g. basic Flannel) they're silently ignored. Once any policy selects a pod, all non-matching traffic to it is denied.

ConfigMaps

☸️ Kubernetes · Config & Storage · ★ Interview Topic · 8 min read

A ConfigMap stores non-confidential configuration as key-value pairs, decoupling config from container images (the 12-factor principle). The same image runs in dev/staging/prod with different ConfigMaps.

Two Ways to Consume — Visual

ConfigMapLOG_LEVEL=info · API_URL=… as env varsenvFrom / valueFrom as mounted filesvolume → /etc/config

Define & Consume

apiVersion: v1 kind: ConfigMap metadata: { name: app-config } data: LOG_LEVEL: "info" application.yml: | server: port: 8080
# as env vars envFrom: - configMapRef: { name: app-config } # as a mounted file volumes: - name: cfg configMap: { name: app-config } volumeMounts: - { name: cfg, mountPath: /etc/config }
💡 ConfigMaps are not encrypted and have a 1 MiB size limit — use them for plain config only. Anything sensitive (passwords, keys) belongs in a Secret. Mounted ConfigMaps update live; env-var values require a pod restart.

Secrets

☸️ Kubernetes · Config & Storage · ★ Interview Topic · 8 min read

A Secret stores sensitive data — passwords, tokens, TLS certs, registry credentials. Structurally like a ConfigMap, but intended for confidential values with extra handling (base64-encoded, can be encrypted at rest, mounted as tmpfs).

Creating Secrets

# from literals (kubectl base64-encodes for you) kubectl create secret generic db-secret \ --from-literal=username=app \ --from-literal=password=s3cr3t # TLS secret kubectl create secret tls app-tls --cert=tls.crt --key=tls.key

Consuming Secrets

env: - name: DB_PASSWORD valueFrom: secretKeyRef: { name: db-secret, key: password } # or mount as files (recommended for certs) volumes: - name: secret-vol secret: { secretName: db-secret }
⚠️ By default Secrets are only base64-encoded, not encrypted — anyone with etcd or API read access can decode them. For real security: enable encryption at rest for etcd, restrict access with RBAC, and consider external stores (Vault, AWS/GCP/Azure secret managers via CSI/External Secrets).
💡 Interview answer for "ConfigMap vs Secret": same shape, but Secrets are for sensitive data — base64-encoded, can be encrypted at rest, mounted in memory (tmpfs), and access-controlled more tightly.

Volumes

☸️ Kubernetes · Config & Storage · 5 min read

A container's filesystem is ephemeral — lost on restart. A Volume gives pods storage with a lifecycle tied to the pod (or longer, for persistent types) and lets containers in a pod share files.

Common Volume Types

TypeLifecycle / Use
emptyDirEmpty dir created with the pod, deleted with it (scratch/shared)
configMap / secretInject config/secrets as files
persistentVolumeClaimDurable storage that outlives the pod (PV/PVC)
hostPathA path on the node (use sparingly)
💡 For data that must survive pod restarts/rescheduling, you need a PersistentVolume via a PVC — plain volumes like emptyDir die with the pod.

Persistent Volumes (PV)

☸️ Kubernetes · Config & Storage · ★ Interview Topic · 9 min read

A PersistentVolume is a piece of cluster storage (an EBS volume, NFS share, disk) provisioned by an admin or dynamically by a StorageClass. It exists independently of any pod — the cluster-level storage resource.

The PV / PVC / Pod Relationship — Visual

Podmounts a PVC PersistentVolumeClaim"I need 10Gi RWO" PersistentVolumeactual disk (EBS/NFS) requests binds to

Key Concepts

  • Access modes: ReadWriteOnce (one node), ReadOnlyMany, ReadWriteMany, ReadWriteOncePod.
  • Reclaim policy: Retain (keep data), Delete (remove with PVC).
  • Static provisioning (admin pre-creates PVs) vs dynamic (StorageClass creates on demand).
apiVersion: v1 kind: PersistentVolume metadata: { name: pv-data } spec: capacity: { storage: 10Gi } accessModes: [ReadWriteOnce] persistentVolumeReclaimPolicy: Retain storageClassName: standard
💡 The abstraction (interview-ready): a PV is the supply (real storage), a PVC is the demand (a pod's request); Kubernetes binds them. Pods reference the PVC, never the PV directly — decoupling apps from infrastructure.

Persistent Volume Claims (PVC)

☸️ Kubernetes · Config & Storage · ★ Interview Topic · 7 min read

A PersistentVolumeClaim is a request for storage by a user/pod — specifying size, access mode, and (optionally) a StorageClass. Kubernetes binds the PVC to a matching PV (or dynamically provisions one).

Claim & Use

apiVersion: v1 kind: PersistentVolumeClaim metadata: { name: data-claim } spec: accessModes: [ReadWriteOnce] resources: { requests: { storage: 10Gi } } storageClassName: standard
# pod mounts the claim volumes: - name: data persistentVolumeClaim: { claimName: data-claim } volumeMounts: - { name: data, mountPath: /var/lib/data }

Binding Lifecycle

PVC states: PendingBound (matched to a PV) → Released (PVC deleted) → reclaimed per policy.

💡 With a StorageClass set, creating a PVC dynamically provisions the underlying PV automatically — no admin pre-provisioning needed. This is how StatefulSets give each replica its own persistent disk.

Storage Classes

☸️ Kubernetes · Config & Storage · 5 min read

A StorageClass defines a "class" of storage and enables dynamic provisioning — when a PVC requests this class, the matching volume (e.g. an AWS EBS gp3 disk) is created automatically.

apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: { name: fast } provisioner: ebs.csi.aws.com parameters: { type: gp3 } reclaimPolicy: Delete volumeBindingMode: WaitForFirstConsumer
  • provisioner — the CSI driver that creates the volume.
  • WaitForFirstConsumer — delays binding until a pod is scheduled, so the disk lands in the right AZ.
  • A cluster can have a default StorageClass used when a PVC omits one.
💡 StorageClasses let you offer tiers (fast SSD vs cheap HDD) and abstract the cloud — apps just ask for a class, not a specific disk type.

Resource Requests & Limits

☸️ Kubernetes · Scaling · 6 min read

Each container can declare CPU/memory requests (guaranteed minimum, used for scheduling) and limits (hard maximum). These drive scheduling, autoscaling, and stability.

resources: requests: { cpu: "250m", memory: "256Mi" } # scheduler reserves this limits: { cpu: "500m", memory: "512Mi" } # enforced ceiling

What Happens at the Limit

  • CPU over limit → throttled (slowed, not killed).
  • Memory over limit → container is OOMKilled (exit 137).

QoS Classes (from requests/limits)

ClassWhen
Guaranteedrequests == limits for all containers
Burstablerequests < limits
BestEffortnone set (evicted first under pressure)
💡 Requests are required for HPA and good scheduling. For the JVM, set -XX:MaxRAMPercentage so heap respects the container memory limit and avoids OOMKills.

Horizontal Pod Autoscaler (HPA)

☸️ Kubernetes · Scaling · ★ Interview Topic · 9 min read

The HPA automatically scales the number of pod replicas up or down based on observed metrics (CPU, memory, or custom). More load → more pods; less load → fewer. It's how K8s apps handle variable traffic.

The Control Loop — Visual

HPA controllertarget CPU 60% metrics-servercurrent CPU 85% scale 3 → 6 replicas ↑ load drops → scale down ↓

HPA Manifest

apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: { name: myapp-hpa } spec: scaleTargetRef: { apiVersion: apps/v1, kind: Deployment, name: myapp } minReplicas: 3 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: { type: Utilization, averageUtilization: 60 }
kubectl autoscale deployment myapp --cpu-percent=60 --min=3 --max=10 kubectl get hpa

How It Decides

desiredReplicas = ceil(currentReplicas × currentMetric / targetMetric). Requires metrics-server (or a custom metrics adapter) and resource requests set on pods.

💡 HPA scales pod count (horizontal); VPA scales pod size (vertical); Cluster Autoscaler scales node count. Interview favourite — know all three and that HPA needs metrics-server + CPU requests to work.

Vertical Pod Autoscaler (VPA)

☸️ Kubernetes · Scaling · 5 min read

The VPA automatically adjusts the CPU/memory requests & limits of pods based on actual usage — right-sizing them rather than adding more replicas.

Modes

  • Off — only recommends values.
  • Initial — sets resources at pod creation.
  • Auto/Recreate — evicts & recreates pods with new sizes.
⚠️ Don't use VPA and HPA on the same CPU/memory metric — they fight. Common pattern: HPA on CPU for scaling out, VPA recommendations to right-size requests.

Cluster Autoscaler

☸️ Kubernetes · Scaling · 5 min read

The Cluster Autoscaler adds or removes nodes in the cluster. When pods can't be scheduled (no capacity), it adds nodes; when nodes are underused, it drains and removes them.

The Three Autoscalers Together

AutoscalerScalesTrigger
HPAPod replicasCPU/mem/custom metrics
VPAPod resource sizesActual usage
Cluster AutoscalerNodesUnschedulable pods / idle nodes
💡 They compose: HPA adds pods → if no node has room, Cluster Autoscaler adds a node → the new pods schedule. On managed clusters (EKS/GKE/AKS) it integrates with node groups / Karpenter.

Rolling Updates

☸️ Kubernetes · Deployments & Health · ★ Interview Topic · 9 min read

A rolling update is the default Deployment strategy — it replaces old pods with new ones gradually, keeping the app available throughout (zero downtime). New pods are added and verified healthy before old ones are removed.

Gradual Replacement — Visual

start mid-rollout done v1 v1 v1 v2 ✓ v2 ✓ v1 v2 v2 v2 old pods removed only after new pods pass readiness — traffic never drops

Tuning the Rollout

spec: strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 # extra pods allowed above desired during update maxUnavailable: 0 # 0 = never drop below desired (safest)
kubectl set image deployment/myapp app=myapp:2.0 kubectl rollout status deployment/myapp kubectl rollout pause deployment/myapp # pause mid-rollout (canary-ish) kubectl rollout resume deployment/myapp
💡 maxSurge + maxUnavailable control speed vs availability. maxUnavailable: 0, maxSurge: 1 = safest (always full capacity). Readiness probes are essential — without them, traffic hits pods before they're ready.

Rollbacks

☸️ Kubernetes · Deployments & Health · ★ Interview Topic · 6 min read

If a new version is broken, you can roll back to a previous one instantly. Kubernetes keeps a revision history of a Deployment (the old ReplicaSets, scaled to 0), so reverting is just scaling the old ReplicaSet back up.

Rollback Commands

kubectl rollout history deployment/myapp # list revisions kubectl rollout history deployment/myapp --revision=2 kubectl rollout undo deployment/myapp # revert to previous kubectl rollout undo deployment/myapp --to-revision=2

How It Works

  • Each rollout creates a new ReplicaSet; old ones are retained (scaled to 0).
  • revisionHistoryLimit controls how many old ReplicaSets are kept (default 10).
  • Rollback scales the old ReplicaSet up and the current one down — another rolling update in reverse.
💡 Add --record or use kubernetes.io/change-cause annotations so rollout history shows why each revision happened — invaluable during incidents.

Health Checks

☸️ Kubernetes · Deployments & Health · 5 min read

Kubernetes uses probes to know whether a container is alive, ready for traffic, and finished starting. There are three probe types, each answering a different question.

ProbeQuestionOn failure
LivenessIs it alive?Restart the container
ReadinessCan it serve traffic?Remove from Service endpoints
StartupHas it finished booting?Kill if it never starts; gates the others

Probe Mechanisms

Each probe can use httpGet, tcpSocket, exec (command), or grpc.

💡 The classic interview distinction: liveness failing → restart; readiness failing → stop sending traffic (no restart). Confusing the two is a common mistake.

Liveness Probes

☸️ Kubernetes · Deployments & Health · ★ Interview Topic · 7 min read

A liveness probe answers "is this container still working?" If it fails (e.g. the app deadlocked), Kubernetes restarts the container — self-healing for hung processes that are running but stuck.

livenessProbe: httpGet: { path: /actuator/health/liveness, port: 8080 } initialDelaySeconds: 30 periodSeconds: 10 failureThreshold: 3 # 3 fails → restart

Key Guidance

  • Probe a lightweight liveness endpoint — not one that checks the DB (a DB outage shouldn't restart your app pointlessly).
  • Set a generous initialDelaySeconds/use a startup probe for slow JVM apps.
  • Too-aggressive liveness = restart loops; tune failureThreshold/periodSeconds.
⚠️ Don't make liveness depend on external systems. If liveness checks the database and the DB blips, every replica restarts simultaneously — turning a small outage into a full one. Use readiness for dependency checks.

Readiness Probes

☸️ Kubernetes · Deployments & Health · ★ Interview Topic · 7 min read

A readiness probe answers "is this container ready to receive traffic?" If it fails, the pod is removed from the Service's endpoints (no traffic) but not restarted — perfect for warm-up and temporary dependency loss.

readinessProbe: httpGet: { path: /actuator/health/readiness, port: 8080 } initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 3

Why It's Critical for Rollouts

  • During a rolling update, traffic only goes to pods that pass readiness — so users never hit a half-started pod.
  • A pod that loses a dependency can fail readiness (drop out of rotation) and rejoin when healthy — without a restart.
💡 Liveness vs Readiness in one line: liveness = restart when broken; readiness = stop traffic until ready. Spring Boot exposes both at /actuator/health/liveness and /readiness when probes are enabled.

Startup Probes

☸️ Kubernetes · Deployments & Health · 5 min read

A startup probe protects slow-starting containers. While it's running, liveness and readiness probes are disabled — so a JVM app that takes 60s to boot isn't killed by an impatient liveness probe.

startupProbe: httpGet: { path: /actuator/health, port: 8080 } failureThreshold: 30 periodSeconds: 5 # allows up to 150s to start
💡 Use a startup probe for legacy/JVM apps with long, variable boot times instead of inflating initialDelaySeconds on liveness. Once it passes once, normal liveness/readiness take over.

Scheduling

☸️ Kubernetes · Scheduling · 5 min read

Scheduling is how the kube-scheduler decides which node runs each new pod. It filters nodes that can't fit the pod, then scores the rest and picks the best.

The Two Phases

  • Filtering — eliminate nodes lacking resources or violating constraints (taints, affinity, node selectors).
  • Scoring — rank remaining nodes (spread, resource balance, affinity preferences) and pick the highest.

Influencing Placement

MechanismEffect
nodeSelectorSimple label match
Node AffinityRich rules (required/preferred)
Pod Affinity/Anti-affinityPlace near/away from other pods
Taints & TolerationsRepel pods unless they tolerate
💡 You declare constraints; the scheduler honours them. If no node satisfies the hard requirements, the pod stays Pending (and may trigger the Cluster Autoscaler).

Node Selectors

☸️ Kubernetes · Scheduling · 4 min read

The simplest way to constrain a pod to specific nodes: nodeSelector matches node labels. The pod only schedules onto nodes with all the listed labels.

# label a node kubectl label node node-1 disktype=ssd # require it in the pod spec spec: nodeSelector: disktype: ssd
💡 nodeSelector is all-or-nothing equality. For "preferred" rules, OR conditions, or anti-affinity, use the more expressive Node Affinity instead.

Node Affinity

☸️ Kubernetes · Scheduling · ★ Interview Topic · 8 min read

Node Affinity is an expressive way to constrain which nodes a pod can run on, based on node labels — supporting required (hard) and preferred (soft) rules, plus rich operators (In, NotIn, Exists).

Hard vs Soft — Visual

Podwants zone=us-east-1a (pref) required: gpu=truemust match (else Pending) preferred: zone=us-east-1anice-to-have (weighted)

Manifest

affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: # hard nodeSelectorTerms: - matchExpressions: - { key: gpu, operator: In, values: ["true"] } preferredDuringSchedulingIgnoredDuringExecution: # soft - weight: 50 preference: matchExpressions: - { key: zone, operator: In, values: ["us-east-1a"] }
💡 "requiredDuringScheduling" = must be satisfied to schedule. "preferredDuringScheduling" = best effort. "IgnoredDuringExecution" means already-running pods aren't evicted if labels later change. Node affinity attracts pods to nodes; taints repel them — they're complementary.

Pod Affinity & Anti-Affinity

☸️ Kubernetes · Scheduling · 6 min read

Pod (anti-)affinity places pods relative to other pods rather than nodes — "co-locate with" (affinity) or "keep apart from" (anti-affinity), using a topology key like node or zone.

affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: { app: myapp } topologyKey: kubernetes.io/hostname # spread replicas across nodes

Typical Uses

  • Anti-affinity — spread replicas across nodes/zones for high availability.
  • Affinity — co-locate a cache with the app that uses it to reduce latency.
💡 For simple "spread my replicas evenly", modern K8s prefers topologySpreadConstraints over pod anti-affinity — it's lighter and more flexible.

Taints & Tolerations

☸️ Kubernetes · Scheduling · ★ Interview Topic · 8 min read

Taints and tolerations work together to repel pods from nodes unless the pod explicitly tolerates the taint. It's the inverse of affinity: affinity attracts pods to nodes; taints keep pods off nodes — used to dedicate nodes (GPU, special hardware) or keep workloads off control-plane nodes.

How They Pair — Visual

Tainted Nodegpu=true:NoSchedulerepels normal pods 🚫 Pod with tolerationtolerates gpu=true ✓ Pod without tolerationcannot land here allowed blocked

Applying Them

# taint a node (repel pods) kubectl taint nodes gpu-node gpu=true:NoSchedule
# pod tolerates it (allowed onto the node) tolerations: - key: "gpu" operator: "Equal" value: "true" effect: "NoSchedule"

Taint Effects

EffectMeaning
NoScheduleNew non-tolerating pods won't schedule
PreferNoScheduleAvoid if possible (soft)
NoExecuteAlso evicts existing non-tolerating pods
💡 Key distinction: a toleration alone doesn't force a pod onto a tainted node — it only permits it. To actively attract the pod there too, combine tolerations with node affinity. Control-plane nodes are tainted by default to keep your workloads off them.

RBAC (Role-Based Access Control)

☸️ Kubernetes · Security · ★ Interview Topic · 9 min read

RBAC controls who can do what on which resources in the cluster. It binds subjects (users, groups, service accounts) to roles (sets of permissions) — the foundation of cluster security and least privilege.

The Four Objects — Visual

Subjectuser / group / SA RoleBindinglinks subject → role Rolenamespaced verbs ClusterRolecluster-wide verbs

Role + RoleBinding

# a Role: read pods in namespace "dev" kind: Role metadata: { namespace: dev, name: pod-reader } rules: - apiGroups: [""] resources: ["pods"] verbs: ["get","list","watch"] --- # bind it to a user kind: RoleBinding metadata: { namespace: dev, name: read-pods } subjects: - { kind: User, name: alice, apiGroup: rbac.authorization.k8s.io } roleRef: { kind: Role, name: pod-reader, apiGroup: rbac.authorization.k8s.io }

Role vs ClusterRole

Scope
Role + RoleBindingA single namespace
ClusterRole + ClusterRoleBindingWhole cluster (or cluster-scoped resources)
kubectl auth can-i delete pods --as alice -n dev # test permissions
💡 RBAC is additive and deny-by-default — there are no "deny" rules; you only grant. Follow least privilege: prefer namespaced Roles, bind to ServiceAccounts for apps, and avoid cluster-admin.

Service Accounts

☸️ Kubernetes · Security · 5 min read

A ServiceAccount is an identity for pods (machine identity), as opposed to user accounts for humans. Pods use it to authenticate to the Kubernetes API and (via cloud integration) to cloud services.

apiVersion: v1 kind: ServiceAccount metadata: { name: myapp-sa, namespace: dev } --- spec: # in the pod serviceAccountName: myapp-sa
  • Each namespace has a default SA; assign a dedicated one per app for least privilege.
  • Bind RBAC Roles to the SA to control what the pod's code can do via the API.
  • Cloud IAM integration: IRSA (EKS), Workload Identity (GKE), Workload Identity (AKS) map SAs to cloud roles.
💡 ServiceAccount = pod identity; (human) User = people. Combine SA + RBAC + cloud workload identity so a pod gets exactly the cluster and cloud permissions it needs — no static keys.

Security Contexts

☸️ Kubernetes · Security · 5 min read

A securityContext sets privilege and access controls for a pod or container — run as non-root, drop Linux capabilities, read-only filesystem, etc.

securityContext: runAsNonRoot: true runAsUser: 1001 allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"]
💡 These settings are your container-hardening checklist. Combined with Pod Security Standards, they enforce that workloads can't run as root or escalate privileges.

Pod Security Standards

☸️ Kubernetes · Security · 5 min read

Pod Security Standards (PSS) define three policy levels enforced by the built-in Pod Security Admission controller — replacing the deprecated PodSecurityPolicy.

LevelMeaning
PrivilegedUnrestricted (trusted system workloads)
BaselinePrevents known privilege escalations
RestrictedHardened best practice (non-root, no caps…)
# enforce a level per namespace via labels kubectl label namespace prod \ pod-security.kubernetes.io/enforce=restricted
💡 Set namespaces to enforce=restricted (with warn/audit for visibility) to block insecure pods at admission time — defense in depth alongside securityContext.

Kubernetes Secrets Management

☸️ Kubernetes · Security · 6 min read

Native Secrets are base64-encoded, not encrypted by default. Production secret management adds encryption, rotation, and external sources.

Hardening & External Options

  • Encryption at rest — enable etcd encryption (or a KMS provider) so Secrets aren't plaintext in etcd.
  • RBAC — tightly restrict who/what can read Secrets.
  • External Secrets Operator — sync from Vault / AWS Secrets Manager / GCP / Azure into K8s Secrets.
  • Secrets Store CSI Driver — mount secrets directly from an external store as files.
  • Sealed Secrets — encrypt secrets so they're safe to commit to Git (GitOps).
⚠️ Never commit raw Secret manifests to Git — the values are only base64, trivially decoded. Use Sealed Secrets or an external store with the CSI driver / External Secrets Operator.

Logging in Kubernetes

☸️ Kubernetes · Observability · ★ Interview Topic · 8 min read

Pods are ephemeral, so their logs vanish when they die. Production logging means shipping logs off the node to a central store. The standard pattern: apps log to stdout/stderr → a node agent collects → a backend aggregates & indexes.

The Logging Pipeline — Visual

Pods→ stdout/stderr Node agentFluent Bit (DaemonSet) StoreLoki / Elasticsearch UIGrafana/Kibana

Key Points

  • 12-factor logging — apps write to stdout/stderr, never to files inside the container.
  • Node-level agent — Fluent Bit/Fluentd runs as a DaemonSet (one per node) and tails container logs.
  • Backends — EFK (Elasticsearch-Fluentd-Kibana) or PLG (Promtail-Loki-Grafana).
  • kubectl logs only shows current/recent logs from a live pod — fine for debugging, not for retention.
kubectl logs <pod> -c <container> --tail=100 -f kubectl logs <pod> --previous # logs from the crashed instance
💡 Interview answer: K8s has no built-in log storage — you deploy a logging stack (EFK/PLG) where a DaemonSet agent ships each node's container logs to a central, searchable backend.

Monitoring with Prometheus

☸️ Kubernetes · Observability · ★ Interview Topic · 8 min read

Prometheus is the de-facto monitoring system for Kubernetes — a time-series database that pulls (scrapes) metrics from targets, stores them, and lets you query (PromQL) and alert on them.

Pull-Based Monitoring — Visual

Prometheusscrapes /metrics · stores TSDB App /actuator/prometheusexposes metrics node-exporternode metrics kube-state-metricsobject state pull every 15s

The Ecosystem

ComponentRole
PrometheusScrapes & stores metrics; PromQL queries
node-exporterNode-level metrics (CPU, mem, disk)
kube-state-metricsMetrics about K8s objects (deployments, pods)
AlertmanagerRoutes alerts (Slack, PagerDuty, email)
GrafanaDashboards on top of Prometheus
# Spring Boot exposes Prometheus metrics via Actuator + Micrometer management.endpoints.web.exposure.include=health,prometheus # scraped at /actuator/prometheus
💡 Key concept: Prometheus is pull-based (it scrapes targets), not push. Install the whole stack easily with the kube-prometheus-stack Helm chart (Prometheus + Grafana + Alertmanager + exporters).

Grafana Integration

☸️ Kubernetes · Observability · 4 min read

Grafana is the visualization layer — it queries data sources (Prometheus, Loki) and renders dashboards and alerts. It turns raw metrics into the graphs teams watch.

  • Add Prometheus as a data source; build panels with PromQL.
  • Import community dashboards (e.g. "Kubernetes cluster monitoring" by ID).
  • Use Loki as a data source to correlate logs with metrics in one place.
💡 The standard observability stack: Prometheus (metrics) + Loki (logs) + Grafana (dashboards) + Alertmanager (alerts) — all installable via the kube-prometheus-stack chart.

Kubernetes Dashboard

☸️ Kubernetes · Observability · 4 min read

The Kubernetes Dashboard is a general-purpose web UI for the cluster — view workloads, drill into pods, see logs, and do basic management without the CLI.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/.../recommended.yaml kubectl proxy # then open the dashboard via the proxy URL
⚠️ Secure it carefully — an over-permissioned dashboard is a known attack vector. Use RBAC, never expose it publicly, and prefer read-only access. Many teams use Lens/k9s or cloud consoles instead.

Observability in Kubernetes

☸️ Kubernetes · Observability · 5 min read

Observability = understanding system state from its outputs, built on three pillars: metrics, logs, and traces.

PillarAnswersTools
MetricsWhat is happening (rates, saturation)Prometheus + Grafana
LogsWhat happened (events, errors)Loki / EFK
TracesWhere time went (request path)Jaeger / Tempo (OpenTelemetry)
💡 Use the RED method (Rate, Errors, Duration) for services and USE (Utilization, Saturation, Errors) for resources. OpenTelemetry is the emerging standard for instrumenting all three pillars consistently.

kubectl Commands

☸️ Kubernetes · Tooling · 6 min read

kubectl is the CLI for talking to the cluster's API server. Here's the everyday toolkit.

Viewing & Describing

kubectl get pods,svc,deploy -n dev kubectl get pods -o wide -w # wide + watch kubectl describe pod <pod> # events & details kubectl logs -f <pod> --previous kubectl top pods # resource usage

Creating & Editing

kubectl apply -f manifest.yaml # declarative (preferred) kubectl edit deployment myapp kubectl scale deployment myapp --replicas=5 kubectl set image deployment/myapp app=myapp:2.0 kubectl delete -f manifest.yaml

Debugging

kubectl exec -it <pod> -- sh kubectl port-forward svc/myapp 8080:80 kubectl get events --sort-by=.lastTimestamp kubectl explain deployment.spec # schema docs
💡 Prefer declarative kubectl apply -f (GitOps-friendly) over imperative create/run. Add -o yaml --dry-run=client to generate manifests from imperative commands.

Helm Charts

☸️ Kubernetes · Tooling · ★ Interview Topic · 9 min read

Helm is the package manager for Kubernetes. A Chart bundles all the manifests for an app into a versioned, templated, reusable package — so you install complex apps with one command and configure them per environment via values.

Chart → Release — Visual

Charttemplates + values.yaml helm installrender templates + values Releaselive K8s objects (versioned) one chart → many releases (dev/staging/prod) via different values

Core Concepts

TermMeaning
ChartA package of templated K8s manifests
ValuesConfig inputs (values.yaml) injected into templates
ReleaseAn installed instance of a chart in a cluster
RepositoryA collection of charts (e.g. Bitnami)

Commands

helm repo add bitnami https://charts.bitnami.com/bitnami helm install myrelease bitnami/postgresql -f values-prod.yaml helm upgrade myrelease ./mychart --set replicaCount=5 helm rollback myrelease 1 # revert to revision 1 helm list helm uninstall myrelease
💡 Why Helm: it templates manifests (DRY across environments), versions releases (easy rollback), and packages dependencies. Interview answer: "Helm is to Kubernetes what apt/npm is to packages — templated, versioned, repeatable deployments."

Operators

☸️ Kubernetes · Extensibility · 5 min read

An Operator extends Kubernetes to manage a complex stateful app (a database, Kafka) by encoding human operational knowledge into software — a custom controller that watches a CRD and reconciles the app's desired state (backups, failover, upgrades).

Pattern

  • CRD defines a new resource type (e.g. kind: PostgresCluster).
  • Custom controller watches it and acts (provision, scale, back up, recover).
  • You manage the app declaratively, like any native K8s object.
💡 Operator = CRD + custom controller. It automates "day-2 operations" (upgrades, backups, failover) that a human SRE would otherwise do manually. See OperatorHub for ready-made ones.

Custom Resource Definitions (CRDs)

☸️ Kubernetes · Extensibility · 5 min read

A CRD lets you extend the Kubernetes API with your own resource types. Once defined, your custom resource behaves like a built-in one — created with kubectl apply, stored in etcd, watched by controllers.

apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: { name: backups.example.com } spec: group: example.com names: { kind: Backup, plural: backups } scope: Namespaced versions: [ { name: v1, served: true, storage: true, schema: {...} } ]
kubectl get crds kubectl get backups # your new resource type
💡 CRDs are how the ecosystem extends K8s (Istio, Argo, Prometheus all add CRDs). Combined with a controller, they form an Operator.

Kubernetes API

☸️ Kubernetes · Extensibility · 5 min read

The Kubernetes API (served by kube-apiserver) is the central interface to everything — kubectl, controllers, and your code all talk to it. It's a RESTful API over resources grouped into API groups and versions.

  • Declarative — you POST/PATCH desired state; controllers reconcile.
  • Versioned groupsapps/v1, batch/v1, networking.k8s.io/v1.
  • Watch — clients stream changes (the basis of controllers).
  • Access it with client libraries (client-go, fabric8 for Java) or kubectl.
kubectl api-resources # list all resource types kubectl api-versions # list API groups/versions kubectl proxy # local proxy to the API
💡 Everything in K8s is an API object reconciled by a controller. Understanding "the API is the contract; controllers make it real" demystifies the whole system.

Container Runtime

☸️ Kubernetes · Extensibility · 5 min read

The container runtime is the software on each node that actually runs containers. The kubelet talks to it through the Container Runtime Interface (CRI), so any CRI-compliant runtime works.

Runtimes

RuntimeNotes
containerdMost common; graduated CNCF project
CRI-OLightweight, built for K8s (OpenShift default)
Docker EngineRemoved as a runtime in v1.24 (dockershim) — images still work
💡 The CRI decouples K8s from any single runtime. runc (the low-level OCI runtime) does the actual container creation underneath containerd/CRI-O.

Docker vs Containerd

☸️ Kubernetes · Extensibility · 5 min read

A common point of confusion. Docker is a full platform (CLI, build, API) built on top of containerd. Kubernetes only needs the runtime part, so it uses containerd directly.

Dockercontainerd
ScopeFull platform (build, CLI, runtime)Core runtime only
CRI-compatibleNo (needed dockershim)Yes (native)
Use in K8sRemoved in v1.24Default runtime
⚠️ "Kubernetes deprecated Docker" = it dropped the Docker runtime shim, not Docker images. Docker-built (OCI) images run perfectly on containerd. You still use Docker to build images.

Kubernetes Deployment Strategies

☸️ Kubernetes · Deployment Strategies · 6 min read

How you roll out a new version trades off speed, risk, and cost. The main strategies:

StrategyHowTrade-off
RecreateKill all old, start all newDowntime; simplest
Rolling UpdateReplace gradually (default)Zero downtime; two versions briefly coexist
Blue-GreenTwo full envs, switch trafficInstant cutover/rollback; 2× resources
CanarySmall % to new version firstLowest risk; needs traffic control
💡 Native Deployments give you Recreate and RollingUpdate. Blue-green and canary need extra tooling (Argo Rollouts, Flagger, or a service mesh) for traffic shifting.

Blue-Green Deployment

☸️ Kubernetes · Deployment Strategies · 5 min read

Run two identical environments — Blue (current) and Green (new). Deploy & test Green while Blue serves traffic, then flip the Service to Green in one switch. Roll back instantly by flipping back.

Service Blue v1 (live) Green v2 (tested) flip selector →instant cutover

In K8s, switch by updating the Service's selector (e.g. version: v2) to point at the Green pods.

💡 Pros: instant rollback, no version mixing. Cons: needs double the resources during the switch. Great for releases that can't tolerate two versions running at once.

Canary Deployment

☸️ Kubernetes · Deployment Strategies · 5 min read

Release the new version to a small subset of users/traffic first (e.g. 5%), watch metrics, then gradually ramp to 100% if healthy — or roll back if errors spike. Lowest-risk strategy.

Traffic v1 — 95% v2 canary — 5% → ramp up
💡 Implemented with Argo Rollouts, Flagger, or a service mesh (Istio) that splits traffic by weight and can auto-promote/rollback based on metrics. The safest way to ship risky changes.

GitOps

☸️ Kubernetes · Deployment Strategies · 5 min read

GitOps makes Git the single source of truth for cluster state. You commit declarative manifests; an in-cluster agent (Argo CD, Flux) continuously syncs the cluster to match Git — and corrects any drift.

Principles

  • Declarative — entire system described in Git.
  • Versioned & auditable — every change is a commit/PR.
  • Pulled automatically — agent applies Git → cluster (no manual kubectl apply).
  • Self-healing — drift is reverted to match Git.
💡 Deploy = merge a PR. Rollback = git revert. Tools: Argo CD (UI-driven) and Flux (GitOps toolkit). GitOps + Helm/Kustomize is the modern K8s delivery standard.

CI/CD with Kubernetes

☸️ Kubernetes · Deployment Strategies · 6 min read

A typical pipeline builds and tests a container image (CI), then deploys it to the cluster (CD) — increasingly via GitOps.

# CI: build → test → scan → push image docker build -t registry/myapp:$SHA . docker push registry/myapp:$SHA # CD option A — imperative kubectl set image deployment/myapp app=registry/myapp:$SHA # CD option B — GitOps (preferred) # bump the image tag in the manifests repo → Argo CD syncs it

Pipeline Stages

  • CI — build image, run tests, scan for CVEs, push to registry (tag = git SHA).
  • CD — update manifests & apply (or let Argo CD/Flux pull).
  • Progressive delivery — canary/blue-green via Argo Rollouts.
💡 Best practice: build once with an immutable SHA tag, then promote that exact image dev→staging→prod by updating manifests in Git — never rebuild per environment.

Managed Kubernetes (EKS / AKS / GKE)

☸️ Kubernetes · Managed & Operations · ★ Interview Topic · 9 min read

Running your own control plane is hard (etcd, HA, upgrades, security). Managed Kubernetes services run the control plane for you — you just manage workloads and (usually) worker nodes. The big three: EKS (AWS), AKS (Azure), GKE (Google).

Managed vs Self-Managed — Visual

Control Planemanaged by cloud (SLA, HA, upgrades) Worker Nodesyou (or managed node groups / Fargate / Autopilot) You focus on:workloads · scaling policiesnetworking & IAM integrationobservability & cost

The Big Three

EKS (AWS)AKS (Azure)GKE (Google)
Pod IAMIRSA / Pod IdentityWorkload IdentityWorkload Identity
Serverless nodesFargateVirtual Nodes (ACI)Autopilot
Node autoscaleKarpenter / CACluster AutoscalerBuilt-in (often best)
OriginGoogle created K8s

EKS Quick Flow

eksctl create cluster --name prod --nodes 3 --region us-east-1 aws eks update-kubeconfig --name prod # wire up kubectl kubectl get nodes
💡 They all run upstream Kubernetes — your manifests are portable across them. The differences are integration (IAM/identity, load balancers, autoscaling, serverless nodes). GKE is often considered the most "batteries-included"; EKS the most common in enterprises.

Kubernetes on Azure (AKS)

☸️ Kubernetes · Managed & Operations · 4 min read

Azure Kubernetes Service is Microsoft's managed K8s — free managed control plane, deep Azure integration (Entra ID, Azure Monitor, ACR).

az aks create -g myRG -n myAKS --node-count 3 --enable-managed-identity az aks get-credentials -g myRG -n myAKS kubectl get nodes
  • Workload Identity maps K8s ServiceAccounts to Entra ID for keyless Azure access.
  • Integrates with Azure Monitor / Container Insights, ACR, and Azure CNI.
  • Virtual Nodes (ACI) for serverless burst capacity.
💡 See Managed Kubernetes (EKS/AKS/GKE) for the full comparison. Manifests are portable; only the cloud integration differs.

Kubernetes on GCP (GKE)

☸️ Kubernetes · Managed & Operations · 4 min read

Google Kubernetes Engine is the most mature managed K8s (Google created Kubernetes). Known for strong autoscaling and the fully-managed Autopilot mode.

gcloud container clusters create-auto prod --region us-central1 gcloud container clusters get-credentials prod --region us-central1 kubectl get nodes
  • Autopilot — Google manages nodes too; you pay per pod resource, not per node.
  • Excellent built-in autoscaling, networking, and release channels.
  • Workload Identity for keyless access to Google Cloud APIs.
💡 GKE Autopilot is the closest to "serverless Kubernetes" — no node management at all. See the EKS/AKS/GKE comparison topic for the side-by-side.

Troubleshooting Kubernetes Clusters

☸️ Kubernetes · Managed & Operations · ★ Interview Topic · 10 min read

A systematic approach to the most common K8s failures. Start broad (get), narrow down (describe → events), then inspect (logs/exec).

The Debug Workflow — Visual

get podswhat state? describe podevents / why logsapp errors exec / eventsdig deeper

Common Pod States & Causes

SymptomLikely cause & fix
ImagePullBackOffBad image name/tag or registry auth → check image & imagePullSecrets
CrashLoopBackOffApp crashes on start → logs --previous; check config/env, liveness probe
PendingNo node fits → resources, taints, affinity, PVC unbound → describe pod
OOMKilled (137)Memory limit too low / leak → raise limit, tune JVM heap
CreateContainerConfigErrorMissing ConfigMap/Secret referenced
Service unreachableSelector/label mismatch, wrong targetPort, no ready endpoints

Command Toolkit

kubectl get pods -o wide kubectl describe pod <pod> # Events section at the bottom! kubectl logs <pod> --previous # logs from last crash kubectl get events --sort-by=.lastTimestamp kubectl get endpoints <svc> # does the Service have ready pods? kubectl exec -it <pod> -- sh kubectl top pods # resource pressure
💡 90% of issues are solved by kubectl describe pod (read the Events) and kubectl logs --previous. For Service issues, always check kubectl get endpoints — empty endpoints = selector/readiness problem.

Cluster Upgrades

☸️ Kubernetes · Managed & Operations · 5 min read

Kubernetes releases ~3 times a year and supports only the latest few versions, so clusters need regular upgrades. Order matters: control plane first, then nodes.

Process

  1. Upgrade the control plane (one minor version at a time).
  2. Upgrade node pools — cordon & drain each node, replace, repeat.
  3. Check deprecated APIs (kubectl deprecations / pluto) before upgrading.
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data # upgrade/replace the node, then kubectl uncordon <node>
💡 On managed clusters (EKS/AKS/GKE) upgrades are largely automated via node-pool rolling replacement. Always check for removed APIs first — that's the most common upgrade breakage.

Backup & Disaster Recovery

☸️ Kubernetes · Managed & Operations · 5 min read

DR for K8s means protecting two things: cluster state (etcd / API objects) and persistent data (volumes).

  • etcd snapshots — back up the control plane's state store (self-managed clusters).
  • Velero — back up/restore K8s objects + PV snapshots; supports cross-cluster migration.
  • Volume snapshots — via CSI for persistent data.
  • GitOps — manifests in Git are themselves a backup of desired state; rebuild a cluster from Git.
velero backup create prod-backup --include-namespaces prod velero restore create --from-backup prod-backup
💡 GitOps + Velero is the common combo: Git restores your config, Velero restores state & data. Test restores regularly — an untested backup isn't a backup.

High Availability (HA) Clusters

☸️ Kubernetes · Managed & Operations · 5 min read

An HA cluster removes single points of failure so the cluster keeps working through node/zone failures.

HA Building Blocks

  • Multiple control-plane nodes (3 or 5) with a quorum etcd.
  • Multi-AZ worker nodes so a zone outage doesn't take everything down.
  • Spread workloads — pod anti-affinity / topologySpreadConstraints + PodDisruptionBudgets.
  • ≥2 replicas per service, behind a Service/Ingress.
# PodDisruptionBudget keeps minimum availability during drains/upgrades kind: PodDisruptionBudget spec: { minAvailable: 2, selector: { matchLabels: { app: myapp } } }
💡 Managed services run the control plane HA for you across AZs. Your job: spread workloads across zones, run multiple replicas, and set PodDisruptionBudgets so upgrades don't drop you below capacity.

Service Mesh (Istio)

☸️ Kubernetes · Managed & Operations · 6 min read

A service mesh adds a networking layer for service-to-service communication — handling traffic management, security (mTLS), and observability without changing app code, via sidecar proxies (Envoy) injected next to each pod.

What Istio Provides

  • Traffic management — fine-grained routing, canary/weighted splits, retries, timeouts.
  • Security — automatic mutual TLS between services, authz policies.
  • Observability — metrics, traces, and a service-dependency map for free.
⚠️ A mesh adds real complexity and resource overhead (a sidecar per pod). Adopt it when you genuinely need mTLS, advanced traffic shifting, or deep observability across many services — not by default. Lighter options: Linkerd, or Istio's ambient (sidecar-less) mode.

Kubernetes Best Practices

☸️ Kubernetes · Managed & Operations · 6 min read

✓ Do

  • Set resource requests & limits on every container
  • Define liveness, readiness & startup probes
  • Run as non-root with a securityContext
  • Use namespaces + RBAC + least privilege
  • Externalize config (ConfigMaps/Secrets)
  • ≥2 replicas + anti-affinity + PodDisruptionBudgets
  • Pin image tags (git SHA); manage via GitOps/Helm

✗ Avoid

  • latest image tags
  • Running as root / privileged
  • No probes (broken pods get traffic)
  • Storing state in pods (use PVCs)
  • Secrets in plain manifests in Git
  • One giant namespace for everything
  • Manual kubectl changes in prod (drift)
💡 The recurring theme: declarative, reproducible, least-privilege, observable, resilient. Almost every best practice maps to one of those five.

Production-Grade Kubernetes Deployments

☸️ Kubernetes · Managed & Operations · 7 min read

A consolidated checklist of what "production-ready" means — tying the whole tutorial together.

Reliability

≥2 replicas · multi-AZ spread · probes · PodDisruptionBudgets · rolling updates · autoscaling (HPA + Cluster Autoscaler).

Resources

Requests & limits on all containers · right-sized · QoS Guaranteed for critical apps.

Security

RBAC least privilege · non-root securityContext · NetworkPolicies · Pod Security restricted · encrypted Secrets.

Observability

Prometheus + Grafana metrics · centralized logging (Loki/EFK) · tracing · alerting.

Delivery

CI builds + scans · immutable SHA tags · GitOps (Argo/Flux) · progressive delivery (canary).

Operations

Backups (Velero + etcd) · tested DR · upgrade plan · managed control plane (EKS/AKS/GKE).

💡 Production-ready in one line: declarative GitOps delivery of least-privilege, resource-bounded, probe-guarded, multi-replica workloads — fully observable and backed up, on a managed HA control plane.