Kubernetes: Container Orchestration from Your First Pod to Certification
Exit

Lesson 1 of 17 · Fundamentals

Why Kubernetes? Orchestration and cluster architecture

30 min kubectl (client Kubernetes)

Objective

Understand the problem that Kubernetes solves. Be able to name each component of a cluster and explain its role. Choose the right distribution for learning, testing or production.

Key points

  • Docker runs containers on one machine. Kubernetes orchestrates containers on a group of machines: it places them, restarts them, scales them and connects them to each other.
  • Kubernetes is declarative: you describe the desired state ("3 copies of the API, version 2.3") and controllers work in a loop to make reality match this description.
  • A cluster = a control plane (kube-apiserver, etcd, kube-scheduler, kube-controller-manager) + worker nodes (kubelet, kube-proxy, container runtime).
  • Everything goes through the API server: kubectl, the controllers, the kubelet. Only the API server talks to etcd.
  • To learn: kind or minikube on your workstation. For a small server: k3s. In production: kubeadm or a managed service (EKS, AKS, GKE…).

The problem: your containers in production

Take a fictional Moroccan payment platform, AtlasPay. Its team has containerized everything with Docker: a payment API, a web front end and an SMS notification service. On a single server, docker compose up -d is enough. Then the real questions arrive:

  • The server goes down on a Friday evening: who restarts the containers on another machine?
  • On Black Friday, traffic grows tenfold: how do you go from 2 to 20 copies of the API, across several servers, and back to 2 afterwards?
  • A new version of the API must be released without interrupting the payments in progress.
  • How do the API copies find the database, when their IP addresses change at every restart?

This is the job of an orchestrator. Kubernetes (often written K8s: a K, eight letters, an s) is the orchestrator that became the standard. It was born at Google, was open-sourced in 2014 and is maintained today by the CNCF (Cloud Native Computing Foundation).

Need With Docker alone With Kubernetes
Restart a crashed container --restart on one machine the Pod is recreated, on another node if needed
Scale by hand, machine by machine replicas: 20, spread across the cluster
Zero-downtime update home-made scripts built-in rolling update and rollback
Find a service IP or local Docker network Service + stable internal DNS
Configuration and secrets variables and .env files ConfigMaps and Secrets

What Kubernetes is not: it is not a turnkey platform. It does not compile your code, does not provide a database and does not impose a monitoring tool. It provides building blocks, and you assemble them.

The declarative model

With Docker, you give orders: "start this container". With Kubernetes, you describe a desired state in a YAML file, then hand it to the API:

# Excerpt: "I want 3 copies of the payment API"
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-paiement
spec:
  replicas: 3

A controller constantly compares the desired state (3 copies) with the actual state. If it counts only 2 because a node went down, it creates a new one. This is the reconciliation loop: observe, compare, correct, repeat. You never say "restart the container"; you say "there must be 3".

Cluster architecture

                    ┌───────────────── CONTROL PLANE ─────────────────┐
  kubectl  ───────▶ │  kube-apiserver  ◀──▶  etcd (cluster state)     │
  (you)             │        ▲                                        │
                    │        ├── kube-scheduler  (where to place Pods)│
                    │        └── kube-controller-manager (loops)      │
                    └────────┼────────────────────────────────────────┘
                             │ (HTTPS)
         ┌───────────────────┼──────────────────────┐
         ▼                   ▼                      ▼
   ┌─ node 1 ──────┐   ┌─ node 2 ──────┐      ┌─ node 3 ──────┐
   │ kubelet       │   │ kubelet       │      │ kubelet       │
   │ kube-proxy    │   │ kube-proxy    │      │ kube-proxy    │
   │ containerd    │   │ containerd    │      │ containerd    │
   │ [Pod][Pod]    │   │ [Pod]         │      │ [Pod][Pod]    │
   └───────────────┘   └───────────────┘      └───────────────┘

The control plane

This is the "brain" of the cluster. In production, it runs on 3 dedicated machines for high availability.

Component Role
kube-apiserver the single entry point: it exposes the Kubernetes HTTP API, authenticates, checks permissions and validates objects
etcd consistent, replicated key-value store: all of the cluster state is stored there. Losing etcd without a backup = losing the cluster
kube-scheduler spots Pods that do not have a node yet and picks the most suitable node for each one (free resources, constraints)
kube-controller-manager runs the controllers: Deployments, ReplicaSets, nodes, Jobs… each with its own reconciliation loop
cloud-controller-manager optional: connects to a cloud provider (creates a load balancer, disks…)

The nodes

These are the machines that run your applications.

Component Role
kubelet the agent on each node: it receives the Pods assigned to its node and makes sure their containers run and stay healthy
kube-proxy maintains the network rules (iptables, IPVS or nftables) that make Services work; some network plugins replace it
container runtime the software that actually starts the containers: containerd or CRI-O, through the CRI interface

Since Kubernetes 1.24, Docker Engine is no longer a directly supported runtime. Images built with Docker remain fully usable: they are standard OCI images, which containerd can run.

Add-ons

A bare cluster is not enough. You almost always add:

  • an internal DNS (CoreDNS): each Service gets a name, for example api.paiement.svc.cluster.local;
  • a network plugin (CNI: Calico, Cilium, Flannel…) that gives an IP to each Pod;
  • metrics collection (metrics-server) and centralized logs;
  • optionally the web dashboard (Dashboard).

Following a command from end to end

What happens when the AtlasPay team creates a Deployment with 3 copies?

kubectl apply -f api-paiement.yaml
  1. kubectl reads the file and sends it over HTTPS to kube-apiserver.
  2. The API server checks your identity and permissions, validates the YAML, then stores the object in etcd.
  3. The Deployment controller (in kube-controller-manager) sees the new object and creates a ReplicaSet, whose controller creates 3 Pods… which do not have a node yet.
  4. kube-scheduler sees 3 Pods without a node and assigns the most suitable node to each one.
  5. On each chosen node, the kubelet sees that a Pod belongs to it, asks the runtime to download the image and start the containers, then reports the status back to the API server.
  6. You see the result:
kubectl get pods -o wide
# NAME                            READY   STATUS    NODE
# api-paiement-6d8f9c7b5d-4kq2x   1/1     Running   noeud-1
# api-paiement-6d8f9c7b5d-9fz7m   1/1     Running   noeud-2
# api-paiement-6d8f9c7b5d-tw8rl   1/1     Running   noeud-3

Notice that no component gives a direct order to another one: each one watches the API server and reacts. This is what makes Kubernetes robust: if the scheduler restarts, it simply picks up the Pods that still have no node.

Distributions: where to run Kubernetes?

Kubernetes is a project. To use it, you need a distribution or a service that installs it for you.

To learn, on your workstation

Tool Principle When to use it
kind each node is a Docker container quick tests, several nodes on a laptop, CI
minikube a single-node cluster in a VM or a container discovery, many add-ons (minikube addons)
Docker Desktop, Rancher Desktop, Podman Desktop Kubernetes built into the desktop tool if you already use them
# kind: a 3-node cluster described in a file (example from the lab)
kind create cluster --name livraison --config kind-livraison.yaml
kubectl get nodes
# livraison-control-plane   Ready   control-plane
# livraison-worker          Ready   <none>
# livraison-worker2         Ready   <none>

# minikube: one node, in one command
minikube start
kubectl get nodes

For a small server or the edge

k3s (a CNCF project) is a certified and very lightweight distribution: a single binary, a few hundred MB of RAM. It is ideal for a test server at a Moroccan hosting provider, a Raspberry Pi or a shop. A comparable option: MicroK8s (Canonical).

For production

  • kubeadm: the official tool to build a cluster yourself on your own servers (on-premises or VPS). You manage everything: upgrades, etcd backups, certificates. See lesson 4.2.
  • Managed services: Amazon EKS, Azure AKS, Google GKE, and other providers. The provider manages the control plane; you pay for and manage the nodes. This is the most common choice when you do not want to operate etcd yourself.
  • Enterprise distributions: Red Hat OpenShift, Rancher (RKE2), with commercial support.
Criterion kind / minikube k3s kubeadm Managed
Installation 1 minute 1 command a few hours a few clicks
High availability no possible yes (to build) yes
Who manages etcd? the tool k3s (or SQLite) you the provider
Use learning, CI small server, edge on-premises, full control cloud production

The common tool: kubectl

Whatever the cluster, you talk to it with kubectl, which reads the cluster address and your credentials from ~/.kube/config:

kubectl version --client        # client version, without contacting a cluster
kubectl cluster-info            # API server address (requires a cluster)
kubectl get nodes               # the nodes and their status
kubectl config get-contexts     # the clusters known in your kubeconfig

In the labs of this course, you have kubectl without a cluster. You will write real manifests and use kubectl … --dry-run=client -o yaml, which works offline. Then reproduce each exercise on a kind or minikube cluster at home.

Versions

Kubernetes publishes about three minor versions per year (1.32, 1.33, 1.34…). Each version is maintained for about 14 months. In practice, a cluster must be upgraded at least once a year, one minor version at a time. Managed services actually force you to do so.

kubectl version
# Client Version: v1.34.x
# Server Version: v1.33.x     ← the client may be one minor version apart from the server

Common pitfalls

  • Believing that Kubernetes replaces Docker: you still build your images with Docker (or Buildah, Podman); Kubernetes runs them with containerd.
  • Building a kubeadm cluster to learn: start with kind or minikube. kubeadm requires several machines and a lot of configuration.
  • Neglecting etcd: without an etcd backup, an incident on the control plane of a kubeadm cluster can wipe out everything.
  • Thinking "servers" instead of "desired state": you do not SSH into a node to restart a container; you fix the manifest and let the controllers act.

Lab

You will:

  1. name the component that stores the cluster state;
  2. sort a list of components to keep only the control plane ones;
  3. write the configuration file of a three-node kind cluster for the delivery application, which you can reuse at home with kind create cluster --config.

To write a file without an editor, use cat > fichier <<EOF … EOF or printf.

Quiz

  1. Which component chooses the node on which a new Pod will run?
  2. What is the only component that reads and writes directly to etcd?
  3. Which component runs on every node and makes sure that the containers of its Pods are working?
  4. You want to test a 3-node cluster on your laptop in two minutes: which tool do you choose?
  5. What does "Kubernetes is declarative" mean?
Answers
  1. kube-scheduler.
  2. kube-apiserver: all the other components go through it.
  3. kubelet.
  4. kind (each node is a Docker container); minikube also works, but it creates a single node by default.
  5. You describe the desired state (in a YAML manifest) instead of giving orders; controllers constantly compare the actual state with this desired state and correct any differences.

Practical exercises

To do on kubectl (client Kubernetes)

The online terminal is coming soon. Meanwhile, do these tasks on your own Linux machine, a virtual machine or WSL.

  1. Write to /root/etat.txt, alone on its line, the name of the component that stores the entire state of the cluster (the key-value store)
    Show a hintIt is a distributed key-value database, with a four-letter name
    Show the solution
    echo etcd > /root/etat.txt

    Check : grep -qx "etcd" /root/etat.txt

  2. The file /root/composants.txt mixes several components. Copy to /root/plan-de-controle.txt, one per line, only the control plane components (there are four)
    Show a hintkubelet, kube-proxy and the container runtime run on every node, not in the control plane
    Show the solution
    grep -Ex "etcd|kube-apiserver|kube-scheduler|kube-controller-manager" /root/composants.txt > /root/plan-de-controle.txt

    Check : f=/root/plan-de-controle.txt; for c in etcd kube-apiserver kube-scheduler kube-controller-manager; do grep -qx "$c" $f || exit 1; done; ! grep -Eqx "kubelet|kube-proxy|containerd" $f

  3. Write /root/kind-livraison.yaml: a kind cluster (kind: Cluster, apiVersion: kind.x-k8s.io/v1alpha4) with one control-plane node and two worker nodes
    Show a hintUnder nodes:, one “- role: …” line per node
    Show the solution
    printf "kind: Cluster\napiVersion: kind.x-k8s.io/v1alpha4\nnodes:\n- role: control-plane\n- role: worker\n- role: worker\n" > /root/kind-livraison.yaml

    Check : f=/root/kind-livraison.yaml; grep -Eq "^kind: *Cluster *$" $f && grep -Eq "^apiVersion: *kind.x-k8s.io/v1alpha4 *$" $f && [ "$(grep -Ec "role: *control-plane" $f)" -eq 1 ] && [ "$(grep -Ec "role: *worker" $f)" -eq 2 ]

Official references consulted: Overview — https://kubernetes.io/docs/concepts/overview/ ; Kubernetes Components — https://kubernetes.io/docs/concepts/overview/components/ ; Environnement d’apprentissage — https://kubernetes.io/fr/docs/setup/learning-environment/ ; Environnement de production — https://kubernetes.io/fr/docs/setup/production-environment/. Original MasterLinux text.