This guide walks through installing Kubernetes components and initializing the cluster using kubeadm.
Install Kubernetes Components
This installation uses Kubernetes v1.33.0. Ensure you use the correct version for compatibility with your Flux configuration.
Add Kubernetes apt repository
Configure the Kubernetes package repository:curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
Install kubeadm, kubelet, and kubectl
sudo apt-get update
sudo apt-get install -y kubelet=1.33.0-1.1 kubeadm=1.33.0-1.1 kubectl=1.33.0-1.1
Hold package versions
Prevent automatic updates of Kubernetes packages:sudo apt-mark hold kubelet kubeadm kubectl
Holding package versions ensures cluster stability and prevents unexpected upgrades during system updates.
Initialize Control Plane
This cluster uses Cilium as the CNI (Container Network Interface) and replaces kube-proxy. We skip the kube-proxy installation phase during initialization.
Initialize the cluster
Run kubeadm init with the following configuration:sudo kubeadm init \
--skip-phases=addon/kube-proxy \
--apiserver-advertise-address=192.168.0.101 \
--pod-network-cidr="10.1.0.0/16" \
--upload-certs
Flag Explanation:
--skip-phases=addon/kube-proxy: Skips kube-proxy installation (Cilium will replace it)
--apiserver-advertise-address=192.168.0.101: API server address for the control plane
--pod-network-cidr="10.1.0.0/16": CIDR for pod networking
--upload-certs: Uploads certificates to the cluster for additional control plane nodes
Configure kubectl access
After initialization completes, configure kubectl for the root user:mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Verify cluster status
Check that the control plane is running:kubectl get nodes
kubectl get pods -A
The control plane node will show as “NotReady” until the CNI (Cilium) is installed in the next step.
Add Worker Nodes (Optional)
If you have additional nodes to add to the cluster:
Generate join command
On the control plane node, generate the join command:kubeadm token create --print-join-command
Join worker nodes
Run the output command on each worker node:sudo kubeadm join 192.168.0.101:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
Verify nodes joined
On the control plane, verify the nodes:
Install Cilium CNI
Cilium provides networking and security for the cluster, replacing kube-proxy.
Install Cilium CLI
Download and install the Cilium CLI tool:CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
Install Cilium
Install Cilium with kube-proxy replacement enabled:cilium install \
--set kubeProxyReplacement=true \
--set k8sServiceHost=192.168.0.101 \
--set k8sServicePort=6443 \
--set nodePort.enabled=true \
--set gatewayAPI.enabled=true
Configuration Options:
kubeProxyReplacement=true: Enables Cilium to replace kube-proxy
k8sServiceHost and k8sServicePort: API server endpoint
nodePort.enabled=true: Enables NodePort service support
gatewayAPI.enabled=true: Enables Gateway API support
Wait for Cilium to be ready
This command waits for all Cilium components to become healthy. Verify cluster is ready
kubectl get nodes
kubectl get pods -A
All nodes should now show as “Ready” status.
Next Steps
With the cluster installed and Cilium networking configured, proceed to Flux Bootstrap to set up GitOps continuous deployment.