Last updated on September 19th, 2026 at 07:34 am
Most teams leave the entrance door to their Kubernetes cluster locked and all their internal windows open. Network policies are tacked on at the end. Service-to-service traffic is not encrypted. “Zero trust” remains a seldom-seen slide in a security deck.
Breaches occur in that same divide between intention and action.
This article explains how Kubernetes network security works, how it’s used in practice, and how it fits into a real zero-trust architecture, including default-deny policies, Istio-supported encryption, ingress hardening, and more. Not theory. Real-world decisions about configuration that actually make a difference.
Table of Contents
The Default-Deny Problem Nobody Talks About Enough
What surprises many people when they learn about Kubernetes is that, by default, all pods can communicate with each other. No restrictions. Complete (E-W) traffic is unrestricted.
It’s okay if you are using a laptop. Its nature is counterproductive in production.
With default-allow networking, a compromised logging pod in a pod namespace can probe your payment service, access your database, and steal your data without traversing any firewall rule. The impact of any hole is the entire cluster.
The fix seems straightforward – set it to default-deny. But teams often don’t use it because it can break things if you don’t carefully consider what you add to the allowlist first…
Writing a Default-Deny Policy That Doesn’t Break Your Cluster
A NetworkPolicy is a network resource applied only to the pods the podSelector selects. A deny-all policy has the form of:
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: default-deny-all namespace: productionspec: podSelector: {} policyTypes: - Ingress - EgressAn empty podSelector matches all items in the namespace. Ingress and egress are listed, but no rules are defined; therefore, nothing goes in or out.
Then gradually increase from there. Only permit primaries: frontend to backend, backend to DB, and only the specified port.
I’ve done this process on medium-sized service portfolios, and the most important takeaway is to map namespace pinging first. If you’re not aware of any traffic patterns before you make policy, you’re going to waste lots of time following the wrong services.
Here are some points to bear in mind:
- NetworkPolicy needs a CNI plugin that implements these network policies: Calico, Cilium, or Weave. The default kube-net doesn’t support this type of private partner.
- Policies are additive. All the policies within the same pod combine their allow rules.
- Egress rules are commonly overlooked, but they do come into play – particularly when considering the external endpoints that your pods can access.
This is a part of solid Kubernetes Security, but not all of it.
What Istio Actually Does for Your Network (And What It Doesn’t)
NetworkPolicies operate on an IP and port basis. Failure to understand HTTP methods, JWT tokens, or service identity. Not understanding web methods, JWTs, or service identity. A service mesh is what fits the bill here.
Istio is the most popular, and its main network-security strength is providing mutual TLS (mTLS) between all services. Each sidecar proxy automatically rotates certificates. Pods encrypt data while traversing and verify each other’s identity before the connection is finalized.
Enabling mTLS Cluster-Wide Without Breaking Everything
Istio’s PeerAuthentication resource controls mTLS behavior. If you choose STRICT mode, Istio will not accept unencrypted traffic.
apiVersion: security.istio.io/v1beta1kind: PeerAuthenticationmetadata: name: default namespace: istio-systemspec: mtls: mode: STRICT
The goal is to apply this cluster-wide. However, strict mode applies to services not yet in the mesh (legacy applications and third-party tools), which breaks them.
Methodology: Be PERMISSIVE (allow both encrypted and plain traffic), gradually move services to the new location, then move to STRICT.
My experience indicated a phase of the migration (migration phase) where most teams get themselves stuck. Permissive mode can remain active for months because no one has cutover “ownership.” It is definitely worth factoring in a rollout-time period.
Authorization Policies – The Part Most Tutorials Skip
mTLS will provide encryption and identity. However, you will need to specify what services you are authenticating can do.
This is managed by the Istio AuthorizationPolicy resource:
apiVersion: security.istio.io/v1beta1kind: AuthorizationPolicymetadata: name: payment-service-policy namespace: productionspec: selector: matchLabels: app: payment-service rules: - from: - source: principals: ["cluster.local/ns/production/sa/checkout-service"] to: - operation: methods: ["POST"] paths: ["/api/v1/charge"]
This is fine-grained. The payment service supports POST requests only on a particular path, and only from the checkout service’s service account. Not a bit of anything passes through — even encrypted.
This type of policy certainly doesn’t meet security needs. This is a first step towards real defense in depth, along with Container Security practices at the pod level.
Ingress Is Still Your Most Exposed Surface
Intercluster east-west traffic receives a lot of focus. The real exposure may come from ingress traffic or traffic from outside.
Kubernetes Ingress maps out external HTTP/HTTPS traffic to services. However, the security configuration isn’t part of the Ingress resource; it’s in the ingress controller. You can do this with Nginx, Traefik, and native controllers for AWS/GCP/Azure.
Some things need to be in place at the entry point:
Do terminate TLS at the controller — Do not run unencrypted traffic in your cluster from the ingress point. On the controller, end TLS and re-encrypt when you are running mTLS internally.
Rate limiting — Most ingress controllers have it as a native feature. Otherwise, a misconfigured client or bot can saturate it.
Web Application Firewall Integration — When you have public-facing APIs, you can have a Web Application Firewall (WAF) in front of your API layer that can intercept common attack patterns before they reach your application code.
Blocking source IPs (if it is necessary) – Use nginx.ingress.kubernetes.io/whitelist-source-range or similar annotations for ingress where it must only accept traffic from a set of known source IPs (internal tools or traffic from a particular region.
I’ve noticed that teams using cloud-managed ingress controllers often assume the provider will manage the security config. They don’t, generally. You need to add these controls explicitly, too.
My Take on Zero Trust – It’s an Architecture, Not a Feature
You are seeing the phrase “Zero trust” pretty much everywhere these days. It basically translates to not completely depending on network location. Not because it’s inside the cluster. Not because that’s in the same namespace. You must consciously maintain trust at each interaction.
Kubernetes provides you with the building blocks. How you combine them is called zero trust.
This makes sense, given the four corners of Kubernetes security: Cloud, Cluster, Container, and Code. At every layer, zero trust thinking is implemented:
- Cloud: Install IAM roles, add access controls to nodes, and monitor your cloud config with KSPM tools.
- Cluster: Attach audit_sink and cluster to the components in the corresponding templates. In the corresponding templates, attach audit_sink and cluster to components.
- Container: Pod Security Admission, read-only filesystems, dropping Linux capabilities
- Code: Dependency scanning and image signing / SBOM generation
Don’t assume you need all of this on day one of adopting zero trust. It’s a process of creating explicit, logged, and revocable access decisions.
Where Kubernetes Network Security Fits in a Zero-Trust Model
The network layer is where enforcement happens. You can’t take policies to the street without enforcing them there.
Within a zero-trust Kubernetes design, this is how to enforce:
- No access to services except when required, using limited service accounts. Workload identity based on SPIFFE/SPIRE or a cloud-based identity system.
- Transit encryption – encrypt everything within the cluster via mTLS with Istio or Linkerd.
- Policy enforcement – NetworkPolicies in the CNI layer, AuthorizationPolicies in the mesh layer.
- Continuous verification – Audit logs, Falco for the detection of runtime anomalies, alerts when policy drift occurs.
- Least-privilege egress (Pods only access the external endpoint(s) they require). Nothing else.
Kubernetes cluster hardening includes the cluster-level controls that underpin all of this: API server flags, etcd encryption, kubeconfig security, and node hardening.
Secrets Management – The Gap That Undermines Everything Else
All your network policies and airtight mTLS can be drifted away by a single hardcoded password in a ConfigMap database.
Every team struggles with Secret Management in Kubernetes. Values are default Secret base64-encoded – which is not encryption. Anyone with read access to the namespace can decrypt it in seconds.
Better options:
- Encryption of secrets before reaching the cluster. Only the controller can decrypt them.
- External Secrets Operator – Fetch secrets from enabled secret storage (AWS Secrets Manager, GCP Secret Manager, or HashiCorp Vault) and store them at runtime.
- Vault Agent Injector – Inject secrets directly into pod filesystems, without modifying environment variables.
The secret that really matters: secrets don’t stay in the cluster when it’s not working. They are pulled from a store at boot and then cycle on schedule; they are never versioned.
Two Unique Angles Most Articles Don’t Cover
eBPF-based policy enforcement is changing the game
Traditional CNI-distro plugins use iptables rules to control NetworkPolicies. On large systems, this becomes a performance blocker and a debugging nightmare.
With significantly lower overhead and much improved observability, Cilium succeeds where other technologies have failed by implementing eBPF (a Linux kernel technology). See all connections being allowed or dropped, and identity context, in real time.
On large clusters, or workloads requiring lower latency, the impact is evident. I’ve seen iptables rule counts in mid-size clusters reach the tens of thousands. eBPF doesn’t suffer from this issue.
NetworkPolicy testing is rarely done.
Creating a policy is one thing. Drafting a policy is easy. Verifying that it is really effective as intended is another. Most teams skip this.
Use netassert, kubectl-netpol, or simply a test pod running curl in the cluster to ensure that deny rules are indeed denying. Policy drift happens, and you don’t need to be reminded that a new deployment, namespace label change, or CNI update can silently make enforcement go down the drain.
Wrapping Up: Who Needs This and Where to Start
Visualizing the placement of a wrap around the world and the processes used to wrap it.
These controls are essential if you’re not running a dev cluster. They keep a security incident limited to one namespace, not a full cluster compromise.
Use the default-deny NetworkPolicies for the most sensitive namespaces. Install the Istio mTLS addon in permissive mode, then move toward strict mode. Check the ingress configuration. Then deploy zero-trust controls (RBAC, workload identity, runtime detection) one at a time.
The intent of the objective is not perfection on day one. It’s about creating a cluster based on trust, not assumption.
I’m a technology writer passionate about AI and digital marketing. I create engaging and useful content that bridges the gap between complex technology concepts and digital technologies. My writing makes the process easy and engaging. I encourage participation I continue to research innovation and technology. Let’s connect and talk technology!




[…] clusters can happen in ways that shock teams that thought pods were isolated by default, even with Kubernetes Network Policies. They’re […]