How to Implement Sophisticated Network Policies in Kubernetes for Least-Privilege Communication
Implement a default-deny baseline in every namespace, then explicitly whitelist required pod-to-pod, cross-namespace, and external flows using label selectors and CIDR blocks, validating configurations with OPA Gatekeeper.
Kubernetes NetworkPolicies provide a firewall-like mechanism to control pod traffic, but achieving true least-privilege requires a systematic approach beyond basic rules. According to the bregman-arie/devops-exercises repository, particularly in topics/kubernetes/README.md around line 2697, implementing sophisticated network policies involves layering default-deny baselines with granular allow rules for both internal and external communication paths.
Establishing a Default-Deny Security Baseline
By default, Kubernetes pods accept traffic from any source. To implement a zero-trust posture, you must first establish a default-deny policy that selects all pods in a namespace and blocks both ingress and egress traffic. This forces every subsequent policy to explicitly define permitted communication paths.
Create a global deny-all policy in each namespace to establish your secure baseline:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: prod
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Because NetworkPolicies are namespace-scoped, apply this pattern to every namespace requiring isolation. This single policy flips the default behavior from allow-all to deny-all, ensuring that only explicitly defined traffic flows are permitted.
Implementing Intra-Namespace Service-to-Service Rules
After establishing the deny-all baseline, whitelist specific service-to-service communication using pod selectors and labels. Consistent labeling (e.g., app=frontend, app=backend) is critical, as NetworkPolicies rely on these selectors to identify traffic endpoints.
Allow front-end pods to communicate with back-end pods on port 8080:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: prod
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
This approach enforces least-privilege within the namespace by ensuring the back-end only accepts connections from explicitly labeled front-end instances on the required port.
Enforcing Cross-Namespace Least-Privilege Communication
Traffic between namespaces is blocked by default once you implement deny-all policies. To enable cross-namespace communication, you must create complementary policies on both sides: an egress rule in the source namespace and an ingress rule in the target namespace.
First, create the ingress policy in the target namespace (backend-ns) allowing traffic from the source namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-ns
namespace: backend-ns
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend-ns
podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Then, create the corresponding egress policy in the source namespace (frontend-ns):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-to-backend-ns
namespace: frontend-ns
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
name: backend-ns
podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 8080
This bidirectional enforcement ensures that namespace isolation remains intact while permitting only the specific pod-to-pod flows required for application functionality.
Controlling External Service Access
To implement least-privilege for external communication, use egress rules with ipBlock selectors to whitelist specific CIDR ranges or DNS-resolved IP blocks. This prevents pods from accessing unauthorized internet endpoints while permitting necessary third-party API calls.
Allow back-end pods to call an external API on HTTPS:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-allow-external-api
namespace: prod
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 203.0.113.0/24
ports:
- protocol: TCP
port: 443
Replace the CIDR with the actual IP range of your external service. For DNS-based external services, you must specify the resolved IP ranges, as NetworkPolicies operate at layer 3/4 and do not perform DNS resolution.
Validating Policies with OPA Gatekeeper
To prevent configuration drift and enforce organizational standards, validate NetworkPolicy configurations using OPA Gatekeeper. As noted in the Policy Testing section of topics/kubernetes/README.md around line 2567, Gatekeeper constraints can require specific policy patterns or deny namespaces lacking proper network isolation.
Deploy a constraint to ensure every namespace contains at least one NetworkPolicy:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredNetworkPolicy
metadata:
name: require-np-per-namespace
spec:
enforcementAction: deny
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
This validation layer ensures that developers cannot bypass the default-deny requirement, maintaining the least-privilege posture across the cluster.
Monitoring and Observability
Verify that only permitted flows are occurring using Falco or Calico audit logs. These tools detect and alert on policy violations, providing visibility into attempted unauthorized connections. For testing, use kubectl exec to attempt connections between pods or employ specialized tools like npdiag to validate policy behavior before production deployment.
Summary
- Start with default-deny policies in every namespace to establish a secure baseline where no traffic is allowed by default.
- Label pods consistently to enable precise selector-based rules for service-to-service communication.
- Require bidirectional rules for cross-namespace traffic, implementing both egress policies in source namespaces and ingress policies in target namespaces.
- Whitelist external access using specific CIDR blocks in egress rules to limit internet exposure.
- Validate configurations with OPA Gatekeeper constraints to prevent misconfiguration drift and ensure compliance with security standards.
Frequently Asked Questions
What is the default traffic behavior in Kubernetes without NetworkPolicies?
Without NetworkPolicies, Kubernetes pods accept traffic from any source both internally and externally. This permissive default allows unrestricted communication between all pods in the cluster and external networks, which violates least-privilege principles. The first step in securing the cluster is implementing a default-deny NetworkPolicy that blocks all ingress and egress traffic until explicitly allowed.
How do you allow traffic between two specific namespaces?
You must create complementary rules on both sides of the connection. In the target namespace, create an ingress policy using namespaceSelector and podSelector to identify the source. In the source namespace, create an egress policy using matching selectors to identify the destination. Both policies must reference the specific ports and protocols required, and both namespaces must have the name label properly set for the namespaceSelector to match.
Can NetworkPolicies block traffic to external services?
Yes, by implementing default-deny egress policies and only whitelisting specific external destinations using ipBlock with CIDR notation. Once a pod is selected by any NetworkPolicy defining egress rules, it can only communicate with explicitly allowed destinations. This effectively blocks all external internet access except for the specific IP ranges and ports defined in your egress whitelist.
How do you validate NetworkPolicy configurations before deployment?
Use OPA Gatekeeper to enforce policy constraints that require specific NetworkPolicy patterns, such as mandatory default-deny rules in every namespace. As documented in topics/kubernetes/README.md at line 2567, Gatekeeper validates resources against rego policies during admission, preventing non-compliant configurations from reaching the cluster. Additionally, test policies using kubectl exec to verify connectivity or tools like Calico's policy preview features to simulate rule behavior.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →