Network Policies

Overview

Longhorn can use Kubernetes NetworkPolicy resources to restrict inbound traffic to Longhorn components. A network plugin that supports and enforces Kubernetes NetworkPolicy is required. Otherwise, the NetworkPolicy resources are created but have no effect on network traffic. Network policies are additive, and when both the source and destination are isolated by NetworkPolicies, a connection must be permitted by both the source’s egress policy and the destination’s ingress policy.

For the component communication matrix, ports, and traffic that is not covered by the Helm policies, see the Longhorn networking reference. Review that reference after every Longhorn upgrade and when changing the CNI, ingress controller, node placement, or topology.

The corresponding Helm chart templates are also available in the Longhorn source repository.

Policy groups generated by the Helm chart

The chart generates two separate policy groups:

  • Internal policy: Controlled by .Values.networkPolicies.restrictInternalTraffic and enabled by default. This policy restricts inbound traffic to Longhorn’s internal components.
  • UI frontend policy: Controlled by .Values.networkPolicies.enabled and disabled by default. This policy restricts inbound traffic to the Longhorn UI frontend.

These settings are independent and can be enabled or disabled separately. The following sections describe the behavior and requirements of each policy group.

Internal Longhorn ingress policies

When .Values.networkPolicies.restrictInternalTraffic is true, the chart creates ingress-only policies for Longhorn’s internal components. The .Values.networkPolicies.kubeAPIServerSourceCIDRs setting configures the allowed source CIDRs for the Longhorn webhook policy.

The internal policies are generated even when .Values.networkPolicies.enabled is false, because restrictInternalTraffic defaults to true. Check the rendered manifests and preserve the required Longhorn labels when adding a new component or moving an existing component to a custom namespace.

UI frontend ingress policy

The UI frontend policy is a separate policy for the longhorn-ui pods. It is generated only when all of the following conditions are met:

  • .Values.networkPolicies.enabled is true.
  • .Values.ingress.enabled is true.
  • .Values.networkPolicies.type is not empty.

The only UI frontend policy is longhorn-ui-frontend. The chart populates ingress-controller source rules only for the following supported types:

  • k3s: Traefik pods in the kube-system namespace.
  • rke2: The RKE2 ingress-nginx controller in the kube-system namespace.
  • rke1: The ingress-nginx controller in the ingress-nginx namespace.

An unsupported, non-empty type still causes the policy to be rendered, but no matching ingress-controller source rule is populated. This can make the UI unreachable. Confirm that the selected type, namespace, and labels match the deployed ingress controller.

The policy does not automatically discover custom ingress controllers. If you use another controller, custom labels, a different namespace, a gateway, host networking, or a custom topology, inspect the generated policy and adjust it to match the actual traffic flow. Use the networking reference to account for all Longhorn component connections rather than widening every policy to allow traffic from all sources.

A representative Helm values example:

networkPolicies:
  enabled: true
  restrictInternalTraffic: true
  type: k3s
  kubeAPIServerSourceCIDRs:
    - 10.42.0.0/32

Set .Values.networkPolicies.enabled to false if the UI policy is not wanted. That does not disable the internal policies; set .Values.networkPolicies.restrictInternalTraffic to false only when you intentionally manage those policies yourself.

Restricting the Webhook API server source

The Kubernetes API server calls admission webhooks when matching resources are created, updated, or deleted. Longhorn provides a conversion webhook on TCP port 9501 and an admission webhook on TCP port 9502 for mutating and validating Longhorn resources. For details about the Kubernetes admission sequence, see the Kubernetes admission webhook documentation.

These webhook endpoints must remain reachable by the Kubernetes API server, but other workloads typically do not need direct access. Longhorn cannot determine the trusted source CIDRs for every Kubernetes distribution and network configuration. Configure .Values.networkPolicies.kubeAPIServerSourceCIDRs with the source CIDRs used by the Kubernetes API server in your cluster.

  • When the list is non-empty, the policy allows TCP ports 9501 and 9502 from either the longhorn-manager pod selector or one ipBlock for each configured CIDR. These are alternatives in the same from list, not an intersection. The pod selector preserves the in-cluster Longhorn manager path, while the configured CIDRs allow traffic from the Kubernetes API server.
  • When the list is empty, normal Longhorn operation is not affected, but source filtering is disabled. The webhook policy has no from restriction, so any workload or client that can reach the webhook pods can connect to TCP ports 9501 and 9502. An empty list does not deny all traffic.

The recovery backend is separate. Its TCP 9503 policy allows only pods labeled longhorn.io/component: share-manager; the API server CIDR list never grants access to 9503.

Why a whole PodCIDR is unsafe

Do not guess a broad PodCIDR for the API server. A PodCIDR also contains workload addresses, so a compromised workload can satisfy an ipBlock rule intended for the API server. In the tested K3s case, 10.42.0.0/24 allowed an attacker pod scheduled on a master node at 10.42.0.4. Replacing it with 10.42.0.0/32 allowed the observed API server source and blocked that attacker.

The example is an observation, not a universal K3s value. Use the exact IPv4 (/32) or IPv6 (/128) source addresses defined by the distribution and cluster network. If the API server can use more than one source, list every documented source, including HA and failover paths.

Distribution-specific guidance

K3s with the default Flannel backend

K3s defines the pod network with the server --cluster-cidr setting and assigns each node a PodCIDR from that range. For the default Flannel backend, use the network address of each K3s server’s assigned PodCIDR as a host prefix (/32 for IPv4 or /128 for IPv6). For example, the server PodCIDR 10.42.0.0/24 produces 10.42.0.0/32, not 10.42.0.0/24. The broader /24 also allows ordinary pods scheduled on that server. In an HA cluster, include the corresponding host-prefix address for every server that can issue webhook requests.

Review the K3s --cluster-cidr, node CIDR mask, and --egress-selector-mode settings and the K3s basic network options. If the cluster uses a custom CNI or a different API server egress path, follow that configuration instead of using the default Flannel example.

RKE2

RKE2 supports Canal, Cilium, Calico, and Flannel, and its egress-selector-mode changes how the API server reaches pod-backed services.

Review the RKE2 server configuration on every control-plane node, including cni, disable-kube-proxy, egress-selector-mode, cluster-cidr, and service-cidr. Determine the API server egress addresses for that configuration and configure only those addresses as /32 or /128 entries. With the default Canal CNI, also inspect the Flannel interface addresses used by the configured egress path. Include every address required after control-plane failover, and re-evaluate the value after changing the CNI, egress selector, kube-proxy mode, or control-plane topology.

See the official RKE2 networking documentation, RKE2 networking services and egress selector documentation, and RKE2 server configuration reference.

Amazon EKS

There is no universal EKS CIDR for kubeAPIServerSourceCIDRs. The public endpoint’s publicAccessCidrs limits client source addresses that may reach the public Kubernetes API endpoint; it is unrelated to the source addresses used when the managed control plane calls a Longhorn webhook.

In AWS_MANAGED mode, Amazon EKS creates two to four requester-managed network interfaces (ENIs) in any configured cluster subnet and replaces them during cluster upgrades, so individual ENI /32 entries are not stable.

For AWS_MANAGED, allow every configured cluster subnet CIDR only when those subnets are dedicated and workloads cannot receive addresses there; otherwise, reconcile the current ENI private addresses as /32 entries using your own automation after upgrades and cluster subnet changes.

For CUSTOMER_ROUTED control-plane egress, allow the trusted source addresses presented to the webhook by the customer-managed route, NAT, or firewall path, including translated addresses and every failover path.

See the official EKS cluster API server endpoint documentation, EKS networking requirements, and EKS control-plane egress routing documentation.

NAT and node-local traffic caveats

Kubernetes does not define one universal order for source NAT and NetworkPolicy processing. A CNI, service implementation, cloud provider, kube-proxy mode, load balancer, NAT gateway, or firewall can change the address evaluated by an ipBlock. Follow the networking documentation for the deployed Kubernetes distribution and CNI rather than copying a value from another cluster.

Kubernetes also documents that traffic to and from the node hosting a Pod is always allowed for NetworkPolicy purposes, regardless of source IP address. NetworkPolicy cannot use kubeAPIServerSourceCIDRs to restrict a compromised node or an equivalent host-network path.

For the Kubernetes semantics and source-rewrite caveats, see the official NetworkPolicy documentation and source IP documentation.


Copyright © 2019-2026 Longhorn a Series of LF Projects, LLC. Documentation Distributed under CC-BY-4.0.


The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our Trademark Usage page.


For website terms of use, trademark policy and other project policies please see lfprojects.org/policies.