kubernetes-the-hard-way/docs/09-bootstrapping-kubernetes...

5.9 KiB

Bootstrapping the Kubernetes Worker Nodes

In this lab you will bootstrap two Kubernetes worker nodes. The following components will be installed: runc, container networking plugins, containerd, kubelet, and kube-proxy.

Prerequisites

The commands in this section must be run from the jumpbox.

Copy the Kubernetes binaries and systemd unit files to each worker instance:

for HOST in node01 node02; do
  SUBNET=$(grep ${HOST} machines.txt | cut -d " " -f 4)
  sed "s|SUBNET|$SUBNET|g" \
    configs/10-bridge.conf > 10-bridge.conf

  scp 10-bridge.conf configs/kubelet-config.yaml \
  vagrant@${HOST}:~/
done
for HOST in node01 node02; do
  scp \
    downloads/worker/* \
    downloads/client/kubectl \
    configs/99-loopback.conf \
    configs/containerd-config.toml \
    configs/kube-proxy-config.yaml \
    units/containerd.service \
    units/kubelet.service \
    units/kube-proxy.service \
    downloads/cni-plugins/ \
    vagrant@${HOST}:~/
done
for HOST in node01 node02; do
  scp -r \
    downloads/cni-plugins/ \
    vagrant@${HOST}:~/cni-plugins/
done

The commands in the next section must be run on each worker instance: node01, node02. Login to the worker instance using the ssh command. Example:

ssh vagrant@node01

Provisioning a Kubernetes Worker Node

Install the OS dependencies:

{
  sudo apt-get update
  sudo apt-get -y install socat conntrack ipset kmod
}

The socat binary enables support for the kubectl port-forward command.

Disable Swap

Kubernetes has limited support for the use of swap memory, as it is difficult to provide guarantees and account for pod memory utilization when swap is involved.

Verify if swap is disabled:

swapon --show

If output is empty then swap is disabled. If swap is enabled run the following command to disable swap immediately:

swapoff -a

To ensure swap remains off after reboot consult your Linux distro documentation.

Create the installation directories:

sudo mkdir -p \
  /etc/cni/net.d \
  /opt/cni/bin \
  /var/lib/kubelet \
  /var/lib/kube-proxy \
  /var/lib/kubernetes \
  /var/run/kubernetes

Install the worker binaries:

{
  sudo mv crictl kube-proxy kubelet kubectl /usr/local/bin/
  sudo mv runc /usr/local/sbin/
  sudo mv containerd ctr containerd-shim-runc-v2 containerd-stress /bin/
  sudo mv cni-plugins/* /opt/cni/bin/
}

Configure CNI Networking

Create the bridge network configuration file:

sudo mv 10-bridge.conf 99-loopback.conf /etc/cni/net.d/

To ensure network traffic crossing the CNI bridge network is processed by iptables, load and configure the br-netfilter kernel module:

{
  sudo modprobe br-netfilter
  echo "br-netfilter" | sudo tee -a /etc/modules-load.d/modules.conf
}
{
  echo "net.bridge.bridge-nf-call-iptables = 1" | sudo tee -a /etc/sysctl.d/kubernetes.conf
  echo "net.bridge.bridge-nf-call-ip6tables = 1" | sudo tee -a /etc/sysctl.d/kubernetes.conf
  sudo sysctl -p /etc/sysctl.d/kubernetes.conf
}

Configure containerd

Install the containerd configuration files:

{
  sudo mkdir -p /etc/containerd/
  sudo mv containerd-config.toml /etc/containerd/config.toml
  sudo mv containerd.service /etc/systemd/system/
}

Configure the Kubelet

Create the kubelet-config.yaml configuration file:

{
  sudo mv kubelet-config.yaml /var/lib/kubelet/
  sudo mv kubelet.service /etc/systemd/system/
}

Configure the Kubernetes Proxy

{
  sudo mv kube-proxy-config.yaml /var/lib/kube-proxy/
  sudo mv kube-proxy.service /etc/systemd/system/
}

Start the Worker Services

{
  sudo systemctl daemon-reload
  sudo systemctl enable containerd kubelet kube-proxy
  sudo systemctl start containerd kubelet kube-proxy
}

Check if the kubelet service is running:

sudo systemctl status kubelet
● kubelet.service - Kubernetes Kubelet
     Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2025-06-03 15:36:24 UTC; 28s ago
       Docs: https://github.com/kubernetes/kubernetes
   Main PID: 5645 (kubelet)
      Tasks: 10 (limit: 1102)
     Memory: 27.8M
        CPU: 501ms
     CGroup: /system.slice/kubelet.service
             └─5645 /usr/local/bin/kubelet --config=/var/lib/kubelet/kubelet-config.yaml --kubeconfig=/var/lib/kubelet/kubeconfig --v=2

Jun 03 15:36:24 node02 kubelet[5645]: I0603 15:36:24.878735    5645 kubelet_node_status.go:687] "Recording event message for node" node="node02" event="NodeHasNoDiskPressure"
Jun 03 15:36:24 node02 kubelet[5645]: I0603 15:36:24.878809    5645 kubelet_node_status.go:687] "Recording event message for node" node="node02" event="NodeHasSufficientPID"
Jun 03 15:36:24 node02 kubelet[5645]: I0603 15:36:24.878879    5645 kubelet_node_status.go:75] "Attempting to register node" node="node02"
Jun 03 15:36:24 node02 kubelet[5645]: I0603 15:36:24.886841    5645 kubelet_node_status.go:78] "Successfully registered node" node="node02"

Be sure to complete the steps in this section on each worker node, node01 and node02, before moving on to the next section.

Verification

Run the following commands from the jumpbox machine.

List the registered Kubernetes nodes:

ssh vagrant@controlplane \
  "kubectl get nodes \
  --kubeconfig admin.kubeconfig"
NAME     STATUS   ROLES    AGE     VERSION
node01   Ready    <none>   2m5s    v1.33.1
node02   Ready    <none>   2m12s   v1.33.1

Next: Configuring kubectl for Remote Access