How to Install & Set Up Kubernetes
Install the kubectl CLI, understand the control-plane/node split, bootstrap a real cluster with kubeadm, and deploy your first workload.
Prerequisites
- ✓One or more Linux hosts (2 GB+ RAM, 2 vCPUs each) with swap disabled — one becomes the control-plane node, the rest are workers
- ✓A container runtime installed (containerd or CRI-O) on every node — Kubernetes talks to it through the CRI (Container Runtime Interface), it no longer runs containers itself
- ✓Unique hostnames, unique MAC addresses, and full network connectivity between every node
Control plane vs. nodes — what you're actually building
A cluster splits into two roles. The control plane is the brain: the API server (every kubectl command and every internal component talks through it), etcd (the cluster's entire state lives in this key-value store), the scheduler (decides which node a new pod lands on), and the controller manager (a set of reconciliation loops that keep reality matching what you declared).
Worker nodes are where your workloads actually run. Each one runs a kubelet (the agent that talks to the API server and starts/stops containers via the runtime), kube-proxy (programs the networking rules that make Services work), and the container runtime itself. kubeadm — the tool below — automates wiring all of this together on your own machines; kubectl is just the client you use to talk to the API server afterward.
If you don't want to run this yourself, k3s, k0s, and MicroK8s package the same control plane into a much lighter single binary — see their dedicated guides — and kind/Minikube spin up a throwaway cluster for local development only.
Install kubectl only (quick, distro-agnostic)
If you only need a client to talk to a cluster someone else runs (managed, or already bootstrapped), the plain binary is all you need — no repo, no package manager.
Install kubeadm, kubelet & kubectl together (for bootstrapping a real cluster)
To actually build a cluster you need kubeadm and kubelet too, not just kubectl — install all three together from Kubernetes' own package repository, on every node that will join the cluster.
Swap v1.31 in the URL for whichever minor version you're targeting — the repo is versioned per minor release, and apt-mark hold / a pinned dnf version stops an unattended upgrade from silently jumping your cluster to an incompatible version.
Bootstrap a control plane with kubeadm
kubeadm init prints a `kubeadm join ...` command with a token near the end of its output — copy it before it scrolls away, you'll need it for every worker.
Install a CNI plugin (required)
Kubernetes doesn't ship pod networking itself — without a CNI (Container Network Interface) plugin, nodes stay stuck in NotReady and pods can't get an IP at all. Flannel is the simplest option and matches the --pod-network-cidr used above.
Join worker nodes
Run the join command kubeadm init printed earlier, on each worker node, as root:
Verify the installation
Every node should report Ready and every pod in the kube-system namespace should be Running before you deploy anything of your own.
The object model, in one deployment
You almost never manage individual containers directly. A Deployment declares how many replicas of a Pod (one or more containers sharing network/storage) you want running and keeps that count true even as nodes fail; a Service gives that shifting set of pods a single stable IP and DNS name to be reached at.
Real workloads live in YAML manifests applied with `kubectl apply -f` (so the config is versioned in Git), not typed imperatively like the create/expose commands above — those are just the fastest way to prove the cluster works.
Working across clusters with kubectl context
Your kubeconfig (~/.kube/config) can hold credentials for several clusters at once, and context is what tells kubectl which one — and which namespace — a command should hit.
Documentation & Knowledge Base
Need Kubernetes deployed and managed for you?
We're OpenStack Dev — we design, deploy, and operate production DevOps infrastructure.