k8s-networking · git:20261028.645512f · 2026-10-28 · sha256 7d00a84d80a2e7af

k8s-networking git:20261028.645512fA

Immutable. This exact content never changes and is served at /api/v1/blob/7d00a84d80a2e7af.

---
name: k8s-networking
description: Kubernetes networking standards — Gateway API versus Ingress, migrating off the retired ingress-nginx controller, choosing a Gateway implementation, Cilium/eBPF CNI and kube-proxy replacement, NetworkPolicy and L7 policy, Hubble observability, DNS and load-balancer cutovers. Use whenever designing or changing ingress or gateways, CNI, network policies, TLS termination, or troubleshooting in-cluster networking — and whenever ingress-nginx is found in a cluster.
when_to_use: Use when designing/changing ingress, Gateway API, CNI (Cilium), NetworkPolicy, TLS, moving off ingress-nginx, or debugging networking inside the cluster. Vietnamese triggers — "thiết kế/đổi ingress", "chuyển khỏi ingress-nginx", "debug mạng trong cluster".
---

# Kubernetes networking standards

<!-- devops-ai-kit · Last reviewed: 2026-10-28 -->

## 1. ingress-nginx is no longer maintained

- The Ingress NGINX project (`kubernetes/ingress-nginx`) was retired in March 2026: no more releases, bug fixes or security patches. Running copies still work, but new vulnerabilities will not be fixed.
- Do not confuse it with F5's **NGINX Ingress Controller** (`nginx/kubernetes-ingress`). That is a different product, and F5 still maintains it. Check the real image that is running.
- **MUST** When recon finds ingress-nginx (`kubectl get pods -A -l app.kubernetes.io/name=ingress-nginx`): write it in the risks part of the report and suggest a migration plan (L2/L3). Do not rewrite routing outside the task scope.
- Migration plan:
  1. List every `nginx.ingress.kubernetes.io/*` annotation in use (rewrite, auth, rate limit, snippet, CORS…). These annotations do **not** work on other controllers; map them to HTTPRoute filters or to the new implementation's own policies.
  2. Build the new Gateway **side by side**, with a new IP / LB.
  3. Lower the DNS TTL; test with the Host header / hosts file.
  4. Move DNS step by step (one host at a time).
  5. Keep the old controller until it has no more traffic.

## 2. Gateway API

- **SHOULD** New platforms use Gateway API with a conformant implementation (e.g. Cilium, Envoy Gateway, Istio, NGINX Gateway Fabric, or a managed cloud service such as Application Gateway for Containers on Azure). Choose based on the conformance report and the features you need, for the **exact version**.
- Roles:
  - The platform team manages `GatewayClass` / `Gateway` (listeners, TLS, IP).
  - App teams manage `HTTPRoute` / `GRPCRoute`.
  - Routes from other namespaces must be allowed with `allowedRoutes`; cross-namespace references (e.g. a TLS Secret) need a `ReferenceGrant`.
- Advanced features (weighted traffic split, header match, mirroring) have different support levels between implementations (Core / Extended / Implementation-specific). Check before you design around them.
- TLS on the Gateway is managed by cert-manager (see `pki-secrets`).
- **CONTEXT** If the system uses Ingress with a controller that is still maintained, keep it. The Ingress API is feature-frozen but not removed.

## 3. CNI & Cilium

- **CONTEXT** Self-managed clusters (on-prem, Hetzner…) can use Cilium with kube-proxy replacement. Check the kernel requirements for the Cilium version. Changing the CNI of a running cluster is L3; building a new cluster is often easier.
- Managed clusters use the provider's option: AKS → Azure CNI Overlay (optional Azure-managed Cilium dataplane), GKE → Dataplane V2, EKS → VPC CNI or Cilium depending on the design. Do **not** install Cilium on top of a managed CNI.
- **SHOULD** Turn on Hubble when you use Cilium, to see network flows, drop reasons, DNS.
- **CONTEXT** L7 policy (`CiliumNetworkPolicy` by method / path) only when really needed; L7 policy sends traffic through a proxy, so it adds overhead.

## 4. NetworkPolicy

- **SHOULD** Default-deny **ingress** for app namespaces, plus specific allows (from the Gateway / ingress namespace, from the monitoring namespace to scrape metrics).
- **CONTEXT** Default-deny **egress** is safer but takes more work to maintain. When you turn it on, always allow:
  - DNS to kube-dns (UDP **and** TCP 53);
  - needed egress: databases, external APIs, the API server for operators.
- **MUST** Roll out in this order: create the allow policies first, then turn on default-deny. Treat it as an L2 change.
- **MUST** Verify with real traffic, not only by reading YAML: a test pod (`kubectl run` / `kubectl debug` + curl), or `hubble observe --verdict DROPPED`.

## 5. DNS & load balancers during a migration

- **MUST** Lower the TTL of the DNS records before the switch (wait at least as long as the old TTL).
- **CONTEXT** `externalTrafficPolicy: Local` keeps the client source IP but can spread load unevenly; use it when you need the real IP for rate limits / logs.

## Verify

```bash
kubectl get gatewayclass,gateway -A
kubectl get httproute -A -o wide            # Accepted / ResolvedRefs = True
kubectl describe httproute <name> -n <ns>   # check conditions when a route does not work
curl -sv --resolve <host>:443:<gateway-ip> https://<host>/healthz
```