PRO DBDATA PRO DBDATA

Kubernetes Ingress에서 Gateway API로 전환하는 방법: 트래픽 라우팅과 권한 분리 가이드

읽는 시간 약 12분
kubernetes ingressec9790ec849c gateway apieba19c eca084ed9998ed9598eb8a94 ebb0a9ebb295 ed8ab8eb9e98ed94bd eb9dbcec9ab0ed8c85eab3bc eab68ced959c 1787467498

Kubernetes에서 외부 트래픽을 서비스로 연결할 때 가장 널리 사용된 리소스는 Ingress다. Ingress는 호스트와 경로를 기준으로 HTTP·HTTPS 요청을 전달하기에 간단한 웹 서비스에서는 충분하다. 하지만 운영 규모가 커지면 상황이 달라진다. 리다이렉트, 헤더 변경, 트래픽 분할, 다중 프로토콜, 팀별 라우팅 권한 같은 요구사항을 구현하기 위해 컨트롤러 전용 Annotation이 계속 늘어나기 때문이다.

Gateway API는 이러한 한계를 보완하기 위해 역할과 책임을 GatewayClass, Gateway, HTTPRoute 등의 리소스로 분리한다. 인프라 관리자는 로드밸런서와 리스너를 관리하고, 애플리케이션 팀은 허용된 범위 안에서 자신의 라우팅 규칙을 배포할 수 있다. 단순히 Ingress 문법을 변경하는 작업이 아니라 트래픽 관리 구조와 운영 권한을 재설계하는 전환이라고 이해하는 것이 좋다.

Ingress와 Gateway API의 구조적 차이

Ingress는 하나의 리소스 안에 호스트, 경로, 백엔드 서비스 정보를 함께 작성한다. TLS 종료, URL 재작성, 세션 고정, 타임아웃처럼 표준 필드만으로 표현하기 어려운 기능은 대부분 Annotation에 의존한다. 문제는 Annotation의 형식과 지원 범위가 NGINX Ingress Controller, Traefik, HAProxy, 클라우드 전용 컨트롤러마다 다르다는 점이다.

Gateway API는 기능을 여러 리소스로 나눈다. GatewayClass는 실제 네트워크 기능을 구현할 컨트롤러를 지정한다. Gateway는 IP 주소, 포트, 프로토콜, TLS 인증서와 같은 트래픽 진입점을 정의한다. HTTPRoute는 호스트와 경로 조건을 이용해 요청을 Kubernetes Service에 연결한다.

예를 들어 플랫폼 운영팀은 공용 Gateway를 만들고 80번과 443번 포트를 관리할 수 있다. 각 개발팀은 자신의 네임스페이스에 HTTPRoute만 생성해 서비스 경로를 추가한다. 이 구조에서는 애플리케이션 개발자가 로드밸런서 전체 설정이나 다른 팀의 라우팅 규칙을 수정할 필요가 없다.

기존 Ingress가 리소스 중심의 단순한 진입점이라면 Gateway API는 조직의 역할까지 반영할 수 있는 트래픽 관리 모델에 가깝다. 특히 여러 팀이 하나의 Kubernetes 클러스터와 공용 로드밸런서를 사용하는 환경에서 차이가 분명하게 나타난다.

기존 Ingress를 HTTPRoute로 전환하는 절차

전환을 시작하기 전에 현재 사용 중인 Gateway API 컨트롤러가 필요한 기능을 지원하는지 확인해야 한다. Gateway API의 CRD만 설치한다고 트래픽이 처리되는 것은 아니다. NGINX Gateway Fabric, Istio, Envoy Gateway 또는 클라우드 사업자의 구현체처럼 GatewayClass를 처리할 컨트롤러가 필요하다.

먼저 클러스터에서 사용할 GatewayClass를 확인한다.

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: production-gateway
spec:
  controllerName: example.net/gateway-controller

다음으로 플랫폼 운영팀이 공용 Gateway를 생성한다. 아래 설정은 80번 포트로 HTTP 요청을 받고 지정된 네임스페이스의 Route 연결을 허용하는 기본 예시다.

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: public-gateway
  namespace: gateway-system
spec:
  gatewayClassName: production-gateway
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              gateway-access: public

애플리케이션 네임스페이스에는 HTTPRoute를 생성한다.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: shop-route
  namespace: shop
spec:
  parentRefs:
    - name: public-gateway
      namespace: gateway-system
      sectionName: http
  hostnames:
    - shop.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: shop-api
          port: 8080

여기서 parentRefs는 HTTPRoute가 연결될 Gateway를 지정하고, sectionName은 특정 리스너를 선택한다. 기존 Ingress의 host, path, service.name, service.port는 각각 HTTPRoute의 hostnames, matches, backendRefs로 옮겨진다.

운영 환경에서는 한 번에 기존 Ingress를 제거하지 않는 것이 안전하다. 신규 Gateway에 별도 테스트 도메인을 연결한 뒤 응답 코드, 리다이렉트, 헤더, 쿠키, 업로드 용량, 타임아웃을 검증해야 한다. 검증이 끝나면 DNS 가중치나 상위 로드밸런서 설정을 이용해 트래픽을 점진적으로 이동시키는 방식이 안정적이다.

트래픽 분할과 경로 제어 구성 방법

Gateway API의 장점 중 하나는 가중치 기반 트래픽 분할을 표준화된 형태로 표현할 수 있다는 점이다. 신규 버전을 바로 전체 사용자에게 공개하지 않고 기존 서비스에 90%, 신규 서비스에 10%를 전달하는 카나리 배포를 구성할 수 있다.

rules:
  - matches:
      - path:
          type: PathPrefix
          value: /
    backendRefs:
      - name: web-v1
        port: 8080
        weight: 90
      - name: web-v2
        port: 8080
        weight: 10

경로뿐 아니라 HTTP 헤더나 쿼리 파라미터를 조건으로 사용할 수도 있다. 특정 테스트 헤더가 포함된 요청만 신규 버전으로 전달하면 내부 검증용 배포에도 활용할 수 있다. 지원되는 필터를 사용하면 요청 헤더 추가·삭제, 리다이렉트, URL 재작성과 같은 동작도 라우팅 규칙에 포함할 수 있다.

다만 모든 Gateway API 구현체가 동일한 확장 기능을 제공하는 것은 아니다. 리소스가 Kubernetes API 서버에 정상적으로 등록됐다는 사실만으로 실제 라우팅이 적용됐다고 판단하면 안 된다. HTTPRoute의 status.parents.conditions를 확인해 AcceptedResolvedRefs 상태가 참인지 점검해야 한다.

개인적으로 전환 과정에서 가장 주의할 부분은 기존 Annotation을 기계적으로 옮기려는 접근이었다. Ingress에 적용된 Annotation 중 일부는 HTTPRoute 필터로 대체할 수 있지만, 연결 제한이나 세부 타임아웃처럼 구현체별 정책 리소스가 필요한 항목도 있다. 먼저 Annotation 목록을 기능별로 분류하고 표준 필드, 필터, 구현체 전용 정책 가운데 어디로 이전할지 결정하는 방식이 시행착오를 줄이는 데 효과적이었다.

네임스페이스 권한 분리와 트러블 슈팅

Gateway API의 권한 분리는 Kubernetes RBAC와 리소스 간 연결 정책을 함께 사용해야 완성된다. 플랫폼 팀에는 GatewayClass와 Gateway 관리 권한을 부여하고, 개발팀에는 담당 네임스페이스의 HTTPRoute 관리 권한만 부여하는 구성이 일반적이다. 이렇게 하면 개발팀이 애플리케이션 경로를 자율적으로 배포하면서도 공용 포트, 인증서, 로드밸런서 설정은 변경하지 못한다.

Gateway의 allowedRoutes는 어떤 네임스페이스의 Route가 리스너에 연결될 수 있는지 제한한다. 네임스페이스 라벨을 기준으로 허용하면 운영팀이 승인한 네임스페이스만 공용 Gateway를 사용할 수 있다. HTTPRoute가 다른 네임스페이스의 Service를 백엔드로 참조해야 한다면 대상 네임스페이스에 ReferenceGrant를 생성해야 한다. 이는 임의의 교차 네임스페이스 접근을 방지하는 안전장치다.

전환 후 요청이 404로 반환된다면 먼저 호스트 헤더와 경로 조건을 확인해야 한다. 테스트할 때 도메인 대신 로드밸런서 IP로 접근하면 HTTPRoute의 hostnames와 일치하지 않아 기본 응답이 반환될 수 있다. 다음과 같이 실제 호스트 헤더를 지정해 테스트하는 것이 정확하다.

curl -H "Host: shop.example.com" http://LOAD_BALANCER_ADDRESS/api/health

503 오류가 발생하면 Service 이름과 포트, EndpointSlice의 백엔드 주소, Pod의 준비 상태를 차례로 확인한다. ResolvedRefs=False라면 존재하지 않는 Service를 참조했거나 포트가 잘못됐거나 ReferenceGrant가 누락됐을 가능성이 크다. Accepted=False라면 allowedRoutes, 네임스페이스 라벨, parentRefs의 이름과 네임스페이스를 점검해야 한다.

또 다른 실무 이슈는 Route 우선순위 충돌이다. 여러 HTTPRoute가 같은 호스트와 유사한 경로를 선언하면 운영자가 예상한 서비스가 아닌 다른 백엔드로 연결될 수 있다. 전환 전에 전체 Ingress의 호스트와 경로를 표로 정리하고 중복 규칙을 제거하는 작업이 필요하다. Gateway와 HTTPRoute 상태뿐 아니라 컨트롤러 로그와 실제 요청 결과를 함께 확인해야 원인을 빠르게 좁힐 수 있다.

TLS 전환 시에는 인증서 Secret의 네임스페이스도 중요하다. 일반적으로 Gateway가 참조하는 인증서는 Gateway와 같은 네임스페이스에 두는 구성이 관리하기 쉽다. 다른 네임스페이스의 인증서를 참조한다면 컨트롤러의 지원 여부와 ReferenceGrant 구성을 확인해야 한다. 인증서가 올바르게 연결되지 않으면 Gateway는 생성돼 있어도 HTTPS 리스너가 준비되지 않을 수 있다.

마치며

Kubernetes Ingress에서 Gateway API로의 전환은 YAML 형식을 바꾸는 작업에 그치지 않는다. 플랫폼 운영팀과 애플리케이션 개발팀의 책임 범위를 분리하고, 컨트롤러 전용 Annotation에 의존하던 라우팅 정책을 보다 명확한 리소스로 옮기는 과정이다.

안전한 전환을 위해서는 현재 Ingress와 Annotation을 먼저 조사하고, 사용 중인 컨트롤러의 Gateway API 지원 범위를 확인해야 한다. 이후 Gateway와 HTTPRoute를 병행 운영하면서 테스트 도메인, 상태 조건, 컨트롤러 로그, 실제 요청 결과를 검증하는 것이 좋다. DNS 전환도 한 번에 진행하기보다 일부 트래픽부터 이동해 오류율과 응답 시간을 비교하는 편이 안전하다.

실제 운영에서는 리소스가 생성됐는지보다 컨트롤러가 해당 리소스를 정상적으로 수락했는지가 더 중요했다. kubectl get 결과만 확인하지 말고 Accepted, Programmed, ResolvedRefs 조건까지 살펴보는 습관이 필요하다. 이러한 점검 체계를 갖추면 Gateway API는 복잡한 멀티팀 Kubernetes 환경에서 트래픽 제어와 권한 분리를 동시에 개선할 수 있는 효과적인 선택이 된다.

PRODB

함께 보면 좋은 글

댓글 0

첫 댓글을 남겨보세요.

error: Content is protected !!

광고 차단 알림

광고 클릭 제한을 초과하여 광고가 차단되었습니다.

단시간에 반복적인 광고 클릭은 시스템에 의해 감지되며, IP가 수집되어 사이트 관리자가 확인 가능합니다.