What shortcomings of the Kubernetes Ingress resource is the Gateway API designed to fix?
answer
- Ingress spec = host + path only, rest is annotations
- annotations: untyped, unvalidated, unportable
- no field-level RBAC → no role separation
- HTTP-only vs HTTPRoute/GRPCRoute/TCPRoute
- rich per-resource status conditions
basics
~20 sIngress can only express host and path rules, so everything else — rewrites, canary weights, header matching, timeouts — became vendor annotations that are untyped and unportable. It also has no role separation and only supports HTTP. Gateway API makes those first-class, typed, and role-split.
solid answer
~50 sFour concrete gaps. 1. **Expressiveness.** Ingress matches on host and path only. Header-based routing, method matching, weighted traffic splits, rewrites and mirroring all had to live in controller-specific annotations such as `nginx.ingress.kubernetes.io/*`. Those are untyped strings the API server cannot validate, and moving controllers means rewriting them. 2. **Role separation.** One Ingress object holds TLS, hostname and app routing, so you cannot grant routing self-service without also granting certificate and hostname control. Gateway API splits this into operator-owned Gateway and developer-owned HTTPRoute, with `allowedRoutes` bounding attachment. 3. **Protocol scope.** Ingress is HTTP/HTTPS only; Gateway API adds GRPCRoute plus experimental TCP, UDP and TLS routes on the same listener model. 4. **Extensibility.** Gateway API is designed for extension — typed filters, `parametersRef`, and policy attachment — rather than every vendor inventing annotations. Ingress is not deprecated; it is frozen, and Gateway API is where new capability lands.
code
yaml · 40 linesapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
ingressClassName: nginx
rules:
- host: shop.example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api
port:
number: 8080
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: shop
spec:
parentRefs:
- name: edge
hostnames: ["shop.example.com"]
rules:
- matches:
- path: {type: PathPrefix, value: /api}
filters:
- type: URLRewrite
urlRewrite:
path: {type: ReplacePrefixMatch, replacePrefixMatch: /}
backendRefs:
- {name: api, port: 8080, weight: 90}
- {name: api-canary, port: 8080, weight: 10}go deeper
It is enough to say Ingress only does host and path, so everything else became vendor annotations, and Gateway API turns those into real fields.
Name specific capabilities that were annotation-only — rewrites, canary weights, header matching — and explain why untyped annotations are unvalidated and unportable.
Add the RBAC and multi-tenancy angle, the protocol scope, and how per-resource status conditions change day-to-day debugging.
Weigh migration cost against benefit: which clusters genuinely need it, conformance-level risk across implementations, and a staged plan where Ingress and Gateway coexist behind the same DNS.
## The annotation problem The `networking.k8s.io/v1` `Ingress` resource expresses exactly one thing: for a given host and path, send traffic to a Service port. Everything else real production traffic needs — rewriting the path before it reaches the backend, splitting 5% of traffic to a canary, routing on a header, setting a timeout or body-size limit, enabling sticky sessions, adding CORS, forcing HTTPS redirects — has no field. Controllers solved this the only way they could: annotations. In practice an Ingress in a mature cluster is three lines of `spec` and fifteen lines of `nginx.ingress.kubernetes.io/...` or `alb.ingress.kubernetes.io/...` keys. Annotations are free-form strings on metadata. The API server cannot validate them, so a typo silently does nothing; there is no schema, no `kubectl explain`, and no defaulting. They are per-implementation, so an Ingress written for one controller is not portable to another — the `spec` moves, the behaviour does not. And because some annotations rewrite request paths or inject configuration snippets, they have been a recurring source of security findings when untrusted tenants can set them. The Gateway API's answer is to make the common cases typed API fields. Path rewriting is a `URLRewrite` filter. Header manipulation is a `RequestHeaderModifier` filter. Traffic splitting is a `weight` on each `backendRef`. Header, method and query matching are structured `matches`. Mirroring is a `RequestMirror` filter. These are validated by the API server, discoverable, and portable across conformant implementations. ## The ownership problem A single Ingress object contains the TLS Secret reference, the public hostname, the class selection, and the application's path rules. In a shared cluster those belong to different people. Because Kubernetes RBAC grants on resource kinds, not on fields, you cannot say "developers may edit paths but not `spec.tls`". Platform teams therefore either accepted the risk or built admission webhooks and templating layers to fake field-level control. Gateway API splits the object along ownership lines. The cluster operator owns the `Gateway` — listeners, ports, hostnames, certificates — and declares in `allowedRoutes` which namespaces and route kinds may attach. Application teams own `HTTPRoute` in their own namespace and reference the Gateway with `parentRefs`. Attachment is two-sided: the route must ask, and the listener must permit. Standard RBAC now expresses exactly the intended permission, with no webhook required. ## The scope problem Ingress models HTTP and HTTPS. Anything else — raw TCP, UDP, or TLS passthrough — was done with per-vendor ConfigMaps or extra Services. Gateway API keeps one listener model and layers protocol-specific route kinds on top: `HTTPRoute`, `GRPCRoute` (GA), and the experimental `TCPRoute`, `UDPRoute` and `TLSRoute`. A single Gateway can carry listeners for several protocols. ## The extensibility and observability problems Gateway API defines conformance levels — Core, Extended, Implementation-specific — so implementations advertise which typed features they support instead of inventing parallel annotation dialects. Implementation-specific behaviour still exists, but it is expressed through `ExtensionRef` filters and `parametersRef` that point at real, schema-bearing CRDs. Policy attachment lets cross-cutting concerns be modelled as separate objects targeting a Gateway or a route. Status is the other quiet improvement. Ingress status carries little more than a load-balancer address, so failures like "this controller ignored your object" or "your TLS Secret is missing" surface only in controller logs. Every Gateway API resource carries conditions: Gateways report `Accepted` and `Programmed` per listener plus `attachedRoutes`; routes report `Accepted` and `ResolvedRefs` per parent, with reasons such as `NotAllowedByListeners`, `NoMatchingListenerHostname` and `BackendNotFound`. Debugging becomes a `kubectl describe` instead of log archaeology. ## What Gateway API does not fix It is still CRDs you install and a controller you operate; it does not remove the data plane or its capacity planning. Not every implementation supports every Extended feature, so real portability requires checking conformance. And there is genuine cost: more objects, more indirection, and a migration for every existing Ingress. For a small single-team cluster with one hostname and simple paths, Ingress remains perfectly adequate — it is frozen, not deleted, and its long install base means it will be served for years.
- Is Ingress deprecated now that Gateway API is GA?No. Ingress is feature-frozen, not deprecated or scheduled for removal. Bug and security fixes continue and existing objects keep working, but new routing capability is being added to Gateway API instead. For simple single-team setups Ingress remains a reasonable choice; the pressure to migrate comes from needing features that only exist as annotations today.
- Give a concrete case where annotations actively hurt, beyond being ugly.Path-rewrite annotations that accept regular expressions or raw configuration snippets let anyone who can create an Ingress influence the shared proxy's config, which has produced real cross-tenant vulnerabilities. Because annotations are unvalidated strings, admission control has to parse them defensively. Typed filters with a schema remove that whole class of problem.
saying these in an interview costs you the question
- Saying Ingress is deprecated — it is frozen, and still supported
- Claiming annotations are just a style issue, ignoring that they are unvalidated and non-portable
- Believing Gateway API removes the need for a controller or data plane
- Assuming every Gateway API implementation supports every feature — conformance is tiered into Core, Extended and Implementation-specific
- Saying Gateway API replaces Service objects; routes still send traffic to Services