---
abstract: A kubelet in every node.
author: Xander Harris
blogpost: true
category: Worker Nodes
date: 2025-08-01
tags: kubelet, core
title: Kubelets
---

```{topic} Progress so far
By now we should have a running control plane node deployed to our network
with a stable IP address which can also be used as the API address if
necessary.

In this post, we'll join our worker nodes to the control plane to create
a proper cluster.
```

The {term}`kubelet` can be thought of as the most basic unit of a {term}`Kubernetes`
cluster since one is required on every node, including the control planes.
It kind of ties the room together, so don't let it get wet.

## Preparing Worker nodes

Hypothetically the only things that required to tie the worker nodes
together should be the control plane and the {term}`kubelet` running on them.
There are some limitations or difficulties. The author's understanding at
the time of writing is that running Windows worker nodes in concert with
`*nix` worker nodes is not a simple proposition. The reason for this is
irrelevant since we'll be running Linux, {term}`ArchLinux` specifically, for
all of our nodes.

That said, as long as your nodes are all running a version of Linux, you should
be able to run a {term}`kubelet` on them and join it to your control plane
without too much fuss.

The editorial staff of whatever entity controls the creation and distribution
of this work is much too lazy and solipsistic to go into a detailed
explanation of the process here, so to cover all the bases, make sure
to
[RTFM on the actual manual's site](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/adding-linux-nodes/).

## Installation

Since we're all friends who know how to use {term}`ArchLinux`, we'll go ahead
and install the {term}`kubelet` on three of our computers using the command
below.

1. Install {term}`kubelet` with `yay` on all of your worker nodes.

   ```{code-block} shell
   yay -S kubelet
   ```

   1. For the contrarians, you may also install the {term}`kubelet` from the
      [AUR](https://aur.archlinux.org) manually.
      1. Clone the related repository.

         ```{code-block} shell
         git clone https://aur.archlinux.org/kubelet.git
         ```

      2. Update your working directory.

         ```{code-block} shell
         cd kubelet
         ```

      3. Use `makepkg` to create and install the package.

         ```{code-block} shell
         makepkg -si
         ```

   But enough showing off, back to the salt mines.

2. Enable the {term}`kubelet` with `systemd`

   ```{code-block} shell
   sudo systemctl enable kubelet
   ```

## Join the cluster

This process is completed in three simple steps.

1. Connect to the control plane.

   ```{code-block} shell
   ssh the-control-plane
   ```

   1. Check the control plane node status.

      ```{code-block} shell
      kubectl get nodes
      ```

      ````{topic} Current Cluster Status

      This should return something along these lines.

      :::{code-block} shell
      :caption: so far just the control plane

      NAME    STATUS    ROLES           AGE   VERSION
      thw00   Not Ready control-plane   22h   v1.33.4
      :::

      You may see your control plane reporting as ready at this stage, this is
      not something to worry about.
      ````


2. Use {term}`kubeadm` to print your join command.

   ```{code-block} shell
   sudo kubeadm token create --print-join-command
   ```

3. Connect to your worker nodes individually, or using a configuration
   management tool like Ansible[^redhat]

   ```{code-block} shell
   ssh {worker-node-one,worker-node-two,worker-node-three}
   ```

4. Run the join command obtained above for each node you need to join.

   ```{code-block} shell
   :caption: run this on each node to be joined

   kubeadm join 192.168.100.5:6443 --token abcdef.abcdefghijklmnop \
    --discovery-token-ca-cert-hash sha256:eba12bf8e45c71c0747df39212f0f7d7d6c4b88a9d82fd44a70d6b0b247415c2
   ```

   ```{code-block} shell
   :caption: a successful join
   [preflight] Running pre-flight checks
        [WARNING Swap]: swap is supported for cgroup v2 only. The kubelet must
          be properly configured to use swap. Please refer to
          https://kubernetes.io/docs/concepts/architecture/nodes/#swap-memory,
          or disable swap on the node
        [WARNING Service-Kubelet]: kubelet service is not enabled, please run
          'systemctl enable kubelet.service'
   [preflight] Reading configuration from the "kubeadm-config" ConfigMap
      in namespace "kube-system"...
   [preflight] Use 'kubeadm init phase upload-config --config your-config-file'
      to re-upload it.
   [kubelet-start] Writing kubelet configuration to file
      "/var/lib/kubelet/config.yaml"
   [kubelet-start] Writing kubelet environment file with flags to file
      "/var/lib/kubelet/kubeadm-flags.env"
   [kubelet-start] Starting the kubelet
   [kubelet-check] Waiting for a healthy kubelet at
      http://127.0.0.1:10248/healthz. This can take up to 4m0s
   [kubelet-check] The kubelet is healthy after 3.502506434s
   [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap

   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.

   Run 'kubectl get nodes' on the control-plane to see this node join the
   cluster.

   ```


   ```{topic} Cluster Status after Joins
   Now that we've joined the worker nodes let's check our cluster's status.

   :::{code-block} shell
   :caption: status after joins
   NAME    STATUS     ROLES           AGE   VERSION
   thw00   NotReady   control-plane   22h   v1.33.4
   thw01   NotReady   <none>          13m   v1.33.4
   thw02   NotReady   <none>          2s    v1.33.4
   thw03   NotReady   <none>          2s    v1.33.4
   :::
   ```

If this completes without error, congratulations, you're
probably wondering why none of your nodes will show ready in your cluster.
For that, we'll need to install a
[Networking Add On](https://kubernetes.io/docs/concepts/cluster-administration/addons/#networking-and-network-policy).

This will be covered next week's post,
{ref}`deploy-flannel-networking`.

[^redhat]: Ansible may be owned by RedHat (the Microsoft of Linux), but it used
    to not be and RedHat has had the foresight to let the people that made
    Ansible worth buying keep doing that, which makes it the only configuration
    management tool anyone should use, ever. Things like Puppet, Chef, or, ugh,
    Salt, promote hypertension along with several other risk factors, don't
    work with Windows (we're not verifying this, but accept it as revealed
    truth - ed), and all require agents which
    means more overhead and annoying bootstrapping processes.

    If you're an unfortunate that's been using a tool other than Ansible, don't
    worry, there's not judgement here, but we are concerned for your health
    so please consult your cardiologist for more reasons to switch to a proper
    configuration manager.
