Kubernetes NetworkPolicy controls which network connections are allowed to and from selected Pods. The safest small-team pattern is to map required traffic first, verify that the cluster network enforces NetworkPolicy, then move toward default-deny with explicit allow rules.
Raff Technologies keeps Kubernetes worker infrastructure private by default, but private infrastructure networking and Kubernetes NetworkPolicy solve different problems. The VPC defines the infrastructure boundary; NetworkPolicy defines allowed workload traffic inside the cluster.
A practical production model is:
VPC / private cluster network → Services → NetworkPolicy → Pods → application authentication
This page owns the Kubernetes NetworkPolicy decision model: default deny, ingress, egress, selectors, DNS, rollout, and verification. It does not replace the broader Kubernetes Networking and Storage Architecture or the application-level Kubernetes Security Best Practices.
What is a Kubernetes NetworkPolicy?
A NetworkPolicy is a namespace-scoped Kubernetes API resource that selects Pods and defines allowed network traffic for ingress, egress, or both.
NetworkPolicy is primarily a Layer 3 / Layer 4 control. It can match traffic using constructs such as:
- Pod selectors;
- namespace selectors;
- IP blocks;
- protocols;
- ports.
It does not decide whether an authenticated user may call an API endpoint, whether a secret is valid, or whether an application role may modify data.
The other important prerequisite is enforcement. Kubernetes requires a network plugin that implements NetworkPolicy. Creating a NetworkPolicy object on a cluster whose networking stack does not enforce it does not create isolation.
Before treating NetworkPolicy as a security control, test the actual cluster.
Pods are non-isolated until a policy selects them
Kubernetes treats ingress and egress isolation independently.
By default, a Pod is non-isolated for ingress and non-isolated for egress. Restrictions begin when a NetworkPolicy selects the Pod for that direction.
That means these are separate states:
| State | Ingress | Egress |
|---|---|---|
| No selecting policy | Allowed | Allowed |
| Ingress policy only | Restricted by allowed ingress rules | Still allowed |
| Egress policy only | Still allowed | Restricted by allowed egress rules |
| Both directions selected | Restricted | Restricted |
This is why a default-deny ingress policy does not automatically block outbound traffic, and a default-deny egress policy does not automatically block inbound traffic.
NetworkPolicies are additive, not ordered firewall rules
NetworkPolicy rules do not behave like a top-to-bottom firewall list.
When multiple policies select the same Pod for the same direction, their allowed traffic is combined. The effective result is the union of the allowed connections.
For Pod A to connect to Pod B:
- Pod A's effective egress policy must allow the connection; and
- Pod B's effective ingress policy must allow the connection.
If either side blocks the flow, the connection fails.
This matters operationally because adding a second policy does not override the first. If one policy already allows a path, a second policy cannot "deny" that same path by being evaluated later.
Small teams should therefore think in terms of allowed traffic sets, not policy order.
Start with a default-deny baseline only after mapping dependencies
A default-deny policy is a useful production baseline because it changes the model from broad implicit trust to explicit allowed paths.
A combined ingress-and-egress default deny can look like this:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-all spec: podSelector: {} policyTypes: - Ingress - Egress
This selects all Pods in the namespace and allows no ingress or egress until another policy permits required flows.
Do not deploy this blindly to an existing production namespace.
Map at least:
- ingress-controller or Gateway traffic;
- internal API calls;
- database and cache access;
- DNS;
- metrics and log collection;
- external APIs;
- object storage;
- identity providers;
- payment, email, webhook, or other SaaS dependencies.
A deny-first model is strongest when the allow-list reflects the application's actual dependency graph.
Allow one workload to reach another with selectors
A typical policy may allow frontend Pods to reach API Pods on one application port.
For example, in the API namespace:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-frontend-to-api spec: podSelector: matchLabels: app: api policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: frontend podSelector: matchLabels: app: web ports: - protocol: TCP port: 8080
This expresses an application relationship rather than relying on Pod IP addresses.
The standardized namespace label kubernetes.io/metadata.name is useful when a policy must target one named namespace. For other namespace labels, treat label changes as security-sensitive configuration because changing a trusted label can change the effective traffic boundary.
Default-deny egress can break DNS immediately
DNS is one of the most common failures after teams introduce egress isolation.
A default-deny egress policy also blocks DNS unless a separate rule allows traffic to the cluster DNS service.
The exact labels and namespace used by DNS can vary by cluster implementation, so inspect your cluster before copying a policy.
A common verification flow is:
kubectl get svc -A | grep -i dns kubectl get pods -A --show-labels | grep -i dns
Then create a narrowly scoped egress rule that matches the actual DNS service and required ports.
Do not assume a copied kube-dns or CoreDNS selector matches every cluster.
After applying egress restrictions, verify both:
kubectl exec <pod> -- nslookup kubernetes.default.svc.cluster.local kubectl exec <pod> -- nslookup example.com
Internal and external DNS can fail for different reasons.
Ingress and egress policies should follow the application traffic graph
A small SaaS stack may need only a few flows:
public routing layer ↓ web Pods ↓ api Pods ↓ database api Pods → DNS api Pods → payment API monitoring → selected metrics endpoints
From that graph, derive policy boundaries.
Ingress policy
Use ingress rules to answer:
Who is allowed to connect to this workload?
Good candidates include:
- APIs that should only accept traffic from the web tier;
- databases or database proxies that should only accept application traffic;
- admin services that should only accept traffic from a management namespace;
- metrics endpoints that should only accept traffic from monitoring.
Egress policy
Use egress rules to answer:
Where is this workload allowed to connect?
Good candidates include:
- a known database service;
- DNS;
- an object-storage endpoint;
- a small set of internal APIs;
- specific CIDRs where IP-based policy is stable and appropriate.
Standard Kubernetes NetworkPolicy does not provide a portable domain-name policy model for arbitrary SaaS domains. If outbound policy must follow changing DNS names, confirm what your CNI, service mesh, or egress gateway supports instead of assuming a standard NetworkPolicy can express it safely.
NetworkPolicy does not replace Services, VPCs, TLS, or RBAC
NetworkPolicy is one security layer.
| Layer | Responsibility |
|---|---|
| VPC / private networking | Infrastructure reachability boundary |
| Service | Stable workload discovery |
| Gateway / Ingress | Public application routing |
| NetworkPolicy | Allowed Pod network flows |
| TLS | Transport encryption and endpoint identity where configured |
| RBAC | Kubernetes API authorization |
| Application auth | Business-level user and service authorization |
A private VPC does not mean every Pod should trust every other Pod.
A NetworkPolicy cannot decide whether a logged-in user may delete a record.
RBAC cannot stop one already-running Pod from opening a TCP connection to another workload.
Treat these controls as complementary.
Use Kubernetes Services Explained for service reachability and Kubernetes Security Best Practices for RBAC, ServiceAccounts, Secrets, and Pod Security.
Multi-tenant clusters need stronger network boundaries
NetworkPolicy becomes especially important when unrelated workloads share a cluster.
Examples include:
- MSP customers;
- multiple internal teams;
- staging and production workloads;
- shared platform services;
- client-specific namespaces.
A useful boundary can be:
client-a namespace ─X→ client-b namespace client-a namespace → shared monitoring client-b namespace → shared monitoring platform ingress → approved application ports
NetworkPolicy is not a complete multi-tenancy model by itself. RBAC, namespace ownership, Secrets, admission controls, node placement, storage isolation, and operational access also matter.
For MSP-specific architecture, use Kubernetes Multi-Tenancy for MSPs.
Test the deny path, not only the allow path
A policy is not verified because kubectl accepted the YAML.
After a policy change, test:
- a connection that should succeed;
- a connection that should fail;
- DNS resolution;
- ingress or Gateway traffic;
- database/cache connectivity;
- monitoring and logging;
- any required external API.
Example:
# Expected allow kubectl exec <frontend-pod> -- curl -sS http://api:8080/health # Expected deny kubectl exec <unrelated-pod> -- curl --connect-timeout 3 http://api:8080/health
Use disposable test Pods where appropriate rather than changing production workloads solely to test networking.
Remember that policy application is implemented by the network plugin and may not be instantaneous during changes. Do not design deployment logic around an assumption that policy transitions happen atomically everywhere.
A safe rollout sequence for existing production clusters
For an existing application, use this order:
1. Inventory traffic
Document Service-to-Service, namespace-to-namespace, and external dependencies.
2. Verify NetworkPolicy enforcement
Apply a small test policy in a non-critical namespace and prove that a denied connection actually fails.
3. Start with one namespace
Do not introduce cluster-wide isolation across every workload at once.
4. Add explicit allow rules
Allow only known application paths.
5. Add default-deny ingress
Ingress isolation is often easier to reason about first because callers are usually better understood.
6. Add egress restrictions carefully
Map DNS and external APIs before denying outbound traffic.
7. Verify after every change
Test both positive and negative cases.
This staged rollout is easier to debug than applying a large policy bundle and discovering hidden dependencies during an incident.
How NetworkPolicy maps to Raff Kubernetes
Raff Kubernetes keeps worker nodes on private cluster networking and provides a managed public endpoint for traffic that should enter the cluster. The live product also includes VPC isolation, node pools, autoscaling, monitoring, logs, and standard Kubernetes tooling.
That infrastructure boundary is separate from workload policy.
NetworkPolicy should still be designed around application flows and verified on the actual cluster before it is treated as an active security control.
The production rule is simple:
Private infrastructure reduces exposure. NetworkPolicy reduces unnecessary trust between workloads.
For current cluster capabilities and pricing, use the Raff Kubernetes product page rather than relying on a security guide as a pricing source of truth.
Kubernetes NetworkPolicy checklist
Before calling a namespace isolated, verify:
Enforcement
- The cluster network plugin supports NetworkPolicy.
- A test deny rule has been proven to block traffic.
Ingress
- Public routing traffic is explicitly allowed where needed.
- Internal APIs accept traffic only from expected callers.
- Database/cache traffic is scoped to required workloads.
Egress
- DNS is explicitly accounted for.
- Required external APIs are documented.
- Observability traffic still works.
- Object storage and managed-service dependencies are covered.
Operations
- Namespace and Pod labels used in policies are controlled.
- Both allowed and denied flows are tested.
- Policy changes have a rollback path.
- The team can explain why each allowed path exists.
Final recommendation
Do not start by writing dozens of NetworkPolicy objects.
Start by drawing the application's required traffic graph. Verify that the cluster actually enforces NetworkPolicy. Then introduce default-deny boundaries one namespace at a time and add only the flows the application requires.
For a small team, a short, explainable set of policies that is tested regularly is stronger than a large policy library nobody understands.
Continue with Kubernetes Networking and Storage Architecture for the infrastructure model, Kubernetes Services Explained for Service and traffic exposure, and Kubernetes Security Best Practices for the wider cluster-security baseline.