Skip to main content
Kubernetes · lesson 1 of 10
Kubernetes beginner Lesson 1 of 10

Kubernetes Fundamentals

Learn the core concepts of Kubernetes—clusters, pods, deployments, services, namespaces, and how to reason about orchestration.

By SkillByExample · Updated

What is Kubernetes?

Kubernetes (often abbreviated as K8s) is a system for running and managing containerized applications across a cluster of machines.

Instead of running a single container on a single server, Kubernetes helps you run many containers as a coordinated application — with automatic scheduling, self-healing, scaling, and rolling updates.

Theory first: desired state over manual operations

Kubernetes is fundamentally a control system: you declare desired state, and controllers continuously reconcile actual state to match it. This is different from imperative server operations where each command directly mutates runtime state.

Once this idea is clear, YAML is easier to reason about: specs describe intent, controllers handle convergence, and observability tells you whether reconciliation is succeeding.

Without Kubernetes                With Kubernetes
──────────────────────            ──────────────────────────────────
One server, one container         Cluster of nodes
  "ssh in and docker run"           desired state declared in YAML
  manual restarts if crash          auto-restart, auto-scale, rolling update
  no load balancing                 built-in load balancing via Services

Key Building Blocks

ObjectRole
ClusterThe full set of machines managed by Kubernetes
Control planeBrain of the cluster: scheduler, API server, etcd
NodeA worker machine that runs your containers
PodSmallest deployable unit — wraps one or more containers
DeploymentManages desired replica count and rolling updates
ServiceStable network endpoint that routes to matching Pods
NamespaceLogical partition inside a cluster for isolation

Setting Up a Local Cluster

# Install minikube (macOS)
brew install minikube

# Install minikube (Linux)
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

# Start a local cluster
minikube start

# Check cluster status
minikube status

Option 2 — kind (Kubernetes IN Docker)

# Install kind
go install sigs.k8s.io/kind@latest
# or via brew: brew install kind

# Create a cluster
kind create cluster --name dev

# Delete when done
kind delete cluster --name dev

Installing kubectl

kubectl is the CLI for talking to any Kubernetes cluster.

# macOS
brew install kubectl

# Linux
curl -LO "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install kubectl /usr/local/bin/kubectl

# Verify
kubectl version --client

Exploring Your Cluster

# Show cluster info (API server address)
kubectl cluster-info

# List all nodes in the cluster
kubectl get nodes

# Detailed info about a node
kubectl describe node minikube

# List all resources across namespaces
kubectl get all --all-namespaces

# Show available API resource types
kubectl api-resources

Namespaces

Namespaces give you logical isolation inside one cluster.

# List namespaces
kubectl get namespaces

# Create a namespace
kubectl create namespace my-app

# Run commands scoped to a namespace
kubectl get pods -n my-app

# Set a default namespace for your current context
kubectl config set-context --current --namespace=my-app

Built-in namespaces:

  • default — where resources land if you don’t specify one
  • kube-system — Kubernetes system components
  • kube-public — publicly readable resources

Mental Model: Desired State

Kubernetes is built around declared desired state.

# You write this:
replicas: 3          # "I want 3 copies running"
image: nginx:1.25    # "using this image"

# Kubernetes continuously ensures:
# - if a pod crashes → start a new one
# - if a node fails  → reschedule pods elsewhere
# - if you update    → rolling replacement

You never say “start container X on server Y”. Instead you say “I want 3 replicas of X” and Kubernetes figures out the rest.

Your First Resource (Imperative)

# Create a pod running nginx (imperative — good for quick tests)
kubectl run my-nginx --image=nginx:1.25

# Check it's running
kubectl get pods

# See pod details
kubectl describe pod my-nginx

# View pod logs
kubectl logs my-nginx

# Open a shell inside the pod
kubectl exec -it my-nginx -- bash

# Delete it when done
kubectl delete pod my-nginx

kubectl Cheat Sheet

# Get resources
kubectl get pods
kubectl get pods -o wide        # extra info (node, IP)
kubectl get pods -o yaml        # full YAML spec
kubectl get pods --watch        # live updates

# Describe (human-readable deep-dive)
kubectl describe pod <name>
kubectl describe node <name>
kubectl describe service <name>

# Apply a manifest file
kubectl apply -f pod.yaml

# Delete from a manifest
kubectl delete -f pod.yaml

# Shorthand resource names
kubectl get po    # pods
kubectl get svc   # services
kubectl get deploy # deployments
kubectl get ns    # namespaces

Learning Outcomes

By the end of this tutorial you should be able to:

  • Explain pods, deployments, and services
  • Set up a local Kubernetes cluster with minikube or kind
  • Use kubectl to explore and manage cluster resources
  • Understand why desired state matters

Practice

  1. Create a namespace called practice, then run the my-nginx Pod from “Your First Resource” inside it. Before you list Pods, predict what a plain kubectl get pods shows.
Solution
kubectl create namespace practice
kubectl run my-nginx --image=nginx:1.25 -n practice
kubectl wait -n practice --for=condition=Ready pod/my-nginx --timeout=180s
kubectl get pods
kubectl get pods -n practice
$ kubectl create namespace practice
namespace/practice created
$ kubectl run my-nginx --image=nginx:1.25 -n practice
pod/my-nginx created
$ kubectl wait -n practice --for=condition=Ready pod/my-nginx --timeout=180s
pod/my-nginx condition met
$ kubectl get pods
No resources found in default namespace.
$ kubectl get pods -n practice
NAME       READY   STATUS    RESTARTS   AGE
my-nginx   1/1     Running   0          17s

Without -n, kubectl reads from your context’s namespace, which is default. The Pod exists, just not where you looked. kubectl wait blocks until the Pod is Ready, so you don’t have to re-run get pods while the image pulls.

  1. Use kubectl exec to ask the running container which nginx version it has and what its hostname is, without opening an interactive shell.
Solution
kubectl exec -n practice my-nginx -- nginx -v
kubectl exec -n practice my-nginx -- hostname
$ kubectl exec -n practice my-nginx -- nginx -v
nginx version: nginx/1.25.5
$ kubectl exec -n practice my-nginx -- hostname
my-nginx

Everything after -- runs inside the container, and without -it you get its output back and nothing more. The nginx:1.25 tag resolved to patch release 1.25.5, and the container’s hostname is the Pod’s name.

  1. Delete my-nginx and list the namespace again. Does Kubernetes bring it back? Explain the answer using the desired-state model.
Solution
kubectl delete pod my-nginx -n practice
kubectl get pods -n practice
$ kubectl delete pod my-nginx -n practice
pod "my-nginx" deleted from practice namespace
$ kubectl get pods -n practice
No resources found in practice namespace.

It stays gone. kubectl run created a bare Pod, and nothing declared “I want one of these running”, so no controller recreates it. A Deployment with replicas: 1 would replace it within seconds, which is what the next lessons build on.

  1. The cheat sheet uses ns and deploy as short names. Use kubectl api-resources to confirm them, and to find out which of the two objects lives inside a namespace.
Solution
kubectl api-resources | grep -E '^NAME|deployments|namespaces'
$ kubectl api-resources | grep -E '^NAME|deployments|namespaces'
NAME                                SHORTNAMES   APIVERSION                        NAMESPACED   KIND
namespaces                          ns           v1                                false        Namespace
deployments                         deploy       apps/v1                           true         Deployment

NAMESPACED false means a Namespace is cluster-wide, so it can’t sit inside another namespace. A Deployment is namespaced, which is why kubectl get deploy needs -n to look outside default.

Clean up with kubectl delete namespace practice. That also deletes anything left inside it.

Frequently Asked Questions

What is the main purpose of Kubernetes?
To automate deployment, scaling, and operations of containerized applications. Kubernetes provides scheduling, self-healing, and rollouts/rollbacks so you can run applications reliably.
Do I need to know Docker first?
You should understand basic containers and Docker images, but Kubernetes concepts can be learned progressively.