[DIP] Ingress & Gateway API

k8s

웹 서버 관련된 궁금증을 해소하기 위해 쿠버네티스 기초에 대해 알려주는 인강을 듣고 간단한 웹 서버를 구축해 볼 계획이었다. 그러던 중 Ingress NGINX에 대한 서비스 종료 소식을 뒤늦게 동료분에게 들었다. 이미 2025년 11월 11일 빼빼로데이에 2026년 3월 프로젝트 중단 예정을 발표하였고, 인프라에 관심 없던 FE 개발자에게 무관심 속 변화에 대한 두려움을 일깨워 주었다.


어쩌면 뒤늦은 정리일지 모르겠지만 앞으로의 인프라 그리고 웹 서버에 대한 관심을 가지고 해당 영역을 나의 영역으로 포용하기 위해 Ingress와 그것을 대체제인 Gateway API에 대해 간단히 살펴볼 예정이다.



Ingress

Ingress는 쿠버네티스 클러스터 외부로부터 들어오는 HTTP/HTTPS 트래픽을 내부 서비스로 라우팅하기 위한 L7 리소스이다. 실제 트래픽에 대한 처리는 Ingress가 아닌 Ingress Controller에 의해 처리되며 Ingress는 정의된 라우팅 처리 규칙들을 제공하는 역할을 한다.


Ingress의 구성요소로는 Ingress Resource / Ingress Controller / Ingress Class를 간단히 정리해 보고자 한다.



Ingress Resource

Ingress Resource는 실제 트래픽이 처리될 경로를 정의하며, 트래픽을 처리해 줄 컨트롤러를 ingressClassName으로 지정한다.

yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: minimal-ingress spec: ingressClassName: nginx-example rules: - http: paths: - path: /testpath pathType: Prefix backend: service: name: test port: number: 80


Ingress Controller

Ingress Controller는 쿠버네티스 API 서버를 통해 정의된 Ingress Resource를 확인하고 실제 트래픽을 처리한다. 기본 쿠버네티스 환경에 포함되어 있지 않으므로 별도 설치가 필요하며, 많이 사용되는 컨트롤러로는 ingress-nginx, Traefik, HAProxy, Kong이 있다.



Ingress Class

쿠버네티스 클러스터 환경에는 여러 종류의 Ingress Controller가 존재할 수 있다. Ingress Class는 쿠버네티스 클러스터 환경에서 어떤 Ingress Resource가 어떤 컨트롤러를 사용할지 참조를 지정할 수 있게 한다.

yaml
apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: external-lb spec: controller: example.com/ingress-controller parameters: apiGroup: k8s.example.com kind: IngressParameters name: external-lb


Ingress 트래픽 흐름

DIP-Ingress-Gateway-API-1

  1. 클라이언트 요청: 사용자가 도메인 https://example.com으로 HTTPS 요청을 보낸다.
  2. L4 진입 (External LB): 클러스터 외부의 LoadBalancer가 요청을 받고, 이를 클러스터 노드 내에서 실행 중인 Ingress Controller 파드로 전달한다.
  3. L7 분석 및 복호화: Ingress Controller가 요청을 수신하여 TLS 복호화(Termination)를 수행하고, HTTP 헤더의 Host와 Path 정보를 추출한다.
  4. 라우팅 규칙 매칭: 컨트롤러는 추출된 정보를 Ingress Resource 규칙과 대조하여 어떤 서비스(Service)로 보낼지 결정한다.
  5. 최종 직접 전송 (Direct Path): 컨트롤러는 서비스의 ClusterIP를 거치지 않고, 해당 서비스에 연결된 최신 Endpoints(파드 IP 목록) 중 하나를 선택하여 파드로 직접 트래픽을 전송한다.


Ingress NGINX Retirement

Ingress NGINX는 가장 인기가 많은 컨트롤러로 많은 프로젝트에 사용되는 것에 비해 실질적으로 유지 관리하는 것에 있어 인력이 부족했다고 한다. 한두 명의 개발자가 퇴근 후 혹은 주말마다 틈틈이 작업을 하며 유지되고 있었고 보안 결함, 기술적 부채를 해결하기 위해 노력했지만 결국 서비스를 종료하는 것으로 결정되었다고 한다.

2026년 3월 이후에는 업데이트가 더 이상 제공되지 않으며, 다른 Ingress 컨트롤러나 Gateway API로의 마이그레이션을 권장한다.


Ingress NGINX 서비스 종료와 더불어 쿠버네티스 Ingress 자체에도 구조적 결함 등으로 공식문서에서도 Gateway API 사용을 권장하고 있다.


  • Ingress API의 L7 전용 설계 구조로 L4 표준 지원 불가

Ingress는 HTTP/HTTPS를 위해 만들어져있어 TCP/UDP를 위한 처리를 위해 표준이 아닌 별도의 구현이 필요하다.

yaml
nginx.ingress.kubernetes.io/backend-protocol: "TCP"

  • 역할 분리 불가능한 단일 리소스 구조

Ingress에서 tls와 HTTP Route 처리가 함께 이루어지고 있어 인프라 관리자와 서비스 개발자가 함께 설정을 관리해야 하는 구조이다. 이 과정에서 서로의 관리 영역에 영향을 미치거나 충돌을 유발할 수 있다.

yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: simple-ingress spec: tls: # TSL 설정 - hosts: - example.com secretName: example-tls rules: # HTTP Route - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: my-service port: number: 80

  • Annotation 중심의 비표준 확장

Ingress에서 지원하는 기능적 한계로 필요한 기능을 비표준 확장하여 사용해야 한다.

yaml
nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "10" nginx.ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/limit-rps: "5"

하나의 생태계에서 가장 인기가 많았던 서비스가 종료되는 모습을 보며 역시나 영원한 건 없다는 생각이 들었다. 녹슬지 않는 코드로 짜인 프로그램이더라도 언젠간 낡은 것이 되고 문제가 발생하며 새로운 것으로 교체할 시기가 오는 것 같다.

아래에서는 Ingress의 대체제로 권장되는 Gateway API에 대해 알아보며 위에서 보았던 문제들을 어떠한 방식, 구조로 해결했는지 알아볼 예정이다.



Gateway API

Gateway API는 조직의 역할에 기반하여 설계되었으며, 네트워크 인프라 프로비저닝(Gateway)과 라우팅(Route) 설정을 분리한 API 집합이다.

Ingress에서 구조적 문제로 뽑혔던 클러스터 외부 진입과 라우팅을 역할 분리 방식으로 설계하였고, 표준에 기반한 기능을 필드 내 선언하여 사용할 수 있도록 지원한다.

Gateway API 구성요소로는 GatewayClass / Gateway Controller / Gateway / Route를 간단히 정리해 보고자 한다.



GatewayClass

GatewayClass는 클러스터에서 사용할 로드밸런서의 종류, 어떤 컨트롤러를 사용할 것인지를 정의한다.

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: external-nginx spec: controllerName: k8s.io/gw-controller-nginx


Gateway Controller

Gateway Controller는 쿠버네티스 API 서버를 실시간으로 감시하며, 사용자가 선언한 Gateway API 리소스들을 실제 네트워크 인프라 설정으로 변환하고 동기화하는 역할을 한다.



Gateway

Gateway는 실제 트래픽이 들어오는 네트워크 진입점(Entry Point)을 정의한다. 리스너 설정을 통해 특정 포트를 개방하여 포트에서 사용할 프로토콜(HTTP, HTTPS, TCP 등)을 지정하고 HTTPS 보안 통신을 위한 인증서 연결 및 암호화, 복호화 정책을 정의한다.

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: prod-gateway spec: gatewayClassName: external-nginx listeners: - name: https port: 443 protocol: HTTPS tls: mode: Terminate certificateRefs: - name: production-certs allowedRoutes: namespaces: from: All


Route

Route는 Gateway로 들어온 트래픽을 어떤 서비스로 보낼지 결정하는 역할을 하며, HTTPRoute / TCPRoute / UDPRoute 등이 존재한다.

Ingress가 주로 웹 트래픽(HTTP/HTTPS) 처리에 국한되었던 것과 달리, Gateway API의 Route는 프로토콜별로 리소스가 세분화되어 있어 더 정교하고 유연한 라우팅 설정을 지원한다.



Gateway API 트래픽 흐름

DIP-Ingress-Gateway-API-2

  1. 클라이언트 요청: 사용자가 https://example.com으로 요청을 보낸다.
  2. L4 진입 (Gateway Listener): 요청이 할당된 외부 IP를 통해 Gateway Listener에 도달한다. 여기서 포트(443)를 확인하고 TLS 복호화를 수행한다.
  3. L7 프록시 수신: 복호화된 HTTP 패킷을 L7 Proxy(Envoy, Nginx)가 전달받는다.
  4. 라우팅 규칙 매칭 (HTTPRoute): 프록시는 주입받은 HTTPRoute 규칙을 조회하여 Host: example.comPath: /가 일치하는지 확인한다.
  5. 엔드포인트 조회: 일치하는 규칙에 연결된 서비스의 EndPoints(파드 IP 목록)를 확인한다.
  6. 최종 전송: 프록시는 서비스를 거치지 않고 실제 파드 IP로 트래픽을 직접 전송한다.


Minikube로 Ingress & Gateway API

아래에서는 minikube를 사용하여 Ingress와 Gateway API 환경을 아주 간단하게 구성해 보는 튜토리얼을 진행해 보려 한다. 너무 간단한 실습이지만 기본적인 트래픽흐름을 살펴보고 그 흐름 속에서 실무에서 챙기면 좋을 부분들에 대한 힌트를 얻지 않을까 기대해 보며 시작해 보겠다.

설치 필요: minikube / kubectl / docker



Ingress 튜토리얼

  1. Minikube 시작

아래 명령을 통해 minikube 시작 시 필요한 리소스를 다운받아 클러스터를 구성하게 된다.

bash
$ minikube start

DIP-Ingress-Gateway-API-3


  1. Ingress Controller 활성화

minikube 클러스터 내 ingress 애드온을 활성화 한다.

bash
$ minikube addons enable ingress

DIP-Ingress-Gateway-API-4

ingress 애드온 활성화 시 안내 사항으로 알려주는 minikube tunnel 명령을 통해 127.0.0.1 IP로 접근이 가능하게 된다.

macOS에서 Docker 드라이버를 사용하여 Minikube를 실행 중이라면, 클러스터 내부 IP에 접근하지 못할 수 있다. minikube tunnel을 활성화하여 IP에 접근 가능하게 한다. 여기서 로컬 환경에서의 minikube tunnel이 하는 역할이 External LoadBalancer의 역할을 한다고 생각하면 될 것 같다.

bash
$ minikube tunnel

DIP-Ingress-Gateway-API-5


ingress Controller의 활성화 여부는 아래 명령을 통해 Running 상태를 확인 할 수 있다.

bash
$ kubectl get pods -n ingress-nginx

DIP-Ingress-Gateway-API-6


  1. 웹 서버와 Service 생성

테스트할 웹 서버를 간단한 샘플 이미지를 사용하여 deployment로 생성한다.

bash
$ kubectl create deployment web --image=gcr.io/google-samples/hello-app:1.0

DIP-Ingress-Gateway-API-7


expose 명령을 통해 생성된 deloyments를 분석하여 서비스를 자동 생성하도록 한다. expose로 생성 시 간단하게 Service를 생성할 수 있지만 추가적인 세부 설정이 필요한 경우 수정이 필요하다. 운영 환경의 경우에는 expose의 사용보다는 프로젝트에 맞는 Service를 yaml로 관리하는 것이 합리적이다.

bash
$ kubectl expose deployment web --port=8080 --target-port=8080

DIP-Ingress-Gateway-API-8


  1. Ingress 리소스 생성

Ingress.yaml을 생성하고 도메인 요청을 어떤 서비스로 보낼 것인지에 대한 규칙을 정의한다.

yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: hello-world.info http: paths: - path: / pathType: Prefix backend: service: name: web port: number: 8080

생성된 Ingress.yaml을 아래 명령을 통해 리소스를 적용한다.

bash
$ kubectl apply -f ingress.yaml

DIP-Ingress-Gateway-API-9


  1. 로컬 호스트 설정

ingress 활성화 단계에서 확인된 IP에 ingress 리소스에서 정의한 도메인(host)을 hosts에 등록한다.

/etc/hosts에 접근하여 파일에 설정된 IP와 도메인들을 확인하고 테스트에 사용할 정보를 추가한다.

  • 127.0.0.1 hello-world.info

  1. 도메인 접근 확인

브라우저에서 도메인에 접근하여 정상적으로 접근되는 것을 확인 할 수 있다.

DIP-Ingress-Gateway-API-10






Gateway API 튜토리얼

  1. Minikube 초기화

시작 전 이전 ingress 튜토리얼에서 했던 minikube 노드를 중지하고 클러스터를 초기화한다.

bash
$ minikube stop $ minikube delete --all --purge

DIP-Ingress-Gateway-API-11

DIP-Ingress-Gateway-API-12


  1. minikube 시작

ingress 튜토리얼과 동일하게 minikube 시작한다.

bash
$ minikube start

  1. Gateway API CRD 설치

쿠버네티스 기본 리소스에는 Gateway API가 포함되어 있지 않으므로 클러스터 내 설치한다.

bash
$ kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml

  1. Gateway Controller 설치 및 활성화

Envoy Gateway 컨트롤러를 설치하고 상태를 확인한다.

bash
$ kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/v1.0.0/install.yaml

DIP-Ingress-Gateway-API-13

bash
$ kubectl get pods -n envoy-gateway-system

DIP-Ingress-Gateway-API-14


  1. GatewayClass와 Gateway 생성

사용될 Controller 참조를 위한 GatewayClass를 정의한다.

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: envoy-gateway spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller
bash
$ kubectl apply -f gateway-class.yaml

트래픽이 들어올 입구 역할을 하는 Gateway를 생성한다.

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-gateway namespace: default spec: gatewayClassName: envoy-gateway listeners: - name: http port: 80 protocol: HTTP allowedRoutes: namespaces: from: All
bash
$ kubectl apply -f gateway.yaml

  1. 웹 서버와 Service 생성

ingress 튜토리얼에 생성했던 것과 동일하게 웹 서버와 Service를 생성한다.

bash
$ kubectl create deployment web --image=gcr.io/google-samples/hello-app:1.0 $ kubectl expose deployment web --port=8080 --target-port=8080

  1. HTTPRoute 생성

어떤 도메인이 어떤 서비스로 갈지를 정의한다. ingress에서는 ingress 리소스에서 인증서 및 Route 처리가 모두 정의되지만, Gateway API에서는 Gateway와 Route 리소스를 분리하여 정의한다.

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: web-route spec: parentRefs: - name: my-gateway hostnames: - "hello-world.info" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: web port: 8080
bash
$ kubectl apply -f route.yaml

  1. 도메인 접근 확인

ingress 튜토리얼에서와 동일하게 로컬 호스트 설정minikube tunnel을 실행하고 도메인에 접근하여 정상적으로 접근되는지 확인한다.

DIP-Ingress-Gateway-API-10






Ingress & Gateway API 비교

마지막으로 위에서 정리한 내용과 튜토리얼을 진행해보며 알아본 Ingress와 Gateway API 차이점을 정리해보려고 한다.


첫 번째로는 역할 분리를 확연하게 확인할 수 있었다. Ingress의 경우에는 하나의 리소스에서 호스트, 경로 및 다양한 설정을 처리하지만 Gateway API에서는 네트워크 진입점(Gateway)에 대한 영역과 서비스 라우팅(HTTPRoute) 영역을 나누어 관리할 수 있는 형태로 구성되어 있다. 트래픽에 대한 네트워크 진입점은 인프라 담당자 그리고 서비스 트래픽은 서비스 라우팅에서 서비스 개발자가 관리하여 보다 명확하게 역할을 나누어 관리 할 수 있다.


두 번째는 기능 확장을 위한 지원 방식이다. Ingress에서는 기능 확장을 위해 어노테이션을 사용하여 확장하는 반면 Gateway API에서는 표준화된 필드로 기능을 사용할 수 있었다.

yaml
# ingress apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: ... # HTTPRoute apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: web-route spec: ... rules: - matches: - path: type: PathPrefix value: ... filters: - type: URLRewrite urlRewrite: path: type: ReplacePrefixMatch replacePrefixMatch: ...

세 번째는 트래픽 제어Ingress는 HTTP(L7)를 위한 웹 서버 입구 역할을 수행한다면, Gateway API는 Gateway를 네트워크 진입점(L4)으로 사용하고 HTTPRoute(L7)를 위한 웹 서버 입구 역할 혹은 TCPRoute, UDPRoute 등 여러 트래픽에 대한 처리를 관리 할 수 있다.



Ingress & Gateway API를 알아보며

위 정리된 내용들은 쿠버네티스 공식 문서 혹은 어딘가 블로그에 아주 잘 정리된 내용이다. 누군가에게는 아주 쉬운 내용일지도 모르지만, 실무에서 직접 만지는 일이 많지 않은 나의 포지션에서는 뒤돌아서면 금세 잊히는 것 같다.

이번 Ingress NGINX에 대한 서비스 종료 소식을 들은 계기로 간단히라도 정리해 봐야겠다는 생각이 들었고, 단순히 읽기만 하는 것보다는 필기하며 공부한다는 생각으로 내용들을 정리해 보고, 간단한 튜토리얼을 진행해 보며 이번 Ingress NGINX 서비스 종료 사태에 대해 조금 더 가까이서 보려고 노력해 보았다.

지금 인기가 많은 서비스들도 언젠가는 기술적 혹은 해결할 수 없는 어떠한 문제에 부딪혀 종료하는 날이 올지도 모르겠다. 그럴 때 지금처럼 그것에 대한 문제와 어떠한 대안과 해결책을 가지고 풀어나가는지를 조금 더 가까이서 보려고 노력한다면, 훗날 나에게 풀기 힘든 문제가 주어졌을 때 앞선 과정들을 떠올리며 도움받을 수 있진 않을까 기대해 본다.

DIP-Ingress-Gateway-API-15

"You can't connect the dots looking forward; you can only connect them looking backward." - Steve Jobs -