# Installing kubeadm

LLMS index: [llms.txt](/llms.txt)

---

<!-- overview -->

<img src="/images/kubeadm-stacked-color.png" align="right" width="150px"></img>
This page shows how to install the `kubeadm` toolbox.
For information on how to create a cluster with kubeadm once you have performed this installation process,
see the [Creating a cluster with kubeadm](/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/) page.







<div class="version-list">
    <p>
        This installation guide is for Kubernetes v1.36. If you want to use a different Kubernetes version, please refer to the following pages instead:
    </p>
    <ul>
        
            
        
            
            <li>
                <a href="https://v1-35.docs.kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/">Installing kubeadm (Kubernetes v1.35)</a>
            </li>
            
        
            
            <li>
                <a href="https://v1-34.docs.kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/">Installing kubeadm (Kubernetes v1.34)</a>
            </li>
            
        
            
            <li>
                <a href="https://v1-33.docs.kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/">Installing kubeadm (Kubernetes v1.33)</a>
            </li>
            
        
            
            <li>
                <a href="https://v1-32.docs.kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/">Installing kubeadm (Kubernetes v1.32)</a>
            </li>
            
        
    </ul>
</div>


## Before you begin

* A compatible Linux host. The Kubernetes project provides generic instructions for Linux distributions
  based on Debian and Red Hat, and those distributions without a package manager.
* 2 GB or more of RAM per machine (any less will leave little room for your apps).
* 2 CPUs or more for control plane machines.
* Full network connectivity between all machines in the cluster (public or private network is fine).
* Unique hostname, MAC address, and product_uuid for every node. See [here](#verify-mac-address) for more details.
* Certain ports are open on your machines. See [here](#check-required-ports) for more details.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>The <code>kubeadm</code> installation is done via binaries that use dynamic linking and assumes that your target system provides <code>glibc</code>.
This is a reasonable assumption on many Linux distributions (including Debian, Ubuntu, Fedora, CentOS, etc.)
but it is not always the case with custom and lightweight distributions which don't include <code>glibc</code> by default, such as Alpine Linux.
The expectation is that the distribution either includes <code>glibc</code> or a
<a href="https://wiki.alpinelinux.org/wiki/Running_glibc_programs">compatibility layer</a>
that provides the expected symbols.</div>


<!-- steps -->

## Check your OS version

<div class="alert alert-secondary callout third-party-content" role="note"><strong>Note:</strong>&puncsp;This section links to third party projects that provide functionality required by Kubernetes. The Kubernetes project authors aren't responsible for these projects, which are listed alphabetically. To add a project to this list, read the <a href="/docs/contribute/style/content-guide/#third-party-content">content guide</a> before submitting a change. <a href="#third-party-content-disclaimer">More information.</a></div>


<ul class="nav nav-tabs" id="tabs-operating-system-version-check" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-operating-system-version-check-0" role="tab" aria-controls="tabs-operating-system-version-check-0" aria-selected="true">Linux</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-operating-system-version-check-1" role="tab" aria-controls="tabs-operating-system-version-check-1">Windows</a></li></ul>

<div class="tab-content" id="tabs-operating-system-version-check-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-operating-system-version-check-0" role="tabpanel" aria-labelledby="tabs-operating-system-version-check-0-tab" tabindex="operating-system-version-check"><ul>
<li>The kubeadm project supports LTS kernels. See <a href="https://www.kernel.org/category/releases.html">List of LTS kernels</a>.</li>
<li>You can get the kernel version using the command <code>uname -r</code></li>
</ul>
<p>For more information, see <a href="/docs/reference/node/kernel-version-requirements/">Linux Kernel Requirements</a>.</p>
</div><div class="tab-body tab-pane fade"
        id="tabs-operating-system-version-check-1" role="tabpanel" aria-labelledby="tabs-operating-system-version-check-1-tab" tabindex="operating-system-version-check"><ul>
<li>The kubeadm project supports recent kernel versions. For a list of recent kernels, see <a href="https://learn.microsoft.com/en-us/windows/release-health/windows-server-release-info">Windows Server Release Information</a>.</li>
<li>You can get the kernel version (also called the OS version) using the command <code>systeminfo</code></li>
</ul>
<p>For more information, see <a href="/docs/concepts/windows/intro/#windows-os-version-support">Windows OS version compatibility</a>.</p>
</div></div>


A Kubernetes cluster created by kubeadm depends on software that use kernel features.
This software includes, but is not limited to the
<a class='glossary-tooltip' title='The container runtime is the software that is responsible for running containers.' data-bs-toggle='tooltip' data-bs-placement='top' href='/docs/setup/production-environment/container-runtimes' target='_blank' aria-label='container runtime'>container runtime</a>,
the <a class='glossary-tooltip' title='An agent that runs on each node in the cluster. It makes sure that containers are running in a pod.' data-bs-toggle='tooltip' data-bs-placement='top' href='/docs/reference/command-line-tools-reference/kubelet' target='_blank' aria-label='kubelet'>kubelet</a>, and a <a class='glossary-tooltip' title='Container network interface (CNI) plugins are a type of Network plugin that adheres to the appc/CNI specification.' data-bs-toggle='tooltip' data-bs-placement='top' href='/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/' target='_blank' aria-label='Container Network Interface'>Container Network Interface</a> plugin.

To help you avoid unexpected errors as a result of an unsupported kernel version, kubeadm runs the `SystemVerification`
pre-flight check. This check fails if the kernel version is not supported.

You may choose to skip the check, if you know that your kernel
provides the required features, even though kubeadm does not support its version.

## Verify the MAC address and product_uuid are unique for every node {#verify-mac-address}

* You can get the MAC address of the network interfaces using the command `ip link` or `ifconfig -a`
* The product_uuid can be checked by using the command `sudo cat /sys/class/dmi/id/product_uuid`

It is very likely that hardware devices will have unique addresses, although some virtual machines may have
identical values. Kubernetes uses these values to uniquely identify the nodes in the cluster.
If these values are not unique to each node, the installation process
may [fail](https://github.com/kubernetes/kubeadm/issues/31).

## Check network adapters

If you have more than one network adapter, and your Kubernetes components are not reachable on the default
route, we recommend you add IP route(s) so Kubernetes cluster addresses go via the appropriate adapter.

## Check required ports {#check-required-ports}

These [required ports](/docs/reference/networking/ports-and-protocols/)
need to be open in order for Kubernetes components to communicate with each other.
You can use tools like [netcat](https://netcat.sourceforge.net) to check if a port is open. For example:

```shell
nc 127.0.0.1 6443 -zv -w 2
```

The pod network plugin you use may also require certain ports to be
open. Since this differs with each pod network plugin, please see the
documentation for the plugins about what port(s) those need.

## Swap configuration {#swap-configuration}

The default behavior of a kubelet is to fail to start if swap memory is detected on a node.
This means that swap should either be disabled or tolerated by kubelet.

* To tolerate swap, add `failSwapOn: false` to kubelet configuration or as a command line argument.
  Note: even if `failSwapOn: false` is provided, workloads wouldn't have swap access by default.
  This can be changed by setting a `swapBehavior`, again in the kubelet configuration file. To use swap,
  set a `swapBehavior` other than the default `NoSwap` setting.
  See [Swap memory management](/docs/concepts/cluster-administration/swap-memory-management) for more details.
* To disable swap, `sudo swapoff -a` can be used to disable swapping temporarily.
  To make this change persistent across reboots, make sure swap is disabled in
  config files like `/etc/fstab`, `systemd.swap`, depending how it was configured on your system.


## Installing a container runtime {#installing-runtime}

To run containers in Pods, Kubernetes uses a
<a class='glossary-tooltip' title='The container runtime is the software that is responsible for running containers.' data-bs-toggle='tooltip' data-bs-placement='top' href='/docs/setup/production-environment/container-runtimes' target='_blank' aria-label='container runtime'>container runtime</a>.

By default, Kubernetes uses the
<a class='glossary-tooltip' title='Protocol for communication between the kubelet and the local container runtime.' data-bs-toggle='tooltip' data-bs-placement='top' href='/docs/concepts/architecture/cri' target='_blank' aria-label='Container Runtime Interface'>Container Runtime Interface</a> (CRI)
to interface with your chosen container runtime.

If you don't specify a runtime, kubeadm automatically tries to detect an installed
container runtime by scanning through a list of known endpoints.

If multiple or no container runtimes are detected kubeadm will throw an error
and will request that you specify which one you want to use.

See [container runtimes](/docs/setup/production-environment/container-runtimes/)
for more information.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>Docker Engine does not implement the <a href="/docs/concepts/architecture/cri/">CRI</a>
which is a requirement for a container runtime to work with Kubernetes.
For that reason, an additional service <a href="https://mirantis.github.io/cri-dockerd/">cri-dockerd</a>
has to be installed. cri-dockerd is a project based on the legacy built-in
Docker Engine support that was <a href="/dockershim">removed</a> from the kubelet in version 1.24.</div>


The tables below include the known endpoints for supported operating systems:

<ul class="nav nav-tabs" id="tabs-container-runtime" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-container-runtime-0" role="tab" aria-controls="tabs-container-runtime-0" aria-selected="true">Linux</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-container-runtime-1" role="tab" aria-controls="tabs-container-runtime-1">Windows</a></li></ul>

<div class="tab-content" id="tabs-container-runtime-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-container-runtime-0" role="tabpanel" aria-labelledby="tabs-container-runtime-0-tab" tabindex="container-runtime"><table><caption style="display: none;">Linux container runtimes</caption>
	<thead>
			<tr>
					<th>Runtime</th>
					<th>Path to Unix domain socket</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>containerd</td>
					<td><code>unix:///var/run/containerd/containerd.sock</code></td>
			</tr>
			<tr>
					<td>CRI-O</td>
					<td><code>unix:///var/run/crio/crio.sock</code></td>
			</tr>
			<tr>
					<td>Docker Engine (using cri-dockerd)</td>
					<td><code>unix:///var/run/cri-dockerd.sock</code></td>
			</tr>
	</tbody>
</table>
</div><div class="tab-body tab-pane fade"
        id="tabs-container-runtime-1" role="tabpanel" aria-labelledby="tabs-container-runtime-1-tab" tabindex="container-runtime"><table><caption style="display: none;">Windows container runtimes</caption>
	<thead>
			<tr>
					<th>Runtime</th>
					<th>Path to Windows named pipe</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>containerd</td>
					<td><code>npipe:////./pipe/containerd-containerd</code></td>
			</tr>
			<tr>
					<td>Docker Engine (using cri-dockerd)</td>
					<td><code>npipe:////./pipe/cri-dockerd</code></td>
			</tr>
	</tbody>
</table>
</div></div>


## Installing kubeadm, kubelet and kubectl

You will install these packages on all of your machines:

* `kubeadm`: the command to bootstrap the cluster.

* `kubelet`: the component that runs on all of the machines in your cluster
  and does things like starting pods and containers.

* `kubectl`: the command line util to talk to your cluster.

kubeadm **will not** install or manage `kubelet` or `kubectl` for you, so you will
need to ensure they match the version of the Kubernetes control plane you want
kubeadm to install for you. If you do not, there is a risk of a version skew occurring that
can lead to unexpected, buggy behaviour. However, _one_ minor version skew between the
kubelet and the control plane is supported, but the kubelet version may never exceed the API
server version. For example, the kubelet running 1.7.0 should be fully compatible with a 1.8.0 API server,
but not vice versa.

For information about installing `kubectl`, see [Install and set up kubectl](/docs/tasks/tools/).

<div class="alert alert-danger" role="note"><h4 class="alert-heading">Warning:</h4>These instructions exclude all Kubernetes packages from any system upgrades.
This is because kubeadm and Kubernetes require
<a href="/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/">special attention to upgrade</a>.</div>


For more information on version skews, see:

* Kubernetes [version and version-skew policy](/docs/setup/release/version-skew-policy/)
* Kubeadm-specific [version skew policy](/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#version-skew-policy)

<div class="alert alert-secondary callout note" role="note">
  <strong>Note:</strong> The legacy package repositories (<code>apt.kubernetes.io</code> and <code>yum.kubernetes.io</code>) have been
<a href="/blog/2023/08/31/legacy-package-repository-deprecation/">deprecated and frozen starting from September 13, 2023</a>.
<strong>Using the <a href="/blog/2023/08/15/pkgs-k8s-io-introduction/">new package repositories hosted at <code>pkgs.k8s.io</code></a>
is strongly recommended and required in order to install Kubernetes versions released after September 13, 2023.</strong>
The deprecated legacy repositories, and their contents, might be removed at any time in the future and without
a further notice period. The new package repositories provide downloads for Kubernetes versions starting with v1.24.0.
</div>



<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>There's a dedicated package repository for each Kubernetes minor version. If you want to install
a minor version other than v1.36, please see the installation guide for
your desired minor version.</div>


<ul class="nav nav-tabs" id="tabs-k8s-install" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-k8s-install-0" role="tab" aria-controls="tabs-k8s-install-0" aria-selected="true">Debian-based distributions</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-k8s-install-1" role="tab" aria-controls="tabs-k8s-install-1">Red Hat-based distributions</a></li>
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-k8s-install-2" role="tab" aria-controls="tabs-k8s-install-2">Without a package manager</a></li></ul>

<div class="tab-content" id="tabs-k8s-install-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-k8s-install-0" role="tabpanel" aria-labelledby="tabs-k8s-install-0-tab" tabindex="k8s-install"><p>These instructions are for Kubernetes v1.36.</p>
<ol>
<li>
<p>Update the <code>apt</code> package index and install packages needed to use the Kubernetes <code>apt</code> repository:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">sudo apt-get update
</span></span><span class="line"><span class="cl"><span class="c1"># apt-transport-https may be a dummy package; if so, you can skip that package</span>
</span></span><span class="line"><span class="cl">sudo apt-get install -y apt-transport-https ca-certificates curl gpg
</span></span></code></pre></div></li>
<li>
<p>Download the public signing key for the Kubernetes package repositories.
The same signing key is used for all repositories so you can disregard the version in the URL:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># If the directory `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below.</span>
</span></span><span class="line"><span class="cl"><span class="c1"># sudo mkdir -p -m 755 /etc/apt/keyrings</span>
</span></span><span class="line"><span class="cl">curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key <span class="p">|</span> sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
</span></span></code></pre></div></li>
</ol>
<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>In releases older than Debian 12 and Ubuntu 22.04, directory <code>/etc/apt/keyrings</code> does not
exist by default, and it should be created before the curl command.</div>
<ol start="3">
<li>
<p>Add the appropriate Kubernetes <code>apt</code> repository. Please note that this repository have packages
only for Kubernetes 1.36; for other Kubernetes minor versions, you need to
change the Kubernetes minor version in the URL to match your desired minor version
(you should also check that you are reading the documentation for the version of Kubernetes
that you plan to install).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s1">&#39;deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /&#39;</span> <span class="p">|</span> sudo tee /etc/apt/sources.list.d/kubernetes.list
</span></span></code></pre></div></li>
<li>
<p>Update the <code>apt</code> package index, install kubelet, kubeadm and kubectl, and pin their version:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">sudo apt-get update
</span></span><span class="line"><span class="cl">sudo apt-get install -y kubelet kubeadm kubectl
</span></span><span class="line"><span class="cl">sudo apt-mark hold kubelet kubeadm kubectl
</span></span></code></pre></div></li>
<li>
<p>(Optional) Enable the kubelet service before running kubeadm:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> --now kubelet
</span></span></code></pre></div></li>
</ol>
</div><div class="tab-body tab-pane fade"
        id="tabs-k8s-install-1" role="tabpanel" aria-labelledby="tabs-k8s-install-1-tab" tabindex="k8s-install"><ol>
<li>
<p>Set SELinux to <code>permissive</code> mode:</p>
<p>These instructions are for Kubernetes 1.36.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># Set SELinux in permissive mode (effectively disabling it)</span>
</span></span><span class="line"><span class="cl">sudo setenforce <span class="m">0</span>
</span></span><span class="line"><span class="cl">sudo sed -i <span class="s1">&#39;s/^SELINUX=enforcing$/SELINUX=permissive/&#39;</span> /etc/selinux/config
</span></span></code></pre></div></li>
</ol>
<div class="alert alert-caution" role="note"><h4 class="alert-heading">Caution:</h4><ul>
<li>Setting SELinux in permissive mode by running <code>setenforce 0</code> and <code>sed ...</code>
effectively disables it. This is required to allow containers to access the host
filesystem; for example, some cluster network plugins require that. You have to
do this until SELinux support is improved in the kubelet.</li>
<li>You can leave SELinux enabled if you know how to configure it but it may require
settings that are not supported by kubeadm.</li>
</ul>
</div>
<ol start="2">
<li>
<p>Add the Kubernetes <code>yum</code> repository. The <code>exclude</code> parameter in the
repository definition ensures that the packages related to Kubernetes are
not upgraded upon running <code>yum update</code> as there's a special procedure that
must be followed for upgrading Kubernetes. Please note that this repository
have packages only for Kubernetes 1.36; for other
Kubernetes minor versions, you need to change the Kubernetes minor version
in the URL to match your desired minor version (you should also check that
you are reading the documentation for the version of Kubernetes that you
plan to install).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># This overwrites any existing configuration in /etc/yum.repos.d/kubernetes.repo</span>
</span></span><span class="line"><span class="cl">cat <span class="s">&lt;&lt;EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
</span></span></span><span class="line"><span class="cl"><span class="s">[kubernetes]
</span></span></span><span class="line"><span class="cl"><span class="s">name=Kubernetes
</span></span></span><span class="line"><span class="cl"><span class="s">baseurl=https://pkgs.k8s.io/core:/stable:/v1.36/rpm/
</span></span></span><span class="line"><span class="cl"><span class="s">enabled=1
</span></span></span><span class="line"><span class="cl"><span class="s">gpgcheck=1
</span></span></span><span class="line"><span class="cl"><span class="s">gpgkey=https://pkgs.k8s.io/core:/stable:/v1.36/rpm/repodata/repomd.xml.key
</span></span></span><span class="line"><span class="cl"><span class="s">exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span></code></pre></div></li>
<li>
<p>Install kubelet, kubeadm and kubectl:</p>
<p>For systems with DNF:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">sudo yum install -y kubelet kubeadm kubectl --disableexcludes<span class="o">=</span>kubernetes
</span></span></code></pre></div><p>For systems with DNF5:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">sudo yum install -y kubelet kubeadm kubectl --setopt<span class="o">=</span><span class="nv">disable_excludes</span><span class="o">=</span>kubernetes
</span></span></code></pre></div></li>
<li>
<p>(Optional) Enable the kubelet service before running kubeadm:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> --now kubelet
</span></span></code></pre></div></li>
</ol>
</div><div class="tab-body tab-pane fade"
        id="tabs-k8s-install-2" role="tabpanel" aria-labelledby="tabs-k8s-install-2-tab" tabindex="k8s-install"><p>Install CNI plugins (required for most pod network):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">CNI_PLUGINS_VERSION</span><span class="o">=</span><span class="s2">&#34;v1.3.0&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">ARCH</span><span class="o">=</span><span class="s2">&#34;amd64&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">DEST</span><span class="o">=</span><span class="s2">&#34;/opt/cni/bin&#34;</span>
</span></span><span class="line"><span class="cl">sudo mkdir -p <span class="s2">&#34;</span><span class="nv">$DEST</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">curl -L <span class="s2">&#34;https://github.com/containernetworking/plugins/releases/download/</span><span class="si">${</span><span class="nv">CNI_PLUGINS_VERSION</span><span class="si">}</span><span class="s2">/cni-plugins-linux-</span><span class="si">${</span><span class="nv">ARCH</span><span class="si">}</span><span class="s2">-</span><span class="si">${</span><span class="nv">CNI_PLUGINS_VERSION</span><span class="si">}</span><span class="s2">.tgz&#34;</span> <span class="p">|</span> sudo tar -C <span class="s2">&#34;</span><span class="nv">$DEST</span><span class="s2">&#34;</span> -xz
</span></span></code></pre></div><p>Define the directory to download command files:</p>
<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>The <code>DOWNLOAD_DIR</code> variable must be set to a writable directory.
If you are running Flatcar Container Linux, set <code>DOWNLOAD_DIR=&quot;/opt/bin&quot;</code>.</div>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">DOWNLOAD_DIR</span><span class="o">=</span><span class="s2">&#34;/usr/local/bin&#34;</span>
</span></span><span class="line"><span class="cl">sudo mkdir -p <span class="s2">&#34;</span><span class="nv">$DOWNLOAD_DIR</span><span class="s2">&#34;</span>
</span></span></code></pre></div><p>Optionally install crictl (required for interaction with the Container Runtime Interface (CRI), optional for kubeadm):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">CRICTL_VERSION</span><span class="o">=</span><span class="s2">&#34;v1.31.0&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">ARCH</span><span class="o">=</span><span class="s2">&#34;amd64&#34;</span>
</span></span><span class="line"><span class="cl">curl -L <span class="s2">&#34;https://github.com/kubernetes-sigs/cri-tools/releases/download/</span><span class="si">${</span><span class="nv">CRICTL_VERSION</span><span class="si">}</span><span class="s2">/crictl-</span><span class="si">${</span><span class="nv">CRICTL_VERSION</span><span class="si">}</span><span class="s2">-linux-</span><span class="si">${</span><span class="nv">ARCH</span><span class="si">}</span><span class="s2">.tar.gz&#34;</span> <span class="p">|</span> sudo tar -C <span class="nv">$DOWNLOAD_DIR</span> -xz
</span></span></code></pre></div><p>Install <code>kubeadm</code>, <code>kubelet</code> and add a <code>kubelet</code> systemd service:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">RELEASE</span><span class="o">=</span><span class="s2">&#34;</span><span class="k">$(</span>curl -sSL https://dl.k8s.io/release/stable.txt<span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">ARCH</span><span class="o">=</span><span class="s2">&#34;amd64&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> <span class="nv">$DOWNLOAD_DIR</span>
</span></span><span class="line"><span class="cl">sudo curl -L --remote-name-all https://dl.k8s.io/release/<span class="si">${</span><span class="nv">RELEASE</span><span class="si">}</span>/bin/linux/<span class="si">${</span><span class="nv">ARCH</span><span class="si">}</span>/<span class="o">{</span>kubeadm,kubelet<span class="o">}</span>
</span></span><span class="line"><span class="cl">sudo chmod +x <span class="o">{</span>kubeadm,kubelet<span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">RELEASE_VERSION</span><span class="o">=</span><span class="s2">&#34;v0.16.2&#34;</span>
</span></span><span class="line"><span class="cl">curl -sSL <span class="s2">&#34;https://raw.githubusercontent.com/kubernetes/release/</span><span class="si">${</span><span class="nv">RELEASE_VERSION</span><span class="si">}</span><span class="s2">/cmd/krel/templates/latest/kubelet/kubelet.service&#34;</span> <span class="p">|</span> sed <span class="s2">&#34;s:/usr/bin:</span><span class="si">${</span><span class="nv">DOWNLOAD_DIR</span><span class="si">}</span><span class="s2">:g&#34;</span> <span class="p">|</span> sudo tee /usr/lib/systemd/system/kubelet.service
</span></span><span class="line"><span class="cl">sudo mkdir -p /usr/lib/systemd/system/kubelet.service.d
</span></span><span class="line"><span class="cl">curl -sSL <span class="s2">&#34;https://raw.githubusercontent.com/kubernetes/release/</span><span class="si">${</span><span class="nv">RELEASE_VERSION</span><span class="si">}</span><span class="s2">/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf&#34;</span> <span class="p">|</span> sed <span class="s2">&#34;s:/usr/bin:</span><span class="si">${</span><span class="nv">DOWNLOAD_DIR</span><span class="si">}</span><span class="s2">:g&#34;</span> <span class="p">|</span> sudo tee /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
</span></span></code></pre></div><div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>Please refer to the note in the <a href="#before-you-begin">Before you begin</a> section for Linux distributions
that do not include <code>glibc</code> by default.</div>
<p>Install <code>kubectl</code> by following the instructions on <a href="/docs/tasks/tools/#kubectl">Install Tools page</a>.</p>
<p>Optionally, enable the kubelet service before running kubeadm:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> --now kubelet
</span></span></code></pre></div><div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>The Flatcar Container Linux distribution mounts the <code>/usr</code> directory as a read-only filesystem.
Before bootstrapping your cluster, you need to take additional steps to configure a writable directory.
See the <a href="/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/#usr-mounted-read-only">Kubeadm Troubleshooting guide</a>
to learn how to set up a writable directory.</div>
</div></div>


The kubelet is now restarting every few seconds, as it waits in a crashloop for
kubeadm to tell it what to do.

## Configuring a cgroup driver

Both the container runtime and the kubelet have a property called
["cgroup driver"](/docs/setup/production-environment/container-runtimes/#cgroup-drivers), which is important
for the management of cgroups on Linux machines.

<div class="alert alert-danger" role="note"><h4 class="alert-heading">Warning:</h4><p>Matching the container runtime and kubelet cgroup drivers is required or otherwise the kubelet process will fail.</p>
<p>See <a href="/docs/tasks/administer-cluster/kubeadm/configure-cgroup-driver/">Configuring a cgroup driver</a> for more details.</p>
</div>


## Troubleshooting

If you are running into difficulties with kubeadm, please consult our
[troubleshooting docs](/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/).

## What's next

* [Using kubeadm to Create a Cluster](/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/)
