Container Orchestration/Kubernetes

Kubernetes Gateway API 완전 정복

Somaz 2025. 4. 4. 13:54
728x90
반응형

Overview

Kubernetes는 기본적으로 Ingress 리소스를 통해 L7(HTTP/HTTPS) 트래픽을 처리하지만, 이 방식은 Layer 4(L4) 수준의 트래픽 제어나 멀티 프로토콜, 복잡한 인증 처리 등에서 한계를 가진다.

 

이를 해결하기 위해 등장한 Kubernetes Gateway APIL4~L7까지 유연하게 다룰 수 있는 새로운 네트워크 모델이다.

 

Ingress를 단순히 확장한 것이 아닌, 현대 클라우드 네트워크를 위한 진화된 표준이며, 서비스 메시, API Gateway, 로드밸런서 등을 하나의 공통 구조로 통합 관리할 수 있게 해준다.

 

 

 

 

 

 

📅 관련 글

2022.08.08 - [Container Orchestration/Kubernetes] - Kubernetes Ingress란? (클러스터 외부 트래픽 관리)

2024.06.24 - [Container Orchestration/Kubernetes] - Ingress Nginx란?

 

 

 

주요 이정표

시점 내용
2019년 후반 SIG-Network에서 Ingress의 한계를 해결하기 위한 새로운 API 디자인 논의 시작
2020년 4월 Gateway API 최초 알파 릴리스 (v1alpha1) 발표
2021~2022 다양한 컨트롤러(Envoy, Istio, NGINX, GKE 등)에서 Gateway API 지원 시작
2023년 일부 리소스(Gateway, HTTPRoute)가 v1beta1 또는 v1 로 안정화 준비
2024년 이후 많은 클라우드/서비스메시 벤더들이 공식 지원 중, Ingress 대비 실전 배포 증가

 

 

 

 

 

 

 


 

 

 

 

Gateway API란?

Gateway API는 Kubernetes에서 네트워크 트래픽을 외부로부터 클러스터 내부의 서비스로 안전하고 유연하게 전달하기 위한 새로운 표준 API 리소스 집합이다.

 

전통적으로는 Ingress 리소스를 통해 HTTP/HTTPS 요청을 클러스터 내부 서비스로 라우팅했지만, Ingress는 기능 확장에 한계가 있었고, L4(Transport Layer) 수준의 트래픽이나 멀티 프로토콜고급 라우팅 제어를 지원하기 어려웠다.

 

이러한 배경에서 등장한 것이 바로 Gateway API 이다.

 

 

왜 나왔어?

기존 Ingress 리소스는 너무 단순하고 확장성 부족,
모든 컨트롤러가 annotation에 의존해서 혼란스럽고 표준화 어려움.

👉 그래서 Gateway API는 Ingress의 진화 버전이자, L4~L7 통합을 위한 차세대 표준으로 만들어졌다.

 

 

 

 

Gateway API의 목적

Gateway API는 단순히 Ingress를 대체하는 것이 아니라, 다음과 같은 목표를 가지고 설계되었다.

 

  1. L4~L7 트래픽을 모두 지원하는 유연한 아키텍처
  2. 멀티 테넌시 및 보안 분리 구조 지원
  3. 컨트롤러 벤더 독립적인 표준화된 API
  4. Cloud Provider, Service Mesh, API Gateway 등 다양한 환경에서 통합 가능
  5. 선언적 구성(Helm/Kustomize)에 적합한 구조

 

 

 

 

핵심 리소스 구조

리소스 설명
GatewayClass 인프라 제공자가 정의하는 Gateway 구현 클래스
Gateway 실제 L4/L7 트래픽을 수신하는 리소스
Route (HTTPRoute, TLSRoute, TCPRoute, GRPCRoute) 서비스로 트래픽을 라우팅하는 규칙
ReferencePolicy, BackendPolicy 고급 권한과 정책 제어 리소스

 

 

 

어떤 문제를 해결할 수 있을까?

  • 단순 HTTP 트래픽 외에 TCP, TLS, gRPC 등 다양한 프로토콜을 하나의 Gateway에서 처리할 수 있음
  • 서로 다른 팀/서비스 간에 Gateway 자원을 안전하게 공유 가능
  • cert-manager, Service Mesh 등과 통합해 TLS 자동화 및 보안 구성 간소화
  • 멀티 클러스터 환경에서 Gateway를 통합 API로 추상화하여 외부 진입점 관리

 

 

 

왜 L4/L7 혼합 시나리오가 필요한가?

현실의 서비스는 단일 프로토콜로만 동작하지 않는다. 예를 들어:

  • HTTP API는 HTTPRoute로 처리
  • gRPC 서버는 GRPCRoute로 라우팅
  • 게임 서버는 TCP를 사용하므로 TCPRoute 필요
  • TLS termination은 TLSRoute에서 처리

이러한 혼합된 요구를 단일 Gateway 리소스로 구성할 수 있는 것이 Gateway API의 강점이다.

 

 

 

 

 


 

 

 

 

 

Gateway API vs Ingress 비교표

항목 Ingress Gateway API
API 안정성 v1 (Stable) v1 / v1alpha2 (일부 기능)
지원 프로토콜 HTTP/HTTPS (L7 전용) HTTP, HTTPS, gRPC, TCP, TLS (L4~L7 혼합 지원)
라우팅 리소스 단일 리소스 (Ingress) 다중 리소스 (HTTPRoute, TCPRoute, TLSRoute, GRPCRoute)
TLS 처리 방식 Secret 참조 (단순 구성) certificateRefs로 세분화, 다양한 모드 지원 (Terminate, Passthrough 등)
역할 분리 없음 (Ingress 하나로 구성) GatewayClass/Gateway/Route로 명확히 분리
멀티 테넌시 제한적 (네임스페이스 기반 공유 불명확) AllowedRoutes로 네임스페이스/권한 범위 제어
커스텀 확장성 제한적 (annotation 기반) 고도로 유연함 (CRD 기반 확장 및 표준화)
컨트롤러 독립성 대부분 NGINX에 종속 (Ingress Controller) 컨트롤러 선택 가능 (NGINX, Istio, Envoy, GKE, AWS 등)
gRPC 지원 불완전 (Path 기반 라우팅만) 완전한 GRPCRoute 지원 (서비스/메서드 기준)
L4 지원 (TCP 등) 미지원 TCPRoute로 가능
Helm/Kustomize 호환성 제한적 구조 선언적 구조로 자동화에 용이
향후 확장성 개발 중단 예정 아님, 그러나 제한적 Kubernetes 공식 차세대 네트워크 표준으로 확장 중
  • Ingress는 단순하고 빠르게 설정할 수 있지만, 기능 확장성과 역할 분리가 부족하다.
  • Gateway API는 더 복잡해 보일 수 있지만, 실제 운영 환경에서 요구되는 다양한 기능(L4~L7, TLS 자동화, 멀티 테넌시 등)을 체계적으로 지원한다.
  • 특히 `Service Mesh`, `Multi-cluster`, `TLS 관리`, `gRPC` 등 최신 트렌드와 어울리는 구조

 

 

 

 


 

 

 

 

 

Ingress NGINX Controller가 이미 설치되어 있어도 괜찮을까?

 

문제 없다.

 

  • Gateway API는 Ingress Controller와 완전히 별개로 동작한다.
  • 서로 다른 리소스 (Ingress vs HTTPRoute, Gateway)를 바라보며, 서로 다른 컨트롤러가 관리한다.
  • 단, 포트 충돌만 조심하면 됩니다 (예: 두 컨트롤러가 모두 LoadBalancer 80/443 포트를 쓰려 할 때).

 

  • Ingress NGINX는 보통 ingress-nginx 네임스페이스에 설치되고 Ingress 리소스를 감지한다.
  • NGINX Gateway Controller는 nginx-gateway 네임스페이스에 설치되며 Gateway, HTTPRoute 등을 감지한다.

 

 

결론

항목 가능 여부 설명
Helm으로 NGINX Gateway 설치 ✅ 가능 nginx-stable/kubernetes-gateway Chart 사용
Ingress NGINX Controller와 동시 운영 ✅ 가능 리소스/컨트롤러가 분리되어 충돌 없음
포트 충돌 가능성 ⚠️ 주의 ❌ LoadBalancer IP가 다르면 충돌 없음

 

 

 

 


 

 

 

 

 

Gateway 리소스를 어디에 만들어야 할까?

리소스 위치 기준 설명
GatewayClass 클러스터 전역 어떤 Gateway 컨트롤러를 사용할지 지정
Gateway 애플리케이션(Service)이 존재하는 네임스페이스 실제로 트래픽을 수신하는 진입점
Route (HTTPRoute 등) 애플리케이션 네임스페이스 Gateway를 참조하여 라우팅 정의

 

 

이해 포인트

  • `GatewayClass` 는 전역 리소스니까 네임스페이스가 없다 (`cluster-scoped`)
  • `Gateway` 는 특정 네임스페이스에 생성되며, 해당 네임스페이스에 존재하는 Route만 기본적으로 받아들인다
    • 물론 `allowedRoutes` 설정으로 다른 네임스페이스도 허용할 수 있다.
  • `Route` (`HTTPRoute`, `TLSRoute` 등)는 자신의 네임스페이스에서 Gateway를 `parentRefs` 로 참조한다

 

`default` 네임스페이스에 있는 애플리케이션을 외부에서 노출하고 싶다면:

  • `Gateway` → `default` 네임스페이스에 생성
  • `HTTPRoute` → `default` 네임스페이스에 생성
  • `Service`, `Deployment` → 역시 `default` 에 존재

 

 

advanced: 네임스페이스 분리하고 싶다면?

예를 들어 Gateway는 `ingress-system` 네임스페이스에 있고, 애플리케이션은 `app-namespace` 에 있을 수도 있다.
이때는 `Gateway` 의 `allowedRoutes` 설정을 다음처럼 바꿔줘야 한다.

allowedRoutes:
  namespaces:
    from: All

 

 

또는 더 안전하게

allowedRoutes:
  namespaces:
    from: Selector
    selector:
      matchLabels:
        route-allowed: "true"

 

 

그리고 app-namespace에 label 추가

kubectl label namespace app-namespace route-allowed=true
  • 이렇게 하면 네임스페이스 간 정책 기반 라우팅 제어도 가능하다.

 

 

 

 

 


 

 

 

 

 

 

 

ReferenceGrant란?

ReferenceGrant는 다른 네임스페이스에 있는 리소스를 참조할 수 있도록 허용하는 보안 리소스이다.

 

Kubernetes Gateway API는 보안 원칙에 따라,
HTTPRoute, TCPRoute 등의 Route 리소스가 다른 네임스페이스의 Service를 참조하려면 명시적인 허가가 필요하다.

 

이때 필요한 것이 바로 ReferenceGrant이다.

 

 

언제 필요할까?

  • `Gateway` 는 `default` 네임스페이스에 있고,
  • 실제 애플리케이션은 `mario-ns, tetris-ns` 등 다른 네임스페이스에 존재
  • `HTTPRoute` 에서 해당 서비스를 라우팅 대상으로 지정하고 싶은 경우

이 경우 서비스가 위치한 네임스페이스에서 `ReferenceGrant` 를 선언해야 한다.

 

 

 

왜 필요한가?

Ingress에서는 네임스페이스 간 참조를 자유롭게 했지만,
Gateway API는 보안에 더 민감하게 설계되어 있어,


명확한 허가 없이는 다른 네임스페이스의 리소스를 참조할 수 없다.

이는 멀티 테넌시 환경이나 팀 간 리소스 분리를 할 때 강력한 보안 이점을 제공한다.

 

 

 

예시

# mario-ns에 생성
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-mario-service
  namespace: mario-ns
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: default
  to:
    - group: ""
      kind: Service
  • 이 예시는 default 네임스페이스에 있는 `HTTPRoute` 가
  • `mario-ns` 네임스페이스에 있는 `Service` 를 참조할 수 있도록 허용한다.

 

 

 

참고 요약

항목 설명
리소스 타입 ReferenceGrant
배치 위치 서비스가 존재하는 네임스페이스
목적 네임스페이스 간 Route → Service 참조 허용
보안 효과 L7 트래픽 제어에 RBAC 수준의 제한을 제공

 

ReferenceGrant는 Gateway API의 보안 모델에서 매우 중요한 핵심 개념으로,
서비스 간 경계를 명확히 하고, 네임스페이스 기반의 안전한 라우팅을 가능하게 한다.

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

실습 1: HTTPRoute + TLSRoute + GRPCRoute + TCPRoute

실습 환경: Kind 또는 Minikube + NGINX Gateway Controller

 

 

CRD 설치

kubectl kustomize https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard | kubectl apply -f -

 

 

NGINX Gateway Controller - Helm 설치 방법

# Installing the Chart from the OCI Registry
helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
  --namespace nginx-gateway \
  --create-namespace \
  --wait

# Installing the Chart from the OCI Registry NodePort
helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
  --namespace nginx-gateway \
  --create-namespace \
  --set service.type=NodePort
  
# Installing the Chart via Sources

## Pulling the Chart
helm pull oci://ghcr.io/nginx/charts/nginx-gateway-fabric --untar
cd nginx-gateway-fabric

## Installing the Chart
helm install ngf . --create-namespace -n nginx-gateway
  • 위 명령어는 기본 설치이며, 필요 시 values.yaml 파일을 커스터마이징해서 사용할 수도 있다.

 

 

 

설명 요약

필드 설명
`nginxGateway.gatewayClassName` Gateway 리소스에서 사용하는 class 이름 (예: nginx)
`replicaCount` 기본적으로 1이지만, 가용성 확보를 위해 2로 설정
`service.type` LoadBalancer로 설정하여 외부 IP 할당
`externalTrafficPolicy` Local 설정 시 클라이언트의 실제 IP 유지 가능
`metrics.enable` Prometheus에서 수집할 수 있도록 메트릭 활성화
`pullPolicy` 이미지 캐시 정책 (IfNotPresent이면 캐시 있음)

 

 

 

 

 

 

GatewayClass, Gateway 설정

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: nginx-gateway
spec:
  controllerName: nginx.org/gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: mixed-gateway
  namespace: default
spec:
  gatewayClassName: nginx-gateway
  listeners:
    - name: http
      port: 80
      protocol: HTTP
      allowedRoutes:
        namespaces:
          from: Same
    - name: tls
      port: 443
      protocol: HTTPS
      tls:
        mode: Terminate
        certificateRefs:
          - name: my-cert
            kind: Secret
      allowedRoutes:
        namespaces:
          from: Same
    - name: grpc
      port: 50051
      protocol: HTTP
      allowedRoutes:
        namespaces:
          from: Same
    - name: tcp
      port: 3306
      protocol: TCP
      allowedRoutes:
        namespaces:
          from: Same

 

 

`from: Same` vs `from: All` vs `from: Selector`

설정 값 의미 특징
Same Gateway와 같은 네임스페이스의 Route만 허용 보안에 좋고, 단순함
All 모든 네임스페이스의 Route 허용 유연하지만 보안적으로 넓은 권한
Selector 특정 라벨을 가진 네임스페이스만 허용 유연 + 안전의 균형

 

 

 

Same 사용 시 (기본값)

allowedRoutes:
  namespaces:
    from: Same
  • `Gateway` 와 같은 네임스페이스에 존재하는 `HTTPRoute` 만 사용 가능
  • 다른 네임스페이스의 서비스 라우팅 불가
  • 운영 초기나 보안 민감 환경에서는 추천

 

 

All 사용 시

allowedRoutes:
  namespaces:
    from: All
  • 모든 네임스페이스에 존재하는 `HTTPRoute`, `GRPCRoute`, `TCPRoute` 등을 수용 가능
  • 여러 팀, 여러 앱이 각자 네임스페이스에 `Route` 를 정의하고도 공통 `Gateway` 로 진입 가능
  • 운영 유연성은 높지만, 신중한 관리 필요

 

 

Selector 사용 시

allowedRoutes:
  namespaces:
    from: Selector
    selector:
      matchLabels:
        route-allowed: "true"
  • 특정 라벨을 가진 네임스페이스의 Route만 허용
  • `from: All` 보다 더 안전하고 세밀한 권한 제어 가능
  • 팀/서비스 단위로 네임스페이스에 라벨을 부여해서 정교한 멀티테넌시 구성에 적합
kubectl label namespace mario-ns route-allowed=true
kubectl label namespace tetris-ns route-allowed=true

 

 

 

 

 

 

 

HTTPRoute 예시

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: web-http
spec:
  parentRefs:
    - name: mixed-gateway
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: web
          port: 80

 

 

 

 

TLSRoute 예시

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
  name: tls-app
spec:
  parentRefs:
    - name: mixed-gateway
  hostnames:
    - "tls.example.com"
  rules:
    - backendRefs:
        - name: secure-svc
          port: 443

 

 

 

 

GRPCRoute 예시

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: GRPCRoute
metadata:
  name: grpc-api
spec:
  parentRefs:
    - name: mixed-gateway
  rules:
    - matches:
        - method:
            service: my.grpc.Service
            method: GetStatus
      backendRefs:
        - name: grpc-service
          port: 50051

 

 

 

 

 

TCPRoute 예시

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: tcp-db
spec:
  parentRefs:
    - name: mixed-gateway
  rules:
    - backendRefs:
        - name: mysql-db
          port: 3306

 

 

 

 

 


 

 

 

 

 

 

실습 2: Helm 템플릿으로 Gateway 리소스 자동화

다양한 환경(dev, staging, prod)에 따라 Gateway 리소스를 자동 생성하고 싶을 때 Helm은 큰 도움이 된다.

 

 

 

`templates/gateway.yaml`

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: {{ include "myapp.fullname" . }}-gateway
spec:
  gatewayClassName: {{ .Values.gateway.className }}
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: Same
    {{- if .Values.gateway.enableTLS }}
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: {{ .Values.gateway.tlsSecret }}
      allowedRoutes:
        namespaces:
          from: Same
    {{- end }}

 

 

 

 

`values.yaml`

gateway:
  className: nginx-gateway
  enableTLS: true
  tlsSecret: my-cert

 

 

 

 

설치

helm upgrade --install myapp ./mychart -f values.yaml

 

 

 

 


 

 

 

 

실습 3: Gateway API 기반의 클러스터 간 통신 (Multi-cluster Gateway)

멀티 클러스터 환경에서는 클러스터 A의 Gateway를 통해 클러스터 B의 서비스를 노출하거나 통신을 중계해야 하는 경우가 많다.

 

Gateway API는 이런 구조에서 다음과 같은 방법으로 사용된다.

 

시나리오 구성

  • 클러스터 A: 외부 요청 수신용 Gateway
  • 클러스터 B: 내부 서비스 제공
  • 클러스터 간 연결: VPN, VPC Peering, 혹은 Istio/Linkerd 기반 서비스 메시

 

설정 예시

 

 

클러스터 A에서의 TCPRoute

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: db-forward
spec:
  parentRefs:
    - name: mixed-gateway
  rules:
    - backendRefs:
        - name: db-proxy
          port: 3306

 

`db-proxy` 는 클러스터 B에 있는 DB에 연결하는 Proxy Pod이다. (예: `socat`, `cloud-sql-proxy`, custom TCP forwarder 등)

이런 방식으로 클러스터 A에서 들어온 외부 요청을 클러스터 B로 안전하게 전달할 수 있다.

 

 

 

 


 

 

 

 

 

 

실습 4: GRPCRoute와 Service Mesh 통합 전략

gRPC는 HTTP/2 기반 프로토콜이므로 기존 Ingress에서는 정교한 라우팅이 어려웠다. Gateway API는 GRPCRoute를 통해 서비스 메시와의 통합에 유리하다.

 

 

📎 시나리오

  • Istio 또는 Linkerd 환경에서 Gateway API를 통합 엔트리 포인트로 사용
  • 내부 통신은 메시를 통해 이루어지고, 외부 진입만 Gateway가 담당

 

예시: Istio + GRPCRoute

Istio 1.21 이상에서는 Gateway API를 지원한다.

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: GRPCRoute
metadata:
  name: grpc-public
spec:
  parentRefs:
    - name: istio-ingressgateway
      namespace: istio-system
  rules:
    - matches:
        - method:
            service: my.grpc.Service
      backendRefs:
        - name: internal-grpc
          port: 50051
  • 이렇게 하면 Gateway API → Istio Envoy → 내부 서비스 흐름이 만들어져, 외부 진입 포인트를 Gateway API로 통합할 수 있다.

 

 

 

 


 

 

 

 

실습 5: Gateway API + Cert-Manager로 TLS 자동화 구성

TLS 인증서를 수동으로 관리하는 것은 번거롭고 위험하다. Gateway API는 cert-manager와 함께 사용할 때 매우 강력한 TLS 자동화를 제공한다.

 

 

💡 구성 흐름

  1. `cert-manager` 가 Let's Encrypt에서 인증서 자동 발급
  2. `Secret` 으로 저장
  3. Gateway에서 `certificateRefs` 로 해당 Secret 참조

 

 

예시: 자동 TLS 구성

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: tls-cert
spec:
  secretName: my-cert
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
    - example.mydomain.com

 

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: game-gateway
  namespace: default
spec:
  gatewayClassName: nginx-gateway
  listeners:
    - name: https
      port: 443
      protocol: HTTPS
      hostname: example.domain.com
      tls:
        mode: Terminate
        certificateRefs:
          - name: my-cert  # cert-manager 가 발급한 Secret
      allowedRoutes:
        namespaces:
          from: Same
  • 이렇게 구성하면 Gateway 리스너가 자동 발급된 인증서를 사용하게 되며, `cert-manager` 는 자동 갱신까지 관리한다.

 

 

 

 

 


 

 

 

 

 

실습6: 구성 요약

  • GatewayClass 이름: `nginx-gateway`
  • 도메인: 하나 (예: `game.example.com`)
    • `metal-lb-nginx-gateway.domain → A → 10.10.10.62`
    • `game.example.com → CNAME → metal-lb-nginx-gateway.domain`
  • Path 기반 분기:
    • `/mario` → mario 서비스
    • `/tetris` → tetris 서비스
  • Pod 2개: 각각 mario, tetris 앱
  • 외부 접속 가능: LoadBalancer 타입

 

 

설치 순서 정리

# helm chart pull
helm pull oci://ghcr.io/nginx/charts/nginx-gateway-fabric --untar
cd nginx-gateway-fabric

# 1. CRD 설치
kubectl kustomize https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard | kubectl apply -f -

## experimental CRD (Option)
kubectl kustomize https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/experimental | kubectl apply -f -


# 2. Helm 차트 설치
helm install ngf . --create-namespace -n nginx-gateway -f mgmt.yaml

# 3. 리소스 배포
kubectl apply -f gateway.yaml
kubectl apply -f httproute.yaml
kubectl apply -f mario-refer.yaml
kubectl apply -f tetris-refer.yaml
kubectl apply -f mario-deployment.yaml
kubectl apply -f tetris-deployment.yaml

# 업그레이드
helm upgrade ngf . -n nginx-gateway -f mgmt.yaml

 

 

 

`values.yaml` 복사한다.

cp values.yaml mgmt.yaml

 

 

 

`mgmt.yaml`

# yaml-language-server: $schema=values.schema.json

nginxGateway:
  kind: deployment
  gatewayClassName: nginx-gateway
  gatewayControllerName: gateway.nginx.org/nginx-gateway-controller
  replicaCount: 1

  # The configuration for leader election.
  leaderElection:
    enable: true
  image:
    # -- The NGINX Gateway Fabric image to use
    repository: ghcr.io/nginx/nginx-gateway-fabric
    tag: 1.6.2
    pullPolicy: IfNotPresent

  snippetsFilters:
    enable: true

nginx:
  image:
    # -- The NGINX image to use.
    repository: ghcr.io/nginx/nginx-gateway-fabric/nginx
    tag: 1.6.2
    pullPolicy: IfNotPresent

service:
  create: true
  type: LoadBalancer
  externalTrafficPolicy: Local
  loadBalancerIP: "10.10.10.62"
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
      name: http
    - port: 443
      targetPort: 443
      protocol: TCP
      name: https

metrics:
  enable: true
  • loadbalancer ip 는 본인이 사용할 ip를 넣어주면 된다.

 

 

 

 

GatewayClass + Gateway

# gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: nginx-gateway
spec:
  controllerName: gateway.nginx.org/nginx-gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: game-gateway
  namespace: default
spec:
  gatewayClassName: nginx-gateway
  listeners:
    - name: http
      port: 80
      protocol: HTTP
      allowedRoutes:
        namespaces:
          from: All

 

 

또는 아래와 같이 설정도 가능하다. (보안 설정)

# gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: nginx-gateway
spec:
  controllerName: gateway.nginx.org/nginx-gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: game-gateway
  namespace: default
spec:
  gatewayClassName: nginx-gateway
  listeners:
    - name: http
      port: 80
      protocol: HTTP
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              allow-gateway: "true"

 

 

그리고 네임스페이스에 추가해준다.

kubectl create ns mario-ns 
kubectl create ns tetris-ns

kubectl label namespace mario-ns allow-gateway=true
kubectl label namespace tetris-ns allow-gateway=true
kubectl label ns default allow-gateway=true

 

 

 

 

 

`HTTPRoute`

# httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: game-route
  namespace: default
spec:
  parentRefs:
    - name: game-gateway
  hostnames:
    - game.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /mario
      filters:
        - type: URLRewrite
          urlRewrite:
            path:
              type: ReplaceFullPath
              replaceFullPath: /
      backendRefs:
        - name: mario
          namespace: mario-ns
          port: 80
    - matches:
        - path:
            type: PathPrefix
            value: /tetris
      filters:
        - type: URLRewrite
          urlRewrite:
            path:
              type: ReplaceFullPath
              replaceFullPath: /
      backendRefs:
        - name: tetris
          namespace: tetris-ns
          port: 80

 

 

 

ReferenceGrant 생성

 

Gateway API는 보안에 민감하게 설계되어 있어서,
네임스페이스 간 리소스 참조는 반드시 ReferenceGrant로 명시적으로 허용해야 한다.

 

이게 바로 Ingress보다 더 강력한 RBAC 기반 L7 라우팅 컨트롤이 가능한 이유 중 하나이다.

 

 

`tetris-refer.yaml`

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-tetris-service
  namespace: tetris-ns
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: default
  to:
    - group: ""
      kind: Service

 

 

`mario-refer.yaml`

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-mario-service
  namespace: mario-ns
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: default
  to:
    - group: ""
      kind: Service

 

 

 

 

Deployments & Services

# mario-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mario
  namespace: mario-ns
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mario
  template:
    metadata:
      labels:
        app: mario
    spec:
      containers:
        - name: mario
          image: pengbai/docker-supermario
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: mario
  namespace: mario-ns
spec:
  selector:
    app: mario
  ports:
    - port: 80
      targetPort: 8080  # mario 컨테이너는 8080 포트 사용
  type: ClusterIP

 

 

# tetris-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tetris
  namespace: tetris-ns
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tetris
  template:
    metadata:
      labels:
        app: tetris
    spec:
      containers:
        - name: tetris
          image: bsord/tetris
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: tetris
  namespace: tetris-ns
spec:
  selector:
    app: tetris
  ports:
    - port: 80
      targetPort: 80
  type: ClusterIP

 

 

 

 

문제 발생시 확인

 

httproute 확인

 kubectl get httproute -n default game-route -o yaml |grep conditions -A12
  - conditions:
    - lastTransitionTime: "2025-03-21T07:32:12Z"
      message: The route is accepted
      observedGeneration: 1
      reason: Accepted
      status: "True"
      type: Accepted
    - lastTransitionTime: "2025-03-21T07:32:12Z"
      message: All references are resolved
      observedGeneration: 1
      reason: ResolvedRefs
      status: "True"
      type: ResolvedRefs
  • 전부 `status` 가 `True` 여야 한다.

 

 

nginx-fabric-controller 확인

kubectl logs -n nginx-gateway deployment/ngf-nginx-gateway-fabric -c nginx

kubectl logs -n nginx-gateway deployment/ngf-nginx-gateway-fabric -c nginx-gateway
  • nginx는 실제 요청 처리하는 데이터 플레인이고, nginx-gateway는 컨트롤 플레인 역할이다.

 

 

 

정리(삭제)

# app 삭제
kubectl delete -f mario-deployment.yaml
kubectl delete -f tetris-deployment.yaml

# 나머지 삭제
kubectl delete -f httproute.yaml
kubectl delete -f gateway.yaml
kubectl delete -f mario-refer.yaml
kubectl delete -f tetris-refer.yaml

helm delete ngf -n nginx-gateway
kubectl kustomize https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard | kubectl delete -f -
kubectl kustomize https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/experimental | kubectl delete -f -

kubectl delete ns nginx-gateway
kubectl delete ns mario-ns
kubectl delete ns tetris-ns

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

마무리: Gateway API의 미래는?

 

Gateway API는 단순히 Ingress의 대체제가 아니다. 다음과 같은 특징으로 현대 클라우드 아키텍처의 핵심 네트워크 표준으로 자리잡고 있다.

  • 멀티 프로토콜 지원 (HTTP/gRPC/TCP/TLS)
  • 멀티 테넌시 및 RBAC 기반 트래픽 제어
  • 컨트롤러 벤더와 무관한 표준화
  • Helm/Kustomize 등과 잘 어울리는 선언적 구성

 

 

앞으로 Istio, Envoy, GKE Gateway, AWS VPC Lattice 등 다양한 환경에서 Gateway API를 중심으로 서비스 메시 + API Gateway + LoadBalancer 통합 전략이 본격화될 것이다.

 

 

 

 

 

 

 

 


Reference

 

 

728x90
반응형