Advanced Kubernetes Security with Cilium Network Policies

Kubernetes Network Policies are essential for securing pod-to-pod and pod-to-external communication. However, traditional Kubernetes NetworkPolicies come with several limitations that make them insufficient for complex, production-grade environments.
This is where Cilium Network Policy (CNP) and Cilium Clusterwide Network Policy (CCNP) come in, offering more expressive, feature-rich, and secure policies at L3 (IP), L4 (Port), and L7 (Application) layers.
π Limitations of Traditional Kubernetes Network Policies
Before exploring Cilium, letβs understand where Kubernetesβ built-in policies fall short:
No Explicit Deny Rules
Policies are allow-list only.
You canβt explicitly deny certain traffic while allowing everything else.
Limited Scope
Policies only apply to pods by labels and namespaces.
No ability to directly target nodes, host traffic, or localhost access.
Lack of Advanced Features
No complex querying for combining multiple selectors.
No network reachability analysis to simulate/validate policy impacts.
No visualization or monitoring for blocked/allowed connections.
No TLS or Application-Layer (L7) Policies
Limited to IP + port (L3/L4) only.
Canβt enforce rules based on HTTP methods, paths, DNS names, TLS identities, etc.
No Global Default Policies
You canβt create a single cluster-wide default policy.
Need to manually define in each namespace.
No Gateway Enforcement
- Cannot force traffic to flow through a common egress gateway.
These limitations make securing large, dynamic Kubernetes environments challenging.
π Enter Cilium Network Policy (CNP)
Cilium extends Kubernetes networking and security with eBPF-powered policies that go far beyond the default NetworkPolicy model.
With CiliumNetworkPolicy and CiliumClusterwideNetworkPolicy, you get:
β
Explicit Deny Rules
β
Cluster-wide policies
β
L3, L4, and L7 filtering
β
Entity-based policies (host, world, kube-apiserver, etc.)
β
DNS-based egress control
β
Service-based policies
β
Fine-grained observability & monitoring
π Examples of Cilium Network Policies
Letβs break it down with YAML examples across different layers:
πΉ Layer 3 (IP/Endpoint-Based Policies)
Ingress Policy β Allow only frontend β backend
π Only pods with role=frontend
can talk to pods with role=backend
in dev
namespace.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l3-rule"
namespace: dev
spec:
endpointSelector:
matchLabels:
role: backend
ingress:
- fromEndpoints:
- matchLabels:
role: frontend
Ingress Policy β Allow from all pods
π Any pod in the namespace can access backend pods.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l3-rule"
namespace: dev
spec:
endpointSelector:
matchLabels:
role: backend
ingress:
- fromEndpoints:
- {}
Ingress Policy β Block from everywhere
π Block all ingress traffic to backend pods.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l3-rule"
namespace: dev
spec:
endpointSelector:
matchLabels:
role: backend
ingress:
- {}
Egress Policy β Allow frontend β backend
π Frontend pods can only talk to backend pods.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l3-rule"
namespace: dev
spec:
endpointSelector:
matchLabels:
role: frontend
egress:
- toEndpoints:
- matchLabels:
role: backend
Egress Policy β Allow frontend to all pods
π Frontend can reach any pod in the namespace.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l3-rule"
namespace: dev
spec:
endpointSelector:
matchLabels:
role: frontend
egress:
- toEndpoints:
- {}
Egress Policy β Block frontend to anywhere
π Block, frontend pods can connect anywhere.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l3-rule"
namespace: dev
spec:
endpointSelector:
matchLabels:
role: frontend
egress:
- {}
πΉ Service-Based Policies
π Frontend pods in dev
namespace:
Can access
myservice
service indev
.Can access any service in another-namespace with label
env=staging
.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l3-rule"
namespace: dev
spec:
endpointSelector:
matchLabels:
role: frontend
egress:
- toServices:
- k8sService:
serviceName: myservice
namespace: dev
- k8sServiceSelector:
selector:
matchLabels:
env: staging
namespace: another-namespace
πΉ CIDR-Based Policies
π myService pods can connect to:
A single IP
20.1.1.1
.Any IP in
10.0.0.0/8
except10.96.0.0/12
.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "cidr-rule"
spec:
endpointSelector:
matchLabels:
app: myService
egress:
- toCIDR:
- 20.1.1.1/32
- toCIDRSet:
- cidr: 10.0.0.0/8
except:
- 10.96.0.0/12
πΉ Layer 4 (Port & Protocol-Based)
Port Range Rule
π myService pods can egress to any TCP port between 80β444.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l4-port-range-rule"
spec:
endpointSelector:
matchLabels:
app: myService
egress:
- toPorts:
- ports:
- port: "80"
endPort: 444
protocol: TCP
Ingress with Port Restriction
π Frontend β Backend allowed only on port 80/TCP.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l4-rule"
spec:
endpointSelector:
matchLabels:
role: backend
ingress:
- fromEndpoints:
- matchLabels:
role: frontend
toPorts:
- ports:
- port: "80"
protocol: TCP
CIDR + Port Rule
π Crawlers can connect to 192.0.2.0/24 on port 80/TCP only.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "cidr-l4-rule"
spec:
endpointSelector:
matchLabels:
role: crawler
egress:
- toCIDR:
- 192.0.2.0/24
toPorts:
- ports:
- port: "80"
protocol: TCP
πΉ Layer 7 (Application-Aware Policies)
HTTP Policy
π Only allows HTTP GET requests to /public on port 80 from pods labeled env=prod
.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "rule1"
spec:
description: "Allow HTTP GET /public from env=prod to app=service"
endpointSelector:
matchLabels:
app: service
ingress:
- fromEndpoints:
- matchLabels:
env: prod
toPorts:
- ports:
- port: "80"
protocol: TCP
rules:
http:
- method: "GET"
path: "/public"
DNS Restriction
π test-app pods can resolve only google.com and its subdomains.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "to-fqdn"
spec:
endpointSelector:
matchLabels:
app: test-app
egress:
- toEndpoints:
- matchLabels:
"k8s:io.kubernetes.pod.namespace": kube-system
"k8s:k8s-app": kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchName: "google.com"
- matchPattern: "*.google.com"
Combined DNS + FQDN Rules
π Allows DNS resolution + HTTP access to specific domains and patterns.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: "tofqdn-dns-visibility"
spec:
endpointSelector:
matchLabels:
any:org: alliance
egress:
- toEndpoints:
- matchLabels:
"k8s:io.kubernetes.pod.namespace": kube-system
"k8s:k8s-app": kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchName: "cilium.io"
- matchPattern: "*.cilium.io"
- matchPattern: "*.api.cilium.io"
- toFQDNs:
- matchName: "cilium.io"
- matchName: "sub.cilium.io"
- matchName: "service1.api.cilium.io"
- matchPattern: "special*service.api.cilium.io"
toPorts:
- ports:
- port: "80"
protocol: TCP
πΉ Entity-Based Policies
Pod β Kube-API
π dev pods can talk to kube-apiserver entity (secure API access).
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "dev-to-kube-apiserver"
spec:
endpointSelector:
matchLabels:
env: dev
egress:
- toEntities:
- kube-apiserver
Ingress from Host & Nodes
π Allows traffic from host and cluster nodes into dev pods.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "to-dev-from-nodes-in-cluster"
spec:
endpointSelector:
matchLabels:
env: dev
ingress:
- fromEntities:
- host
- remote-node
World Entity
π Public pods can be accessed from outside cluster (internet).
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "from-world-to-role-public"
spec:
endpointSelector:
matchLabels:
role: public
ingress:
- fromEntities:
- world
πΉ Deny & Clusterwide Policies
Clusterwide Deny
π Denies all external (world) traffic clusterwide.
π Deny rules always override allow rules.
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
name: "external-lockdown"
spec:
endpointSelector: {}
ingressDeny:
- fromEntities:
- "world"
ingress:
- fromEntities:
- "all"
π Key Takeaways
Cilium policies enhance Kubernetes NetworkPolicy with:
β Deny rules
β Cluster-wide enforcement
β L7 security (HTTP, DNS, Kafka, gRPC)
β DNS/FQDN support
β Entity-based targeting (host, world, kube-apiserver)
You can start with namespace-level CNPs and gradually move to clusterwide CCNPs for stronger defaults.
Subscribe to my newsletter
Read articles from avinash gawade directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
