Kubernetes: container orchestration step by step
Kubernetes solves a real problem: managing dozens of containers in production is chaotic without an orchestrator. This guide explains its architecture and components and takes you from scratch to an exposed service in Minikube.
What problem does Kubernetes solve?
With a single server and a couple of Docker containers, docker run is enough. The problem arises when you have ten services, need to scale the payment processor on Black Friday without touching the rest, want another container to start automatically if one dies, and need to update the app without downtime. That is exactly what Kubernetes orchestrates.
Kubernetes (K8s) is an open-source container orchestration system created by Google in 2014 and donated to the CNCF. It abstracts the underlying infrastructure and exposes a declarative API: you describe the desired state (“I want 3 replicas of this service”), and K8s continuously works to maintain that state.
Key components
The cluster is divided into two planes:
- Control Plane — the brain of the cluster. It consists of the API Server (entry point for all communication), etcd (key-value database that stores the state), the Scheduler (decides which node each Pod runs on) and the Controller Manager (reconciliation loop that applies changes).
- Worker Nodes — machines that run workloads. Each node has kubelet (an agent that communicates with the API Server), kube-proxy (manages network rules) and a container runtime (Docker, containerd, CRI-O).
The smallest deployable unit is the Pod: one or more containers that share networking and storage, always co-located on the same node.
Installation with Minikube (local environment)
Minikube starts a single-node cluster on your machine, ideal for learning and development.
# Instalar Minikube (Linux/macOS con Homebrew)
brew install minikube
# Instalar kubectl
brew install kubectl
# Levantar el clúster (usa Docker como driver por defecto)
minikube start
# Verificar que el clúster está listo
kubectl cluster-info
kubectl get nodes
On Windows, you can use winget install Kubernetes.minikube and winget install Kubernetes.kubectl. Once started, kubectl get nodes should return the node with status Ready.
First deployment
A Deployment is the K8s object that manages Pod replicas and controls updates. You can create it in two ways: imperatively (quick for testing) or declaratively with a YAML manifest (the right approach for production).
# Forma imperativa — útil para explorar
kubectl create deployment hello-web \
--image=nginx:1.25 \
--replicas=2
# Verificar
kubectl get deployments
kubectl get pods
The YAML equivalent, which you should version in your repository:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-web
labels:
app: hello-web
spec:
replicas: 2
selector:
matchLabels:
app: hello-web
template:
metadata:
labels:
app: hello-web
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "250m"
memory: "128Mi"
# Aplicar el manifiesto
kubectl apply -f deployment.yaml
# Ver eventos de despliegue
kubectl rollout status deployment/hello-web
kubectl apply: the YAML reaches the API Server, is persisted in etcd, the Scheduler assigns a node, and kubelet creates the Pod.Expose the service
A Pod has an ephemeral internal IP. To make it accessible, use a Service, which acts as a stable load balancer in front of the group of Pods.
apiVersion: v1
kind: Service
metadata:
name: hello-web-svc
spec:
selector:
app: hello-web # apunta a los Pods con este label
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort # en Minikube; en cloud usar LoadBalancer
kubectl apply -f service.yaml
# En Minikube, abrir en el navegador directamente:
minikube service hello-web-svc
For cloud clusters (GKE, EKS, AKS), use type: LoadBalancer and the provider automatically provisions a public IP. For custom domains and TLS, add an Ingress with an Ingress Controller such as nginx.
Scale and update without downtime
# Escalar a 5 réplicas
kubectl scale deployment hello-web --replicas=5
# Actualizar imagen (rolling update automático)
kubectl set image deployment/hello-web nginx=nginx:1.26
# Ver progreso del rolling update
kubectl rollout status deployment/hello-web
# Revertir si algo salió mal
kubectl rollout undo deployment/hello-web
By default, K8s uses a RollingUpdatestrategy: it starts new Pods before terminating old ones, ensuring continuous availability. You can configure maxUnavailable and maxSurge in the Deployment spec to control the speed of the process.
Namespaces and organization
The Namespaces are logical partitions of the cluster. They let you isolate teams, environments (dev/staging/prod) or applications without separate clusters. Each resource exists within a namespace.
# Crear namespace para el entorno de staging
kubectl create namespace staging
# Desplegar en ese namespace
kubectl apply -f deployment.yaml -n staging
# Ver todos los recursos de staging
kubectl get all -n staging
Next steps
- ConfigMaps and Secrets — externalize container configuration and credentials.
- Persistent Volumes — persistent storage for databases and state files.
- Horizontal Pod Autoscaler (HPA) — automatically scale based on CPU/memory or custom metrics.
- Helm — a package manager for K8s; package, version and share manifests as charts.
- Observability — Prometheus + Grafana for metrics, Loki for logs and Jaeger for distributed tracing.