Skip to content

필사 모드: Ingress에서 Gateway API로 — 왜, 무엇이, 어떻게 바뀌는가

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

들어가며: 왜 지금 Gateway API인가

지난 몇 년간 Kubernetes에서 L7 트래픽을 외부로 노출하는 표준은 사실상 Ingress였습니다. 그러나 2026년 현재 상황은 분명히 달라졌습니다. **Ingress API는 frozen 상태**로 더 이상 새로운 기능이 추가되지 않으며, 그 후계로 **Gateway API**가 표준 자리를 잡아가고 있습니다. 동시에 가장 널리 쓰이던 ingress-nginx는 유지보수 모드에 가까운 흐름으로 신규 기능보다 보안 패치 중심으로 운영되고 있습니다.

이 글은 "왜 바뀌어야 하는가(Why)", "무엇이 바뀌는가(What)", "어떻게 바꾸는가(How)"의 세 축으로 구성됩니다. 단순히 새 API를 소개하는 것이 아니라, 기존 Ingress 자산을 가진 팀이 현실적으로 어떤 순서로 전환할 수 있는지에 초점을 맞춥니다.

Ingress의 한계 — 왜 바꿔야 하는가

Ingress는 단순한 라우팅에는 훌륭하지만, 운영 규모가 커질수록 두 가지 근본적인 한계가 드러납니다.

1. 어노테이션 지옥

Ingress 표준 스펙(rules/paths/backend/tls)은 기본적인 호스트·경로 라우팅만 커버합니다. 그런데 실무에서는 헤더 기반 라우팅, 트래픽 가중치 분할(카나리), 타임아웃, 리트라이, CORS, 인증, rewrite 등 수많은 고급 기능이 필요합니다. Ingress 표준에는 이런 기능이 없으므로, 각 컨트롤러는 **어노테이션**으로 이를 우회했습니다.

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";

문제는 이 어노테이션이 **컨트롤러마다 완전히 다르다**는 점입니다. ingress-nginx의 `nginx.ingress.kubernetes.io/canary-weight`는 Traefik에서 동작하지 않고, Traefik의 미들웨어 어노테이션은 ingress-nginx에서 무의미합니다. 결과적으로 Ingress 리소스가 특정 컨트롤러에 강하게 종속되고, 컨트롤러를 바꾸려면 모든 어노테이션을 다시 작성해야 합니다. 이것이 "어노테이션 지옥"이라 불리는 이식성 문제입니다.

게다가 `configuration-snippet` 같은 자유 텍스트 어노테이션은 임의의 nginx 설정을 주입할 수 있어 보안상으로도 위험하며, 실제로 관련 취약점이 보고되기도 했습니다.

2. 역할 분리의 부재

Ingress 리소스 하나에는 인프라 관심사(TLS 인증서, 진입점 설정)와 애플리케이션 관심사(어떤 경로를 어떤 서비스로 보낼지)가 뒤섞여 있습니다. 대규모 조직에서는 플랫폼 팀이 진입점·인증서·정책을 관리하고, 각 애플리케이션 팀은 자기 서비스의 라우팅만 관리하고 싶어 합니다. 그러나 Ingress는 이 책임을 분리할 표준 메커니즘이 없습니다. 모든 팀이 같은 Ingress 리소스를 만지거나, 네임스페이스 단위로 어색하게 쪼개야 합니다.

Gateway API의 리소스 모델 — 무엇이 바뀌는가

Gateway API는 위 두 문제를 정면으로 해결하기 위해 **역할 기반으로 분리된 여러 리소스**를 도입합니다. 핵심 리소스는 다음과 같습니다.

- **GatewayClass**: 어떤 구현(컨트롤러)을 쓸지 정의하는 클러스터 스코프 리소스. Ingress의 IngressClass에 대응합니다. 보통 인프라 제공자가 만듭니다.

- **Gateway**: 실제 진입점(리스너, 포트, 프로토콜, TLS)을 정의합니다. 플랫폼/인프라 팀이 소유합니다.

- **HTTPRoute**: HTTP 라우팅 규칙(호스트, 경로, 헤더 매칭, 트래픽 분할, 필터)을 정의합니다. 애플리케이션 개발자가 소유합니다.

- **TLSRoute / TCPRoute / GRPCRoute / UDPRoute**: HTTP 외 프로토콜을 위한 라우트 리소스.

- **ReferenceGrant**: 크로스 네임스페이스 참조를 명시적으로 허용하는 리소스.

이 분리 덕분에 인프라 팀은 Gateway를, 앱 팀은 HTTPRoute를 각자 관리하면서 하나의 진입점을 공유할 수 있습니다.

개념 매핑 테이블

기존 Ingress 개념이 Gateway API에서 어디에 대응하는지 정리하면 다음과 같습니다.

| Ingress 개념 | Gateway API 대응 | 비고 |

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

| IngressClass | GatewayClass | 클러스터 스코프, 구현 선택 |

| Ingress (진입점 부분) | Gateway + listener | 포트/프로토콜/TLS 정의 |

| Ingress (라우팅 규칙 부분) | HTTPRoute | 호스트/경로/매칭 규칙 |

| spec.rules.host | HTTPRoute hostnames | 호스트 매칭 |

| spec.rules.http.paths | HTTPRoute rules.matches | 경로/헤더 매칭 |

| pathType Prefix/Exact | PathPrefix/Exact match | 의미가 거의 동일 |

| backend.service | backendRefs | 서비스 참조 |

| spec.tls | Gateway listener TLS | 진입점에서 종료 |

| canary 어노테이션 | backendRefs weight | 표준 트래픽 분할 |

| rewrite 어노테이션 | URLRewrite filter | 표준 필터 |

| 헤더 조작 어노테이션 | RequestHeaderModifier filter | 표준 필터 |

핵심은 **어노테이션으로 우회하던 기능 상당수가 Gateway API에서는 표준 스펙 필드**가 된다는 점입니다. 트래픽 분할, rewrite, 헤더 조작, 리다이렉트 등이 모두 이식 가능한 표준 형태로 표현됩니다.

실습 YAML 비교

같은 요구사항을 Ingress와 Gateway API로 각각 표현해 차이를 봅니다.

기본 호스트/경로 라우팅

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

Gateway API로는 Gateway와 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

트래픽 가중치 분할(카나리)

Ingress(ingress-nginx)에서는 별도의 카나리 Ingress와 어노테이션이 필요했습니다.

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

Gateway API에서는 backendRefs의 weight로 표준화되어 한 리소스에서 표현됩니다.

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와 헤더 필터

Gateway에서 TLS를 종료하고 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

마이그레이션 전략 — 어떻게 바꾸는가

전환은 한 번에 끝내려 하지 말고 단계적으로 진행합니다.

ingress2gateway 도구

Kubernetes SIG Network는 기존 Ingress(및 일부 공급자 CRD)를 Gateway API 리소스로 변환해 주는 **ingress2gateway** 도구를 제공합니다. 표준 Ingress 필드를 HTTPRoute/Gateway로 변환하고, 일부 공급자별 어노테이션도 가능한 범위에서 매핑합니다.

ingress2gateway print --input-file=ingress.yaml

이 도구는 출발점을 만들어 줄 뿐, **모든 어노테이션을 자동 변환하지는 못합니다.** 표준화되지 않은 컨트롤러 특화 기능(자유 텍스트 snippet 등)은 수동 검토가 필요합니다. 따라서 변환 결과는 반드시 검토하고, 동작을 재현 가능한 환경에서 검증해야 합니다.

점진적 전환

권장 순서는 다음과 같습니다.

1. **준비**: Gateway API를 지원하는 컨트롤러를 클러스터에 추가 설치합니다. 기존 Ingress 컨트롤러는 그대로 둡니다.

2. **병행 운영**: 새 서비스나 카나리 트래픽부터 Gateway/HTTPRoute로 노출합니다. DNS 또는 가중치로 트래픽을 점진적으로 옮깁니다.

3. **변환**: ingress2gateway로 기존 Ingress를 일괄 변환하고, 결과를 검토·수정합니다.

4. **검증**: 스테이징에서 라우팅, TLS, 헤더, 타임아웃 동작이 동일한지 확인합니다.

5. **컷오버**: 트래픽을 Gateway로 완전히 이전한 뒤 기존 Ingress를 제거합니다.

이 과정에서 두 시스템이 같은 호스트를 동시에 노출하지 않도록 주의해야 합니다.

컨트롤러별 Gateway API 지원 현황

Gateway API는 표준 스펙이고, 이를 구현하는 컨트롤러는 여러 개입니다. 적합성 수준(Core / Extended 기능 지원 정도)은 컨트롤러마다 다릅니다.

| 구현 | 데이터 플레인 | 비고 |

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

| Envoy Gateway | Envoy | CNCF, Gateway API 중심 설계 |

| Contour | Envoy | HTTPProxy와 Gateway API 모두 지원 |

| Istio | Envoy | 서비스 메시, Gateway API 지원 성숙 |

| Traefik | Traefik | Ingress·CRD·Gateway API 모두 지원 |

| Cilium | eBPF/Envoy | CNI 통합 Gateway 지원 |

| Kong | Kong | Gateway API 지원 |

| NGINX Gateway Fabric | NGINX | NGINX 기반 Gateway API 구현 |

| HAProxy | HAProxy | Gateway API 지원 진행 |

실제 선택 시에는 공식 적합성 리포트(conformance)를 확인해 필요한 기능(트래픽 분할, 헤더 매칭 등)이 지원되는지 검증하는 것이 안전합니다.

함정과 트러블슈팅

전환 과정에서 자주 만나는 문제들입니다.

**1. HTTPRoute가 Gateway에 attach되지 않는다.**

`parentRefs`가 잘못되었거나, Gateway listener의 `allowedRoutes`(네임스페이스/종류 제한)에 막힌 경우입니다. HTTPRoute의 status에서 attach 조건을 확인합니다.

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

**2. 크로스 네임스페이스 참조가 거부된다.**

Gateway와 HTTPRoute, 또는 HTTPRoute와 backend Service가 다른 네임스페이스에 있을 때는 **ReferenceGrant**가 필요합니다. 이를 명시적으로 허용해야 참조가 성립합니다.

**3. 변환했더니 동작이 미묘하게 다르다.**

어노테이션 기반 기능(특히 rewrite, 정규식 경로, snippet)은 의미가 정확히 1:1로 대응하지 않을 수 있습니다. 표준 필터로 표현 가능한지 먼저 확인하고, 불가능하면 구현별 확장 기능을 검토합니다.

**4. TLS 인증서가 적용되지 않는다.**

Gateway listener의 `certificateRefs`가 가리키는 Secret이 다른 네임스페이스에 있으면 ReferenceGrant가 필요합니다. cert-manager는 Gateway API 통합을 지원하므로, Gateway 리소스에 직접 인증서 발급을 연동할 수 있습니다.

**5. 두 컨트롤러가 같은 호스트를 잡는다.**

병행 운영 중 기존 Ingress와 새 Gateway가 동일 호스트를 노출하면 트래픽이 섞입니다. 컷오버 전까지 호스트 또는 가중치로 명확히 분리합니다.

마치며

Gateway API로의 전환은 단순한 API 교체가 아니라 운영 모델의 진화입니다. **왜**(어노테이션 지옥과 역할 분리 부재), **무엇**(GatewayClass/Gateway/HTTPRoute로의 책임 분리와 표준 필터), **어떻게**(ingress2gateway와 점진적 병행 전환)를 차례로 이해하면, 무리 없이 마이그레이션을 설계할 수 있습니다.

2026년 컨텍스트에서 Ingress는 여전히 동작하지만 frozen이고, ingress-nginx는 유지보수 중심입니다. 따라서 신규 설계는 Gateway API를 1차 후보로 두고, 기존 자산은 검증을 거쳐 단계적으로 옮기는 것이 합리적입니다. 변환 도구는 출발점일 뿐 모든 어노테이션을 대신해 주지 않으므로, 핵심은 항상 검증입니다.

참고 자료

- Gateway API 공식 사이트: https://gateway-api.sigs.k8s.io/

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

- ingress2gateway 프로젝트: https://github.com/kubernetes-sigs/ingress2gateway

- Kubernetes 공식 문서 — Ingress: https://kubernetes.io/docs/concepts/services-networking/ingress/

- Envoy Gateway 공식 문서: https://gateway.envoyproxy.io/docs/

- Project Contour 공식 문서: https://projectcontour.io/docs/

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

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

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

- ingress-nginx 공식 문서: https://kubernetes.github.io/ingress-nginx/

현재 단락 (1/204)

지난 몇 년간 Kubernetes에서 L7 트래픽을 외부로 노출하는 표준은 사실상 Ingress였습니다. 그러나 2026년 현재 상황은 분명히 달라졌습니다. **Ingress AP...

작성 글자: 0원문 글자: 7,410작성 단락: 0/204