← Back to DevBytes

Flannel Networking: Complete Setup and Configuration Guide

Understanding Flannel Networking

Flannel is a simple and robust overlay network fabric designed for Kubernetes. Its primary purpose is to provide a flat, layer 3 IP network between all nodes in a cluster, ensuring that every pod can communicate with every other pod across node boundaries without requiring port mapping or complex routing configurations. Flannel operates by assigning a unique subnet to each node in the cluster and managing the routing between these subnets through a configurable backend mechanism.

What Flannel Actually Does

At its core, Flannel solves a fundamental Kubernetes networking problem: pods scheduled on different nodes need to communicate with each other using their pod IP addresses directly. Without an overlay network, pods would be isolated to their host's network namespace. Flannel creates a virtual network that spans all nodes by:

Why Flannel Matters for Kubernetes Deployments

Flannel is often the first Container Network Interface (CNI) plugin that operators encounter because of its simplicity. It matters for several practical reasons:

Flannel Architecture Deep Dive

🚀 Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

Flannel consists of two main components working together: the flanneld daemon running on every node and the backend mechanism that handles actual packet delivery. Understanding this architecture is crucial for proper configuration and troubleshooting.

The flanneld Daemon

flanneld is a long-running process deployed as a DaemonSet in the kube-system namespace (or as a static pod in some bootstrap configurations). It performs these critical functions:

Backend Modes Explained

Flannel supports several backend modes, each with distinct encapsulation behavior and performance characteristics:

VXLAN Backend (Default)

VXLAN (Virtual Extensible LAN) is the most widely used backend. It encapsulates original Ethernet frames inside UDP packets, creating a virtual layer 2 overlay across the physical network. The flannel.1 VTEP (VXLAN Tunnel Endpoint) device on each node handles encapsulation and decapsulation. This mode works on virtually any network infrastructure because it only requires standard IP/UDP connectivity between nodes.

# Example VXLAN configuration snippet
{
  "Network": "10.244.0.0/16",
  "Backend": {
    "Type": "vxlan",
    "VNI": 1,
    "Port": 8472
  }
}

host-gw Backend

The host-gw (host gateway) backend eliminates encapsulation entirely. Instead, it adds direct static routes on each node pointing to the next-hop IP of the destination node for its subnet. This provides near-native performance but requires that all nodes have layer 2 adjacency — they must be on the same physical network segment without any router hops in between. For on-premises bare metal clusters, this is often the ideal choice.

# Example host-gw configuration snippet
{
  "Network": "10.244.0.0/16",
  "Backend": {
    "Type": "host-gw"
  }
}

Additional Backends

Flannel also provides specialized backends for cloud environments. The aws-vpc backend integrates with AWS networking to use VPC route tables instead of overlay tunnels. The gce backend similarly leverages Google Cloud networking primitives. The ipip backend uses IP-in-IP encapsulation for environments where VXLAN overhead is undesirable but direct layer 2 routing is impossible. The wireguard backend provides encrypted tunnels using the WireGuard protocol, adding security to node-to-node traffic.

Prerequisites and Planning

Before deploying Flannel, ensure your environment meets these requirements:

Complete Flannel Deployment Guide

Step 1: Choosing Your Pod Network CIDR

The default Flannel pod network CIDR is 10.244.0.0/16, which provides approximately 65,536 IP addresses across up to 255 nodes (each node gets a /24 subnet with 254 usable pod IPs). If you need more nodes, consider a larger CIDR like 10.0.0.0/12. The CIDR must not overlap with your node network, service network, or any network ranges used by your infrastructure.

Step 2: Deploy Flannel via the Official Manifest

The standard deployment method uses the official Kubernetes manifest from the Flannel repository. This manifest creates the necessary ClusterRole, ServiceAccount, ConfigMap, and DaemonSet objects. Apply it directly to your cluster:

# Download and apply the official Flannel manifest
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

This manifest configures Flannel with VXLAN backend, the default 10.244.0.0/16 pod network, and uses the Kubernetes API server as the subnet registry (eliminating the need for a separate etcd instance).

Step 3: Verifying the Deployment

After applying the manifest, verify that the Flannel pods are running on all nodes. The DaemonSet ensures one pod per node, including control-plane nodes if they aren't tainted:

# Check Flannel DaemonSet status
kubectl -n kube-system get daemonset kube-flannel-ds

# Verify pods are running on all nodes
kubectl -n kube-system get pods -l app=flannel -o wide

# Check the logs for any errors
kubectl -n kube-system logs -l app=flannel --tail=50

Expected output shows one pod per node in Running state. The pod distribution across nodes confirms the DaemonSet is working correctly.

Step 4: Testing Pod-to-Pod Communication

Create test pods on different nodes to validate cross-node networking. The following example deploys two busybox pods and tests connectivity between them:

# Create test namespace
kubectl create namespace flannel-test

# Deploy two busybox pods with anti-affinity to ensure different nodes
cat <

Successful ping responses indicate Flannel is working correctly. If pings fail, proceed to the troubleshooting section below.

Customizing Flannel Configuration

Modifying the kube-flannel ConfigMap

Flannel reads its configuration from a ConfigMap named kube-flannel-cfg in the kube-system namespace. To customize the network CIDR, backend type, or other parameters, edit this ConfigMap before deploying or update it and restart the flanneld pods:

# View the current configuration
kubectl -n kube-system get configmap kube-flannel-cfg -o yaml

# Edit the configuration
kubectl -n kube-system edit configmap kube-flannel-cfg

Here is a complete example of a custom ConfigMap using the host-gw backend with a different pod network CIDR:

apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-flannel-cfg
  namespace: kube-system
  labels:
    tier: node
    app: flannel
data:
  cni-conf.json: |
    {
      "name": "cbr0",
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "flannel",
          "delegate": {
            "hairpinMode": true,
            "isDefaultGateway": true
          }
        },
        {
          "type": "portmap",
          "capabilities": {
            "portMappings": true
          }
        }
      ]
    }
  net-conf.json: |
    {
      "Network": "172.16.0.0/16",
      "Backend": {
        "Type": "host-gw"
      }
    }

After updating the ConfigMap, restart the Flannel DaemonSet to apply changes:

# Delete existing pods to force recreation with new config
kubectl -n kube-system delete pods -l app=flannel

# Watch pods come back online
kubectl -n kube-system get pods -l app=flannel -w

Enabling Direct Server Return (DSR) with host-gw

When using host-gw backend in environments where nodes have multiple network interfaces, you may want to specify the exact external interface for routing. Use the "DirectRouting" option combined with explicit node IP annotations:

net-conf.json: |
  {
    "Network": "10.244.0.0/16",
    "Backend": {
      "Type": "host-gw",
      "DirectRouting": true
    }
  }

Advanced Flannel Configuration

Configuring Flannel with External etcd

While the default deployment uses the Kubernetes API server for subnet management, Flannel can also use an external etcd cluster. This is useful in bootstrap scenarios or when running Flannel outside of Kubernetes:

# Start flanneld with etcd backend
/opt/bin/flanneld \
  --etcd-endpoints=http://10.0.0.1:2379,http://10.0.0.2:2379 \
  --etcd-prefix=/coreos.com/network \
  --etcd-keyfile=/etc/ssl/etcd/key.pem \
  --etcd-certfile=/etc/ssl/etcd/cert.pem \
  --etcd-cafile=/etc/ssl/etcd/ca.pem

# Pre-configure etcd with network settings
etcdctl --endpoints=http://10.0.0.1:2379 \
  set /coreos.com/network/config \
  '{"Network":"10.244.0.0/16","Backend":{"Type":"vxlan","Port":8472}}'

WireGuard Backend for Encrypted Tunnels

The WireGuard backend encrypts all node-to-node traffic, which is essential in multi-tenant or untrusted network environments. To enable it, you must have WireGuard kernel modules loaded on all nodes:

# Install WireGuard tools on each node
sudo apt-get install wireguard-tools

# Verify WireGuard kernel module
lsmod | grep wireguard

# Configure Flannel for WireGuard
net-conf.json: |
  {
    "Network": "10.244.0.0/16",
    "Backend": {
      "Type": "wireguard",
      "PersistentKeepaliveInterval": 25
    }
  }

The PersistentKeepaliveInterval option (in seconds) helps maintain tunnels through NAT gateways by periodically sending keepalive packets.

Specifying Node Network Interface

In multi-homed nodes with several network interfaces, flanneld may select the wrong interface for tunnel traffic. Override this by setting the --iface or --public-ip flags in the DaemonSet pod spec:

# Relevant section of the DaemonSet container args
args:
- --ip-masq
- --kube-subnet-mgr
- --iface=ens192
- --public-ip=$(NODE_IP)

IP Masquerade Configuration

Flannel includes an IP masquerade rule by default (the --ip-masq flag) that NATs pod traffic exiting the node to the node's primary IP. This is essential for pods to reach external networks. You can disable it if you have other NAT rules or if you want to route pod IPs directly:

# Disable masquerade in the DaemonSet
args:
- --kube-subnet-mgr
# Remove --ip-masq from args list

When disabling masquerade, ensure your upstream network knows how to route pod IP ranges back to the respective nodes.

Troubleshooting Flannel Networking

Common Issues and Diagnostic Commands

Flannel problems typically manifest as pod-to-pod communication failures across nodes. Here is a systematic diagnostic approach:

# 1. Verify Flannel pods are healthy
kubectl -n kube-system get pods -l app=flannel
kubectl -n kube-system describe pod -l app=flannel

# 2. Check flanneld logs for subnet allocation issues
kubectl -n kube-system logs -l app=flannel --tail=100 | grep -i error

# 3. Verify the flannel virtual interface exists
ip link show flannel.1
ip addr show flannel.1

# 4. Check routing table entries managed by Flannel
ip route | grep flannel
# Expected output shows routes to remote pod subnets via flannel.1

# 5. Verify VXLAN UDP port is open (for VXLAN backend)
sudo tcpdump -i eth0 udp port 8472 -c 10

# 6. Check node subnet annotations
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}'

# 7. Inspect Flannel's internal network configuration
kubectl -n kube-system exec -it $(kubectl -n kube-system get pod -l app=flannel -o jsonpath='{.items[0].metadata.name}') -- cat /run/flannel/subnet.env

Diagnosing VXLAN Encapsulation Issues

If you suspect VXLAN forwarding problems, capture traffic on both the source and destination nodes:

# On source node: capture VXLAN traffic to destination node IP
sudo tcpdump -i eth0 -n "udp port 8472 and host " -w flannel-vxlan.pcap

# On destination node: capture incoming VXLAN traffic
sudo tcpdump -i eth0 -n "udp port 8472 and host " -w flannel-incoming.pcap

# Analyze the captures
tcpdump -r flannel-vxlan.pcap -n -v

Fixing Stale Subnet Allocations

When a node is removed from the cluster without proper cleanup, its subnet allocation may remain reserved, preventing new nodes from getting subnets. Clear stale allocations:

# List all subnet allocations stored in Kubernetes
kubectl get nodes -o custom-columns=NAME:.metadata.name,PODCIDR:.spec.podCIDR

# If a node no longer exists but its subnet is still allocated,
# check Flannel's lease cleanup mechanism or manually remove
# the node object if it's truly gone
kubectl delete node 

# Force flanneld to re-allocate by restarting pods
kubectl -n kube-system delete pods -l app=flannel

MTU Considerations

VXLAN encapsulation adds overhead (approximately 50 bytes for the VXLAN header plus UDP and IP headers). If your physical network MTU is 1500, pods will see a reduced MTU. Flannel automatically sets the correct MTU on the flannel.1 interface, but verify it matches your expectations:

# Check the MTU on the flannel interface
ip link show flannel.1 | grep mtu

# Verify pod interfaces have correct MTU
kubectl exec -it  -- ip link show eth0 | grep mtu

If you're using jumbo frames (MTU 9000) on your physical network, you can configure Flannel to take advantage of them by setting the MTU in the backend configuration.

Flannel in Production: Best Practices

Choose the Right Backend for Your Environment

  • On-premises bare metal with flat network — use host-gw for maximum throughput and minimal overhead
  • Cloud environments or routed networks — use VXLAN for universal compatibility
  • Security-sensitive deployments — use WireGuard backend to encrypt all inter-node traffic
  • AWS deployments — consider aws-vpc backend to offload routing to VPC route tables

Dedicated Pod Network CIDR Planning

Allocate a pod network CIDR that is large enough for your cluster's growth. A /16 provides 255 node subnets; if you expect more than 200 nodes, use a /12 or /8. Reserve this CIDR exclusively for pods — never let it overlap with service CIDRs, node IP ranges, or VPN address spaces. Document the allocation in your network architecture diagrams.

Monitoring Flannel Health

Set up monitoring for Flannel-specific metrics and logs. Key indicators to watch:

  • Flannel pod restarts — frequent restarts indicate configuration or resource issues
  • Subnet allocation failures — visible in flanneld logs as "failed to register subnet" errors
  • VXLAN packet loss — monitor UDP port 8472 traffic for drops
  • Node pod CIDR assignment — every node should have a non-empty podCIDR in its spec
# Example Prometheus alert for Flannel pod status
alert: FlannelDaemonSetUnhealthy
expr: |
  sum(kube_daemonset_status_number_ready{
    namespace="kube-system",
    daemonset="kube-flannel-ds"
  }) < sum(kube_node_info)
for: 5m
labels:
  severity: critical
annotations:
  summary: "Flannel pods missing on some nodes"

Securing Flannel Traffic

By default, VXLAN traffic is unencrypted. If your nodes communicate over untrusted networks, implement one of these strategies:

  • Use the WireGuard backend for built-in encryption
  • Apply IPsec transport mode encryption between nodes at the system level
  • Restrict VXLAN UDP port 8472 to only the cluster node IPs using firewall rules
# Example iptables rule to restrict VXLAN traffic to cluster nodes
iptables -A INPUT -p udp --dport 8472 \
  -s  -j ACCEPT
iptables -A INPUT -p udp --dport 8472 -j DROP

# Example firewall rules for WireGuard port
iptables -A INPUT -p udp --dport 51820 \
  -s  -j ACCEPT
iptables -A INPUT -p udp --dport 51820 -j DROP

Upgrading Flannel

Flannel upgrades are typically handled by applying the updated manifest. The DaemonSet's update strategy should be set to RollingUpdate with appropriate maxUnavailable values to ensure zero-downtime upgrades:

# Check current update strategy
kubectl -n kube-system get daemonset kube-flannel-ds -o yaml | grep -A5 updateStrategy

# Apply new manifest
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

# Monitor rollout
kubectl -n kube-system rollout status daemonset/kube-flannel-ds

# Verify all pods updated
kubectl -n kube-system get pods -l app=flannel -o wide

During upgrades, pods on a node may experience brief network interruptions while the local flanneld restarts. Schedule upgrades during maintenance windows for production clusters and test the new version in a staging environment first.

Resource Limits and Node Sizing

Flanneld is lightweight but should have appropriate resource limits to prevent it from consuming excessive resources under abnormal conditions:

# Example resource limits in DaemonSet pod spec
resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 200m
    memory: 256Mi

Migrating Between Flannel Backends

Changing from one backend to another (e.g., VXLAN to host-gw) requires careful planning because it affects routing for all pods. The safest approach is a rolling migration:

# 1. Update the ConfigMap with the new backend configuration
kubectl -n kube-system apply -f - <

This approach minimizes disruption by ensuring that at any given time, most nodes are still operating with working networking. Test connectivity between pods on migrated and unmigrated nodes during the transition — they should still communicate through the overlay while both backends are active on different nodes.

Conclusion

Flannel remains one of the most reliable and straightforward CNI solutions for Kubernetes networking. Its architecture — a simple per-node subnet allocation model paired with configurable backends — strikes a balance between operational simplicity and performance flexibility. By understanding the different backend modes, properly planning your pod network CIDR, and implementing the monitoring and security practices outlined here, you can deploy Flannel with confidence in environments ranging from small development clusters to large-scale production deployments. The key to long-term success with Flannel is choosing the right backend for your network topology and maintaining clear documentation of your pod network addressing scheme. When configured correctly, Flannel provides transparent, high-performance pod networking that just works, allowing you to focus on the applications rather than the underlying network fabric.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles