Skip to content

필사 모드: From Ingress to Gateway API — Why, What, and How It Changes

English
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

Introduction: Why Gateway API Now

For the past several years, the de facto standard for exposing L7 traffic externally in Kubernetes was Ingress. But in 2026 the situation has clearly changed. **The Ingress API is frozen** — no new features are being added — and **Gateway API** is establishing itself as the successor standard. At the same time, the once-ubiquitous ingress-nginx is trending toward maintenance mode, operating with a focus on security patches rather than new features.

This article is organized along three axes: "Why it must change," "What changes," and "How to change it." Rather than merely introducing a new API, it focuses on the realistic order in which a team with existing Ingress assets can migrate.

The Limits of Ingress — Why It Must Change

Ingress is excellent for simple routing, but two fundamental limits surface as operational scale grows.

1. Annotation Hell

The standard Ingress spec (rules/paths/backend/tls) covers only basic host/path routing. Yet in practice you need many advanced features: header-based routing, weighted traffic splitting (canary), timeouts, retries, CORS, auth, rewrites, and so on. Since the Ingress standard lacks these, each controller worked around them with **annotations**.

metadata:

annotations:

nginx.ingress.kubernetes.io/rewrite-target: /$2

nginx.ingress.kubernetes.io/canary: "true"

nginx.ingress.kubernetes.io/canary-weight: "20"

nginx.ingress.kubernetes.io/proxy-read-timeout: "120"

nginx.ingress.kubernetes.io/configuration-snippet: |

more_set_headers "X-Custom: value";

The problem is that these annotations are **completely different per controller**. ingress-nginx's `nginx.ingress.kubernetes.io/canary-weight` does not work in Traefik, and Traefik's middleware annotations are meaningless in ingress-nginx. As a result, an Ingress resource becomes strongly coupled to a specific controller, and switching controllers means rewriting every annotation. This is the portability problem known as "annotation hell."

Moreover, free-text annotations like `configuration-snippet` can inject arbitrary nginx config, which is also a security risk; related vulnerabilities have in fact been reported.

2. No Role Separation

A single Ingress resource mixes infrastructure concerns (TLS certificates, entry-point config) with application concerns (which path goes to which service). In a large organization, the platform team wants to manage the entry point, certificates, and policy, while each application team wants to manage only its own service's routing. But Ingress has no standard mechanism to separate these responsibilities. Every team either touches the same Ingress resource or splits it awkwardly per namespace.

The Gateway API Resource Model — What Changes

Gateway API introduces **several role-separated resources** to tackle both problems head-on. The core resources are as follows.

- **GatewayClass**: A cluster-scoped resource defining which implementation (controller) to use. It corresponds to Ingress's IngressClass and is usually created by the infrastructure provider.

- **Gateway**: Defines the actual entry point (listeners, ports, protocols, TLS). Owned by the platform/infrastructure team.

- **HTTPRoute**: Defines HTTP routing rules (hostnames, paths, header matching, traffic splitting, filters). Owned by application developers.

- **TLSRoute / TCPRoute / GRPCRoute / UDPRoute**: Route resources for non-HTTP protocols.

- **ReferenceGrant**: A resource that explicitly permits cross-namespace references.

Thanks to this separation, the infra team manages Gateways and the app teams manage HTTPRoutes, while sharing a single entry point.

Concept Mapping Table

Here is where existing Ingress concepts map in Gateway API.

| Ingress concept | Gateway API equivalent | Notes |

| --- | --- | --- |

| IngressClass | GatewayClass | Cluster-scoped, implementation selection |

| Ingress (entry-point part) | Gateway + listener | Defines port/protocol/TLS |

| Ingress (routing-rule part) | HTTPRoute | Host/path/match rules |

| spec.rules.host | HTTPRoute hostnames | Host matching |

| spec.rules.http.paths | HTTPRoute rules.matches | Path/header matching |

| pathType Prefix/Exact | PathPrefix/Exact match | Almost identical meaning |

| backend.service | backendRefs | Service reference |

| spec.tls | Gateway listener TLS | Terminated at entry point |

| canary annotation | backendRefs weight | Standard traffic splitting |

| rewrite annotation | URLRewrite filter | Standard filter |

| header-manipulation annotation | RequestHeaderModifier filter | Standard filter |

The key point is that **many features previously worked around with annotations become standard spec fields in Gateway API**. Traffic splitting, rewrites, header manipulation, redirects — all are expressed in a portable, standard form.

Side-by-Side YAML Comparison

Let us express the same requirements in Ingress and Gateway API to see the difference.

Basic Host/Path Routing

In Ingress:

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: shop-ingress

spec:

ingressClassName: nginx

rules:

- host: shop.example.com

http:

paths:

- path: /api

pathType: Prefix

backend:

service:

name: api-service

port:

number: 8080

In Gateway API, it splits into a Gateway and an HTTPRoute.

apiVersion: gateway.networking.k8s.io/v1

kind: Gateway

metadata:

name: shop-gateway

spec:

gatewayClassName: envoy

listeners:

- name: http

protocol: HTTP

port: 80

apiVersion: gateway.networking.k8s.io/v1

kind: HTTPRoute

metadata:

name: shop-route

spec:

parentRefs:

- name: shop-gateway

hostnames:

- shop.example.com

rules:

- matches:

- path:

type: PathPrefix

value: /api

backendRefs:

- name: api-service

port: 8080

Weighted Traffic Splitting (Canary)

In Ingress (ingress-nginx), a separate canary Ingress and annotations were required.

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: shop-canary

annotations:

nginx.ingress.kubernetes.io/canary: "true"

nginx.ingress.kubernetes.io/canary-weight: "20"

spec:

ingressClassName: nginx

rules:

- host: shop.example.com

http:

paths:

- path: /

pathType: Prefix

backend:

service:

name: shop-v2

port:

number: 80

In Gateway API, it is standardized as backendRefs weights and expressed in a single resource.

apiVersion: gateway.networking.k8s.io/v1

kind: HTTPRoute

metadata:

name: shop-canary

spec:

parentRefs:

- name: shop-gateway

hostnames:

- shop.example.com

rules:

- backendRefs:

- name: shop-v1

port: 80

weight: 80

- name: shop-v2

port: 80

weight: 20

TLS and Header Filters

An example terminating TLS at the Gateway and adding a header in the HTTPRoute.

apiVersion: gateway.networking.k8s.io/v1

kind: Gateway

metadata:

name: secure-gateway

spec:

gatewayClassName: envoy

listeners:

- name: https

protocol: HTTPS

port: 443

tls:

mode: Terminate

certificateRefs:

- name: shop-tls

apiVersion: gateway.networking.k8s.io/v1

kind: HTTPRoute

metadata:

name: secure-route

spec:

parentRefs:

- name: secure-gateway

hostnames:

- shop.example.com

rules:

- filters:

- type: RequestHeaderModifier

requestHeaderModifier:

add:

- name: X-Env

value: prod

backendRefs:

- name: shop-service

port: 80

Migration Strategy — How to Change It

Do not try to finish the migration in one shot; proceed in stages.

The ingress2gateway Tool

Kubernetes SIG Network provides **ingress2gateway**, a tool that converts existing Ingress (and some provider CRDs) into Gateway API resources. It converts standard Ingress fields into HTTPRoute/Gateway, and maps some provider-specific annotations where possible.

ingress2gateway print --input-file=ingress.yaml

This tool gives you a starting point only; **it cannot auto-convert every annotation.** Non-standardized controller-specific features (free-text snippets, etc.) require manual review. So always review the conversion output and validate behavior in a reproducible environment.

Gradual Transition

The recommended order is as follows.

1. **Prepare**: Additionally install a controller that supports Gateway API in the cluster. Leave the existing Ingress controller in place.

2. **Run in parallel**: Expose new services or canary traffic via Gateway/HTTPRoute first. Shift traffic gradually with DNS or weights.

3. **Convert**: Bulk-convert existing Ingress with ingress2gateway, then review and adjust the result.

4. **Validate**: Confirm in staging that routing, TLS, headers, and timeout behavior are identical.

5. **Cut over**: After fully moving traffic to the Gateway, remove the old Ingress.

During this process, be careful that the two systems do not expose the same host simultaneously.

Per-Controller Gateway API Support Status

Gateway API is a standard spec, and several controllers implement it. The conformance level (degree of Core / Extended feature support) differs per controller.

| Implementation | Data plane | Notes |

| --- | --- | --- |

| Envoy Gateway | Envoy | CNCF, designed around Gateway API |

| Contour | Envoy | Supports both HTTPProxy and Gateway API |

| Istio | Envoy | Service mesh, mature Gateway API support |

| Traefik | Traefik | Supports Ingress, CRDs, and Gateway API |

| Cilium | eBPF/Envoy | CNI-integrated Gateway support |

| Kong | Kong | Gateway API support |

| NGINX Gateway Fabric | NGINX | NGINX-based Gateway API implementation |

| HAProxy | HAProxy | Gateway API support in progress |

When actually selecting, it is safest to check the official conformance reports to verify that the features you need (traffic splitting, header matching, etc.) are supported.

Pitfalls and Troubleshooting

Problems frequently encountered during the transition.

**1. An HTTPRoute does not attach to the Gateway.**

Either `parentRefs` is wrong, or the Gateway listener's `allowedRoutes` (namespace/kind restrictions) blocks it. Check the attach condition in the HTTPRoute status.

kubectl get httproute shop-route -o yaml | grep -A20 status

**2. Cross-namespace references are denied.**

When the Gateway and HTTPRoute, or the HTTPRoute and backend Service, live in different namespaces, a **ReferenceGrant** is required. The reference only holds once this is explicitly permitted.

**3. After conversion, behavior is subtly different.**

Annotation-based features (especially rewrites, regex paths, snippets) may not map exactly 1:1. First check whether they can be expressed with standard filters; if not, evaluate implementation-specific extensions.

**4. The TLS certificate is not applied.**

If the Secret referenced by the Gateway listener's `certificateRefs` is in a different namespace, a ReferenceGrant is required. cert-manager supports Gateway API integration, so you can wire certificate issuance directly to the Gateway resource.

**5. Two controllers claim the same host.**

During parallel operation, if the old Ingress and the new Gateway expose the same host, traffic gets mixed. Separate them clearly by host or weight until cutover.

Closing

Migrating to Gateway API is not a mere API swap but an evolution of the operating model. Understanding **Why** (annotation hell and the lack of role separation), **What** (responsibility separation into GatewayClass/Gateway/HTTPRoute and standard filters), and **How** (ingress2gateway and gradual parallel transition) in order lets you design the migration smoothly.

In the 2026 context, Ingress still works but is frozen, and ingress-nginx is maintenance-focused. So it is reasonable to put Gateway API first for new designs and move existing assets in stages after validation. The conversion tool is only a starting point and does not replace every annotation, so the key is always validation.

References

- Gateway API official site: https://gateway-api.sigs.k8s.io/

- Gateway API — Migrating from Ingress: https://gateway-api.sigs.k8s.io/guides/migrating-from-ingress/

- ingress2gateway project: https://github.com/kubernetes-sigs/ingress2gateway

- Kubernetes official docs — Ingress: https://kubernetes.io/docs/concepts/services-networking/ingress/

- Envoy Gateway official docs: https://gateway.envoyproxy.io/docs/

- Project Contour official docs: https://projectcontour.io/docs/

- Istio Gateway API docs: https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/

- Traefik Kubernetes Gateway API docs: https://doc.traefik.io/traefik/providers/kubernetes-gateway/

- cert-manager — using Gateway API: https://cert-manager.io/docs/usage/gateway/

- ingress-nginx official docs: https://kubernetes.github.io/ingress-nginx/

현재 단락 (1/204)

For the past several years, the de facto standard for exposing L7 traffic externally in Kubernetes w...

작성 글자: 0원문 글자: 10,795작성 단락: 0/204