Cilium Series Part 14: Introduction to Cilium NetworkPolicy

This article was last updated on: May 17, 2026 am

Series Articles

Introduction

Today we dive into Cilium security topics, introducing Kubernetes network policies and the additional capabilities supported by CiliumNetworkPolicies.

Types of NetworkPolicy

By default, all pods in a Kubernetes cluster are accessible by other pods and network endpoints.

Network policies allow users to define which traffic is allowed and which is denied in a Kubernetes cluster. Traditional firewalls configure allow or deny rules based on source or destination IP addresses and ports (5-tuple), whereas Cilium uses Kubernetes identity information — such as label selectors, namespace names, and even fully qualified domain names — to define allowed and denied traffic rules. This enables network policies to work in dynamic environments like Kubernetes, where IP addresses are constantly assigned and reused as pods are created and destroyed.

When running Cilium on Kubernetes, you can define network policies using Kubernetes resources (networking.k8s.io/v1 NetworkPolicy). The Cilium Agent watches the Kubernetes API server for network policy updates and loads the necessary eBPF programs and maps to enforce the desired network policies. A Cilium-enabled Kubernetes cluster provides three network policy formats:

  • Standard Kubernetes NetworkPolicy resources supporting L3 and L4 policies (the built-in Kubernetes NetworkPolicy, also supported by other CNIs like Calico)
  • CiliumNetworkPolicy resources supporting L3, L4, and L7 (application layer) policies (a Cilium-specific CRD: CiliumNetworkPolicy)
  • CiliumClusterwideNetworkPolicy resources for specifying policies that apply to the entire cluster rather than a specific namespace (a Cilium-specific CRD: CiliumClusterwideNetworkPolicy — as the name implies, cluster-wide network policies that can even enforce Node-level network policy restrictions)

Cilium supports using all of these policy types simultaneously. However, caution should be exercised when using multiple policy types, as understanding the complete set of allowed traffic across multiple policy types can be confusing. Without close attention, this may lead to unexpected policy behavior. Therefore, it is recommended to use the latter two resource types with Cilium.

This time we focus primarily on the CiliumNetworkPolicy resource, as it represents a superset of the standard Kubernetes NetworkPolicy functionality.

NetworkPolicy Resource

The NetworkPolicy resource is a standard Kubernetes resource (networking.k8s.io/v1 NetworkPolicy) that lets you control traffic at the IP address or port level (OSI model Layer 3 or Layer 4). NetworkPolicy capabilities include:

  • L3/L4 Ingress and Egress policies using label matching
  • L3 IP/CIDR Ingress and Egress policies using IP/CIDR for endpoints external to the cluster
  • L4 TCP and ICMP port Ingress and Egress policies

│ 🐾Warning

│ NetworkPolicy does not apply to the host network namespace. Pods with host networking enabled are not affected by network policy rules.

Network policies cannot block traffic from localhost or from the node where they reside.

CiliumNetworkPolicy Resource

CiliumNetworkPolicy is an extension of the standard NetworkPolicy. CiliumNetworkPolicy extends the L3/L4 capabilities of the standard Kubernetes NetworkPolicy resource and adds several features:

  • L7 HTTP protocol policy rules that restrict Ingress and Egress to specific HTTP paths
  • Support for other L7 protocols such as DNS, Kafka, and gRPC
  • Egress policies for intra-cluster communication based on service names
  • L3/L4 Ingress and Egress policies using entity-based matching for special entities
  • L3 Ingress and Egress policies using DNS FQDN matching

You can find specific examples of CiliumNetworkPolicy YAML manifests for several common use cases in the Cilium project documentation.

Reading the YAML definition of a network policy and predicting which traffic it will allow and deny can be difficult, and getting a policy to do exactly what you want is not always straightforward. Fortunately, the visual policy editor at networkpolicy.io makes this much easier.

Networkpolicy.io Visual Policy Editor

The NetworkPolicy.io policy editor provides an excellent way to explore and craft L3 and L4 network policies. It graphically depicts a cluster and lets you select the correct policy elements for the desired network policy type. The policy editor supports both standard Kubernetes NetworkPolicy and CiliumNetworkPolicy resources.

Screenshot below:

Networkpolicy.io

At the top, there is an interactive service map visualization that you can use to create new policies. Green lines indicate traffic allowed by the current policy definition, and red lines indicate denied traffic. You can use the interactive service map UI to configure ingress and egress policies targeting endpoints inside or outside the cluster.

In the lower left is a read-only YAML description of the network policy matching the service map described above. You can choose to view either the standard Kubernetes NetworkPolicy specification or the CiliumNetworkPolicy specification. You can also download the policy from here and apply it to your cluster using kubectl. You can also upload existing policy definitions in either format, and the policy editor will update the visual service map representation to show how it works. Visualizing what a policy does in the service map UI helps ensure that policy rules operate as expected. You will have the opportunity to try the NetworkPolicy editor yourself in the lab later in this section.

In the lower right, the editor provides a tutorial interface with some common scenarios to help you think about how to craft policies. You can also use this area to upload Hubble traffic and generate network policies based on what Hubble has observed.

Hands-On Practice

Consider the following scenario:

A Kubernetes cluster has multiple Namespaces, each representing a tenant. These tenants need tenant isolation — meaning they cannot access each other. However, each tenant should allow:

  1. Traffic from Ingress
  2. Traffic from the Internet
  3. Scraping from monitoring

How should the policies be configured?

Allow Traffic from Ingress

NetworkPolicy: allow-from-ingress

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-ingress
spec:
ingress:
- from:
- namespaceSelector:
matchLabels:
policy-group: ingress
podSelector: {}
policyTypes:
- Ingress

Explanation:

  • This matches the Namespace where Ingress resides via labels, so you need to ensure the Ingress Namespace has the policy-group: ingress label applied.

Policy visualization:

allow-from-ingress

Allow Traffic from the Internet

│ 🐾Warning

│ For security reasons, tenant Namespaces should only receive business traffic from Ingress, and should not directly allow traffic from the Internet.
│ I recommend not enabling this policy.

NetworkPolicy: allow-from-outside

1
2
3
4
5
6
7
8
9
10
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: untitled-policy
spec:
podSelector: {}
ingress:
- from:
- ipBlock:
cidr: 0.0.0.0/0

Explanation:

  • Adjust the CIDR as needed.

Policy visualization:

allow-from-outside

Allow Traffic from Monitoring

NetworkPolicy: allow-from-monitoring

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-monitoring
spec:
ingress:
- from:
- namespaceSelector:
matchLabels:
policy-group: monitoring
podSelector: {}
policyTypes:
- Ingress

Explanation:

  • This matches the Namespace where monitoring resides via labels, so you need to ensure the monitoring Namespace has the policy-group: monitoring label applied.

Policy visualization:

allow-from-monitoring

Allow Traffic within the Same Namespace

NetworkPolicy: allow-same-namespace

1
2
3
4
5
6
7
8
9
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-same-namespace
spec:
podSelector:
ingress:
- from:
- podSelector: {}

Policy visualization:

allow-same-namespace

Putting It All Together

Combining all the above, the result is as follows:

NetworkPolicy: tenant-isolation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-same-namespace
spec:
podSelector: {}
ingress:
- from:
- podSelector: {}
- from:
- namespaceSelector:
matchLabels:
policy-group: ingress
- from:
- ipBlock:
cidr: 0.0.0.0/0
- from:
- namespaceSelector:
matchLabels:
policy-group: monitoring
- from:
- podSelector: {}
policyTypes:
- Ingress

Converted to CiliumNetworkPolicy, the content is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-same-namespace
spec:
endpointSelector: {}
ingress:
- fromEndpoints:
- {}
- fromEndpoints:
- matchLabels:
io.kubernetes.pod.namespace.labels.policy-group: ingress
- fromEndpoints:
- matchLabels:
io.kubernetes.pod.namespace.labels.policy-group: monitoring
- fromEntities:
- world

Policy visualization:

tenant-isolation

Summary

Today we dove into Cilium security topics, introducing Kubernetes network policies and the additional capabilities supported by CiliumNetworkPolicies. We introduced a useful visual NetworkPolicy editor: <networkpolicy.io>. We also demonstrated a practical “tenant isolation” network policy use case.