Back

[TIL] Ingress Nginx → Envoy Gateway, 왜 그리고 어떻게

2026. 03. 04.Yeji Kim
Platform

Ingress Nginx가 지원 종료?

2026년 3월, Ingress Nginx가 공식 EOL(End of Life) 을 선언했다. Kubernetes 초창기부터 사실상 표준이었던 인그레스 컨트롤러가 더 이상 보안 패치조차 받지 못하게 된 것이다.

왜 이렇게 됐을까?

  • Ingress API 자체의 한계: Ingress 리소스는 기본 HTTP 라우팅만 표준으로 정의하고, 나머지는 전부 어노테이션에 의존했다. 컨트롤러마다 어노테이션이 달라서 이식성이 없었다.
  • Gateway API의 성숙: Kubernetes SIG-Network이 만든 Gateway API가 2023년 GA를 달성하면서, Ingress의 모든 기능 + 그 이상을 표준 리소스로 제공하게 됐다.
  • 커뮤니티 이동: Istio, Envoy Gateway, Cilium 등 주요 프로젝트가 Gateway API를 기본으로 채택했다.

Ingress Nginx 프로젝트 자체가 "Gateway API로 마이그레이션하세요" 라고 공식 권고하고 있다.

당장 안 바꾸면?

EOL 이후에는 CVE 패치가 중단된다. 프로덕션에서 Ingress Nginx를 계속 쓰면 보안 리스크를 직접 감수해야 한다.

Ingress Controller는 뭐하는 친구야?

웹 브라우저가 app.example.com에 접속하면, 요청은 쿠버네티스 클러스터의 Ingress Controller에 먼저 도착한다. Ingress Controller는 본질적으로 리버스 프록시(Reverse Proxy) 다.

리버스 프록시란 클라이언트와 서버 사이에서 대리인 역할을 하는 서버다. 클라이언트는 프록시의 주소만 알면 되고, 뒤에 실제 서버가 몇 개인지, 어디 있는지 몰라도 된다. Ingress Nginx는 내부에 nginx를 돌려서 이 역할을 했고, Envoy Gateway는 Envoy Proxy를 돌린다.

zsh
[브라우저] → [리버스 프록시 (Ingress Controller)] → [Service A]

URL 경로(/api, /web)나 도메인(a.example.com, b.example.com)을 보고 어떤 백엔드 서비스로 보낼지 결정하는 게 핵심이다. 이걸 L7(Layer 7) 라우팅이라 부르는데, HTTP 레벨의 내용(경로, 헤더, 호스트)을 보고 판단하기 때문.


Gateway API, 개념부터 잡기

리소스, 어노테이션, 네임스페이스?

이 글에서 계속 나오는 쿠버네티스 용어를 먼저 정리하자.

리소스(Resource) 는 쿠버네티스가 관리하는 오브젝트다. Pod(컨테이너 묶음), Service(네트워크 접점), Deployment(배포 단위) 같은 게 다 리소스다. YAML 파일에 원하는 상태를 적어서 kubectl apply하면 쿠버네티스가 만들어준다. Ingress도 리소스고, 이 글에서 나올 Gateway, HTTPRoute도 리소스다.

yaml
apiVersion: v1
kind: Pod           # ← 이 "kind"가 리소스의 종류
metadata:
  name: my-pod      # ← 리소스의 이름
  namespace: my-app # ← 어떤 네임스페이스에 속하는지
  annotations:      # ← 부가 메타데이터
    example: "hello"
spec:               # ← 리소스의 실제 설정 (스펙)
  ...

어노테이션(Annotation) 은 리소스에 붙이는 메모다. 쿠버네티스 자체는 신경 안 쓰지만, 특정 컨트롤러(예: nginx)가 읽고 동작을 바꾼다. 문제는 이 메모가 표준이 아니라 컨트롤러마다 다르다는 점.

네임스페이스(Namespace) 는 리소스를 폴더처럼 묶는 논리적 구분이다. my-app 네임스페이스와 infra 네임스페이스의 리소스는 서로 격리돼 있어서, 팀별/서비스별로 나눠서 권한 관리에 쓴다.

Gateway API를 이해하려면 먼저 왜 리소스를 3개로 쪼갰는지를 이해해야 한다.

기존 Ingress 리소스는 하나의 YAML에 도메인 → 서비스 매핑을 다 적었다. 단순할 땐 편했는데, TLS 설정이나 rate limit, 헤더 조작, 카나리 배포 같은 걸 하려면 annotations에 nginx 전용 설정을 잔뜩 넣어야 했다. 다른 컨트롤러(Traefik, HAProxy 등)로 바꾸면 어노테이션을 전부 다시 써야 했고.

여기서 말하는 것들이 뭐야?
  • TLS (Transport Layer Security): 브라우저 주소창에 자물쇠가 뜨는 그것. HTTP를 암호화해서 HTTPS로 만드는 프로토콜이다. 중간에 누가 트래픽을 가로채도 내용을 못 읽게 한다.
  • Rate Limit: 특정 클라이언트가 초당 요청을 너무 많이 보내는 걸 제한하는 것. DDoS 방어나 API 남용 방지에 쓴다. 1초에 10번까지만 허용, 이런 식으로 건다.
  • 헤더(Header): HTTP 요청/응답에 딸려오는 메타데이터. Content-Type: application/json처럼 요청의 부가 정보를 담는다. 커스텀 헤더를 추가/수정하는 것도 프록시의 일.
  • 카나리 배포: 뒤에서 자세히 다룬다!

Gateway API는 이걸 관심사 분리로 풀었다. 누가 뭘 담당하느냐에 따라 리소스를 쪼갠 거다.

GatewayClass - 게이트웨이 구현체 선택

StorageClass가 스토리지 백엔드를 정해주듯, GatewayClass는 어떤 게이트웨이 구현체를 쓸지 정한다.

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: eg                # 이 이름을 아래 Gateway에서 참조
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller

보통 클러스터에 한 번만 만들고 거의 건드리지 않는다. 클라우드 환경이라면 AWS ALB, GCP GLB 같은 제공자의 GatewayClass가 이미 있을 수도 있다.

Gateway - 트래픽이 들어오는 문

클러스터 외부 트래픽의 입구다. 어떤 포트에서 어떤 프로토콜을 받을지, TLS를 어떻게 처리할지를 여기서 잡는다.

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
  namespace: infra        # 보통 인프라 네임스페이스에 위치
spec:
  gatewayClassName: eg    # 위에서 만든 GatewayClass 참조
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: wildcard-tls
    - name: http
      protocol: HTTP
      port: 80

호텔로 치면 로비다. 손님(트래픽)이 들어오는 곳이고, 보안 검색(TLS)도 여기서 한다. 대신 몇 호실로 가라는 안내는 안 한다 - 그건 HTTPRoute가 할 일이다.

TLS Termination이 뭐야?

위 YAML에서 tls.mode: Terminate가 보인다. HTTPS 암호화를 이 지점에서 풀겠다는 뜻이다.

브라우저 → Gateway 구간은 HTTPS(암호화)로 통신하고, Gateway → 백엔드 Pod 구간은 HTTP(평문)로 통신한다. 왜 이렇게 할까?

  1. 인증서 관리를 한 곳에서: TLS 인증서를 각 Pod마다 넣을 필요 없이 Gateway에서만 관리
  2. 성능: 암호화/복호화는 CPU를 먹는 작업. Gateway에서 한 번만 하면 됨
  3. 클러스터 내부는 안전: 같은 클러스터 내부 통신은 보통 신뢰할 수 있는 네트워크

Terminate 외에 Passthrough(암호화를 풀지 않고 그대로 백엔드로 전달)도 있다.

HTTPRoute - 요청을 어디로 보낼지

실제 라우팅 규칙이다. 이 도메인의 이 경로로 들어온 요청을 어떤 Service로 보낼지 정한다.

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: my-app-route
  namespace: my-app       # 앱 네임스페이스에 위치!
spec:
  parentRefs:
    - name: my-gateway
      namespace: infra    # 어떤 Gateway에 붙을지 참조
  hostnames:
    - my-app.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api-svc
          port: 80

중요한 건 HTTPRoute를 앱 네임스페이스에 만든다는 점이다. 앱 개발자는 자기 서비스 라우팅만 신경 쓰면 된다. TLS 설정이나 게이트웨이 구현체가 뭔지 알 필요 없다. parentRefs로 어떤 Gateway에 붙을지만 지정하면 끝이다.

Listener, Port, Protocol?

Gateway YAML에 listeners 배열이 있었다. Gateway에서 어떤 트래픽을 받을지 정의하는 부분이다.

  • Port 443 + Protocol HTTPS: 암호화된 웹 트래픽 (브라우저 주소창에 https://로 시작하는 것)
  • Port 80 + Protocol HTTP: 암호화되지 않은 웹 트래픽 (보통은 443으로 리다이렉트)

포트 번호는 약속이다. 80과 443은 웹 트래픽용 well-known 포트라서 브라우저가 생략할 수 있는 것이다 (https://example.com = https://example.com:443).

Listener를 여러 개 만들면 한 Gateway에서 HTTP, HTTPS, 나중에는 gRPC나 TCP까지 동시에 받을 수 있다.

정리하면:

  • GatewayClass → Envoy 쓸 거야 (인프라팀, 클러스터 레벨)
  • Gateway → 443 포트에서 HTTPS 받을 거야 (플랫폼팀, 인프라 네임스페이스)
  • HTTPRoute → /api로 오면 api-svc로 보내줘 (앱팀, 앱 네임스페이스)

각 팀이 자기 리소스만 건드리면 된다.


역할 분리가 실제로 어떻게 동작하는지

역할 분리가 왜 중요한지, 기존 Ingress랑 비교하면 바로 느낌이 온다.

Ingress 시절의 문제

yaml
# 앱 개발자가 이걸 다 알아야 했다
metadata:
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"       # TLS? 내가 왜...
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"      # nginx 설정을...
    nginx.ingress.kubernetes.io/limit-rps: "10"             # 어노테이션으로...
    nginx.ingress.kubernetes.io/canary: "true"              # 이렇게 많이...
    nginx.ingress.kubernetes.io/canary-weight: "20"         # 알아야 하지?
    cert-manager.io/cluster-issuer: "letsencrypt-prod"      # 인증서까지?

앱 개발자가 nginx 내부 동작 방식, TLS 인증서 관리, rate limit 설정까지 전부 알아야 했다. 그냥 /api 경로를 서비스에 연결하고 싶을 뿐인데 알아야 할 게 너무 많았다.

Gateway API에서의 분리

관심사누가 관리?어떤 리소스?네임스페이스
게이트웨이 구현체 선택인프라팀GatewayClass클러스터 스코프
TLS, 포트, 프로토콜플랫폼팀Gatewayinfra
Rate limit, 보안 정책플랫폼팀BackendTrafficPolicyinfra
라우팅 규칙앱팀HTTPRoutemy-app
CRD가 뭐야?

CRD(Custom Resource Definition) 는 쿠버네티스에 새로운 종류의 리소스를 추가하는 방법이다.

쿠버네티스는 기본적으로 Pod, Service, Deployment 같은 리소스를 알고 있다. 하지만 GatewayClassHTTPRoute 같은 건 기본 리소스가 아니다. Gateway API의 CRD를 설치하면 쿠버네티스가 이 새로운 리소스 타입들을 이해하게 된다.

Envoy Gateway의 BackendTrafficPolicy, SecurityPolicy 같은 것도 CRD다. 즉 Envoy Gateway가 추가한 자체 리소스 타입이다.

RBAC으로 자연스럽게 매핑된다:

yaml
# 앱팀에게 HTTPRoute 권한만 부여
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: my-app
rules:
  - apiGroups: ["gateway.networking.k8s.io"]
    resources: ["httproutes"]
    verbs: ["get", "list", "create", "update", "patch"]
  # Gateway, GatewayClass는 권한 없음 → 건드릴 수 없음
RBAC이 뭐야?

RBAC(Role-Based Access Control) 은 누가 무엇을 할 수 있는지 권한을 정의하는 쿠버네티스 메커니즘이다.

위 Role 예시에서 앱팀은 httproutes에 대해 get, create, update 등을 할 수 있지만, gatewaysgatewayclasses에 대한 권한이 없다. 즉 앱팀이 실수로 Gateway 설정을 건드리는 걸 시스템 레벨에서 차단한다.

Ingress 시절에는 리소스 하나에 모든 설정이 들어가니까, 앱팀에게 Ingress 수정 권한을 주면 TLS 설정까지 건드릴 수 있었다. Gateway API는 리소스 자체를 나눠서 이 문제를 구조적으로 막았다.

앱 개발자는 HTTPRoute만 알면 된다. TLS 인증서가 어떻게 관리되는지, rate limit이 어디서 걸리는지 몰라도 된다. 플랫폼팀이 Gateway에서 한 번만 설정하면 모든 HTTPRoute에 자동 적용된다.

Ingress Nginx

Client외부 트래픽
Ingress Controllernginx.conf 생성
Ingress Resource+ annotations (많음)
Service A
Service B
특징: 단일 리소스, 어노테이션으로 모든 설정 관리. 컨트롤러마다 어노테이션이 다름.

설정 비교 - 실전 YAML

실제 YAML을 나란히 비교해 보자. 각 탭을 눌러서 시나리오별 차이를 확인할 수 있다.

  • Basic Routing: 단순 경로 기반 라우팅. Gateway API 쪽이 어노테이션 없이 더 명시적이다.
  • TLS: Ingress는 어노테이션 + tls 블록이 섞이지만, Gateway API는 Gateway 리소스에서 TLS를 한 번에 관리한다. HTTPRoute는 TLS를 몰라도 된다.
  • Canary: 가장 차이가 극적이다. Ingress는 리소스 2개 + canary 어노테이션이 필요하지만, Gateway API는 backendRefsweight만 추가하면 끝이다.
  • Rate Limit: Ingress는 nginx 전용 어노테이션, Gateway API는 Envoy Gateway의 BackendTrafficPolicy CRD로 더 세밀한 제어가 가능하다.
Ingress Nginx
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-svc
                port:
                  number: 80
Gateway API
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: my-app
spec:
  parentRefs:
    - name: my-gateway
  hostnames:
    - app.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api-svc
          port: 80

카나리 배포가 이렇게 쉬워진다

카나리 배포란?

새 버전(v2)을 배포할 때, 한 번에 다 바꾸지 않고 일부 사용자에게만 먼저 보내서 문제 없는지 확인하는 전략이다. 이름은 탄광의 카나리아에서 왔다 - 위험 징후를 먼저 감지하는 역할.

예를 들어 100명의 사용자가 app.example.com에 접속한다고 하면:

  • weight: 80 / weight: 20 설정 → 약 80명은 기존 v1으로, 약 20명은 새 v2로 보내진다
  • v2에서 에러가 터지면? 영향 범위가 20%로 제한된다
  • 문제 없으면? weight를 50 → 80 → 100으로 점진적으로 올려서 완전히 전환한다

Ingress에서는 왜 번거로웠나

Ingress Nginx에서 카나리를 하려면 Ingress 리소스를 2개 만들어야 했다:

  1. 기본 Ingress → v1 서비스 연결
  2. 카나리 Ingress → v2 서비스 연결 + canary: "true" + canary-weight: "20" 어노테이션

리소스가 2개이니 관리 포인트도 2배다. 가중치를 바꾸려면 카나리 Ingress의 어노테이션을 수정해야 한다.

Gateway API에서는?

HTTPRoute 하나에서 backendRefsweight 필드만 바꾸면 된다:

yaml
rules:
  - backendRefs:
      - name: app-v1
        port: 80
        weight: 80    # stable: 80%
      - name: app-v2
        port: 80
        weight: 20    # canary: 20%

가중치를 바꾸고 싶으면? 이 숫자만 수정하면 끝이다. 리소스 1개, 필드 1개.

아래 데모에서 슬라이더를 움직이면 v2의 가중치(weight)가 바뀔 때 트래픽이 어떻게 분배되는지 시각화로 볼 수 있다. 각 원이 하나의 요청이라고 생각하면 된다 - 가중치 비율에 따라 v1(검정) 또는 v2(초록)으로 갈라진다.

v1v2
80%

app-v1 (stable)

20%

app-v2 (canary)

v1
v2

Ingress 방식

Ingress 리소스 2개 생성
+ canary annotation 설정

Gateway API 방식

HTTPRoute 1개
backendRefs에 weight: 20

* 슬라이더를 움직여 트래픽 가중치를 조절해 보세요


App of Apps 패턴에서 Gateway API 적용하기

ArgoCD의 App of Apps 패턴을 쓰고 있다면, Gateway API 리소스를 어디에 넣어야 할지 고민이 된다. 결론부터 말하면, Gateway API의 역할 분리가 App of Apps 계층 구조랑 잘 맞아떨어진다.

구조

zsh
root-app/                          # Root Application
├── infra-app/                     # 인프라 레벨
   ├── envoy-gateway/             # Envoy Gateway Helm chart
   └── (GatewayClass 자동 생성)
   ├── cert-manager/
   └── ...
├── platform-app/                  # 플랫폼 레벨
   ├── gateway.yaml               # Gateway 리소스
   ├── backend-traffic-policy.yaml # 공통 rate limit 등
   └── ...
├── app-a/                         # 앱 레벨
   ├── deployment.yaml
   ├── service.yaml
   └── httproute.yaml             # ← 여기!
├── app-b/
   ├── deployment.yaml
   ├── service.yaml
   └── httproute.yaml             # ← 여기!
└── ...

각 레이어가 관리하는 것

infra-app - Envoy Gateway 설치

yaml
# infra-app의 Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: envoy-gateway
  namespace: argocd
spec:
  destination:
    namespace: envoy-gateway-system
  source:
    repoURL: oci://docker.io/envoyproxy/gateway-helm
    chart: gateway-helm
    targetRevision: v1.3.0

Envoy Gateway Helm chart를 설치하면 GatewayClass가 자동으로 생성된다. 인프라팀 외에는 건드릴 일이 없다.

platform-app - Gateway 리소스

yaml
# platform-app이 관리하는 Gateway
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: main-gateway
  namespace: infra
spec:
  gatewayClassName: eg
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: wildcard-tls
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              gateway-access: "true"    # 이 라벨이 있는 NS만 연결 허용

allowedRoutes로 어떤 네임스페이스의 HTTPRoute가 이 Gateway에 붙을 수 있는지 제어한다. 아무 앱이나 함부로 못 붙게 하는 장치다.

각 앱 - HTTPRoute만 관리

yaml
# app-a의 Helm chart 또는 kustomize에 포함
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: app-a-route
  namespace: app-a              # 앱 자기 네임스페이스
spec:
  parentRefs:
    - name: main-gateway
      namespace: infra          # 플랫폼팀이 만든 Gateway 참조
  hostnames:
    - app-a.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: app-a-svc
          port: 80

앱 개발자는 자기 Helm chart에 httproute.yaml만 추가하면 된다. TLS, 인증서, 게이트웨이 구현체가 뭔지 전혀 몰라도 된다.

기존 Ingress와의 차이

기존에는 각 앱의 Helm chart에 ingress.yaml이 있었고, 거기에 TLS 설정 + nginx 어노테이션이 잔뜩 들어갔을 것이다. Gateway API로 전환하면 그 파일이 httproute.yaml로 바뀌는데, 훨씬 깔끔해진다 - TLS 관련 설정이 전부 빠지니까.

ArgoCD sync 순서

App of Apps에서 주의할 점은 리소스 생성 순서다:

  1. GatewayClass (Envoy Gateway 설치 시 자동 생성)
  2. Gateway (GatewayClass가 있어야 생성 가능)
  3. HTTPRoute (Gateway가 있어야 parentRefs 참조 가능)

ArgoCD의 Sync Wave로 순서를 보장할 수 있다:

yaml
# Gateway에 sync wave 설정
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "1"    # infra-app(wave 0) 이후에 sync
 
# HTTPRoute는 별도 설정 불필요 - 앱 Application이 나중에 sync 됨

마이그레이션 가이드

병렬 운영 전략

한 번에 전환하는 건 위험하다. Ingress Nginx와 Envoy Gateway를 동시에 운영하면서 점진적으로 옮기는 걸 추천한다.

  1. Envoy Gateway 설치 + GatewayClass, Gateway 생성 (기존 Ingress에 영향 없음)
  2. 트래픽이 적은 서비스부터 HTTPRoute 생성 + DNS를 새 Gateway로 변경
  3. 문제 없으면 다음 서비스로. 문제 있으면 DNS만 돌리면 즉시 롤백
DNS로 롤백?

DNS(Domain Name System) 는 도메인 이름(app.example.com)을 IP 주소(203.0.113.10)로 변환하는 시스템이다.

Ingress Nginx와 Envoy Gateway는 각각 다른 IP(또는 로드밸런서) 를 가진다. app.example.com의 DNS 레코드가 가리키는 IP를 바꾸면 트래픽이 다른 게이트웨이로 흘러간다.

zsh
# 기존: Ingress Nginx의 LB IP를 가리킴
app.example.com 10.0.1.100 (Ingress Nginx)
 
# 전환: Envoy Gateway의 LB IP로 변경
app.example.com 10.0.2.200 (Envoy Gateway)
 
# 롤백: 다시 원래 IP로 변경하면 끝
app.example.com 10.0.1.100 (Ingress Nginx)

DNS 변경만으로 트래픽 경로를 바꿀 수 있으니, 양쪽 게이트웨이를 동시에 띄워두면 안전하게 왔다갔다 할 수 있다.

  1. 모든 서비스 전환 완료 후 Ingress Nginx 제거

App of Apps 패턴이면 더 쉽다 - 각 앱의 차트에서 ingress.yamlhttproute.yaml로 바꾸고, 앱별로 하나씩 sync하면 된다.

ingress2gateway 도구

Kubernetes SIG-Network에서 공식 제공하는 ingress2gateway CLI로 기존 Ingress 리소스를 Gateway API 리소스로 자동 변환할 수 있다.

bash
# 설치
go install github.com/kubernetes-sigs/ingress2gateway@latest
 
# 변환 (현재 클러스터의 Ingress 읽어서 변환)
ingress2gateway print
 
# 특정 네임스페이스만
ingress2gateway print --namespace my-app
주의

자동 변환은 기본 라우팅만 커버한다. nginx 전용 어노테이션(rate limit, custom headers 등)은 수동으로 Envoy Gateway CRD에 맞게 변환해야 한다.

주의사항 / Gotchas

  • 어노테이션 매핑이 1:1이 아니다: nginx 전용 기능은 Envoy Gateway의 SecurityPolicy, BackendTrafficPolicy 등 별도 CRD로 옮겨야 한다.
  • IngressClass vs GatewayClass: 기존 ingressClassName: nginxgatewayClassName: eg (Envoy Gateway 기본값). 이름이 달라서 놓치기 쉽다.
  • 기본 경로 매칭 방식이 다르다: Ingress는 기본이 Prefix, Gateway API는 type: PathPrefix를 명시해야 한다.
  • Health check 설정 위치 변경: Ingress에서 어노테이션으로 하던 health check가 BackendTrafficPolicy로 이동한다. Health check는 게이트웨이가 주기적으로 백엔드 Pod에 살아있는지 확인하고, 응답 없으면 트래픽을 안 보내는 메커니즘이다.
  • CRD 버전 확인: Gateway API CRD v1.2+ 인지 확인. 구 버전에서는 일부 필드(backendRefs.weight 등)가 없을 수 있다.
  • cross-namespace 참조: HTTPRoute가 다른 네임스페이스의 Gateway를 참조하려면, Gateway의 allowedRoutes에서 해당 네임스페이스를 허용해야 한다. 빠뜨리면 HTTPRoute가 Accepted: false로 남는다.

요약

Ingress Nginx EOL은 쿠버네티스 네트워킹의 세대 교체다. Gateway API는 Ingress를 그냥 갈아끼우는 게 아니라, 근본적으로 더 나은 구조를 제공한다고 한다.

  • 역할 기반 리소스 분리 → 인프라/플랫폼/앱 팀이 각자 영역만 관리
  • 표준 API → 구현체(Envoy, Istio, Cilium)를 바꿔도 HTTPRoute는 그대로
  • 카나리, 트래픽 미러링 같은 고급 기능이 네이티브
  • App of Apps랑 계층 구조가 딱 맞음