Kubernetes Networking â CNI Plugins, Network Policies, and Service Mesh Integration
In this tutorial, you'll learn about Kubernetes Networking. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Kubernetes networking provides a flat network model where every Pod gets a unique IP address and can communicate with any other Pod without NAT, with CNI plugins implementing the underlying network fabric and Network Policies controlling traffic flow.
What You'll Learn
Why It Matters
Kubernetes networking is complex but fundamental to cluster security and application reliability. Without understanding CNI plugins, teams face mysterious connectivity issues. Without Network Policies, every Pod can talk to every other Pod, creating a massive security risk if one workload is compromised. A single vulnerable Pod in a flat network can scan and exploit every other application in the cluster.
Real-World Use
DodaTech runs Durga Antivirus Pro across multiple Kubernetes clusters with Calico CNI enforcing 150+ Network Policies, Cilium for eBPF-based Observability, and a service mesh for mTLS between Microservices. This layered networking approach contains breaches and provides full traffic visibility.
flowchart TD
A["Pod A: 10.0.1.5"] -->|"CNI: Calico"| B["Node 1: eth0"]
B -->|"Overlay/VXLAN"| C["Node 2: eth0"]
C -->|"CNI: Calico"| D["Pod B: 10.0.2.7"]
A -.->|"Blocked by NetworkPolicy"| E["Pod C: 10.0.3.9"]
F["NetworkPolicy: default-deny"] -->|"Deny all ingress"| A
G["NetworkPolicy: allow-api"] -->|"Allow port 8080 from frontend"| H["Pod: API v2"]
I["CoreDNS"] --> J["Service DNS: my-svc.namespace.svc.cluster.local"]
J --> K["Service -> Pod IPs"]
style A fill:#326CE5,color:#fff
style D fill:#326CE5,color:#fff
style H fill:#326CE5,color:#fff
Prerequisites: Working Kubernetes cluster, understanding of Pods and Services, and basic networking knowledge (IP addresses, ports, DNS).
CNI Plugin Architecture
Container Network Interface plugins implement the Kubernetes networking model. The choice of CNI affects performance, security features, and operational complexity.
| CNI Plugin | Type | Performance | NetworkPolicies | eBPF | Key Feature |
|---|---|---|---|---|---|
| Calico | Overlay/BGP | High | Yes | Yes | Rich policy language |
| Cilium | eBPF | Very high | Yes | Yes | L7 policies, Hubble |
| Flannel | Overlay | Medium | No | No | Simplest setup |
| Weave | Overlay | Medium | Yes | No | Automatic encryption |
| Antrea | Overlay | High | Yes | Yes | VMware integration |
Network Policies
Network Policies are firewall rules for Pods. They are namespace-scoped and use label selectors to define allowed traffic. By default, all Pod-to-Pod traffic is allowed -- Network Policies change this to a deny-by-default model when applied.
# default-deny-all.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
Expected behavior: No ingress traffic is allowed to any Pod in the production namespace. All existing connections are dropped. Any new connection attempt from another Pod is blocked unless a more specific NetworkPolicy allows it.
# allow-api-from-frontend.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-traffic
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Expected behavior: Only Pods with label app: frontend can send TCP traffic to port 8080 on Pods with label app: api. All other ingress traffic to api Pods is blocked by the default-deny policy.
# allow-db-from-api-only.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-db-access
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
ports:
- protocol: TCP
port: 5432
Expected behavior: Database Pods accept traffic only from Pods with label app: api in the same namespace and from any Pod in the monitoring namespace (for monitoring tools). This prevents the frontend from directly accessing the database.
Egress Network Policies
Control outbound traffic from Pods to prevent data exfiltration and restrict access to external services.
# restrict-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-egress
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
ports:
- protocol: TCP
port: 443
Expected behavior: The API Pods can only connect to database Pods on port 5432 and to external HTTPS endpoints (port 443) on the internet. All traffic to private IP ranges (RFC 1918) except the database is blocked, preventing the API from reaching other internal services if compromised.
Cilium and eBPF for Advanced Networking
Cilium uses eBPF to implement networking, security, and Observability at the kernel level without modifying the application or sidecar proxies.
# cilium-network-policy.yaml
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: api-layer7-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: api
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v2/public/*"
- method: "POST"
path: "/api/v2/auth/*"
Expected behavior: Cilium inspects HTTP requests at L7 and allows only GET requests to public endpoints and POST requests to auth endpoints. Any other HTTP method or path is blocked, providing application-layer security beyond what standard Network Policies (L3/L4 only) can achieve.
# Verify Cilium is working
kubectl -n kube-system exec daemonset/cilium -- cilium status
# Expected output:
# KVStore: Ok Disabled
# Kubernetes: Ok 1.0 (v1.28.0) [linux/amd64]
# Kubernetes APIs: ["Endpoint", "CiliumNode", "CiliumNetworkPolicy", ...]
# Cilium: Ok OK
# NodeMonitor: Listening for events on 4 CPUs with 64x4096 shared memory
# Cilium health daemon: Ok
# Test connectivity
kubectl run test-pod --image=busybox -it --rm -- wget -qO- http://api-service:8080/api/v2/public/healthz
# Expected output (if policy allows):
# {"status":"ok"}
Service Mesh Integration
Service meshes like Istio and Linkerd add mTLS, traffic splitting, and Observability on top of Kubernetes networking.
# istio-peerauthentication.yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: strict-mtls
namespace: production
spec:
mtls:
mode: STRICT
Expected behavior: All traffic between services in the production namespace is encrypted with mutual TLS. Communication is authenticated and encrypted at the application layer, adding defense in depth beyond Network Policies.
Common Errors
Network Policies not working because no CNI plugin supports them: Flannel does not enforce Network Policies. If you apply a NetworkPolicy with Flannel, it has no effect. Always verify your CNI plugin supports policy enforcement (Calico, Cilium, Weave, Antrea).
Forgetting podSelector in NetworkPolicy: A NetworkPolicy with an empty
podSelector({}) affects all Pods in the namespace. This is useful for default-deny policies but dangerous if applied by mistake to a production namespace without understanding the impact.CIDR exceptions in egress policies not covering all private ranges: The standard RFC 1918 ranges are 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16. Missing any of these in the
exceptblock allows traffic to those private IPs, potentially bypassing your security controls.DNS resolution failures when egress policies block port 53: CoreDNS runs inside the cluster. If an egress policy blocks UDP port 53, Pods cannot resolve DNS names. Always include an explicit egress rule for DNS:
kube-systemnamespace on port 53/UDP.Overlapping Network Policies causing unexpected allow rules: Network Policies are additive. If one policy allows traffic from
app: frontendon port 8080 and another allows all traffic fromapp: monitoringwith no port restriction, the effective rule is the union. Traffic frommonitoringis allowed on all ports. Use a default-deny policy to start from a clean slate.
Practice Questions
What is the default networking behavior in Kubernetes when no Network Policies exist? Answer: By default, all Pod-to-Pod traffic is allowed across all namespaces. There is no isolation. This flat network model is convenient for development but dangerous for production with multi-tenant or sensitive workloads.
How does a NetworkPolicy with
podSelector: {}differ from one withpodSelector: matchLabels: app: api? Answer: An emptypodSelector({}) matches all Pods in the namespace. A labeled selector matches only Pods with that label. The empty selector is used for default-deny policies.Why does Calico support Network Policies but Flannel does not? Answer: Flannel only handles IP address management and packet Encapsulation (L2/L3). It does not implement a firewall or policy engine. Calico includes a distributed firewall that enforces policy rules at each node using iptables or eBPF.
What is the difference between a Kubernetes NetworkPolicy and a CiliumNetworkPolicy? Answer: Kubernetes NetworkPolicy operates at L3/L4 (IP addresses, ports, protocols). CiliumNetworkPolicy extends this to L7 (HTTP methods, paths, API endpoints) and supports DNS-based rules, CIDR rules with FQDN resolution, and Kafka/gRPC-aware policies.
Challenge
Design a zero-trust network for a three-tier application (frontend, API, database) with these requirements: all namespaces default to deny-all ingress and egress, frontend can only reach API on port 8080, API can only reach database on port 5432, database has no egress access, monitoring namespace (Prometheus) can scrape metrics on all tiers, API can reach external HTTPS services on port 443 only, and DNS resolution is allowed for all Pods. Implement with both standard Network Policies and one Cilium L7 policy that restricts API access to specific HTTP paths.
Mini Project
Build a complete network isolation framework for a Microservices platform: install Calico or Cilium on a kind cluster, create namespaces (frontend, backend, data, monitoring), deploy sample applications in each namespace, implement namespace-level default-deny policies, create tier-specific ingress policies (frontend->backend->data chain), configure egress policies that restrict outbound traffic to only necessary external endpoints, set up a Cilium Hubble UI for traffic visualization, generate traffic with a load testing tool, and observe blocked/allowed flows in Hubble. Document the policy hierarchy and test each rule with connectivity probes.
Related Resources
| Resource | Description |
|---|---|
| Kubernetes Services | Service networking and DNS |
| Service Mesh | Advanced traffic management |
| Monitoring Tools | Network Observability |
| Container Security | Network security best practices |
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro