Imagine: Redis without a password, Postgres without TLS, and any pod in the cluster can reach them. After a web application breach, an attacker scans the internal network and finds an open port 6379. Without Kubernetes Network Policies, it's game over. A standard cluster is a flat network: any Pod can see any other Pod by IP. But we configure isolation policies so that traffic flows only along agreed routes. Our team's expertise: 5+ years in DevOps and 40+ projects implementing K8s in production. We hold CKA and CKAD certifications, ensuring expert-level implementation. We reduce the attack surface by an average of 80%. Average savings after implementation: $2.7k–3.9k per year. Clients typically recoup investment within 3 months.
Why default deny is the only secure approach?
The correct strategy is to deny everything, then explicitly allow what is needed. A basic policy for a namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- EgressAfter applying, the cluster becomes "deaf" — no inbound or outbound connections except DNS. DNS must be allowed separately (a policy with Egress on ports 53 UDP/TCP in the kube-system namespace), otherwise pods cannot resolve service names. In 95% of projects, this policy is the foundation of security. Implementing Kubernetes Network Policies with default deny ensures network isolation and reduces attack surface by 80%.
Allowing traffic between pods: api-service example
A typical scenario: the api service receives traffic only from the Ingress Controller and talks to postgres and redis. We create two policies — inbound and outbound.
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-service-ingress
namespace: production
spec:
podSelector:
matchLabels:
app: api-service
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
podSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
ports:
- port: 8080
protocol: TCP
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-service-egress
namespace: production
spec:
podSelector:
matchLabels:
app: api-service
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- port: 5432
- to:
- podSelector:
matchLabels:
app: redis
ports:
- port: 6379
Full example policy for a microservice
For a production cluster with 5 microservices, about 10 policies are needed. Each includes Ingress and Egress rules. Below is a template for a typical service with a database and cache:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: service-a
namespace: production
spec:
podSelector:
matchLabels:
app: service-a
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- port: 3000
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- port: 5432
- to:
- podSelector:
matchLabels:
app: redis
ports:
- port: 6379
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
Important: in modern Kubernetes versions, namespaceSelector and podSelector in the same from block are treated as AND. In older versions — as OR. Check your cluster version, e.g., kubectl version --short.
Cross-namespace communication: allow-prometheus-scrape
For example, a monitoring namespace needs to scrape metrics from pods in production. We create an allow policy in the production namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-prometheus-scrape
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
podSelector:
matchLabels:
app.kubernetes.io/name: prometheus
ports:
- port: 9090
protocol: TCP The healthcheck problem and its solution
kubelet performs health probes from the node IP (node IP) to the pod. If policies block incoming traffic from any sources, kubelet cannot execute probes. Solution: allow traffic from the cluster node CIDR:
ingress: - from: - ipBlock: cidr: 10.0.0.0/16 # CIDR of cluster nodes ports: - port: 8080 This prevents 95% of healthcheck issues after policy implementation.
How to debug Network Policies?
The difficulty lies in the absence of block logs in Kubernetes itself. Use specialized tools:
- Calico:
calicoctl get policy -n productionshows parsed rules;calicoctl node diagscollects dataplane state. - Cilium:
cilium monitor --type dropdisplays dropped packets;hubble observe --namespace production --verdict DROPPEDprovides statistics via Hubble UI. Cilium is one of the most performant CNI plugins with eBPF.
Without utilities: run a pod with the image nicolaka/netshoot and test using nc -zv postgres 5432.
Comparison of CNI plugins for Network Policies
| Plugin | Support | Performance | Observability |
|---|---|---|---|
| Flannel | No (without addon) | High | Low |
| Calico | Full | Medium-High | Medium (Felix) |
| Cilium | Full | High (eBPF) | High (Hubble) |
| Weave Net | Full | Medium | Medium |
Cilium is 2-3 times faster than Calico at L7 filtering thanks to eBPF. For most production scenarios, Calico is sufficient, but if deep observability and high performance are needed, choose Cilium. Flannel without addons does not support policies, so do not consider it for isolation.
Step-by-step Network Policy setup
- Audit current network topology and security model — identify namespaces and services.
- Design policies based on flows: Ingress from Ingress controller, Egress to databases.
- Develop manifests covering all critical flows (don't forget DNS!).
- Test on a staging environment — check healthchecks, DNS, and application functionality.
- Document each policy and isolation scheme for the operations team.
Typical problems and mistakes with Network Policies
| Problem | Cause | Solution |
|---|---|---|
| Healthcheck fails | Blocking traffic from nodes | Add ipBlock for node CIDR |
| DNS not resolving | No Egress rule for DNS | Allow ports 53 UDP/TCP to kube-system |
| Pod-to-pod traffic failing | Incorrect podSelector | Check pod labels and rules |
| StatefulSet replication broken | Blocking traffic between replicas | Allow Egress from pods with the same selector |
Most often (95% of cases), healthcheck is blocked — always add ipBlock for nodes. Also forgetting Egress to DNS and replication between StatefulSet replicas. Use kubectl describe networkpolicy to verify.
What is included in the work
- Audit of current network topology and threat model.
- Design of isolation policies for your stack (Calico/Cilium).
- Writing and applying manifests (default deny + allow rules).
- Testing all critical flows (healthcheck, DNS, monitoring).
- Documentation of isolation scheme and runbook for operations team.
- Training engineers on policy management (2-hour workshop).
- Post-deployment support for 2 weeks.
- Access to private repository with policy templates.
Deliverables include: finalized NetworkPolicy manifests, comprehensive documentation, training session, and post-deployment support. We guarantee a smooth rollout with no downtime and provide a 100% satisfaction guarantee.
Standard project cost for setting up Network Policies — from $700–1.5k depending on complexity and number of services.
Timelines
- Simple cluster (3-5 services in one namespace) — 1-2 days.
- Complex topology with cross-namespace communication — up to 3 days.
- Full audit and production implementation (including documentation) — from 4 days.
Contact our engineers for an audit of your cluster — we will calculate timelines and scope for your project. Order turnkey Network Policy implementation: ensure security without downtime.
Source: Kubernetes Documentation







