Skip to content

Before running any workload we need a cluster. There are three broad routes, and which one you pick depends on what you are trying to do.

Route Examples Best for
Local learning cluster minikube, kind, k3s, Docker Desktop Learning, testing manifests, CI pipelines
Self-managed cluster kubeadm, Kubespray, Talos On-premises, full control, bare metal
Managed cloud cluster Amazon EKS, Google GKE, Azure AKS Production without running the control plane

Prerequisites

Whatever route you choose, you need the kubectl client installed (see the end of the previous chapter). Local clusters also need a driver to host the node, typically a container runtime or hypervisor:

  • Docker (most common)
  • Podman
  • KVM / QEMU
  • VirtualBox

Check what you have:

$ docker version
$ kubectl version --client

Local Clusters

minikube

minikube runs a single-node cluster (control plane and compute node on the same machine) inside a container or VM. It is the quickest way to get a working cluster and ships with handy add-ons.

Installing on Linux

$ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
$ sudo install minikube-linux-amd64 /usr/local/bin/minikube
$ minikube version

Starting the cluster

$ minikube start

By default it picks a driver automatically. You can be explicit:

$ minikube start --driver=docker

What minikube start does behind the scenes: - Creates the node (a Docker container or VM) - Downloads the Kubernetes component images (kube-apiserver, etcd, kube-scheduler ...) - Bootstraps the control plane - Writes a new entry into your ~/.kube/config so kubectl points at the new cluster

Verifying

$ kubectl cluster-info
$ kubectl get nodes
NAME       STATUS   ROLES           AGE   VERSION
minikube   Ready    control-plane   1m    v1.xx.x

Ready means the kubelet on that node is healthy and reporting to the kube-apiserver.

You can also see the components from Chapter 2 running as Pods in the kube-system namespace:

$ kubectl get pods -n kube-system

Expect to see etcd-minikube, kube-apiserver-minikube, kube-scheduler-minikube, kube-controller-manager-minikube, kube-proxy-xxxxx and coredns-xxxxx.

Useful minikube commands

$ minikube status              # state of the cluster
$ minikube dashboard           # opens the Web UI add-on
$ minikube addons list         # list available add-ons
$ minikube addons enable metrics-server
$ minikube ssh                 # shell into the node
$ minikube stop                # stop, keep the state
$ minikube delete              # remove the cluster entirely

Multi-node with minikube

$ minikube start --nodes 3 -p multi

-p creates a separate profile so it does not clash with the default cluster.

kind (Kubernetes IN Docker)

kind runs every node as a Docker container. Because nodes are cheap containers, it is excellent for multi-node clusters and for CI.

$ go install sigs.k8s.io/kind@latest      # or download the binary from the releases page
$ kind create cluster                     # single node named "kind"

A multi-node cluster is described in a config file:

# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
  - role: worker
$ kind create cluster --name demo --config kind-config.yaml
$ kubectl get nodes
$ kind delete cluster --name demo

Docker Desktop

Docker Desktop includes a single-node Kubernetes cluster. Enable it under Settings → Kubernetes → Enable Kubernetes. Convenient on Windows and macOS, but you get less control over the version and configuration than with minikube or kind.

Choosing between them

Tool Nodes Notes
minikube 1 or many Rich add-ons, built-in dashboard, good for learning
kind Many Fast to create and destroy, great for CI
Docker Desktop 1 Zero setup if you already use Docker Desktop
k3s 1 or many Lightweight, runs well on small hardware / edge

Self-Managed Cluster with kubeadm

kubeadm is the official tool for bootstrapping a production-style cluster on machines you provide. It installs the control plane components, but you are responsible for the machines, networking and upgrades.

What you need on every node

  • A supported Linux distribution
  • 2 GB RAM or more (2 CPUs on the control plane)
  • Full network connectivity between nodes
  • Swap disabled (the kubelet expects this by default)
  • A container runtime that implements the CRI (e.g. containerd or CRI-O)
  • kubeadm, kubelet and kubectl installed
$ sudo swapoff -a
$ sudo apt-get install -y kubelet kubeadm kubectl
$ sudo apt-mark hold kubelet kubeadm kubectl     # avoid accidental upgrades

Bootstrapping the control plane

On the first control plane node:

$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16

At the end it prints two things you need:

  1. Commands to configure kubectl for your user
  2. A kubeadm join ... command with a token for the compute nodes
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

Installing a network plugin

Nodes stay NotReady until a Container Network Interface (CNI) plugin is installed. This is one of the add-on components from Chapter 2.

$ kubectl apply -f <cni-plugin-manifest.yaml>     # Calico, Flannel, Cilium ...

Joining compute nodes

Run the join command on each compute node:

$ sudo kubeadm join <control-plane-ip>:6443 --token <token> \
    --discovery-token-ca-cert-hash sha256:<hash>

Verify from the control plane:

$ kubectl get nodes

If the token expired (they last 24 hours), create a new one with kubeadm token create --print-join-command.


Managed Kubernetes in the Cloud

As covered in Chapter 2, cloud providers run the control plane for you. You only create and pay for compute nodes (and sometimes a small fee for the control plane).

Service Provider CLI
EKS AWS eksctl / aws eks
GKE Google gcloud container
AKS Azure az aks

Typical flow, using Azure as an example:

$ az group create --name k8s-demo --location southafricanorth
$ az aks create --resource-group k8s-demo --name demo-aks --node-count 2
$ az aks get-credentials --resource-group k8s-demo --name demo-aks
$ kubectl get nodes

The get-credentials step merges the cluster into your local kubeconfig, just like minikube start did.

Remember to delete the cluster when you finish, as compute nodes are billed per hour:

$ az group delete --name k8s-demo

kubeconfig and Contexts

kubectl knows which cluster to talk to from the kubeconfig file, ~/.kube/config by default. It holds three things:

  • clusters: the API server address and its certificate authority
  • users: credentials (client certificates, tokens, or exec plugins)
  • contexts: a pairing of a cluster, a user and an optional default namespace
$ kubectl config get-contexts                  # list all contexts
$ kubectl config current-context               # which one is active
$ kubectl config use-context minikube          # switch cluster
$ kubectl config set-context --current --namespace=dev

When you have a local cluster and a cloud cluster on the same machine, always check the current context before running destructive commands.


Cleaning Up

Tool Command
minikube minikube delete
kind kind delete cluster --name demo
kubeadm sudo kubeadm reset
Cloud Delete the cluster / resource group

Summary

  • Use minikube or kind to learn; use kubeadm when you need to own the machines; use EKS / GKE / AKS when you want someone else to run the control plane.
  • A fresh cluster is verified with kubectl cluster-info and kubectl get nodes.
  • The control plane components are visible as Pods in the kube-system namespace.
  • kubectl finds clusters through contexts in ~/.kube/config.