Kubernetes from Basics to Practice: Core Concepts in Plain English
K8s documentation can feel impenetrable, but its core concepts are not complicated. This guide explains in plain English what Pod, Deployment, Service, and Ingress do, how they work together to run a web application, hands-on practice with kind/minikube, and when you really do or do not need K8s.
Key Points
- Topic Focus: DevOps
- Suitable for: indie hackers, full-stack engineers, AI application developers
- Core value: quickly understand background, practical paths, common pitfalls, and engineering advice
Kubernetes from Basics to Practice: Core Concepts in Plain English
Open the official documentation and Controller, Reconcile, CRD, CNI, CSI... all hit you at once. Most people give up by page three. But honestly, K8s's core concepts are far simpler than they look. You only need to work out "what problems must be solved to run a web application across multiple machines"; the rest is just mapping those problems to terminology.
This article does not cover everything. It focuses on the 20% developers truly need to understand and walks you through running an application locally.
1. What Problem Does K8s Actually Solve?
Before discussing concepts, imagine this scenario: you wrote a web service, and it runs perfectly well in Docker. One day traffic arrives. You need to scale it to three instances, automatically restart one if it fails, deploy upgrades without downtime, keep configuration out of the image, and expose it through a domain name.
You could cobble all this together yourself with docker run + nginx + a pile of shell scripts, but it falls apart at scale. K8s is a system dedicated to handling these container-related chores. The industry calls it "container orchestration"; in plain terms:
- Multi-node deployment: Schedule containers across a group of machines, placing each one wherever sufficient resources are available
- Scaling: Change the instance count from 3 to 30 with one command or one metric
- Self-healing: If a container fails or a machine goes down, automatically start it again elsewhere
- Rolling updates: Roll out a new version gradually, replacing instances one at a time without downtime
- Configuration/secret management: Decouple configuration from images so the same image can run in dev/staging/prod
Taken together, these capabilities are the value of K8s. It is not about "making Docker run better on one machine"; it is about "managing a hundred machines as if they were one."
2. Core Objects in Plain English
Everything in K8s is an "object" represented by declarative YAML. You tell the system "the state I want," and it makes the current state match. There are only a handful of core objects. Here is an analogy based on a company's organizational structure:
Pod (like a pea pod) - the smallest runtime unit. Note that it is not a container. A Pod is the smallest unit K8s schedules, and it can contain one or more tightly coupled containers that share networking and storage. In 99% of cases, a Pod contains one container, so you can roughly think of a Pod as "a container instance managed by K8s." However, it has its own IP, which all containers inside the Pod share.
Deployment - the Pod manager. You rarely create Pods directly. Instead, you write a Deployment and tell it, "I want three replicas of this Pod." It maintains that number for you, creating replacements when there are too few and terminating extras when there are too many. It also handles rolling updates and rollbacks. A Deployment is like a foreman who constantly watches the replica count.
Service - the Pod's stable street address. Pods die and are recreated, and their IP changes after every restart, so you cannot access them reliably by IP. A Service places a fixed name and IP in front of a group of Pods and also provides load balancing. You access the Service, and it automatically forwards traffic to one of the healthy Pods behind it.
Ingress - the cluster's front door. Services are internal to the cluster by default. To allow external clients such as browsers to access them through a domain name, something must receive traffic on ports 80/443 and route it to the appropriate Service based on the domain. That is Ingress. You can think of it as nginx for the cluster.
ConfigMap / Secret - configuration and secrets. These extract configuration files and environment variables from the image and mount them into a Pod as files or env values. Secret works like ConfigMap, except its data is base64-encoded and it semantically indicates "this is sensitive data." Do not treat that as encryption; production environments should still use KMS or an external secret manager.
Remember these five plus Secret/ConfigMap, and you can already handle 80% of everyday work. Learn advanced features such as CRD, Operator, and scheduling policies when you actually need them.
3. How They Work Together
In one sentence: a request enters from outside and first hits Ingress; Ingress sends it to a Service based on the domain name; Service then load-balances it across the Pods managed by a Deployment.
Here is the journey of a single HTTP request:
Browser → Ingress Controller (cluster gateway, 80/443)
→ Match an Ingress rule by domain name
→ Forward to Service (a virtual IP + domain name)
→ Service uses a label selector to find all matching Pods
→ Load-balance to one of those Pods
→ The container inside the Pod handles the request
Meanwhile, the Deployment continuously watches the replica count in the background. If a Pod fails, it starts another one to replace it, with no externally visible disruption. ConfigMap and Secret are mounted at startup, so the container reads the configuration for the current environment.
Once this diagram clicks in your head, you can match every subsequent YAML file to the corresponding role.
4. Hands-on Locally: Run an Application in Five Minutes
Do not wait until production for your first encounter with K8s. You have two options locally; choose either one:
- kind (Kubernetes in Docker): Uses Docker containers to simulate K8s nodes. It starts quickly, uses few resources, and is my top recommendation for individuals
- minikube: A mature, full-featured option, but slightly heavier than kind
Once installed, kubectl is your only remote control. The following example deploys nginx.
First, create deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3 # I want 3 replicas
selector:
matchLabels:
app: my-app # Deployment uses this label to find the Pods it manages
template: # Pod template
metadata:
labels:
app: my-app # Give the Pod the same label (critical!)
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests: { cpu: 100m, memory: 128Mi }
limits: { cpu: 500m, memory: 256Mi }
Then create service.yaml to give these Pods a stable entry point:
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
selector:
app: my-app # Also uses the label to find Pods
ports:
- port: 80 # Port exposed by the Service
targetPort: 80 # Forward to the container port
type: ClusterIP # Default type; reachable inside the cluster
Two commands are all you need:
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl get pods # You should see 3 Running Pods
kubectl get svc my-app # See the cluster IP assigned to the Service
Want to access it from your local browser? For local development, port-forward is the fastest option:
kubectl port-forward svc/my-app 8080:80
# Open http://localhost:8080
When you need domain-based access in production, add an Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 80
See the pattern? Each object handles one responsibility, and labels connect them. When selector and labels match, traffic reaches the right place. This is K8s's most important "wiring" mechanism.
5. Everyday kubectl Operations (Just Memorize Them)
You will use these commands every day. Practice them until they become muscle memory:
# Check status
kubectl get pods / deployments / svc / ingress
kubectl get pods -o wide # Include IPs and nodes
kubectl describe pod <name> # Essential for troubleshooting; shows events and status
# View logs / enter a container
kubectl logs <pod> # View logs
kubectl logs -f <pod> --tail=100 # Follow the last 100 lines in real time
kubectl exec -it <pod> -- sh # Enter the container and run commands
# Scale (in seconds)
kubectl scale deployment my-app --replicas=5
# Rolling update: changing the image is enough
kubectl set image deployment/my-app nginx=nginx:1.28
kubectl rollout status deployment/my-app # Check progress
# Roll back (a lifesaver when something goes wrong)
kubectl rollout undo deployment/my-app
kubectl rollout history deployment/my-app # View revision history
Remember one principle: if it can be described in yaml, do not type an imperative command. Imperative operations such as kubectl create are only suitable for temporary experiments. In formal environments, always use kubectl apply -f, keep the files under version control, and you will have a smooth path to GitOps, where CI/CD pushes yaml.
6. When to Use K8s and When Not To
This is important because K8s is not a silver bullet. It is a technical choice with significant operational costs.
Use it when:
- You have multiple services, languages, and teams that need a unified foundation for deployment and governance
- You genuinely need multi-node deployment and high availability across availability zones
- Traffic fluctuates significantly and you need metric-based automatic scaling
- Someone on the team can maintain it continuously, because the K8s cluster itself needs patching, upgrades, and monitoring
Do not use it when (do not make life harder for yourself):
- You have a small project with one monolithic application and one database that
docker composecan handle in five lines of configuration - You have a small team with no DevOps capacity, and a PaaS such as Render, Fly, Alibaba Cloud SAE, or Vercel can solve 90% of the problem
- You have no multi-node requirement at all, and one or two ECS instances are enough
I have seen far too many teams adopt K8s because it "looks advanced," only to have nobody maintain it. The version stays stuck at 1.2x because no one dares touch it; certificates expire, etcd fails, and the CNI network becomes flaky... The complexity of K8s is borrowed debt, and sooner or later you must repay it.
A simple rule: if docker compose has started to hurt because, for example, you need multiple machines, automatic scaling, or zero-downtime updates, then seriously consider K8s. Before that point, most decisions to introduce K8s "for future scalability" will become liabilities.
7. Recommended Learning Path
Finally, here is a path that avoids unnecessary detours:
- Get one application running first. Do not begin by poring over architecture diagrams. Follow section 4 of this article and run a complete Pod + Service + Ingress setup in kind until you can access the response.
- Become comfortable with the dozen or so common kubectl commands. get / describe / logs / exec / apply / rollout cover 90% of everyday work.
- Understand declarative configuration and the Reconcile model. What makes K8s K8s is the model of "I tell you the desired state, and the system continuously makes the current state match it." Once you understand that, CRD and Operator follow the same underlying idea.
- Then learn Helm (package management), how to choose an Ingress Controller, and persistent storage (PV/PVC).
- Only then move to advanced topics: scheduling policies, network plugin internals, RBAC, GitOps (ArgoCD), and Service Mesh.
Do not reverse this order. I have seen far too many people start by grinding through the 600- or 700-page "Definitive Guide to Kubernetes" and still be unable to deploy an application afterward.
Summary
- The value of K8s is container orchestration: multi-node scheduling, scaling, self-healing, and rolling updates, not "making Docker easier to use"
- There are only five core objects: Pod (run) → Deployment (manage) → Service (address) → Ingress (gateway) → ConfigMap/Secret (configuration), connected by labels
- Request path: Ingress → Service → Pods managed by Deployment. Once this path is clear in your head, everything else is detail
- Use kind locally and
applya YAML file to get started. Do not wait until production to learn - K8s is a liability with operational costs, not a KPI decoration. Use docker compose or a PaaS for small projects
In one sentence: Do not let the documentation intimidate you. Get one application running first. Between someone who can use K8s and someone who only memorizes K8s concepts lie a hundred
kubectl applycommands.
Related
Related Content
Article
Considerations for Deploying a Next.js Community Project with Docker
Technical trends, engineering practices, and an independent developer perspective on DevOps and Next.js.
Article
How Can OpenTelemetry Help You Observe AI Applications?
Technical trends, engineering practices, and an independent developer's perspective on DevOps and AI.
Article
Long-Running Tool Calls: The Terminal-State Protocol for Operation, Poll, and Cancel
After the initial request times out, the tool may still be running server-side; issuing a cancel does not mean the side effects have stopped. This article establishes an operation identity, polling watermark, cancellation race handling, and a single terminal-state acceptance point for a single long-running tool call.
Article
Agent Memory Erasure Propagation: From User Forgetting Request to Verifiable Purge
Deleting one row in the primary table won't clear vectors, summaries, caches, or restored backups. This article uses a deletion state machine, generational tombstones, derived lineage, and end-to-end canary verification to truly forget.