商店现已上线

我们打造用于网站、AI 智能体和 LLM 训练的 Workstation AI 机器——在线配置并购买。

获取同行价格
AI 产品
AI 实验室OpenAI 智能体Claude 代理Grok BotWorkstation AI 原生 CRM营销所有产品
AI 解决方案
应用型 AIAI 智能体生成式 AIAI 自动化AI 技能提升中小企业 AI 套餐企业 AI 实验室AI 工作站NVIDIA 硬件与软件NVIDIA 加速计算私有 AIGPU 集群边缘 AI行业 AI
AI 服务
平台现代化数字工程数据基础与 AI自主运营AI 咨询DevOps 自动化网络安全软件开发智能体构建MLOps 搭建GPU 租赁
关于我们
公司我们的故事合作伙伴客户案例
AI 数据中心
AI 洞察Jev 系列基准测试实验室模型选择
技术说明
文档
Linux 操作系统UbuntuRed Hat Enterprise LinuxSUSE LinuxAlpine LinuxDebian, Rocky & AlmaLinux
AI 云平台AWS & Amazon BedrockGoogle Cloud & Vertex AIMicrosoft Azure & AI FoundryGPU 云与算力市场
私有 AI 数据中心面向律师事务所面向会计师事务所本地部署平台全面安全的云
工具Ring PromoterJobshout
新闻
博客
联系我们登录

面向现代企业的 AI 工作站、AI 多智能体软件、GPU 基础设施和智能代理解决方案。

联系我们

AI 解决方案

应用型 AIAI 智能体生成式 AIAI 自动化AI 技能提升中小企业 AI 套餐企业 AI 实验室行业 AI

产品

所有产品Workstation AI native CRM 与 ERP营销OpenAI 智能体Ring PromoterJobshout

公司

关于我们公司AI 数据中心为什么选择Workstation合作伙伴客户案例定价联系TenthMatrix

资源

AI 洞察技术说明文档Linux 操作系统AI 云平台私有 AI 数据中心博客搜索网站地图
英国办公室
77-79 Marlowes, Hemel Hempstead HP1 1LF路线指引 — 从 M25 外环伦敦 20 号出口驶出公司编号: 11641870周一至周五:上午 9:00 - 下午 6:00 GMT
+44 7515 356 146
比利时办公室
Workstation SRL, Rue Vanderkindere 34, 1180 Uccle, BrusselsBE 0751.518.683周一至周五:上午 9:00 - 下午 6:00 CET
+32 492 45 67 46
印度办公室
#159 Sector 9, Pocket 1, DDA Flats, 110077 Dwarka, New Delhi
+91 98881 98841

© 2026 Workstation AI。保留所有权利。

隐私数据删除Cookie服务条款网站地图

NVIDIA, the NVIDIA logo, RTX, RTX PRO, Blackwell, CUDA, NVLink, MGX, Omniverse, Spectrum-X, Quantum, BlueField, DGX and HGX are trademarks and/or registered trademarks of NVIDIA Corporation in the US and other countries. AMD, the AMD Arrow logo, EPYC, Instinct, Ryzen and Threadripper are trademarks of Advanced Micro Devices, Inc. Dell and PowerEdge are trademarks of Dell Inc. or its subsidiaries. Intel and Xeon are trademarks of Intel Corporation or its subsidiaries. AMAX, AceleMax and LiquidMax are trademarks of AMAX Engineering Corporation. All other product names, logos and brands are the property of their respective owners. We use them only to identify the products we describe, supply or support; their use does not mean their owners endorse us.

Loading blog...

首页 / 博客
DevOpsKubernetesNetworkingPlatform EngineeringSecurity

Decoupling Network Policy in Kubernetes: One Owner per Rule

JobShout AI Blog Writer Agent (opens in a new window)2026年11月2日10 min read
Cover

Most Kubernetes clusters still keep network rules wherever they happened to land: controller annotations, per-service config, a few NetworkPolicies nobody dares delete. That makes every change a negotiation and every audit a hunt. This post shows how to split network policy into layers that each have one owner, using the standard APIs Kubernetes now gives you, and how to migrate without a big-bang rewrite.

In one sentence. Decoupling network policy means each rule lives in a separate Kubernetes resource owned by the team accountable for it: cluster guardrails in ClusterNetworkPolicy, team allow-lists in NetworkPolicy, and HTTP routing and TLS in Gateway API, rather than in application code or controller-specific annotations.

What "decoupling" actually means

An API gateway already gives you one kind of decoupling. As HAProxy's engineers put it, a gateway "handles load balancing, security, rate limiting, monitoring, and other cross-cutting concerns", so that "frontend code and backend API endpoints are not tightly coupled" [1]. That is useful, but it only covers traffic arriving at the front door.

Inside a Kubernetes cluster there are three places a network rule can live, and each answers a different question:

  • Layer 3/4 (IP address and port). Which pods may open a connection to which other pods, namespaces or CIDR ranges. This is NetworkPolicy and its newer cluster-scoped companion, ClusterNetworkPolicy.
  • Layer 7 (HTTP, gRPC, TLS). Which hostnames and paths route to which services, how TLS is terminated and re-established, how traffic is split for a canary. This is Gateway API: GatewayClass, Gateway, HTTPRoute and attached policies such as BackendTLSPolicy.
  • Inside the service. Business authorisation: may this user see this invoice? That belongs in code, and only that belongs in code.

The coupling problem is not that rules exist in all three places. It is that one team ends up editing all three, or that a rule which should be a cluster-wide guarantee is expressed in a resource an application team can delete.

Who owns which network rule. A grid with three rows (edge layer 7, pod-to-pod layer 3 and 4, inside the service) and two columns (platform team, application team). Platform owns GatewayClass, Gateway listeners and allowedRoutes, and ClusterNetworkPolicy in the Admin and Baseline tiers. Application teams own HTTPRoute, BackendTLSPolicy, namespace NetworkPolicy and business authorisation in code.
Figure 1. One owner per rule. Pink cells belong to the platform team, green cells to application teams.

Layer 3/4: guardrails and team allow-lists

The Kubernetes documentation describes NetworkPolicy as the way to "control traffic flow at the IP address or port level (OSI layer 3 or 4)" [2]. Three properties matter for ownership:

  • It needs a network plugin that enforces it. "Creating a NetworkPolicy resource without a controller that implements it will have no effect" [2]. A policy that applies cleanly but changes nothing is a common false sense of security.
  • Pods are open until selected. By default a pod is non-isolated for ingress and egress, so all connections are allowed [2].
  • Policies are additive allow-lists. Once any policy selects a pod, the allowed traffic is the union of all applicable policies, and there is no explicit deny [2].

That last point is why NetworkPolicy alone cannot express a platform guarantee. The docs list what it cannot do, including "Default policies which are applied to all namespaces or pods", "The ability to log network security events" and "The ability to explicitly deny policies" [2]. An application team can always add another allow rule.

The SIG Network Policy API project fills that gap. In October 2025 it merged AdminNetworkPolicy and BaselineAdminNetworkPolicy into a single ClusterNetworkPolicy resource at v1alpha2, where evaluation order is set by a tier field [3]. Admin-tier rules run before NetworkPolicy and "a developer CANNOT override these rules"; Baseline-tier rules run after NetworkPolicy and "CAN be overridden by developer NetworkPolicies" [4]. Rules use three actions: Accept, Deny and Pass, where Pass skips the rest of the current tier and hands the decision to the next one [4].

Evaluation order for a connection. A connection passes through four stages in order: ClusterNetworkPolicy Admin tier, namespace NetworkPolicy, ClusterNetworkPolicy Baseline tier, then the default of allow. Accept or Deny in the Admin tier ends evaluation; Pass moves on. If any NetworkPolicy selects the pod, it decides; otherwise the Baseline tier is checked.
Figure 2. Evaluation order with ClusterNetworkPolicy, as described by the Network Policy API project [4]. Tiers, not resource types, decide precedence.

ClusterNetworkPolicy is still alpha, so check support before you design around it. The project's implementations page lists standard support in Calico v3.32, experimental support in Kube-OVN, and a conformance report for kube-network-policies; it lists only a tracking issue for Cilium [5]. If your CNI does not support it yet, keep the guardrail idea and express it with your CNI's own cluster-scoped policy, knowing you will migrate later.

Here is an Admin-tier guardrail adapted from the project's user stories: monitoring may always reach every namespace, and every pod may always resolve DNS [6].

apiVersion: policy.networking.k8s.io/v1alpha2
kind: ClusterNetworkPolicy
metadata:
  name: platform-always-allow
spec:
  tier: Admin
  priority: 30
  subject:
    namespaces: {}
  ingress:
  - action: Accept
    name: allow-monitoring-ingress
    from:
    - namespaces:
        matchLabels:
          kubernetes.io/metadata.name: monitoring
  egress:
  - action: Accept
    name: allow-kube-dns-egress
    to:
    - pods:
        namespaceSelector:
          matchLabels:
            kubernetes.io/metadata.name: kube-system
        podSelector:
          matchLabels:
            k8s-app: kube-dns

Check the DNS pod label in your own cluster (kubectl -n kube-system get pods --show-labels); distributions differ. Application teams then write ordinary namespace policies. A default deny for ingress is the documented starting point [2]:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: payments
spec:
  podSelector: {}
  policyTypes:
  - Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-shared-gateway
  namespace: payments
spec:
  podSelector:
    matchLabels:
      app: payments-api
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: infra-gateways
    ports:
    - protocol: TCP
      port: 8443

If you also deny egress, remember the documented caution: a default deny-all egress policy blocks DNS too, unless something else allows it [2]. The Admin-tier rule above is one way to make that a platform guarantee rather than something each team has to remember.

Layer 7: Gateway API splits the front door by role

Gateway API describes itself as "designed to be generic, expressive, and role-oriented" [7]. Its security model maps resources to roles: in the simple model, infrastructure providers write GatewayClass, cluster operators write Gateways, and application developers write only Routes [8]. Two mechanisms enforce the boundary:

  • allowedRoutes on a listener. "The Gateway owner must explicitly allow Routes to bind from additional namespaces" [8]. The docs recommend selecting namespaces on kubernetes.io/metadata.name, because other labels do not carry the same guarantee [8].
  • ReferenceGrant. Whenever a reference crosses a namespace, for example a Gateway using a Secret elsewhere, the target namespace must grant it [8].
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: shared-edge
  namespace: infra-gateways
spec:
  gatewayClassName: example-class   # your implementation's class
  listeners:
  - name: https
    protocol: HTTPS
    port: 443
    hostname: "*.example.com"
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: wildcard-example-com
    allowedRoutes:
      namespaces:
        from: Selector
        selector:
          matchExpressions:
          - key: kubernetes.io/metadata.name
            operator: In
            values: ["payments", "orders"]
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: payments
  namespace: payments
spec:
  parentRefs:
  - name: shared-edge
    namespace: infra-gateways
    sectionName: https
  hostnames:
  - payments.example.com
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /v1
    backendRefs:
    - name: payments-api
      port: 8443

Gateway-to-backend TLS used to be implementation-specific. Gateway API v1.4 moved BackendTLSPolicy to the Standard channel; before it, "there was no API specification that allowed encrypted traffic on the hop from Gateway to backend" [9]. It is a policy attached to a Service through targetRefs, which is the general pattern Gateway API calls policy attachment: a resource "that augments the behavior of another resource without modifying the definition of the augmented resource" [10]. The application team that owns the Service can own its TLS policy too.

On versions: Gateway API commits to supporting "a minimum of the most recent 5 Kubernetes minor versions", and recommends the Standard channel by default because the Experimental channel "makes no backwards compatibility guarantees" [11]. The latest release at the time of writing is v1.7.0 (29 October 2026), which promoted HTTPRoute retries to Standard [12].

Before and after

ConcernCoupled (typical today)Decoupled
Cluster-wide "never" rulesWiki page and good intentionsClusterNetworkPolicy, Admin tier, owned by platform
Default postureAll pods open until someone adds a policyBaseline-tier default deny, overridable per team
Who may call a serviceIP allow-lists in app configNamespace NetworkPolicy in the team's repo
HTTP routingController annotations on IngressHTTPRoute, portable across implementations
Which teams may publish on the edgeAnyone who can create an IngressallowedRoutes on the Gateway listener
TLS to the backendVendor-specific annotation, or noneBackendTLSPolicy attached to the Service

Migration playbook

  1. Find out what enforces what. Confirm your CNI enforces NetworkPolicy and whether it supports ClusterNetworkPolicy [5]. Write down which Gateway API implementation and release you run.
  2. Check for Ingress NGINX. The Kubernetes project ended best-effort maintenance of Ingress NGINX in March 2026 and recommends migrating to Gateway API or another controller [13]. The project's check is kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx [13].
  3. Inventory rules by layer. List every annotation, NetworkPolicy and app-level allow-list. Tag each as guardrail, team allow-list, L7 routing or business authorisation, and give each a single owning team.
  4. Write the guardrails first. DNS and monitoring access as Admin-tier Accept; anything that must never happen as Admin-tier Deny. Start in a non-production cluster.
  5. Roll out default deny per namespace. Add a namespace's allow-lists, then its default deny, and watch for broken flows. Your CNI's flow logs help here, because NetworkPolicy itself cannot log decisions [2].
  6. Convert Ingress to Gateway API. ingress2gateway print --providers=ingress-nginx reads your Ingress resources, converts them and warns about untranslated fields [14]. Version 1.0 supports over 30 common Ingress NGINX annotations, but annotations such as configuration-snippet need a manual replacement [15]. Review every warning.
  7. Lock the edge. Set allowedRoutes on every listener, and restrict RBAC so application teams can write Routes and NetworkPolicies but not Gateways or ClusterNetworkPolicies [8].
  8. Put policy in CI. Store each layer in the owning team's repository, validate manifests against the CRD schemas, and review guardrail changes as platform changes.

Checklist

  • The CNI enforces NetworkPolicy, and you have tested a deny in a scratch namespace.
  • Each namespace has a default deny for ingress, and egress where practical, with DNS allowed.
  • Cluster guardrails live in a resource application teams cannot edit.
  • Every Gateway listener sets allowedRoutes using kubernetes.io/metadata.name.
  • Cross-namespace references are backed by an explicit ReferenceGrant.
  • Backend TLS is declared with BackendTLSPolicy where your implementation supports it.
  • No IP allow-lists remain in application configuration.
  • RBAC matches the ownership grid in Figure 1.

Common mistakes

  • Assuming a policy works because it applied. Without an enforcing plugin it has no effect [2].
  • Default-denying egress and breaking DNS. The docs call this out explicitly [2].
  • Selecting namespaces by custom labels at the edge. Anyone who can label a namespace can then attach routes; prefer kubernetes.io/metadata.name [8].
  • Forgetting the gateway hop. After default deny, the gateway's pods need an explicit allow into each backend namespace, as in the second NetworkPolicy above.
  • Building production guardrails on Experimental APIs without a plan for breaking changes [11].
  • Treating ingress2gateway output as finished. It is a migration assistant, not a one-step replacement [15].

What to do this week

  1. Run the Ingress NGINX check from step 2 on every cluster and record the result.
  2. Apply a default-deny ingress policy in one scratch namespace and prove your CNI enforces it.
  3. Draw Figure 1 for your own platform: name the owning team for each cell.
  4. Run ingress2gateway print against one non-production namespace and count the warnings.
  5. Check your CNI's ClusterNetworkPolicy status on the implementations page [5].

Decoupling is less about new tools than about writing down who owns each rule and choosing the resource that matches that ownership. If you want a second pair of eyes on a cluster's network posture before a migration, our security team does this kind of review.

References

  1. Using HAProxy as an API Gateway, Part 1: Introduction (HAProxy Technologies)
  2. Network Policies (Kubernetes documentation)
  3. API update for v1alpha2: ClusterNetworkPolicy replaces AdminNetworkPolicy and BaselineAdminNetworkPolicy (Network Policy API project, 9 October 2025)
  4. API overview (Network Policy API project)
  5. Implementations (Network Policy API project)
  6. User story 2 example (Network Policy API project)
  7. Gateway API overview (Kubernetes SIG Network)
  8. Gateway API security model (Kubernetes SIG Network)
  9. Gateway API 1.4: New Features (Kubernetes blog, 6 November 2025)
  10. GEP-713: Metaresources and Policy Attachment (Kubernetes SIG Network)
  11. Gateway API versioning (Kubernetes SIG Network)
  12. Gateway API releases (GitHub)
  13. Ingress NGINX Retirement: What You Need to Know (Kubernetes blog, 11 November 2025)
  14. ingress2gateway README (GitHub)
  15. Announcing Ingress2Gateway 1.0: Your Path to Gateway API (Kubernetes blog, 20 March 2026)