Flannel Reference
Scope
Look-up facts for Flannel v0.28.x: net-conf.json keys, backend matrix and options, flanneld flags and environment variables, node annotations, files and ports, K3s flags, Helm values, release history, performance estimates, and a hardening checklist. For why things work this way see Explanation; for step-by-step tasks see How-to Guides.
Version and Support Facts
| Item |
Value |
Source |
| Latest release |
v0.28.9 (2026-08-07) |
GitHub releases, Chart.yaml |
| 0.28 line started |
v0.28.0 (2026-01-06) |
GitHub releases |
| Release cadence (2026) |
Patch releases roughly every 2-6 weeks (v0.28.0 to v0.28.9 in about 7 months) |
GitHub releases |
| Supported versions |
Latest release only; older releases are not patched |
SECURITY.md |
| Vulnerability reporting |
GitHub private vulnerability reporting; acknowledgement within 7 days, fix target 90 days |
SECURITY.md |
| Container images |
ghcr.io/flannel-io/flannel:v0.28.9, ghcr.io/flannel-io/flannel-cni-plugin:v1.9.1-flannel3 |
kube-flannel.yml |
| Helm repo |
https://flannel-io.github.io/flannel/ (chart flannel/flannel, since v0.21.4) |
upgrade.md |
| Manifest Kubernetes minimum |
v1.17+ for the current kube-flannel.yml |
README |
| Build toolchain |
Go 1.26 (go.mod) |
go.mod |
| License |
Apache-2.0 |
LICENSE |
| Maintainers |
Manuel Buil, Michael Fritch, Roberto Bonafiglia, Thomas Ferrandiz (all SUSE) |
GOVERNANCE.md |
Release History (selected)
| Version |
Date |
Notable change |
| v0.28.9 |
2026-08-07 |
/healthz (liveness) and /readyz (readiness) endpoints, wired into manifest and chart on port 8081. etcd single-subnet watch recovers from compaction. Dependency CVE fixes (CVE-2026-46600, CVE-2026-56852). |
| v0.28.8 |
2026-07-22 |
Atomic write of subnet.env |
| v0.28.6 / v0.28.7 |
2026-07-07 |
New install-conf command used by the install-cni init container |
| v0.28.5 |
2026-06-04 |
VXLAN IPv4-only guard fix, zombie-process handling, k8s client libraries v0.33.11 |
| v0.28.3 |
2026-04-15 |
GOVERNANCE.md added, VXLAN IPv6 route deletion fix |
| v0.28.2 |
2026-03-27 |
Fix for CVE-2026-32241 (extension backend RCE); build hardening |
| v0.28.0 |
2026-01-06 |
Go and k8s dependency upgrade, nftables pre-check, better primary-address selection |
| v0.26.0 |
2024-10-23 |
Multiple nodes behind a single public IP |
| v0.25.5 |
2024-07-17 |
kube-network-policies controller option in the Helm chart (netpol.enabled) |
| v0.25.0 |
2024-04-08 |
nftables implementation (EnableNFTables, experimental) |
| v0.24.0 |
2023-12-19 |
riscv64 support |
Dates for v0.25.x and v0.26.0 come from the GitHub releases pages. Cross-check against newreleases.io if exact dates matter.
net-conf.json Keys
In kube mode Flannel reads /etc/kube-flannel/net-conf.json (the net-conf.json key of ConfigMap kube-flannel-cfg). In etcd mode it reads /coreos.com/network/config.
| Key |
Type |
Default |
Notes |
Network |
string (CIDR) |
none |
IPv4 cluster pod CIDR. Required if EnableIPv4. Upstream manifest uses 10.244.0.0/16; K3s uses 10.42.0.0/16. |
IPv6Network |
string (CIDR) |
none |
Required if EnableIPv6 |
EnableIPv4 |
bool |
true |
Set false for IPv6-only |
EnableIPv6 |
bool |
false |
Dual-stack or IPv6-only |
EnableNFTables |
bool |
false |
EXPERIMENTAL. Use nftables instead of iptables for masquerade and forward rules (since v0.25.0). |
SubnetLen |
int |
24 |
If Network is smaller than /22, defaults to network prefix + 2. Ignored in kube mode (node podCIDR wins). |
SubnetMin / SubnetMax |
string (IP) |
2nd / last subnet |
Allocation range (etcd mode) |
IPv6SubnetLen |
int |
64 |
If IPv6Network is smaller than /62, defaults to network prefix + 2 |
IPv6SubnetMin / IPv6SubnetMax |
string (IP) |
2nd / last subnet |
IPv6 allocation range |
Backend |
object |
{"Type": "vxlan"} |
See backend tables below |
Backend Matrix
Backend Type |
Upstream status |
Encapsulation |
MTU overhead |
Port / protocol |
Device |
Encrypted |
Dual-stack |
Windows |
vxlan |
Recommended (default) |
VXLAN (L2 in UDP) |
50 B |
UDP 8472 (Linux), 4789 (Windows) |
flannel.<VNI>, flannel-v6.<VNI> |
No |
Yes |
Yes |
host-gw |
Recommended (needs L2 adjacency) |
None |
0 |
none |
none (routes only) |
No |
Yes (Linux) |
Yes |
wireguard |
Recommended |
WireGuard |
80 B |
UDP 51820 (v4), 51821 (v6) |
flannel-wg, flannel-wg-v6 |
Yes |
Yes |
No |
udp |
Debugging only, linux/amd64 only |
UDP via userspace TUN proxy |
28 B |
UDP 8285 |
flannel0 |
No |
No |
No |
ipip |
Experimental |
IP-in-IP |
20 B |
IP protocol 4 |
flannel.ipip (plus kernel tunl0) |
No |
No (IPv4 unicast only) |
No |
ipsec |
Experimental |
ESP (strongSwan IKEv2) |
TBD (not documented upstream) |
ESP (IP 50), UDP 500, UDP 4500 |
XFRM policies |
Yes |
TBD |
No |
alloc |
Experimental |
None (allocation only) |
0 |
none |
none |
No |
n/a |
No |
extension |
Experimental, prototyping |
User scripts |
user-defined |
user-defined |
user-defined |
n/a |
Yes (IPv6 vars) |
No |
tencent-vpc |
Experimental |
Tencent Cloud VPC routes |
0 |
none |
none |
No |
TBD |
No |
MTU overheads come from the encapOverhead/overhead constants in each backend's source. "Dual-stack: Yes" follows configuration.md: only vxlan, wireguard and host-gw (Linux) support it. Windows support follows the Windows notes in backends.md and hostgw_windows.go / vxlan_windows.go.
VXLAN Options
| Option |
Type |
Default |
Notes |
VNI |
number |
1 (Linux) |
Windows needs >= 4096 |
Port |
number |
kernel default 8472 |
Windows must use 4789 |
GBP |
bool |
false |
VXLAN Group Based Policy; not on Windows |
DirectRouting |
bool |
false |
host-gw routes for same-subnet peers; not on Windows |
Learning |
bool |
false |
Kernel MAC learning on the VXLAN link (Linux) |
MTU |
number |
external interface MTU |
Linux only |
MacPrefix |
string |
0E-2A |
Windows only |
Name |
string |
flannel.<VNI> |
Windows only |
WireGuard Options
| Option |
Type |
Default |
Notes |
PSK |
string |
none |
Generate with wg genpsk |
ListenPort |
int |
51820 |
IPv4 tunnel |
ListenPortV6 |
int |
51821 |
IPv6 tunnel |
MTU |
number |
external interface MTU |
|
Mode |
string |
separate |
separate, auto, ipv4, ipv6 |
PersistentKeepaliveInterval |
int (seconds) |
0 (off) |
Use for NAT traversal |
env WIREGUARD_KEY_FILE |
path |
/run/flannel/wgkey |
Private key location |
Other Backend Options
| Backend |
Option |
Default |
Notes |
udp |
Port |
8285 |
|
ipip |
DirectRouting |
false |
|
ipsec |
PSK |
required |
At least 96 characters |
ipsec |
UDPEncap |
false |
Force UDP encapsulation (NAT) |
ipsec |
ESPProposal |
aes128gcm16-sha256-prfsha256-ecp256 |
|
extension |
PreStartupCommand, PostStartupCommand, SubnetAddCommand, SubnetRemoveCommand |
none |
Run through sh with daemon privileges |
tencent-vpc |
AccessKeyID, AccessKeySecret |
env ACCESS_KEY_ID / ACCESS_KEY_SECRET |
50 routes per route table |
flanneld Flags
| Flag |
Default |
Purpose |
--kube-subnet-mgr |
false |
Use the Kubernetes API instead of etcd |
--kube-api-url, --kubeconfig-file |
in-cluster |
API access when not running in a pod |
--kube-annotation-prefix |
flannel.alpha.coreos.com |
Node annotation prefix |
--net-config-path |
/etc/kube-flannel/net-conf.json |
Network config file (kube mode) |
--etcd-endpoints |
http://127.0.0.1:4001,http://127.0.0.1:2379 |
etcd mode |
--etcd-prefix |
/coreos.com/network |
etcd mode |
--etcd-keyfile, --etcd-certfile, --etcd-cafile |
empty |
etcd mTLS |
--etcd-username, --etcd-password |
empty |
etcd basic auth |
--iface (repeatable) |
default-route interface |
Interface name or IP for inter-host traffic |
--iface-regex (repeatable) |
none |
Checked after --iface |
--iface-can-reach |
none |
Pick the interface that ip route get <ip> would use |
--public-ip, --public-ipv6 |
interface IP |
Address advertised to peers |
--ip-masq |
false (manifest sets it) |
Masquerade pod traffic leaving the overlay |
--ip-masq-fully-random-disable |
false |
Disable --random-fully on MASQUERADE |
--iptables-forward-rules |
true |
ACCEPT rules in FORWARD |
--iptables-resync |
5 (seconds) |
Rule resync period |
--ip-blackhole-route |
false |
Blackhole route for the local podCIDR |
--set-node-network-unavailable |
true |
Set the node's NetworkUnavailable condition once Flannel is ready |
--subnet-file |
/run/flannel/subnet.env |
Where subnet and MTU are written |
--subnet-lease-renew-margin |
60 (minutes, 1-1439) |
Lease renewal margin (etcd mode) |
--healthz-ip / --healthz-port |
0.0.0.0 / 0 (disabled) |
/healthz and /readyz; manifest uses 8081 |
-v |
0 |
Log verbosity (-v=10 for most detail) |
--version |
|
Print version |
Every flag also works as an environment variable: prefix FLANNELD_, uppercase, dashes to underscores (for example FLANNELD_ETCD_ENDPOINTS).
Other Environment Variables
| Variable |
Default |
Purpose |
EVENT_QUEUE_DEPTH |
5000 |
Node informer queue depth; raise for very large clusters |
CONT_WHEN_CACHE_NOT_READY |
false |
Continue startup before the node cache fully syncs |
WIREGUARD_KEY_FILE |
/run/flannel/wgkey |
WireGuard private key path |
Node Annotations
Prefix: flannel.alpha.coreos.com/ (configurable).
| Annotation |
Written by |
Meaning |
backend-type |
flanneld |
Backend in use |
backend-data, backend-v6-data |
flanneld |
Backend peer data (VTEP MAC, WireGuard public key, and so on) |
public-ip, public-ipv6 |
flanneld |
Address peers should tunnel to |
kube-subnet-manager |
flanneld |
Marks the node as managed in kube mode |
node-public-ip, node-public-ipv6 |
Operator |
Choose which local IP to use (same as --public-ip) |
public-ip-overwrite, public-ipv6-overwrite |
Operator |
Advertise an IP not configured on the node (behind NAT) |
Files, Interfaces and Paths
| Path / object |
Purpose |
/run/flannel/subnet.env |
FLANNEL_NETWORK, FLANNEL_SUBNET, FLANNEL_IPV6_NETWORK, FLANNEL_IPV6_SUBNET, FLANNEL_MTU, FLANNEL_IPMASQ |
/etc/cni/net.d/10-flannel.conflist |
CNI config (flannel + portmap, cniVersion 1.0.0) |
/opt/cni/bin/flannel |
Flannel CNI plugin; also needs bridge, host-local, portmap |
/etc/kube-flannel/net-conf.json, cni-conf.json |
Mounted from ConfigMap kube-flannel-cfg |
/run/xtables.lock |
Shared iptables lock (hostPath) |
cni0 |
Per-node Linux bridge created by the bridge plugin |
Namespace kube-flannel |
Pod Security privileged; DaemonSet kube-flannel-ds, ServiceAccount flannel, ClusterRole/Binding flannel |
| iptables chains |
FLANNEL-POSTRTG (nat), FLANNEL-FWD (filter) |
| nftables tables |
flannel-ipv4, flannel-ipv6 |
| Kernel modules |
br_netfilter (required; kubeadm >= 1.30 no longer checks it), vxlan, wireguard (kernel < 5.6 needs package) |
Ports
| Protocol |
Port |
Needed for |
| UDP |
8472 |
VXLAN (Linux) |
| UDP |
4789 |
VXLAN (Windows) |
| UDP |
51820 |
WireGuard IPv4 |
| UDP |
51821 |
WireGuard IPv6 |
| UDP |
8285 |
UDP backend |
| IP proto 50, UDP 500, UDP 4500 |
|
IPsec backend |
| IP proto 4 |
|
IPIP backend |
| TCP |
8081 |
/healthz and /readyz (manifest default, node-local) |
Open these only between node IPs. K3s docs warn that exposing 8472 publicly "opens up your cluster network to be accessed by anyone".
K3s Flannel Flags
| Flag |
Where |
Notes |
--flannel-backend |
servers |
vxlan (default), host-gw, wireguard-native, none. ipsec and wireguard are deprecated; the current --help lists only the first four. |
--flannel-ipv6-masq |
servers |
Masquerade IPv6 pod traffic (dual-stack or IPv6-only) |
--flannel-external-ip |
servers |
Tunnel to node external IPs (needs --node-external-ip) |
--flannel-iface |
each node |
Override interface |
--flannel-conf, --flannel-cni-conf |
each node |
Override Flannel or CNI config file |
--cluster-cidr |
servers |
Default 10.42.0.0/16; dual-stack example 10.42.0.0/16,2001:db8:42::/56 |
--disable-network-policy |
servers |
Turn off the embedded kube-router netpol controller |
Flannel options must be identical on all K3s servers. Dual-stack must be set when the cluster is created (K3s basic network options).
Helm Chart Values (flannel/flannel v0.28.9)
| Value |
Default |
podCidr / podCidrv6 |
10.244.0.0/16 / empty |
flannel.image.repository / tag |
ghcr.io/flannel-io/flannel / v0.28.9 |
flannel.backend |
vxlan |
flannel.backendPort, mtu, vni, GBP, directRouting, macPrefix |
unset (backend defaults) |
flannel.backendPortv6, psk, tunnelMode, keepaliveInterval |
unset (WireGuard) |
flannel.enableNFTables |
false |
flannel.args |
--ip-masq, --kube-subnet-mgr |
flannel.skipCNIConfigInstallation |
false |
flannel.resources.requests |
cpu: 100m, memory: 50Mi |
flannel.healthz.port |
8081 |
netpol.enabled |
false |
netpol.image |
registry.k8s.io/networking/kube-network-policies:v1.0.0 |
Unverified estimates, not benchmarks
Earlier versions of this note carried the figures below without test conditions or a source. Upstream publishes no benchmark suite yet (it is a ROADMAP item). Treat these as order-of-magnitude guidance only and measure on your own hardware, NICs, kernel and MTU.
| Backend |
Throughput on 10GbE (estimate) |
Added latency (estimate) |
| host-gw |
~9.5+ Gbps |
~10-20 us |
| VXLAN |
~8-9 Gbps |
~80-100 us |
| WireGuard |
~7-8 Gbps |
~100-200 us |
| UDP |
~5-6 Gbps |
~200-500 us |
The order host-gw > VXLAN > UDP matches upstream's qualitative guidance. The absolute numbers are TBD (no sourced benchmark).
| Resource |
Value |
Source |
| Requested CPU / memory per node |
100m / 50Mi |
Upstream manifest and chart |
| Typical idle usage |
TBD (earlier note claimed < 10m CPU, 30-50Mi; unverified) |
none |
| Node informer queue |
5000 nodes before EVENT_QUEUE_DEPTH tuning |
configuration.md |
| Pods per node |
Bounded by the node subnet (/24 gives 254 IPs) and kubelet maxPods (default 110) |
Kubernetes defaults |
Hardening Checklist
| Item |
Action |
| Version |
Run the latest patch release; only it receives security fixes |
| Encryption |
Use wireguard (K3s: wireguard-native) when the underlay is untrusted |
| Firewall |
Allow backend ports only between node IPs; never expose 8472 to the internet |
| NetworkPolicy |
Enable netpol.enabled, the K3s embedded controller, Canal or Cilium chaining |
| Pod Security |
Keep kube-flannel namespace restricted to admins; apply restricted PSS elsewhere (drops NET_RAW) |
| RBAC |
Limit who can patch Node annotations (flannel.alpha.coreos.com/*) |
| Backends |
Avoid extension in production; if used, run v0.28.2 or later |
| etcd mode |
Enable etcd mTLS and a dedicated user limited to /coreos.com/network/ |
| Health |
Keep --healthz-port enabled so /readyz gates pod scheduling readiness |
| Egress |
Enable --ip-masq unless pod CIDRs are routed upstream |
| External filtering |
Use cloud security groups or host firewalls for north-south traffic; Flannel does not filter it |
| Monitoring |
Flannel has no flow telemetry; use node-exporter, packet capture, or a policy engine with visibility |
| Node hardening |
Restrict SSH, limit privileged workloads, keep kernels patched (VXLAN and WireGuard are in-kernel) |
Sources