Home DevOps Kubernetes Installation and Cluster Setup
Beginner 4 min · July 12, 2026

Kubernetes Installation and Cluster Setup

Learn Kubernetes Installation and Cluster Setup with plain-English explanations and real examples..

N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.

Follow
Verified
production tested
July 12, 2026
last updated
2,073
articles · all by Naren
Before you start⏱ 20 min
  • Two or more Ubuntu 22.04 LTS nodes (physical or VM), sudo access, 2 CPU cores and 2 GB RAM per node, network connectivity between nodes, basic Linux command-line knowledge, familiarity with YAML syntax.
✦ Definition~90s read
What is Kubernetes Installation and Cluster Setup?

Kubernetes installation and cluster setup is the process of deploying a Kubernetes control plane and worker nodes to orchestrate containerized applications. It matters because it provides a standardized, scalable platform for managing containers in production. Use it when you need automated deployment, scaling, and operations of application containers across clusters of hosts.

Think of Kubernetes Installation and Cluster Setup like a tool in your DevOps toolkit — once you understand what it does and when to reach for it, managing Kubernetes clusters becomes second nature.
Plain-English First

Think of Kubernetes Installation and Cluster Setup like a tool in your DevOps toolkit — once you understand what it does and when to reach for it, managing Kubernetes clusters becomes second nature.

Your first production Kubernetes cluster will fail. Not because Kubernetes is broken, but because you skipped the boring parts: networking, storage, and security. I've seen teams spend weeks on YAML only to realize their cluster can't even pull images from a private registry. Kubernetes installation isn't just running a script—it's designing a control plane that survives a node failure, a network that doesn't drop packets, and a storage backend that doesn't corrupt data. This guide walks you through a production-grade setup using kubeadm, from prerequisites to cluster validation. No fluff, just the steps that matter.

Prerequisites and Environment Preparation

Before installing Kubernetes, your nodes must meet specific requirements. You need at least two machines (physical or virtual) running Ubuntu 22.04 LTS or CentOS 7/8. Each node should have a minimum of 2 CPU cores, 2 GB RAM, and 20 GB free disk space. All nodes must have unique hostnames, MAC addresses, and product_uuids. Disable swap: sudo swapoff -a and remove swap entries from /etc/fstab. Ensure the container runtime is installed—containerd is recommended over Docker. Install containerd from the official Docker repository. Configure the kernel modules overlay and br_netfilter: sudo modprobe overlay && sudo modprobe br_netfilter. Set sysctl params: net.bridge.bridge-nf-call-iptables = 1, net.ipv4.ip_forward = 1. Apply with sudo sysctl --system. These steps prevent common networking and resource issues during cluster initialization.

prepare-node.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
# Disable swap
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

# Install containerd
sudo apt-get update
sudo apt-get install -y containerd
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd

# Kernel modules
sudo modprobe overlay
sudo modprobe br_netfilter

# Sysctl params
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
sudo sysctl --system
Output
Swap disabled. containerd installed and configured. Kernel modules loaded. Sysctl params applied.
⚠ Swap Must Be Disabled
Kubernetes requires swap to be disabled. If swap is enabled, kubelet will fail to start. Double-check with free -h and ensure Swap line shows 0.
📊 Production Insight
In production, we automate node preparation with Ansible or Terraform to ensure consistency across hundreds of nodes. Manual steps lead to drift.
🎯 Key Takeaway
Proper node preparation prevents 90% of installation failures.

Installing kubeadm, kubelet, and kubectl

With the environment ready, install the Kubernetes components. kubeadm initializes the cluster, kubelet runs on all nodes, and kubectl is the CLI. Add the Kubernetes repository and install specific versions to avoid compatibility issues. Use version 1.28.x as of this writing. Pin the versions to prevent accidental upgrades. On all nodes, run: sudo apt-get install -y kubelet=1.28.0-00 kubeadm=1.28.0-00 kubectl=1.28.0-00. Hold the packages: sudo apt-mark hold kubelet kubeadm kubectl. This ensures the cluster remains stable. After installation, enable and start kubelet: sudo systemctl enable --now kubelet. Verify with kubeadm version and kubectl version --client.

install-k8s.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
# Add Kubernetes repository
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

# Install specific version
sudo apt-get update
sudo apt-get install -y kubelet=1.28.0-00 kubeadm=1.28.0-00 kubectl=1.28.0-00
sudo apt-mark hold kubelet kubeadm kubectl

# Enable kubelet
sudo systemctl enable --now kubelet
Output
kubelet, kubeadm, kubectl installed and held at version 1.28.0. kubelet enabled.
💡Version Pinning
Always pin Kubernetes versions across all nodes. Mismatched versions cause cluster instability. Use apt-mark hold or equivalent for your package manager.
📊 Production Insight
We once had a production outage because a node auto-upgraded kubelet to a newer minor version. Now we pin versions in our CI/CD pipeline.
🎯 Key Takeaway
Pin versions to avoid accidental upgrades that break the cluster.
kubernetes-installation-setup THECODEFORGE.IO Kubernetes Cluster Setup Steps Step-by-step process from prerequisites to test app Prepare Environment OS, Docker, swap off, ports open Install kubeadm, kubelet, kubectl Add repo, install packages, hold versions Initialize Control Plane kubeadm init, configure kubeconfig Install Pod Network (CNI) Apply Flannel, Calico, or Weave manifest Join Worker Nodes Run kubeadm join token on each worker Deploy Test Application kubectl create deployment, expose service ⚠ Forgetting to disable swap on all nodes Run 'swapoff -a' and remove swap entries from /etc/fstab THECODEFORGE.IO
thecodeforge.io
Kubernetes Installation Setup

Initializing the Control Plane with kubeadm

On the control plane node, initialize the cluster. kubeadm init sets up the control plane components: API server, controller manager, scheduler, and etcd. Choose a pod network CIDR that doesn't conflict with your existing network. Common choices: 10.244.0.0/16 for Flannel, 10.96.0.0/12 for services. Run: sudo kubeadm init --pod-network-cidr=10.244.0.0/16. This downloads images and starts containers. After success, you'll get a kubeconfig file and a join token. Copy the kubeconfig to your user directory: mkdir -p $HOME/.kube && sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config. Verify with kubectl get nodes—the control plane node should show as NotReady until a network plugin is installed.

init-control-plane.shBASH
1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# Initialize control plane
sudo kubeadm init --pod-network-cidr=10.244.0.0/16

# Set up kubeconfig
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# Check nodes
kubectl get nodes
Output
Your Kubernetes control-plane has been initialized successfully!
NAME STATUS ROLES AGE VERSION
control-plane-node NotReady control-plane 1m v1.28.0
🔥Pod Network CIDR
Choose a pod network CIDR that doesn't overlap with your host network or service CIDR. Flannel uses 10.244.0.0/16 by default. Calico uses 192.168.0.0/16.
📊 Production Insight
In production, we use a dedicated network range for pods and services to avoid conflicts with corporate VPNs. Document your CIDR choices.
🎯 Key Takeaway
kubeadm init creates the control plane; the node stays NotReady until a CNI plugin is installed.

Installing a Pod Network (CNI Plugin)

A Container Network Interface (CNI) plugin enables pod-to-pod communication. Without it, nodes remain NotReady and pods cannot communicate. Choose a CNI that fits your environment: Flannel (simple overlay), Calico (network policies), Weave (easy setup), or Cilium (eBPF). For this guide, install Flannel: kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml. After applying, check nodes: kubectl get nodes should show Ready. If nodes stay NotReady, check kubelet logs: journalctl -u kubelet -f. Common issues: wrong CIDR, firewall blocking ports 8472 (VXLAN), or missing kernel modules. Flannel uses VXLAN overlay; ensure UDP port 8472 is open between nodes.

install-flannel.shBASH
1
2
3
4
5
6
7
#!/bin/bash
# Install Flannel CNI
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

# Wait for nodes to become Ready
sleep 30
kubectl get nodes
Output
NAME STATUS ROLES AGE VERSION
control-plane-node Ready control-plane 2m v1.28.0
⚠ Firewall Rules
Flannel uses VXLAN on UDP port 8472. Ensure this port is open between all nodes. Also open ports 6443 (API server), 10250 (kubelet), and 10255 (read-only kubelet).
📊 Production Insight
We switched from Flannel to Calico for network policies. Flannel doesn't support NetworkPolicy, which is critical for multi-tenant clusters.
🎯 Key Takeaway
CNI plugin is mandatory for pod networking; Flannel is a simple choice for beginners.

Joining Worker Nodes to the Cluster

Worker nodes run your applications. To join them, use the token and hash from the kubeadm init output. If you lost it, generate a new token on the control plane: kubeadm token create --print-join-command. This prints the full join command. On each worker node, run the command with sudo: sudo kubeadm join <control-plane-ip>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>. After joining, verify on the control plane: kubectl get nodes. Worker nodes will show as NotReady initially, then become Ready after the CNI plugin is installed (if not already). Ensure the worker node has the same container runtime and Kubernetes version as the control plane. If join fails, check network connectivity to port 6443 and that the token hasn't expired (default 24 hours).

join-worker.shBASH
1
2
3
4
5
6
#!/bin/bash
# On worker node, run the join command from control plane
sudo kubeadm join 192.168.1.100:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef

# On control plane, verify
kubectl get nodes
Output
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
NAME STATUS ROLES AGE VERSION
control-plane-node Ready control-plane 5m v1.28.0
worker-node-1 Ready <none> 1m v1.28.0
💡Token Management
Tokens expire after 24 hours. For long-running clusters, use a bootstrap token or certificate-based joining. Store the join command securely.
📊 Production Insight
Automate worker node joining with a bootstrap token and a script. Manual joins are error-prone and don't scale.
🎯 Key Takeaway
Worker nodes join with a token; ensure version parity and network connectivity.

Configuring kubectl for Remote Access

By default, kubectl uses the admin.conf file on the control plane. To manage the cluster from your local machine, copy the kubeconfig file and update the server IP. On your local machine, install kubectl matching the cluster version. Copy the admin.conf from the control plane: scp user@control-plane:/etc/kubernetes/admin.conf ~/.kube/config. Edit the file to change the server address from localhost to the control plane's public IP or DNS. Test with kubectl cluster-info. For security, create a dedicated user with limited permissions instead of using admin.conf. Use RBAC to grant only necessary access. For example, create a read-only user for developers.

remote-kubectl.shBASH
1
2
3
4
5
6
7
8
9
#!/bin/bash
# On local machine
scp user@192.168.1.100:/etc/kubernetes/admin.conf ~/.kube/config

# Update server IP
sed -i 's/127.0.0.1/192.168.1.100/g' ~/.kube/config

# Test
kubectl cluster-info
Output
Kubernetes control plane is running at https://192.168.1.100:6443
CoreDNS is running at https://192.168.1.100:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
⚠ Admin Credentials
Never share admin.conf. It has full cluster access. Use RBAC to create restricted kubeconfig files for users.
📊 Production Insight
We use OIDC with Dex for authentication instead of static tokens. This allows SSO and easy revocation.
🎯 Key Takeaway
Remote kubectl access requires copying and modifying the kubeconfig file.

Deploying a Test Application

Verify the cluster works by deploying a simple application. Create a deployment: kubectl create deployment nginx --image=nginx:1.25. Expose it as a service: kubectl expose deployment nginx --port=80 --type=NodePort. Get the NodePort: kubectl get svc nginx. Access the application using any node's IP and the NodePort (e.g., http://192.168.1.101:30080). If it works, your cluster is functional. Check pod logs: kubectl logs deployment/nginx. If pods are pending, check node resources: kubectl describe node. Common issues: insufficient CPU/memory, image pull errors (check registry access), or network policy blocking.

test-app.shBASH
1
2
3
4
5
6
7
8
9
10
#!/bin/bash
# Deploy nginx
kubectl create deployment nginx --image=nginx:1.25
kubectl expose deployment nginx --port=80 --type=NodePort

# Get service details
kubectl get svc nginx

# Access (replace with actual node IP)
curl http://192.168.1.101:$(kubectl get svc nginx -o jsonpath='{.spec.ports[0].nodePort}')
Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx NodePort 10.96.0.100 <none> 80:30080/TCP 10s
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
🔥NodePort vs LoadBalancer
NodePort exposes the service on a static port on each node. For production, use a LoadBalancer or Ingress controller.
📊 Production Insight
We always deploy a health-check application (like httpbin) to validate cluster health before production workloads.
🎯 Key Takeaway
A test deployment confirms cluster functionality; NodePort provides quick external access.
kubernetes-installation-setup THECODEFORGE.IO Kubernetes Cluster Architecture Layered components from hardware to application Application Layer Deployments | Services | Pods Control Plane kube-apiserver | kube-controller-manager | kube-scheduler Node Components kubelet | kube-proxy | Container Runtime Networking CNI Plugin | Pod Network | Service Network Infrastructure Host OS | Docker/containerd | Storage THECODEFORGE.IO
thecodeforge.io
Kubernetes Installation Setup

Setting Up Persistent Storage with HostPath

Stateful applications need persistent storage. For a simple setup, use HostPath volumes—they mount a directory from the node's filesystem into the pod. Create a PersistentVolume (PV) and PersistentVolumeClaim (PVC). Example PV: hostPath: path: /data. Then create a PVC that requests storage. Deploy a pod that uses the PVC. HostPath is not suitable for production because pods may be scheduled on different nodes. For production, use a network storage solution like NFS, Ceph, or cloud provider volumes. Test with a simple pod that writes to the volume and verify data persists after pod restart.

hostpath-pv.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v1
kind: PersistentVolume
metadata:
  name: hostpath-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: hostpath-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
Output
persistentvolume/hostpath-pv created
persistentvolumeclaim/hostpath-pvc created
⚠ HostPath Limitations
HostPath volumes are node-specific. If a pod is rescheduled to another node, data is lost. Use only for testing or single-node clusters.
📊 Production Insight
We use Rook/Ceph for production storage. It provides distributed, replicated storage across nodes.
🎯 Key Takeaway
HostPath provides simple persistent storage but is not production-ready.

Enabling the Kubernetes Dashboard

The Kubernetes Dashboard provides a web UI for cluster management. Install it with: kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml. Create a service account and cluster role binding for admin access. Then get a bearer token: kubectl -n kubernetes-dashboard create token admin-user. Start the proxy: kubectl proxy. Access the dashboard at http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/. Use the token to log in. The dashboard shows cluster resources, logs, and allows basic operations. For production, secure the dashboard with RBAC and HTTPS.

dashboard-setup.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
# Install dashboard
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml

# Create admin user
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard
EOF

# Get token
kubectl -n kubernetes-dashboard create token admin-user
Output
Token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9...
🔥Dashboard Security
Never expose the dashboard publicly. Use kubectl proxy or an ingress with authentication.
📊 Production Insight
We don't use the dashboard in production. It's a security risk and encourages manual changes. Use GitOps with ArgoCD instead.
🎯 Key Takeaway
Dashboard offers a visual interface; secure it with RBAC and avoid public exposure.

Cluster Backup and Restore with etcd

etcd stores all cluster state. Backing up etcd is critical for disaster recovery. Use etcdctl (v3) to take snapshots. On the control plane, run: ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key snapshot save /backup/etcd-snapshot.db. To restore, stop the API server and etcd, then restore the snapshot to a new data directory: ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db --data-dir=/var/lib/etcd-restore. Update the etcd manifest to use the new data directory. Test by starting the cluster and verifying resources.

etcd-backup.shBASH
1
2
3
4
5
6
7
8
9
10
#!/bin/bash
# Backup etcd
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  snapshot save /backup/etcd-snapshot-$(date +%Y%m%d).db

# Verify snapshot
ETCDCTL_API=3 etcdctl --write-out=table snapshot status /backup/etcd-snapshot-$(date +%Y%m%d).db
Output
Snapshot saved at /backup/etcd-snapshot-20260712.db
+----------+----------+------------+------------+
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| abcdef12 | 12345 | 1024 | 4.5 MB |
+----------+----------+------------+------------+
⚠ etcd Backup Frequency
Backup etcd regularly, especially before any cluster change. In production, we backup every hour and store off-site.
📊 Production Insight
We once lost a cluster because a corrupted etcd snapshot wasn't tested. Always verify backups by restoring to a test environment.
🎯 Key Takeaway
etcd backups are your lifeline for disaster recovery; automate them.

Troubleshooting Common Installation Issues

Even with careful setup, issues arise. Common problems: kubelet fails to start (check journalctl -u kubelet), nodes stay NotReady (CNI not installed or network issues), pods stuck in Pending (insufficient resources or PVC not bound), API server not responding (check firewall port 6443). Use kubectl describe to get details. For kubeadm init failures, check pre-flight checks: kubeadm init --dry-run. Ensure all nodes have synchronized clocks (install ntp). If images fail to pull, check container runtime and registry access. For network issues, verify CNI plugin logs: kubectl -n kube-system logs <cni-pod>. Keep a checklist and validate each step.

troubleshoot.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
# Check kubelet status
sudo systemctl status kubelet

# View kubelet logs
journalctl -u kubelet -n 50 --no-pager

# Check node details
kubectl describe node <node-name>

# Check pod events
kubectl describe pod <pod-name>

# Check CNI pods
kubectl -n kube-system get pods -l k8s-app=flannel

# Test API server
curl -k https://localhost:6443/healthz
Output
kubelet is running.
...
Conditions:
Type Status LastHeartbeatTime
Ready True 2026-07-12T10:00:00Z
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 1m default-scheduler Successfully assigned...
ok
💡Dry Run First
Always run kubeadm init --dry-run to catch issues before actual initialization.
📊 Production Insight
We have a runbook for common failures. Document your own issues and solutions—it saves hours during incidents.
🎯 Key Takeaway
Systematic troubleshooting with logs and describe commands resolves most issues.
kubeadm vs Manual Setup Trade-offs between automated and manual cluster installation kubeadm Setup Manual Setup Installation Speed Fast, automated Slow, manual steps Configuration Complexity Simplified, defaults provided Full control, complex Best For Production clusters, beginners Learning, custom setups Upgrade Path Supported via kubeadm upgrade Manual, error-prone Security Defaults Secure by default Requires manual hardening Community Support Official Kubernetes tool Varies by method THECODEFORGE.IO
thecodeforge.io
Kubernetes Installation Setup

Production Hardening and Next Steps

Your cluster is running, but it's not production-ready. Hardening steps: enable RBAC, use network policies, set resource limits, enable audit logging, and use a private container registry. Implement Pod Security Standards (baseline or restricted). Set up monitoring with Prometheus and Grafana. Configure logging with Fluentd or Loki. Use a service mesh like Istio for advanced traffic management. Automate deployments with CI/CD (GitLab CI, Jenkins). Finally, document your cluster architecture, backup procedures, and runbooks. Kubernetes is a platform, not a magic bullet—invest in operations.

network-policy.yamlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - port: 53
      protocol: UDP
Output
networkpolicy.networking.k8s.io/deny-all created
networkpolicy.networking.k8s.io/allow-dns created
🔥Start with Deny-All
Apply a default deny-all network policy to enforce least privilege. Then allow necessary traffic.
📊 Production Insight
We run a weekly security scan on our clusters using kube-bench and Trivy. Fixing vulnerabilities early prevents breaches.
🎯 Key Takeaway
Production hardening is an ongoing process; start with RBAC and network policies.
⚙ Quick Reference
12 commands from this guide
FileCommand / CodePurpose
prepare-node.shsudo swapoff -aPrerequisites and Environment Preparation
install-k8s.shsudo apt-get updateInstalling kubeadm, kubelet, and kubectl
init-control-plane.shsudo kubeadm init --pod-network-cidr=10.244.0.0/16Initializing the Control Plane with kubeadm
install-flannel.shkubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Doc...Installing a Pod Network (CNI Plugin)
join-worker.shsudo kubeadm join 192.168.1.100:6443 --token abcdef.0123456789abcdef --discovery...Joining Worker Nodes to the Cluster
remote-kubectl.shscp user@192.168.1.100:/etc/kubernetes/admin.conf ~/.kube/configConfiguring kubectl for Remote Access
test-app.shkubectl create deployment nginx --image=nginx:1.25Deploying a Test Application
hostpath-pv.yamlapiVersion: v1Setting Up Persistent Storage with HostPath
dashboard-setup.shkubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/a...Enabling the Kubernetes Dashboard
etcd-backup.shETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \Cluster Backup and Restore with etcd
troubleshoot.shsudo systemctl status kubeletTroubleshooting Common Installation Issues
network-policy.yamlapiVersion: networking.k8s.io/v1Production Hardening and Next Steps

Key takeaways

1
Proper Node Preparation
Disable swap, configure kernel modules, and install containerd to avoid 90% of installation failures.
2
Version Pinning
Pin kubelet, kubeadm, and kubectl versions to prevent accidental upgrades that break cluster stability.
3
CNI Plugin is Mandatory
Install a pod network like Flannel immediately after control plane init; nodes stay NotReady without it.
4
Backup etcd Regularly
etcd stores all cluster state; automate backups and test restores to ensure disaster recovery works.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What is the minimum number of nodes required for a Kubernetes cluster?
Q02JUNIOR
Can I use Docker as the container runtime with Kubernetes 1.24+?
Q03JUNIOR
How do I reset a Kubernetes cluster initialized with kubeadm?
Q01 of 03JUNIOR

What is the minimum number of nodes required for a Kubernetes cluster?

ANSWER
You need at least one control plane node and one worker node. For high availability, use three control plane nodes and multiple workers.
FAQ · 6 QUESTIONS

Frequently Asked Questions

01
What is the minimum number of nodes required for a Kubernetes cluster?
02
Can I use Docker as the container runtime with Kubernetes 1.24+?
03
How do I reset a Kubernetes cluster initialized with kubeadm?
04
What is the default pod network CIDR for Flannel?
05
How do I upgrade a Kubernetes cluster to a new minor version?
06
Why are my pods stuck in ContainerCreating state?
N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.

Follow
Verified
production tested
July 12, 2026
last updated
2,073
articles · all by Naren
🔥

That's Kubernetes. Mark it forged?

4 min read · try the examples if you haven't

Previous
Kubernetes RBAC — Service Accounts, Roles, and Bindings
38 / 38 · Kubernetes
Next
Introduction to CI/CD