商店現已上線

我們打造用於網站、AI 智慧體和 LLM 訓練的 Workstation AI 機器——線上配置併購買。

獲取同行價格
AI 產品
AI 實驗室OpenAI 智慧體Claude 代理Grok BotWorkstation AI 原生 CRM營銷所有產品
AI 解決方案
應用型 AIAI 智慧體生成式 AIAI 自動化AI 技能提升中小企業 AI 套餐企業 AI 實驗室AI 工作站NVIDIA 硬體與軟體NVIDIA 加速計算私有 AIGPU 私有云GPU 叢集邊緣 AI行業 AI
AI 服務
平臺現代化數字工程資料基礎與 AI自主運營AI 諮詢DevOps 自動化網路安全軟體開發智慧體構建MLOps 搭建GPU 租賃GPU 私有云
關於我們
公司我們的故事合作伙伴客戶案例
AI 資料中心
AI 資料中心GPU 私有云GPU 叢集GPU 租賃
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
台灣辦公室
3F, No. 2-4, Aisi Rd., Ren'ai Dist., Keelung City 200, Taiwan基隆市仁愛區愛四路2之4號3樓週一至週五:上午 9:00 - 下午 6:00 臺灣時間(GMT+8)
+886 926 892 701+32 492 45 67 46

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

隱私資料刪除Cookie服務條款網站地圖

NVIDIA、NVIDIA 標誌、RTX、RTX PRO、Blackwell、CUDA、NVLink、MGX、Omniverse、Spectrum-X、Quantum、BlueField、DGX 與 HGX 為 NVIDIA Corporation 在美國及其他國家的商標及/或註冊商標。AMD、AMD Arrow 標誌、EPYC、Instinct、Ryzen 與 Threadripper 為 Advanced Micro Devices, Inc. 的商標。Dell 與 PowerEdge 為 Dell Inc. 或其子公司的商標。Intel 與 Xeon 為 Intel Corporation 或其子公司的商標。AMAX、AceleMax 與 LiquidMax 為 AMAX Engineering Corporation 的商標。所有其他產品名稱、標誌與品牌均為其各自所有者之財產。我們使用它們僅為識別我們所描述、供應或支援的產品;使用這些名稱並不表示其所有者為我們背書。

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)