---
abstract: This post describes a simple networking implementation with Flannel.
author: Xander Harris
blogpost: true
category: Networking
date: 2025-08-08
tags: kubelet, networking, flannel
title: Deploy the Flannel Networking Add On
---

```{topic} Cluster Status before Flannel
At this point in our cluster deployment we should have 1 control plane node
and at least two worker nodes that will not present themselves as ready
due to the lack of a proper CNI plugin.

:::{code-block} shell
:caption: current node status

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
:::

In this post, we'll install that plugin and make sure it's working.
```

(deploy-flannel-networking)=
## Flannel for networking

There are quite a few
[Networking Add Ons](https://kubernetes.io/docs/concepts/cluster-administration/addons/#networking-and-network-policy)
for {term}`Kubernetes` to choose from.

The author has direct experience with
{term}`Calico`, {term}`Cillium`, and {term}`Flannel` of
which {term}`Flannel` is the easiest to work with and explain.

## Flannel Install Guide

There are at least two methods for installing {term}`Flannel`.

### Install Flannel with `kubectl`{l=shell}

For those in a rush, the simplest method[^simplest-method] is to install via
`kubectl apply`{l=shell}.

```{code-block} shell
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
```

### Install Flannel with Helm

Deploying with Helm[^helm-method] requires a few more steps, but also allows
for much easier customization.

1. Create a namespace called `kube-flannel`.

   ```{code-block} shell
   :caption: make a namespace

   kubectl create ns kube-flannel
   ```

2. Enable privileged containers in the new `kube-flannel` namespace.

   ```{code-block} shell
   :caption: update the namespace properties

   kubectl label --overwrite ns kube-flannel pod-security.kubernetes.io/enforce=privileged
   ```

3. Add the {term}`Flannel` Helm repository to your local repositories.

   ```{code-block} shell
   :caption: add the repository to your local list

   helm repo add flannel https://flannel-io.github.io/flannel/
   ```

4. Install {term}`Flannel` with Helm, adjusting values as required.

   ```{code-block} shell
   :caption: finally install flannel

   helm install flannel --set podCidr="10.244.0.0/16" --namespace kube-flannel flannel/flannel
   ```

   If this runs as expected, you'll see a result like the following.

   ```{code-block} shell
   :caption: flannel deployed via helm

   NAME: flannel
   LAST DEPLOYED: Sun Sep  7 07:43:51 2025
   NAMESPACE: kube-flannel
   STATUS: deployed
   REVISION: 1
   TEST SUITE: None
   ```

We now have a cluster that's ready to run workloads.

```{topic} Cluster Status after Flannel
With {term}`Flannel` installed we can check the status of our cluster and see
the control plane and our worker nodes reporting ready.

:::{code-block} shell
NAME    STATUS   ROLES           AGE     VERSION
thw00   Ready    control-plane   6d20h   v1.33.4
thw01   Ready    <none>          6d20h   v1.33.4
thw02   Ready    <none>          6d20h   v1.33.4
thw03   Ready    <none>          6d20h   v1.33.4
:::

The next thing we'll look at is enabling dynamically provisioned storage.
```

[^simplest-method]: [Install with kubectl](https://github.com/flannel-io/flannel?tab=readme-ov-file#deploying-flannel-with-kubectl).

[^helm-method]: [Install with Helm](https://github.com/flannel-io/flannel?tab=readme-ov-file#deploying-flannel-with-helm).
