A Policy Precedence Guide for Using Istio and Kubernetes NetworkPolicy Together Safely, Without Conflicts
Adopting a service mesh in a Kubernetes environment is a transformative step that maximizes application reliability and observability. These powerful tools, however, come with equally complex networking policies. In particular, when you combine native Kubernetes NetworkPolicy with Istio’s fine-grained controls (AuthorizationPolicy, VirtualService), you quickly hit a fundamental question: “Which rule actually wins?”
This article clearly explains policy precedence—the question senior DevOps engineers and SREs ask most—when these two powerful networking policies collide, and it provides practical architecture guidelines that prevent conflicts at the source.
Understanding Networking Policy Layers: L3/L4 vs. L7
To understand policy conflicts, you first need to recognize that the two policies operate at fundamentally different layers.
🌐 NetworkPolicy: Infrastructure Firewall (L3/L4)
NetworkPolicy acts as the lowest-level firewall, operating at the Kubernetes CNI (Container Network Interface) layer. Think of it as the physical entrance of a data center.
- Control scope: Controls traffic reachability based on IP addresses (L3) and port numbers (L4).
- How it works: Decides whether a given namespace or pod group can communicate on a specific port.
- Core principle: Follows "deny by default"—all traffic is blocked unless explicitly allowed.
🛡️ Istio Policy: Application Gateway (L7)
Istio intercepts and inspects traffic through sidecar proxies (Envoy). Think of this as a security checkpoint inside the data center.
- Control scope: Inspects application-layer details such as HTTP methods (GET, POST), header values, and user authentication (JWT, etc.).
- How it works: Assumes traffic has already reached the destination, then verifies who (identity) is accessing and how (method).
- Core principle: Also follows "deny by default".
🚨 Core Comparison: Policy Precedence Matrix
This is the most important question: when traffic arrives, which policy runs first, and which one is the final winner?
🚀 Traffic Flow Order: CNI → Sidecar → Application
Traffic always flows through layers. Understanding this order is the key to solving every related problem.
- CNI/NetworkPolicy check (L3/L4): The moment a packet enters the cluster network, the CNI plugin checks ports and IPs first. If it is blocked here, nothing after this runs.
- Sidecar/Istio check (L7): When the packet reaches the pod and passes through the sidecar proxy, Istio evaluates L7 rules (authentication, routing).
- Application check: Only traffic that passes every check is delivered to the application port.
💡 A practitioner’s note: The most common mistake I see is the development team tightening only L7 policy (“Istio must authenticate this”) while the infrastructure team locks down L3/L4 too tightly. Traffic is then dropped at L3/L4, so Istio’s sophisticated L7 auth never even gets a chance to run.
📊 Policy Layer and Control Scope Comparison
| Policy type | Control layer | Primary controls | Default behavior | What it controls |
|---|---|---|---|---|
| NetworkPolicy | L3/L4 | IP, port | Deny by default | The network connection itself |
| Istio AuthorizationPolicy | L7 | HTTP method, header, identity | Deny by default | Access permission (authorization) |
| Istio VirtualService | L7 | Host, path, weight | Routing rules | Traffic path and distribution |
🛑 Rule Application Principles by Conflict Scenario (Most Important)
Rule: If traffic is blocked at a lower layer (L3/L4), higher-layer (L7) rules are ignored.
If NetworkPolicy blocks all inbound traffic to a given port (for example, 8080), then even if AuthorizationPolicy says “this user must be allowed to POST,” the packet never reaches the sidecar proxy, so authorization never starts.
🛠️ Best Practices for a Safe Architecture
The most reliable way to prevent policy conflicts is to strictly follow separation of concerns.
1. Apply Separation of Concerns
- NetworkPolicy (L3/L4): Owns only “Can it reach?” (Example: Service A may reach Service B only on port 8080.)
- Istio Policy (L7): Owns only “Is it allowed?” (Example: Service B’s port 8080 is reachable, but only the
GETmethod is permitted.)
2. Practical Example: Open the Port, Then Add Auth
The following YAML implements this principle cleanly.
- NetworkPolicy (L3/L4): Opens the minimum path so Service A can reach Service B on port 8080.
- AuthorizationPolicy (L7): Adds authorization so that traffic that already passed the path is allowed only for users with a JWT token.
# 1. NetworkPolicy: L3/L4 통로 확보 (최소한의 연결만 허용)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-service-b-port
namespace: default
spec:
podSelector:
matchLabels:
app: service-b
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: service-a
ports:
- port: 8080
protocol: TCP
---
# 2. AuthorizationPolicy: L7 인증 추가 (실질적인 접근 제어)
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-jwt-auth
namespace: default
spec:
selector:
matchLabels:
app: service-b
action: ALLOW
rules:
- from:
- source:
namespaces: ["default"]
to:
- operation:
methods: ["GET"] # L7: GET 메서드만 허용
paths: ["/api/v1/data"]
requestPrincipals: ["cluster.local/ns/default/sa/service-a-sa"] # L7: 특정 서비스 계정만 허용In this example, without NetworkPolicy traffic never arrives; without AuthorizationPolicy anyone who can reach the port can access it. You need both for a safe setup.
🔍 Debugging Tips: Tracing Traffic Flow
When you suspect a policy conflict, use these two tools in order.
kubectl get events: Check the namespace for policy-violation or CNI-related error messages. (Detects L3/L4 problems.)istioctl proxy-config logs <pod-name>: Inspect sidecar proxy logs to see at which stage traffic was denied (for example, “Authentication failed”, “No matching rule found”) and to read the specific L7 error codes.
References: Official Docs
The primary sources for the behavior, configuration, and errors covered in this article are the following official docs. Check them for version-specific options and exact behavior.
Frequently Asked Questions (FAQ)
Q: Does applying NetworkPolicy disable all of Istio’s L7 features? A: No. NetworkPolicy only opens (or closes) a path at L3/L4. Once that path is open and the sidecar proxy is working normally, Istio’s L7 policies operate independently. If traffic is blocked at L3/L4, however, L7 cannot run.
Q: Can I set only AuthorizationPolicy and leave NetworkPolicy alone?
A: Not recommended. If the cluster’s default network policy is very restrictive, explicitly opening the minimum L3/L4 path with NetworkPolicy so Istio can receive traffic is the safest way to improve reliability.
Q: When both policies are applied, can I be sure which one has higher precedence? A: Precedence is hierarchical. Being blocked in the network stack (L3/L4) has the highest precedence and is always evaluated before L7 policy.
Closing: Networking policy is like constructing a building. NetworkPolicy owns the exterior walls and foundation (structural safety); Istio owns the internal security system and access control (functional safety). Clearly understanding each system’s role and keeping them from overlapping is the key to ultimate reliability.
Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.
Comments
Be the first to comment.