EstevezAlvarez
Kubernetes Docker DevOps

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.

Control Plane API Server etcd cluster state Scheduler Controller Manager Cloud Controller Worker Node kubelet kube-proxy Pod Container app:v1 Container sidecar Pod Container · worker Worker Node kubelet kube-proxy Pod Container · replica Pod Container · db-proxy
Anatomy of a Kubernetes cluster: the Control Plane manages the desired state; Worker Nodes run Pods and their containers.

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:

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
YAML deployment.yaml API Server validates + accepts etcd state saved Scheduler selects node Node kubelet creates Pod kubectl apply persists notifies assigns
Complete workflow of 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

  1. ConfigMaps and Secrets — externalize container configuration and credentials.
  2. Persistent Volumes — persistent storage for databases and state files.
  3. Horizontal Pod Autoscaler (HPA) — automatically scale based on CPU/memory or custom metrics.
  4. Helm — a package manager for K8s; package, version and share manifests as charts.
  5. Observability — Prometheus + Grafana for metrics, Loki for logs and Jaeger for distributed tracing.