Kubernetes NetworkPolicy defaults for tenant releases
Direct answer
Kubernetes pods are non-isolated by default. A tenant namespace does not become a network boundary until an enforcing CNI applies NetworkPolicy resources that select its pods. OpenTenant automates the safer pattern: every tenant release starts with default-deny ingress and egress, then receives narrow allow rules compiled from the services, secret delivery, DNS, observability, and edge routes declared for that tenant.
The result is not “a NetworkPolicy.” It is a reproducible policy set tied to one release and tested against the connections that release requires.
What Kubernetes NetworkPolicy controls
Kubernetes NetworkPolicy controls layer 3 and layer 4 traffic involving pods. Rules select peers using pod labels, namespace labels, and IP blocks, then constrain ports and protocols.
Two prerequisites are easy to miss:
- The cluster must use a network plugin that enforces NetworkPolicy. Creating resources without an enforcing implementation has no effect.
- Ingress and egress isolation are independent. A pod becomes isolated in a direction only when a policy selects it for that direction.
Policies are additive rather than ordered. If several policies select a pod, the allowed traffic is the union of their rules. For pod-to-pod traffic, the source egress policy and destination ingress policy must both allow the connection.
Start each tenant from default deny
Kubernetes' multi-tenancy guidance recommends a default policy that denies pod communication, followed by explicit DNS and workload rules. A baseline for a tenant namespace can select every pod and isolate both directions:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: tenant-acme
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
This is intentionally disruptive. Existing charts often assume unrestricted east-west and outbound traffic. That is why OpenTenant treats policy as part of release compilation, not a cluster-wide switch applied after production traffic exists.
Restore DNS deliberately
Default-deny egress can prevent name resolution. The tenant policy set must allow UDP and TCP DNS traffic to the actual DNS pods or service used by the cluster.
Avoid copying an environment-specific label selector blindly. CoreDNS labels and namespaces vary. OpenTenant deployment profiles should discover or declare the DNS target, render the matching rule, and verify resolution from a tenant pod.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: tenant-acme
spec:
podSelector: {}
policyTypes: [Egress]
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- { protocol: UDP, port: 53 }
- { protocol: TCP, port: 53 }
Compile the release graph into allow rules
A tenant chart typically needs a small number of connection classes.
Edge ingress
Allow traffic from the Gateway, ingress controller, or cloudflared connector to only the
tenant service ports. A broad namespace allow would let the edge plane reach every pod; select the actual
workload labels instead.
Intra-release traffic
Allow frontends to APIs, APIs to databases, and workers to queues based on component labels and ports. Keep each edge directional. “Everything in the namespace may talk to everything” is simpler, but it removes much of the value of policy.
Secret delivery
Vault Agent sidecars, CSI providers, Vault Secrets Operator, and External Secrets Operator have different network paths. An operator may fetch secrets from its own namespace and write Kubernetes Secrets through the API server, while an injected agent connects from each application pod to Vault. The policy must match the selected delivery model.
Observability
Declare whether metrics are scraped inbound, logs are pushed outbound, or telemetry uses an in-cluster collector. Do not open all egress because the application “needs monitoring.”
Approved external dependencies
Kubernetes NetworkPolicy uses IP blocks for external networks; it does not natively express arbitrary DNS names. SaaS endpoints with changing IP ranges may require a CNI extension, egress gateway, proxy, or another policy layer. OpenTenant should mark unsupported hostname-only dependencies instead of pretending a static CIDR is durable.
Label integrity is part of the boundary
Policies trust labels. If a tenant-controlled workload can add the label used by an edge connector or privileged service, it may gain access that the author did not intend.
OpenTenant should reserve platform labels, render them from the trusted tenant identity, and use admission
policy to stop tenant workloads from claiming protected identities. Namespace labels used by
namespaceSelector need the same treatment.
Be especially careful with {} as a namespaceSelector: Kubernetes multi-tenancy
guidance warns against broad empty namespace selectors where cross-namespace traffic is allowed.
What NetworkPolicy does not solve
NetworkPolicy is not a complete tenant security boundary.
- It does not authorize Kubernetes API operations; use RBAC.
- It does not limit CPU, memory, or object counts; use quotas and limits.
- It does not encrypt all traffic; use workload TLS or a service mesh when required.
- It does not isolate the shared kernel; use runtime hardening, sandboxing, dedicated nodes, or dedicated clusters for stronger threat models.
- It does not protect storage by itself.
OpenTenant can select a stronger deployment profile when namespace-level isolation is insufficient. Automation should make the trade-off explicit, not hide it.
How OpenTenant automates policy safely
tenant manifest
→ identify release components and ports
→ apply trusted tenant and component labels
→ render default-deny ingress and egress
→ add DNS and declared dependency rules
→ add edge, secrets, and observability paths
→ install chart and policy set together
→ run positive and negative connectivity checks
Every generated policy is owned by the tenant release and carries the source revision and configuration hash. Upgrades reconcile the policy set alongside the Helm release. Removing a dependency removes its allow rule only after readiness checks prove the new release no longer needs it.
Verification checklist
- Confirm the CNI enforces NetworkPolicy with a negative test.
- Verify default-deny covers every tenant pod, including chart hooks and jobs.
- Confirm DNS works over UDP and TCP.
- Test every declared application connection in both directions.
- Prove a pod in tenant A cannot reach tenant B's service, database, or metrics endpoint.
- Verify protected labels cannot be self-assigned.
- Test Vault or external-secret delivery under the same policies.
- Confirm edge connectors can reach only declared tenant services.
- Record policy failures as release failures, not post-deployment warnings.
Sources
OpenTenant turns these controls into a default attached to every tenant lifecycle, while keeping the generated rules visible and reviewable.